* FAILED: patch "[PATCH] drm/amdgpu: avoid force-completing uninitialized UVD rings" failed to apply to 6.18-stable tree
@ 2026-09-09 11:29 gregkh
2026-09-12 11:17 ` [PATCH 6.18.y 1/6] drm/amdgpu: Fix missing unwind in amdgpu_ib_schedule() error path Sasha Levin
0 siblings, 1 reply; 7+ messages in thread
From: gregkh @ 2026-09-09 11:29 UTC (permalink / raw)
To: bobzhou2, Frank.Min, alexander.deucher, leo.liu; +Cc: stable
The patch below does not apply to the 6.18-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.18.y
git checkout FETCH_HEAD
git cherry-pick -x 6760f5cb12d2366ddd58a2d8637f7583d73f596b
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '2026090943-snugness-plexiglas-e964@gregkh' --subject-prefix 'PATCH 6.18.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 6760f5cb12d2366ddd58a2d8637f7583d73f596b Mon Sep 17 00:00:00 2001
From: Bob Zhou <bobzhou2@amd.com>
Date: Wed, 19 Aug 2026 14:23:49 +0800
Subject: [PATCH] drm/amdgpu: avoid force-completing uninitialized UVD rings
uvd_v7_0_sw_init() does not initialize the UVD decode ring for an
SR-IOV VF. However, amdgpu_uvd_resume() unconditionally force-completes
the decode ring when restoring its fence sequence.
Skip fence completion when the fence driver is not initialized.
Fixes: 0a33b11d26c6 ("drm/amdgpu: mark force completed fences with -ECANCELED")
Cc: stable@vger.kernel.org
Signed-off-by: Bob Zhou <bobzhou2@amd.com>
Acked-by: Leo Liu <leo.liu@amd.com>
Acked-by: Frank Min <Frank.Min@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
index 228a405a94c4..ecd7caa95d4b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -517,7 +517,8 @@ int amdgpu_uvd_resume(struct amdgpu_device *adev)
}
memset_io(ptr, 0, size);
/* to restore uvd fence seq */
- amdgpu_fence_driver_force_completion(&adev->uvd.inst[i].ring, NULL);
+ if (adev->uvd.inst[i].ring.fence_drv.initialized)
+ amdgpu_fence_driver_force_completion(&adev->uvd.inst[i].ring, NULL);
}
}
return 0;
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 6.18.y 1/6] drm/amdgpu: Fix missing unwind in amdgpu_ib_schedule() error path
2026-09-09 11:29 FAILED: patch "[PATCH] drm/amdgpu: avoid force-completing uninitialized UVD rings" failed to apply to 6.18-stable tree gregkh
@ 2026-09-12 11:17 ` Sasha Levin
2026-09-12 11:17 ` [PATCH 6.18.y 2/6] drm/amdgpu: add a helper to calculate ring distance Sasha Levin
` (4 more replies)
0 siblings, 5 replies; 7+ messages in thread
From: Sasha Levin @ 2026-09-12 11:17 UTC (permalink / raw)
To: stable
Cc: Srinivasan Shanmugam, Dan Carpenter, Alex Deucher,
Christian König, Sasha Levin
From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
[ Upstream commit ba038065655c45728be346d0b174a6da08d8a5c5 ]
amdgpu_ib_schedule() returns early after calling amdgpu_ring_undo().
This skips the common free_fence cleanup path. Other error paths were
already changed to use goto free_fence, but this one was missed.
Change the early return to goto free_fence so all error paths clean up
the same way.
Fixes the below:
drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c:232 amdgpu_ib_schedule()
warn: missing unwind goto?
drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
124 int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
125 struct amdgpu_ib *ibs, struct amdgpu_job *job,
126 struct dma_fence **f)
127 {
...
224
225 if (ring->funcs->insert_start)
226 ring->funcs->insert_start(ring);
227
228 if (job) {
229 r = amdgpu_vm_flush(ring, job, need_pipe_sync);
230 if (r) {
231 amdgpu_ring_undo(ring);
--> 232 return r;
The patch changed the other error paths to goto free_fence but
this one was accidentally skipped.
233 }
234 }
235
236 amdgpu_ring_ib_begin(ring);
...
338
339 free_fence:
340 if (!job)
341 kfree(af);
342 return r;
343 }
Fixes: f903b85ed0f1 ("drm/amdgpu: fix possible fence leaks from job structure")
Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
Cc: Alex Deucher <alexander.deucher@amd.com>
Cc: Christian König <christian.koenig@amd.com>
Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Stable-dep-of: 6760f5cb12d2 ("drm/amdgpu: avoid force-completing uninitialized UVD rings")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
index 9581643dbb726..f0ba6ac431632 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
@@ -222,7 +222,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
r = amdgpu_vm_flush(ring, job, need_pipe_sync);
if (r) {
amdgpu_ring_undo(ring);
- return r;
+ goto free_fence;
}
}
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 6.18.y 2/6] drm/amdgpu: add a helper to calculate ring distance
2026-09-12 11:17 ` [PATCH 6.18.y 1/6] drm/amdgpu: Fix missing unwind in amdgpu_ib_schedule() error path Sasha Levin
@ 2026-09-12 11:17 ` Sasha Levin
2026-09-12 11:17 ` [PATCH 6.18.y 3/6] drm/amdgpu: reorder IB schedule sequence Sasha Levin
` (3 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Sasha Levin @ 2026-09-12 11:17 UTC (permalink / raw)
To: stable; +Cc: Alex Deucher, Pierre-Eric Pelloux-Prayer, Sasha Levin
From: Alex Deucher <alexander.deucher@amd.com>
[ Upstream commit 08e7d6c3cee880bd3ec3eb14c478f9fa805b0bdc ]
Add a helper to calculate the distance in DWs between
two wptrs.
Reviewed-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Stable-dep-of: 6760f5cb12d2 ("drm/amdgpu: avoid force-completing uninitialized UVD rings")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 18 ++++++++++++------
1 file changed, 12 insertions(+), 6 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
index 0098b1eadfc87..1f1dadba92d75 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
@@ -516,6 +516,17 @@ static inline void amdgpu_ring_write_multiple(struct amdgpu_ring *ring,
ring->count_dw -= count_dw;
}
+static inline unsigned int amdgpu_ring_get_dw_distance(struct amdgpu_ring *ring,
+ u64 start_wptr, u64 end_wptr)
+{
+ unsigned int start = start_wptr & ring->buf_mask;
+ unsigned int end = end_wptr & ring->buf_mask;
+
+ if (end < start)
+ end += ring->ring_size >> 2;
+ return end - start;
+}
+
/**
* amdgpu_ring_patch_cond_exec - patch dw count of conditional execute
* @ring: amdgpu_ring structure
@@ -526,18 +537,13 @@ static inline void amdgpu_ring_write_multiple(struct amdgpu_ring *ring,
static inline void amdgpu_ring_patch_cond_exec(struct amdgpu_ring *ring,
unsigned int offset)
{
- unsigned cur;
-
if (!ring->funcs->init_cond_exec)
return;
WARN_ON(offset > ring->buf_mask);
WARN_ON(ring->ring[offset] != 0);
- cur = (ring->wptr - 1) & ring->buf_mask;
- if (cur < offset)
- cur += ring->ring_size >> 2;
- ring->ring[offset] = cur - offset;
+ ring->ring[offset] = amdgpu_ring_get_dw_distance(ring, offset, ring->wptr - 1);
}
int amdgpu_ring_test_helper(struct amdgpu_ring *ring);
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 6.18.y 3/6] drm/amdgpu: reorder IB schedule sequence
2026-09-12 11:17 ` [PATCH 6.18.y 1/6] drm/amdgpu: Fix missing unwind in amdgpu_ib_schedule() error path Sasha Levin
2026-09-12 11:17 ` [PATCH 6.18.y 2/6] drm/amdgpu: add a helper to calculate ring distance Sasha Levin
@ 2026-09-12 11:17 ` Sasha Levin
2026-09-12 11:17 ` [PATCH 6.18.y 4/6] drm/amdgpu: Make amdgpu_vm_flush() non-failing in submission path Sasha Levin
` (2 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Sasha Levin @ 2026-09-12 11:17 UTC (permalink / raw)
To: stable; +Cc: Alex Deucher, Pierre-Eric Pelloux-Prayer, Sasha Levin
From: Alex Deucher <alexander.deucher@amd.com>
[ Upstream commit d3499de3b737f3f6a2058382f7bff641c74f52a4 ]
This reorders the IB schedule sequence to cleanly
separate the vm operation from the IB submission.
This makes the two independent so we can cleanly
associate each one with its respective fence.
v2: fixes for VCN
Acked-by: Pierre-Eric Pelloux-Prayer <pierre-eric.pelloux-prayer@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Stable-dep-of: 6760f5cb12d2 ("drm/amdgpu: avoid force-completing uninitialized UVD rings")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 22 +++++++++++-----------
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 11 +++++++++++
2 files changed, 22 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
index f0ba6ac431632..908401ad5cdc4 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
@@ -208,16 +208,6 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
dma_fence_put(tmp);
}
- if ((ib->flags & AMDGPU_IB_FLAG_EMIT_MEM_SYNC) && ring->funcs->emit_mem_sync)
- ring->funcs->emit_mem_sync(ring);
-
- if (ring->funcs->emit_wave_limit &&
- ring->hw_prio == AMDGPU_GFX_PIPE_PRIO_HIGH)
- ring->funcs->emit_wave_limit(ring, true);
-
- if (ring->funcs->insert_start)
- ring->funcs->insert_start(ring);
-
if (job) {
r = amdgpu_vm_flush(ring, job, need_pipe_sync);
if (r) {
@@ -228,6 +218,16 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
amdgpu_ring_ib_begin(ring);
+ if (ring->funcs->insert_start)
+ ring->funcs->insert_start(ring);
+
+ if ((ib->flags & AMDGPU_IB_FLAG_EMIT_MEM_SYNC) && ring->funcs->emit_mem_sync)
+ ring->funcs->emit_mem_sync(ring);
+
+ if (ring->funcs->emit_wave_limit &&
+ ring->hw_prio == AMDGPU_GFX_PIPE_PRIO_HIGH)
+ ring->funcs->emit_wave_limit(ring, true);
+
if (ring->funcs->emit_gfx_shadow && adev->gfx.cp_gfx_shadow)
amdgpu_ring_emit_gfx_shadow(ring, shadow_va, csa_va, gds_va,
init_shadow, vmid);
@@ -312,6 +312,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
ring->hw_prio == AMDGPU_GFX_PIPE_PRIO_HIGH)
ring->funcs->emit_wave_limit(ring, false);
+ amdgpu_ring_ib_end(ring);
/* Save the wptr associated with this fence.
* This must be last for resets to work properly
* as we need to save the wptr associated with this
@@ -320,7 +321,6 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
*/
amdgpu_fence_save_wptr(*f);
- amdgpu_ring_ib_end(ring);
amdgpu_ring_commit(ring);
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index d9f6a42859822..6aae94ca7dcb9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -814,6 +814,17 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
return 0;
amdgpu_ring_ib_begin(ring);
+
+ /* There is no matching insert_end for this on purpose for the vm flush.
+ * The IB portion of the submission has both. Having multiple
+ * insert_start sequences is ok, but you can only have one insert_end
+ * per submission based on the way VCN FW works. For JPEG
+ * you can as many insert_start and insert_end sequences as you like as
+ * long as the rest of the packets come between start and end sequences.
+ */
+ if (ring->funcs->insert_start)
+ ring->funcs->insert_start(ring);
+
if (ring->funcs->init_cond_exec)
patch = amdgpu_ring_init_cond_exec(ring,
ring->cond_exe_gpu_addr);
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 6.18.y 4/6] drm/amdgpu: Make amdgpu_vm_flush() non-failing in submission path
2026-09-12 11:17 ` [PATCH 6.18.y 1/6] drm/amdgpu: Fix missing unwind in amdgpu_ib_schedule() error path Sasha Levin
2026-09-12 11:17 ` [PATCH 6.18.y 2/6] drm/amdgpu: add a helper to calculate ring distance Sasha Levin
2026-09-12 11:17 ` [PATCH 6.18.y 3/6] drm/amdgpu: reorder IB schedule sequence Sasha Levin
@ 2026-09-12 11:17 ` Sasha Levin
2026-09-12 11:17 ` [PATCH 6.18.y 5/6] drm/amdgpu: plumb timedout fence through to force completion Sasha Levin
2026-09-12 11:17 ` [PATCH 6.18.y 6/6] drm/amdgpu: avoid force-completing uninitialized UVD rings Sasha Levin
4 siblings, 0 replies; 7+ messages in thread
From: Sasha Levin @ 2026-09-12 11:17 UTC (permalink / raw)
To: stable
Cc: Srinivasan Shanmugam, Christian König, Alex Deucher,
Sasha Levin
From: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
[ Upstream commit 37872d06f85f0349e7b1f0680aea77326f7c135e ]
amdgpu_vm_flush() is used during job submission and is not expected to
fail. Convert it to return void and simplify the caller.
Initialize the COND_EXEC patch location to 0 so it is safe to call
amdgpu_ring_patch_cond_exec() when init_cond_exec is not supported.
Suggested-by: Christian König <christian.koenig@amd.com>
Cc: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Srinivasan Shanmugam <srinivasan.shanmugam@amd.com>
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Stable-dep-of: 6760f5cb12d2 ("drm/amdgpu: avoid force-completing uninitialized UVD rings")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 9 ++-------
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 10 +++-------
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 2 +-
3 files changed, 6 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
index 908401ad5cdc4..97552c74e4552 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
@@ -208,13 +208,8 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
dma_fence_put(tmp);
}
- if (job) {
- r = amdgpu_vm_flush(ring, job, need_pipe_sync);
- if (r) {
- amdgpu_ring_undo(ring);
- goto free_fence;
- }
- }
+ if (job)
+ amdgpu_vm_flush(ring, job, need_pipe_sync);
amdgpu_ring_ib_begin(ring);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 6aae94ca7dcb9..11f58995bf526 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -760,12 +760,9 @@ bool amdgpu_vm_need_pipeline_sync(struct amdgpu_ring *ring,
* @need_pipe_sync: is pipe sync needed
*
* Emit a VM flush when it is necessary.
- *
- * Returns:
- * 0 on success, errno otherwise.
*/
-int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
- bool need_pipe_sync)
+void amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
+ bool need_pipe_sync)
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_isolation *isolation =
@@ -811,7 +808,7 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
if (!vm_flush_needed && !gds_switch_needed && !need_pipe_sync &&
!cleaner_shader_needed)
- return 0;
+ return;
amdgpu_ring_ib_begin(ring);
@@ -902,7 +899,6 @@ int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
}
amdgpu_ring_ib_end(ring);
- return 0;
}
/**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
index 076d9a3a5e624..b06199eaf42fe 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
@@ -516,7 +516,7 @@ int amdgpu_vm_validate(struct amdgpu_device *adev, struct amdgpu_vm *vm,
struct ww_acquire_ctx *ticket,
int (*callback)(void *p, struct amdgpu_bo *bo),
void *param);
-int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, bool need_pipe_sync);
+void amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, bool need_pipe_sync);
int amdgpu_vm_update_pdes(struct amdgpu_device *adev,
struct amdgpu_vm *vm, bool immediate);
int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 6.18.y 5/6] drm/amdgpu: plumb timedout fence through to force completion
2026-09-12 11:17 ` [PATCH 6.18.y 1/6] drm/amdgpu: Fix missing unwind in amdgpu_ib_schedule() error path Sasha Levin
` (2 preceding siblings ...)
2026-09-12 11:17 ` [PATCH 6.18.y 4/6] drm/amdgpu: Make amdgpu_vm_flush() non-failing in submission path Sasha Levin
@ 2026-09-12 11:17 ` Sasha Levin
2026-09-12 11:17 ` [PATCH 6.18.y 6/6] drm/amdgpu: avoid force-completing uninitialized UVD rings Sasha Levin
4 siblings, 0 replies; 7+ messages in thread
From: Sasha Levin @ 2026-09-12 11:17 UTC (permalink / raw)
To: stable; +Cc: Alex Deucher, Christian König, Sasha Levin
From: Alex Deucher <alexander.deucher@amd.com>
[ Upstream commit c184df870db1e328691ea0fbb7d0e59efd9d3f9f ]
When we do a full adapter reset, if we know the timedout fence
mark the fence with -ETIME rather than -ECANCELED so it
gets properly handled by userspace.
v2: rebase
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Stable adaptation: retain the existing fence helper declarations and use
&job->hw_fence.base because this branch embeds the hardware fence in the
job. Preserve the existing job-fence clearing during full adapter reset.
Drop the VCN 4.0.3 and 5.0.1 JPEG reset call-site updates because their
helpers do not exist on this branch; no new functions are introduced.
The two-argument UVD completion call provides the context required by
6760f5cb12d2 ("drm/amdgpu: avoid force-completing uninitialized UVD rings").
Also restore the fallible amdgpu_vm_flush() interface and its caller's
ring rollback. The preceding dependency 014ab3140cf9 converted it to void,
but this stable branch still allocates a fence in amdgpu_fence_emit() and
can return -ENOMEM. That left a value-return in a void function and broke
both x86 and arm64 builds. Keep the error propagation rather than
silently continuing submission after a failed flush. The job embeds its
hardware fence here, so the caller can return after ring rollback without
an additional fence-free path.
[ sashal: Reduced backport -- upstream c184df870db1e touches 9 file(s), this
backport carries 10. Not backported here:
drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
drivers/gpu/drm/amd/amdgpu/vcn_v5_0_1.c
This note is generated from the file lists only; see the resolution record
for the reasoning. ]
Stable-dep-of: 6760f5cb12d2 ("drm/amdgpu: avoid force-completing uninitialized UVD rings")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c | 2 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_device.c | 6 ++++-
drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c | 26 +++++++++++++++++----
drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 9 +++++--
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 3 ++-
drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c | 4 ++--
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 2 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 21 ++++++++++-------
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 10 +++++---
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h | 2 +-
10 files changed, 61 insertions(+), 24 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
index a70651050acff..d6f58128bc741 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_debugfs.c
@@ -1960,7 +1960,7 @@ static int amdgpu_debugfs_ib_preempt(void *data, u64 val)
/* swap out the old fences */
amdgpu_ib_preempt_fences_swap(ring, fences);
- amdgpu_fence_driver_force_completion(ring);
+ amdgpu_fence_driver_force_completion(ring, NULL);
/* resubmit unfinished jobs */
amdgpu_ib_preempt_job_recovery(&ring->sched);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
index ba9c7bd1264c2..dda5d62c8e7b0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c
@@ -5890,6 +5890,7 @@ int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,
{
int i, r = 0;
struct amdgpu_job *job = NULL;
+ struct dma_fence *fence = NULL;
struct amdgpu_device *tmp_adev = reset_context->reset_req_dev;
bool need_full_reset =
test_bit(AMDGPU_NEED_FULL_RESET, &reset_context->flags);
@@ -5902,6 +5903,9 @@ int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,
amdgpu_fence_driver_isr_toggle(adev, true);
+ if (job)
+ fence = &job->hw_fence.base;
+
/* block all schedulers and reset given job's ring */
for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
struct amdgpu_ring *ring = adev->rings[i];
@@ -5915,7 +5919,7 @@ int amdgpu_device_pre_asic_reset(struct amdgpu_device *adev,
amdgpu_fence_driver_clear_job_fences(ring);
/* after all hw jobs are reset, hw fence is meaningless, so force_completion */
- amdgpu_fence_driver_force_completion(ring);
+ amdgpu_fence_driver_force_completion(ring, fence);
}
amdgpu_fence_driver_isr_toggle(adev, false);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
index 89a639044d520..c45267373fd86 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
@@ -582,7 +582,7 @@ void amdgpu_fence_driver_hw_fini(struct amdgpu_device *adev)
r = -ENODEV;
/* no need to trigger GPU reset as we are unloading */
if (r)
- amdgpu_fence_driver_force_completion(ring);
+ amdgpu_fence_driver_force_completion(ring, NULL);
if (!drm_dev_is_unplugged(adev_to_drm(adev)) &&
ring->fence_drv.irq_src &&
@@ -727,16 +727,34 @@ void amdgpu_fence_driver_set_error(struct amdgpu_ring *ring, int error)
* amdgpu_fence_driver_force_completion - force signal latest fence of ring
*
* @ring: fence of the ring to signal
+ * @timedout_fence: fence of the timedout job
*
*/
-void amdgpu_fence_driver_force_completion(struct amdgpu_ring *ring)
+void amdgpu_fence_driver_force_completion(struct amdgpu_ring *ring,
+ struct dma_fence *timedout_fence)
{
- amdgpu_fence_driver_set_error(ring, -ECANCELED);
+ struct amdgpu_fence_driver *drv = &ring->fence_drv;
+ unsigned long flags;
+
+ spin_lock_irqsave(&drv->lock, flags);
+ for (unsigned int i = 0; i <= drv->num_fences_mask; ++i) {
+ struct dma_fence *fence;
+
+ fence = rcu_dereference_protected(drv->fences[i],
+ lockdep_is_held(&drv->lock));
+ if (fence && !dma_fence_is_signaled_locked(fence)) {
+ if (fence == timedout_fence)
+ dma_fence_set_error(fence, -ETIME);
+ else
+ dma_fence_set_error(fence, -ECANCELED);
+ }
+ }
+ spin_unlock_irqrestore(&drv->lock, flags);
+
amdgpu_fence_write(ring, ring->fence_drv.sync_seq);
amdgpu_fence_process(ring);
}
-
/*
* Kernel queue reset handling
*
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
index 97552c74e4552..623a2ae3a10cd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
@@ -208,8 +208,13 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
dma_fence_put(tmp);
}
- if (job)
- amdgpu_vm_flush(ring, job, need_pipe_sync);
+ if (job) {
+ r = amdgpu_vm_flush(ring, job, need_pipe_sync);
+ if (r) {
+ amdgpu_ring_undo(ring);
+ return r;
+ }
+ }
amdgpu_ring_ib_begin(ring);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
index 1f1dadba92d75..2024aa6d231d8 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
@@ -154,7 +154,8 @@ extern const struct drm_sched_backend_ops amdgpu_sched_ops;
void amdgpu_fence_driver_clear_job_fences(struct amdgpu_ring *ring);
void amdgpu_fence_driver_set_error(struct amdgpu_ring *ring, int error);
-void amdgpu_fence_driver_force_completion(struct amdgpu_ring *ring);
+void amdgpu_fence_driver_force_completion(struct amdgpu_ring *ring,
+ struct dma_fence *timedout_fence);
void amdgpu_fence_driver_guilty_force_completion(struct amdgpu_fence *af);
void amdgpu_fence_save_wptr(struct dma_fence *fence);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
index 321310ba2c08e..fcd81242059e6 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
@@ -600,10 +600,10 @@ int amdgpu_sdma_reset_engine(struct amdgpu_device *adev, uint32_t instance_id,
* to be submitted to the queues after the reset is complete.
*/
if (!ret) {
- amdgpu_fence_driver_force_completion(gfx_ring);
+ amdgpu_fence_driver_force_completion(gfx_ring, NULL);
drm_sched_wqueue_start(&gfx_ring->sched);
if (adev->sdma.has_page_queue) {
- amdgpu_fence_driver_force_completion(page_ring);
+ amdgpu_fence_driver_force_completion(page_ring, NULL);
drm_sched_wqueue_start(&page_ring->sched);
}
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
index fb8d879193c94..f10268de0ea3c 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -516,7 +516,7 @@ int amdgpu_uvd_resume(struct amdgpu_device *adev)
}
memset_io(ptr, 0, size);
/* to restore uvd fence seq */
- amdgpu_fence_driver_force_completion(&adev->uvd.inst[i].ring);
+ amdgpu_fence_driver_force_completion(&adev->uvd.inst[i].ring, NULL);
}
}
return 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
index 5e0786ea911b3..2679f32715c0b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
@@ -1480,15 +1480,16 @@ int vcn_set_powergating_state(struct amdgpu_ip_block *ip_block,
/**
* amdgpu_vcn_reset_engine - Reset a specific VCN engine
- * @adev: Pointer to the AMDGPU device
- * @instance_id: VCN engine instance to reset
+ * @ring: Pointer to the VCN ring
+ * @timedout_fence: fence that timed out
*
* Returns: 0 on success, or a negative error code on failure.
*/
-static int amdgpu_vcn_reset_engine(struct amdgpu_device *adev,
- uint32_t instance_id)
+static int amdgpu_vcn_reset_engine(struct amdgpu_ring *ring,
+ struct amdgpu_fence *timedout_fence)
{
- struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[instance_id];
+ struct amdgpu_device *adev = ring->adev;
+ struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me];
int r, i;
mutex_lock(&vinst->engine_reset_mutex);
@@ -1512,9 +1513,13 @@ static int amdgpu_vcn_reset_engine(struct amdgpu_device *adev,
if (r)
goto unlock;
}
- amdgpu_fence_driver_force_completion(&vinst->ring_dec);
+ amdgpu_fence_driver_force_completion(&vinst->ring_dec,
+ (&vinst->ring_dec == ring) ?
+ &timedout_fence->base : NULL);
for (i = 0; i < vinst->num_enc_rings; i++)
- amdgpu_fence_driver_force_completion(&vinst->ring_enc[i]);
+ amdgpu_fence_driver_force_completion(&vinst->ring_enc[i],
+ (&vinst->ring_enc[i] == ring) ?
+ &timedout_fence->base : NULL);
/* Restart the scheduler's work queue for the dec and enc rings
* if they were stopped by this function. This allows new tasks
@@ -1550,7 +1555,7 @@ int amdgpu_vcn_ring_reset(struct amdgpu_ring *ring,
if (adev->vcn.inst[ring->me].using_unified_queue)
return -EINVAL;
- return amdgpu_vcn_reset_engine(adev, ring->me);
+ return amdgpu_vcn_reset_engine(ring, timedout_fence);
}
int amdgpu_vcn_reg_dump_init(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
index 11f58995bf526..6aae94ca7dcb9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
@@ -760,9 +760,12 @@ bool amdgpu_vm_need_pipeline_sync(struct amdgpu_ring *ring,
* @need_pipe_sync: is pipe sync needed
*
* Emit a VM flush when it is necessary.
+ *
+ * Returns:
+ * 0 on success, errno otherwise.
*/
-void amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
- bool need_pipe_sync)
+int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
+ bool need_pipe_sync)
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_isolation *isolation =
@@ -808,7 +811,7 @@ void amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
if (!vm_flush_needed && !gds_switch_needed && !need_pipe_sync &&
!cleaner_shader_needed)
- return;
+ return 0;
amdgpu_ring_ib_begin(ring);
@@ -899,6 +902,7 @@ void amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job,
}
amdgpu_ring_ib_end(ring);
+ return 0;
}
/**
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
index b06199eaf42fe..076d9a3a5e624 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.h
@@ -516,7 +516,7 @@ int amdgpu_vm_validate(struct amdgpu_device *adev, struct amdgpu_vm *vm,
struct ww_acquire_ctx *ticket,
int (*callback)(void *p, struct amdgpu_bo *bo),
void *param);
-void amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, bool need_pipe_sync);
+int amdgpu_vm_flush(struct amdgpu_ring *ring, struct amdgpu_job *job, bool need_pipe_sync);
int amdgpu_vm_update_pdes(struct amdgpu_device *adev,
struct amdgpu_vm *vm, bool immediate);
int amdgpu_vm_clear_freed(struct amdgpu_device *adev,
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH 6.18.y 6/6] drm/amdgpu: avoid force-completing uninitialized UVD rings
2026-09-12 11:17 ` [PATCH 6.18.y 1/6] drm/amdgpu: Fix missing unwind in amdgpu_ib_schedule() error path Sasha Levin
` (3 preceding siblings ...)
2026-09-12 11:17 ` [PATCH 6.18.y 5/6] drm/amdgpu: plumb timedout fence through to force completion Sasha Levin
@ 2026-09-12 11:17 ` Sasha Levin
4 siblings, 0 replies; 7+ messages in thread
From: Sasha Levin @ 2026-09-12 11:17 UTC (permalink / raw)
To: stable; +Cc: Bob Zhou, Leo Liu, Frank Min, Alex Deucher, Sasha Levin
From: Bob Zhou <bobzhou2@amd.com>
[ Upstream commit 6760f5cb12d2366ddd58a2d8637f7583d73f596b ]
uvd_v7_0_sw_init() does not initialize the UVD decode ring for an
SR-IOV VF. However, amdgpu_uvd_resume() unconditionally force-completes
the decode ring when restoring its fence sequence.
Skip fence completion when the fence driver is not initialized.
Fixes: 0a33b11d26c6 ("drm/amdgpu: mark force completed fences with -ECANCELED")
Cc: stable@vger.kernel.org
Signed-off-by: Bob Zhou <bobzhou2@amd.com>
Acked-by: Leo Liu <leo.liu@amd.com>
Acked-by: Frank Min <Frank.Min@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
index f10268de0ea3c..5f8c036773552 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_uvd.c
@@ -516,7 +516,8 @@ int amdgpu_uvd_resume(struct amdgpu_device *adev)
}
memset_io(ptr, 0, size);
/* to restore uvd fence seq */
- amdgpu_fence_driver_force_completion(&adev->uvd.inst[i].ring, NULL);
+ if (adev->uvd.inst[i].ring.fence_drv.initialized)
+ amdgpu_fence_driver_force_completion(&adev->uvd.inst[i].ring, NULL);
}
}
return 0;
--
2.53.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-09-12 11:17 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-09 11:29 FAILED: patch "[PATCH] drm/amdgpu: avoid force-completing uninitialized UVD rings" failed to apply to 6.18-stable tree gregkh
2026-09-12 11:17 ` [PATCH 6.18.y 1/6] drm/amdgpu: Fix missing unwind in amdgpu_ib_schedule() error path Sasha Levin
2026-09-12 11:17 ` [PATCH 6.18.y 2/6] drm/amdgpu: add a helper to calculate ring distance Sasha Levin
2026-09-12 11:17 ` [PATCH 6.18.y 3/6] drm/amdgpu: reorder IB schedule sequence Sasha Levin
2026-09-12 11:17 ` [PATCH 6.18.y 4/6] drm/amdgpu: Make amdgpu_vm_flush() non-failing in submission path Sasha Levin
2026-09-12 11:17 ` [PATCH 6.18.y 5/6] drm/amdgpu: plumb timedout fence through to force completion Sasha Levin
2026-09-12 11:17 ` [PATCH 6.18.y 6/6] drm/amdgpu: avoid force-completing uninitialized UVD rings Sasha Levin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox