* [PATCH] drm/amdgpu/sdma3: Work around POLL_REGMEM / FENCE hang
@ 2026-10-06 22:02 Timur Kristóf
2026-10-13 16:34 ` Deucher, Alexander
0 siblings, 1 reply; 2+ messages in thread
From: Timur Kristóf @ 2026-10-06 22:02 UTC (permalink / raw)
To: amd-gfx, Alexander.Deucher, Natalie Vock, Mario Limonciello,
David Rosca, Christian König, Lijo Lazar, Tvrtko Ursulin
Cc: Timur Kristóf
SDMA can randomly hang on Polaris 10. Hard to reproduce,
but has been occurring sporadically in the Mesa CI
on the RADV Polaris 10 job even when Mesa isn't using
the SDMA engine.
When Mesa actually uses the SDMA on Polaris, the hang
becomes more frequent and the reproduction rate goes up
significantly in the CI system.
We don't know why the hangs occur, but it seems
that inserting a single NOP packet before each
POLL_REGMEM and FENCE packet works around it.
At the moment it's unclear which GPUs are affected,
so let's apply this to SDMA 3.x for now.
Note that this issue is not documented or acknowledged by AMD.
Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
---
drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | 25 +++++++++++++++++++++----
1 file changed, 21 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
index 6f7243370acb..81f804c9d092 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
@@ -458,6 +458,9 @@ static void sdma_v3_0_ring_emit_hdp_flush(struct amdgpu_ring *ring)
else
ref_and_mask = REG_SET_FIELD(ref_and_mask, GPU_HDP_FLUSH_DONE, SDMA1, 1);
+ /* Hang workaround */
+ amdgpu_ring_write(ring, SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP));
+
amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_POLL_REGMEM) |
SDMA_PKT_POLL_REGMEM_HEADER_HDP_FLUSH(1) |
SDMA_PKT_POLL_REGMEM_HEADER_FUNC(3)); /* == */
@@ -485,6 +488,10 @@ static void sdma_v3_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
unsigned flags)
{
bool write64bit = flags & AMDGPU_FENCE_FLAG_64BIT;
+
+ /* Hang workaround */
+ amdgpu_ring_write(ring, SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP));
+
/* write the fence */
amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE));
amdgpu_ring_write(ring, lower_32_bits(addr));
@@ -493,7 +500,11 @@ static void sdma_v3_0_ring_emit_fence(struct amdgpu_ring *ring, u64 addr, u64 se
/* optionally write high bits as well */
if (write64bit) {
+ /* Hang workaround */
+ amdgpu_ring_write(ring, SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP));
+
addr += 4;
+
amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_FENCE));
amdgpu_ring_write(ring, lower_32_bits(addr));
amdgpu_ring_write(ring, upper_32_bits(addr));
@@ -1010,6 +1021,9 @@ static void sdma_v3_0_ring_emit_pipeline_sync(struct amdgpu_ring *ring)
uint32_t seq = ring->fence_drv.sync_seq;
uint64_t addr = ring->fence_drv.gpu_addr;
+ /* Hang workaround */
+ amdgpu_ring_write(ring, SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP));
+
/* wait for idle */
amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_POLL_REGMEM) |
SDMA_PKT_POLL_REGMEM_HEADER_HDP_FLUSH(0) |
@@ -1038,6 +1052,9 @@ static void sdma_v3_0_ring_emit_vm_flush(struct amdgpu_ring *ring,
{
amdgpu_gmc_emit_flush_gpu_tlb(ring, vmid, pd_addr);
+ /* Hang workaround */
+ amdgpu_ring_write(ring, SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP));
+
/* wait for flush */
amdgpu_ring_write(ring, SDMA_PKT_HEADER_OP(SDMA_OP_POLL_REGMEM) |
SDMA_PKT_POLL_REGMEM_HEADER_HDP_FLUSH(0) |
@@ -1467,11 +1484,11 @@ static const struct amdgpu_ring_funcs sdma_v3_0_ring_funcs = {
.get_wptr = sdma_v3_0_ring_get_wptr,
.set_wptr = sdma_v3_0_ring_set_wptr,
.emit_frame_size =
- 6 + /* sdma_v3_0_ring_emit_hdp_flush */
+ 6 + 1 + /* sdma_v3_0_ring_emit_hdp_flush */
3 + /* hdp invalidate */
- 6 + /* sdma_v3_0_ring_emit_pipeline_sync */
- VI_FLUSH_GPU_TLB_NUM_WREG * 3 + 6 + /* sdma_v3_0_ring_emit_vm_flush */
- 10 + 10 + 10, /* sdma_v3_0_ring_emit_fence x3 for user fence, vm fence */
+ 6 + 1 + /* sdma_v3_0_ring_emit_pipeline_sync */
+ VI_FLUSH_GPU_TLB_NUM_WREG * 3 + 6 + 1 + /* sdma_v3_0_ring_emit_vm_flush */
+ (10 + 1) * 3, /* sdma_v3_0_ring_emit_fence x3 for user fence, vm fence */
.emit_ib_size = 7 + 6, /* sdma_v3_0_ring_emit_ib */
.emit_ib = sdma_v3_0_ring_emit_ib,
.emit_fence = sdma_v3_0_ring_emit_fence,
--
2.55.0
^ permalink raw reply related [flat|nested] 2+ messages in thread* RE: [PATCH] drm/amdgpu/sdma3: Work around POLL_REGMEM / FENCE hang
2026-10-06 22:02 [PATCH] drm/amdgpu/sdma3: Work around POLL_REGMEM / FENCE hang Timur Kristóf
@ 2026-10-13 16:34 ` Deucher, Alexander
0 siblings, 0 replies; 2+ messages in thread
From: Deucher, Alexander @ 2026-10-13 16:34 UTC (permalink / raw)
To: Timur Kristóf, amd-gfx@lists.freedesktop.org, Natalie Vock,
Limonciello, Mario, Rosca, David, Koenig, Christian, Lazar, Lijo,
Tvrtko Ursulin
Public
> -----Original Message-----
> From: Timur Kristóf <timur.kristof@gmail.com>
> Sent: Tuesday, October 6, 2026 6:03 PM
> To: amd-gfx@lists.freedesktop.org; Deucher, Alexander
> <Alexander.Deucher@amd.com>; Natalie Vock <natalie.vock@gmx.de>;
> Limonciello, Mario <Mario.Limonciello@amd.com>; Rosca, David
> <David.Rosca@amd.com>; Koenig, Christian <Christian.Koenig@amd.com>;
> Lazar, Lijo <Lijo.Lazar@amd.com>; Tvrtko Ursulin <tursulin@ursulin.net>
> Cc: Timur Kristóf <timur.kristof@gmail.com>
> Subject: [PATCH] drm/amdgpu/sdma3: Work around POLL_REGMEM / FENCE
> hang
>
> SDMA can randomly hang on Polaris 10. Hard to reproduce, but has been
> occurring sporadically in the Mesa CI on the RADV Polaris 10 job even when
> Mesa isn't using the SDMA engine.
>
> When Mesa actually uses the SDMA on Polaris, the hang becomes more
> frequent and the reproduction rate goes up significantly in the CI system.
>
> We don't know why the hangs occur, but it seems that inserting a single NOP
> packet before each POLL_REGMEM and FENCE packet works around it.
> At the moment it's unclear which GPUs are affected, so let's apply this to
> SDMA 3.x for now.
>
> Note that this issue is not documented or acknowledged by AMD.
>
> Signed-off-by: Timur Kristóf <timur.kristof@gmail.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
And applied.
Thanks!
> ---
> drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c | 25
> +++++++++++++++++++++----
> 1 file changed, 21 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
> b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
> index 6f7243370acb..81f804c9d092 100644
> --- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c
> @@ -458,6 +458,9 @@ static void sdma_v3_0_ring_emit_hdp_flush(struct
> amdgpu_ring *ring)
> else
> ref_and_mask = REG_SET_FIELD(ref_and_mask,
> GPU_HDP_FLUSH_DONE, SDMA1, 1);
>
> + /* Hang workaround */
> + amdgpu_ring_write(ring,
> SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP));
> +
> amdgpu_ring_write(ring,
> SDMA_PKT_HEADER_OP(SDMA_OP_POLL_REGMEM) |
>
> SDMA_PKT_POLL_REGMEM_HEADER_HDP_FLUSH(1) |
> SDMA_PKT_POLL_REGMEM_HEADER_FUNC(3)); /*
> == */ @@ -485,6 +488,10 @@ static void sdma_v3_0_ring_emit_fence(struct
> amdgpu_ring *ring, u64 addr, u64 se
> unsigned flags)
> {
> bool write64bit = flags & AMDGPU_FENCE_FLAG_64BIT;
> +
> + /* Hang workaround */
> + amdgpu_ring_write(ring,
> SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP));
> +
> /* write the fence */
> amdgpu_ring_write(ring,
> SDMA_PKT_HEADER_OP(SDMA_OP_FENCE));
> amdgpu_ring_write(ring, lower_32_bits(addr)); @@ -493,7 +500,11
> @@ static void sdma_v3_0_ring_emit_fence(struct amdgpu_ring *ring, u64
> addr, u64 se
>
> /* optionally write high bits as well */
> if (write64bit) {
> + /* Hang workaround */
> + amdgpu_ring_write(ring,
> SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP));
> +
> addr += 4;
> +
> amdgpu_ring_write(ring,
> SDMA_PKT_HEADER_OP(SDMA_OP_FENCE));
> amdgpu_ring_write(ring, lower_32_bits(addr));
> amdgpu_ring_write(ring, upper_32_bits(addr)); @@ -1010,6
> +1021,9 @@ static void sdma_v3_0_ring_emit_pipeline_sync(struct
> amdgpu_ring *ring)
> uint32_t seq = ring->fence_drv.sync_seq;
> uint64_t addr = ring->fence_drv.gpu_addr;
>
> + /* Hang workaround */
> + amdgpu_ring_write(ring,
> SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP));
> +
> /* wait for idle */
> amdgpu_ring_write(ring,
> SDMA_PKT_HEADER_OP(SDMA_OP_POLL_REGMEM) |
>
> SDMA_PKT_POLL_REGMEM_HEADER_HDP_FLUSH(0) | @@ -1038,6 +1052,9
> @@ static void sdma_v3_0_ring_emit_vm_flush(struct amdgpu_ring *ring, {
> amdgpu_gmc_emit_flush_gpu_tlb(ring, vmid, pd_addr);
>
> + /* Hang workaround */
> + amdgpu_ring_write(ring,
> SDMA_PKT_NOP_HEADER_OP(SDMA_OP_NOP));
> +
> /* wait for flush */
> amdgpu_ring_write(ring,
> SDMA_PKT_HEADER_OP(SDMA_OP_POLL_REGMEM) |
>
> SDMA_PKT_POLL_REGMEM_HEADER_HDP_FLUSH(0) | @@ -1467,11
> +1484,11 @@ static const struct amdgpu_ring_funcs sdma_v3_0_ring_funcs
> = {
> .get_wptr = sdma_v3_0_ring_get_wptr,
> .set_wptr = sdma_v3_0_ring_set_wptr,
> .emit_frame_size =
> - 6 + /* sdma_v3_0_ring_emit_hdp_flush */
> + 6 + 1 + /* sdma_v3_0_ring_emit_hdp_flush */
> 3 + /* hdp invalidate */
> - 6 + /* sdma_v3_0_ring_emit_pipeline_sync */
> - VI_FLUSH_GPU_TLB_NUM_WREG * 3 + 6 + /*
> sdma_v3_0_ring_emit_vm_flush */
> - 10 + 10 + 10, /* sdma_v3_0_ring_emit_fence x3 for user
> fence, vm fence */
> + 6 + 1 + /* sdma_v3_0_ring_emit_pipeline_sync */
> + VI_FLUSH_GPU_TLB_NUM_WREG * 3 + 6 + 1 + /*
> sdma_v3_0_ring_emit_vm_flush */
> + (10 + 1) * 3, /* sdma_v3_0_ring_emit_fence x3 for user fence,
> vm
> +fence */
> .emit_ib_size = 7 + 6, /* sdma_v3_0_ring_emit_ib */
> .emit_ib = sdma_v3_0_ring_emit_ib,
> .emit_fence = sdma_v3_0_ring_emit_fence,
> --
> 2.55.0
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2026-10-13 16:34 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-06 22:02 [PATCH] drm/amdgpu/sdma3: Work around POLL_REGMEM / FENCE hang Timur Kristóf
2026-10-13 16:34 ` Deucher, Alexander
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.