* [PATCH 01/30] drm/amdgpu: remove job parameter from amdgpu_fence_emit()
2025-06-25 21:06 [PATCH V11 00/30] Reset improvements Alex Deucher
@ 2025-06-25 21:06 ` Alex Deucher
2025-06-26 9:10 ` Christian König
2025-06-25 21:06 ` [PATCH 02/30] drm/amdgpu: update ring reset function signature Alex Deucher
` (28 subsequent siblings)
29 siblings, 1 reply; 35+ messages in thread
From: Alex Deucher @ 2025-06-25 21:06 UTC (permalink / raw)
To: amd-gfx, christian.koenig, sasundar; +Cc: Alex Deucher
What we actually care about is the amdgpu_fence object
so pass that in explicitly to avoid possible mistakes
in the future.
The job_run_counter handling can be safely removed at this
point as we no longer support job resubmission.
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c | 34 +++++++++--------------
drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 5 +++-
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 4 +--
3 files changed, 19 insertions(+), 24 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
index dc92952bf1269..2d6b2b486baf7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
@@ -99,14 +99,14 @@ static u32 amdgpu_fence_read(struct amdgpu_ring *ring)
*
* @ring: ring the fence is associated with
* @f: resulting fence object
- * @job: job the fence is embedded in
+ * @af: amdgpu fence input
* @flags: flags to pass into the subordinate .emit_fence() call
*
* Emits a fence command on the requested ring (all asics).
* Returns 0 on success, -ENOMEM on failure.
*/
-int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f, struct amdgpu_job *job,
- unsigned int flags)
+int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f,
+ struct amdgpu_fence *af, unsigned int flags)
{
struct amdgpu_device *adev = ring->adev;
struct dma_fence *fence;
@@ -115,36 +115,28 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f, struct amd
uint32_t seq;
int r;
- if (job == NULL) {
+ if (!af) {
/* create a separate hw fence */
am_fence = kzalloc(sizeof(*am_fence), GFP_KERNEL);
if (!am_fence)
return -ENOMEM;
} else {
- /* take use of job-embedded fence */
- am_fence = &job->hw_fence;
+ am_fence = af;
}
fence = &am_fence->base;
am_fence->ring = ring;
seq = ++ring->fence_drv.sync_seq;
- if (job && job->job_run_counter) {
- /* reinit seq for resubmitted jobs */
- fence->seqno = seq;
- /* TO be inline with external fence creation and other drivers */
+ if (af) {
+ dma_fence_init(fence, &amdgpu_job_fence_ops,
+ &ring->fence_drv.lock,
+ adev->fence_context + ring->idx, seq);
+ /* Against remove in amdgpu_job_{free, free_cb} */
dma_fence_get(fence);
} else {
- if (job) {
- dma_fence_init(fence, &amdgpu_job_fence_ops,
- &ring->fence_drv.lock,
- adev->fence_context + ring->idx, seq);
- /* Against remove in amdgpu_job_{free, free_cb} */
- dma_fence_get(fence);
- } else {
- dma_fence_init(fence, &amdgpu_fence_ops,
- &ring->fence_drv.lock,
- adev->fence_context + ring->idx, seq);
- }
+ dma_fence_init(fence, &amdgpu_fence_ops,
+ &ring->fence_drv.lock,
+ adev->fence_context + ring->idx, seq);
}
amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
index 802743efa3b39..206b70acb29a0 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
@@ -128,6 +128,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
struct amdgpu_device *adev = ring->adev;
struct amdgpu_ib *ib = &ibs[0];
struct dma_fence *tmp = NULL;
+ struct amdgpu_fence *af;
bool need_ctx_switch;
struct amdgpu_vm *vm;
uint64_t fence_ctx;
@@ -154,6 +155,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
csa_va = job->csa_va;
gds_va = job->gds_va;
init_shadow = job->init_shadow;
+ af = &job->hw_fence;
} else {
vm = NULL;
fence_ctx = 0;
@@ -161,6 +163,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
csa_va = 0;
gds_va = 0;
init_shadow = false;
+ af = NULL;
}
if (!ring->sched.ready) {
@@ -282,7 +285,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
amdgpu_ring_init_cond_exec(ring, ring->cond_exe_gpu_addr);
}
- r = amdgpu_fence_emit(ring, f, job, fence_flags);
+ r = amdgpu_fence_emit(ring, f, af, fence_flags);
if (r) {
dev_err(adev->dev, "failed to emit fence (%d)\n", r);
if (job && job->vmid)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
index e1f25218943a4..9ae522baad8e7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
@@ -157,8 +157,8 @@ void amdgpu_fence_driver_hw_init(struct amdgpu_device *adev);
void amdgpu_fence_driver_hw_fini(struct amdgpu_device *adev);
int amdgpu_fence_driver_sw_init(struct amdgpu_device *adev);
void amdgpu_fence_driver_sw_fini(struct amdgpu_device *adev);
-int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **fence, struct amdgpu_job *job,
- unsigned flags);
+int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f,
+ struct amdgpu_fence *af, unsigned int flags);
int amdgpu_fence_emit_polling(struct amdgpu_ring *ring, uint32_t *s,
uint32_t timeout);
bool amdgpu_fence_process(struct amdgpu_ring *ring);
--
2.50.0
^ permalink raw reply related [flat|nested] 35+ messages in thread* Re: [PATCH 01/30] drm/amdgpu: remove job parameter from amdgpu_fence_emit()
2025-06-25 21:06 ` [PATCH 01/30] drm/amdgpu: remove job parameter from amdgpu_fence_emit() Alex Deucher
@ 2025-06-26 9:10 ` Christian König
0 siblings, 0 replies; 35+ messages in thread
From: Christian König @ 2025-06-26 9:10 UTC (permalink / raw)
To: Alex Deucher, amd-gfx, sasundar
On 25.06.25 23:06, Alex Deucher wrote:
> What we actually care about is the amdgpu_fence object
> so pass that in explicitly to avoid possible mistakes
> in the future.
>
> The job_run_counter handling can be safely removed at this
> point as we no longer support job resubmission.
>
> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
> ---
> drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c | 34 +++++++++--------------
> drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 5 +++-
> drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 4 +--
> 3 files changed, 19 insertions(+), 24 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
> index dc92952bf1269..2d6b2b486baf7 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
> @@ -99,14 +99,14 @@ static u32 amdgpu_fence_read(struct amdgpu_ring *ring)
> *
> * @ring: ring the fence is associated with
> * @f: resulting fence object
> - * @job: job the fence is embedded in
> + * @af: amdgpu fence input
> * @flags: flags to pass into the subordinate .emit_fence() call
> *
> * Emits a fence command on the requested ring (all asics).
> * Returns 0 on success, -ENOMEM on failure.
> */
> -int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f, struct amdgpu_job *job,
> - unsigned int flags)
> +int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f,
> + struct amdgpu_fence *af, unsigned int flags)
> {
> struct amdgpu_device *adev = ring->adev;
> struct dma_fence *fence;
> @@ -115,36 +115,28 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f, struct amd
> uint32_t seq;
> int r;
>
> - if (job == NULL) {
> + if (!af) {
> /* create a separate hw fence */
> am_fence = kzalloc(sizeof(*am_fence), GFP_KERNEL);
> if (!am_fence)
> return -ENOMEM;
> } else {
> - /* take use of job-embedded fence */
> - am_fence = &job->hw_fence;
> + am_fence = af;
> }
> fence = &am_fence->base;
> am_fence->ring = ring;
>
> seq = ++ring->fence_drv.sync_seq;
> - if (job && job->job_run_counter) {
> - /* reinit seq for resubmitted jobs */
> - fence->seqno = seq;
> - /* TO be inline with external fence creation and other drivers */
> + if (af) {
> + dma_fence_init(fence, &amdgpu_job_fence_ops,
> + &ring->fence_drv.lock,
> + adev->fence_context + ring->idx, seq);
> + /* Against remove in amdgpu_job_{free, free_cb} */
> dma_fence_get(fence);
> } else {
> - if (job) {
> - dma_fence_init(fence, &amdgpu_job_fence_ops,
> - &ring->fence_drv.lock,
> - adev->fence_context + ring->idx, seq);
> - /* Against remove in amdgpu_job_{free, free_cb} */
> - dma_fence_get(fence);
> - } else {
> - dma_fence_init(fence, &amdgpu_fence_ops,
> - &ring->fence_drv.lock,
> - adev->fence_context + ring->idx, seq);
> - }
> + dma_fence_init(fence, &amdgpu_fence_ops,
> + &ring->fence_drv.lock,
> + adev->fence_context + ring->idx, seq);
> }
>
> amdgpu_ring_emit_fence(ring, ring->fence_drv.gpu_addr,
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
> index 802743efa3b39..206b70acb29a0 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
> @@ -128,6 +128,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
> struct amdgpu_device *adev = ring->adev;
> struct amdgpu_ib *ib = &ibs[0];
> struct dma_fence *tmp = NULL;
> + struct amdgpu_fence *af;
> bool need_ctx_switch;
> struct amdgpu_vm *vm;
> uint64_t fence_ctx;
> @@ -154,6 +155,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
> csa_va = job->csa_va;
> gds_va = job->gds_va;
> init_shadow = job->init_shadow;
> + af = &job->hw_fence;
> } else {
> vm = NULL;
> fence_ctx = 0;
> @@ -161,6 +163,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
> csa_va = 0;
> gds_va = 0;
> init_shadow = false;
> + af = NULL;
> }
>
> if (!ring->sched.ready) {
> @@ -282,7 +285,7 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
> amdgpu_ring_init_cond_exec(ring, ring->cond_exe_gpu_addr);
> }
>
> - r = amdgpu_fence_emit(ring, f, job, fence_flags);
> + r = amdgpu_fence_emit(ring, f, af, fence_flags);
> if (r) {
> dev_err(adev->dev, "failed to emit fence (%d)\n", r);
> if (job && job->vmid)
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
> index e1f25218943a4..9ae522baad8e7 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
> @@ -157,8 +157,8 @@ void amdgpu_fence_driver_hw_init(struct amdgpu_device *adev);
> void amdgpu_fence_driver_hw_fini(struct amdgpu_device *adev);
> int amdgpu_fence_driver_sw_init(struct amdgpu_device *adev);
> void amdgpu_fence_driver_sw_fini(struct amdgpu_device *adev);
> -int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **fence, struct amdgpu_job *job,
> - unsigned flags);
> +int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f,
> + struct amdgpu_fence *af, unsigned int flags);
> int amdgpu_fence_emit_polling(struct amdgpu_ring *ring, uint32_t *s,
> uint32_t timeout);
> bool amdgpu_fence_process(struct amdgpu_ring *ring);
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 02/30] drm/amdgpu: update ring reset function signature
2025-06-25 21:06 [PATCH V11 00/30] Reset improvements Alex Deucher
2025-06-25 21:06 ` [PATCH 01/30] drm/amdgpu: remove job parameter from amdgpu_fence_emit() Alex Deucher
@ 2025-06-25 21:06 ` Alex Deucher
2025-06-25 21:06 ` [PATCH 03/30] drm/amdgpu: rework queue reset scheduler interaction Alex Deucher
` (27 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Alex Deucher @ 2025-06-25 21:06 UTC (permalink / raw)
To: amd-gfx, christian.koenig, sasundar; +Cc: Alex Deucher
Going forward, we'll need more than just the vmid. Add the
guilty amdgpu_fence.
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 2 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 5 +++--
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 7 +++++--
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 8 ++++++--
drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c | 8 ++++++--
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 3 ++-
drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c | 3 ++-
drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c | 4 +++-
drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c | 4 +++-
drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c | 4 +++-
drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c | 4 +++-
drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c | 4 +++-
drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c | 4 +++-
drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c | 4 +++-
drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c | 4 +++-
drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c | 4 +++-
drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c | 4 +++-
drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c | 4 +++-
drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 4 +++-
drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 4 +++-
drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c | 4 +++-
drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c | 4 +++-
22 files changed, 70 insertions(+), 26 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
index ddb9d3269357c..a7ff1fa4c778e 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
@@ -155,7 +155,7 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
if (is_guilty)
dma_fence_set_error(&s_job->s_fence->finished, -ETIME);
- r = amdgpu_ring_reset(ring, job->vmid);
+ r = amdgpu_ring_reset(ring, job->vmid, NULL);
if (!r) {
if (amdgpu_ring_sched_ready(ring))
drm_sched_stop(&ring->sched, s_job);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
index 9ae522baad8e7..de972f69d96e7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
@@ -268,7 +268,8 @@ struct amdgpu_ring_funcs {
void (*patch_cntl)(struct amdgpu_ring *ring, unsigned offset);
void (*patch_ce)(struct amdgpu_ring *ring, unsigned offset);
void (*patch_de)(struct amdgpu_ring *ring, unsigned offset);
- int (*reset)(struct amdgpu_ring *ring, unsigned int vmid);
+ int (*reset)(struct amdgpu_ring *ring, unsigned int vmid,
+ struct amdgpu_fence *timedout_fence);
void (*emit_cleaner_shader)(struct amdgpu_ring *ring);
bool (*is_guilty)(struct amdgpu_ring *ring);
};
@@ -425,7 +426,7 @@ struct amdgpu_ring {
#define amdgpu_ring_patch_cntl(r, o) ((r)->funcs->patch_cntl((r), (o)))
#define amdgpu_ring_patch_ce(r, o) ((r)->funcs->patch_ce((r), (o)))
#define amdgpu_ring_patch_de(r, o) ((r)->funcs->patch_de((r), (o)))
-#define amdgpu_ring_reset(r, v) (r)->funcs->reset((r), (v))
+#define amdgpu_ring_reset(r, v, f) (r)->funcs->reset((r), (v), (f))
unsigned int amdgpu_ring_max_ibs(enum amdgpu_ring_type type);
int amdgpu_ring_alloc(struct amdgpu_ring *ring, unsigned ndw);
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
index 75ea071744eb5..4b2af95203b26 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
@@ -9522,7 +9522,9 @@ static void gfx_v10_ring_insert_nop(struct amdgpu_ring *ring, uint32_t num_nop)
amdgpu_ring_insert_nop(ring, num_nop - 1);
}
-static int gfx_v10_0_reset_kgq(struct amdgpu_ring *ring, unsigned int vmid)
+static int gfx_v10_0_reset_kgq(struct amdgpu_ring *ring,
+ unsigned int vmid,
+ struct amdgpu_fence *timedout_fence)
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_kiq *kiq = &adev->gfx.kiq[0];
@@ -9579,7 +9581,8 @@ static int gfx_v10_0_reset_kgq(struct amdgpu_ring *ring, unsigned int vmid)
}
static int gfx_v10_0_reset_kcq(struct amdgpu_ring *ring,
- unsigned int vmid)
+ unsigned int vmid,
+ struct amdgpu_fence *timedout_fence)
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_kiq *kiq = &adev->gfx.kiq[0];
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
index ec9b84f92d467..8d5c0ab016d2b 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -6811,7 +6811,9 @@ static int gfx_v11_reset_gfx_pipe(struct amdgpu_ring *ring)
return 0;
}
-static int gfx_v11_0_reset_kgq(struct amdgpu_ring *ring, unsigned int vmid)
+static int gfx_v11_0_reset_kgq(struct amdgpu_ring *ring,
+ unsigned int vmid,
+ struct amdgpu_fence *timedout_fence)
{
struct amdgpu_device *adev = ring->adev;
int r;
@@ -6973,7 +6975,9 @@ static int gfx_v11_0_reset_compute_pipe(struct amdgpu_ring *ring)
return 0;
}
-static int gfx_v11_0_reset_kcq(struct amdgpu_ring *ring, unsigned int vmid)
+static int gfx_v11_0_reset_kcq(struct amdgpu_ring *ring,
+ unsigned int vmid,
+ struct amdgpu_fence *timedout_fence)
{
struct amdgpu_device *adev = ring->adev;
int r = 0;
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
index 1234c8d64e20d..795bd353a9cea 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
@@ -5307,7 +5307,9 @@ static int gfx_v12_reset_gfx_pipe(struct amdgpu_ring *ring)
return 0;
}
-static int gfx_v12_0_reset_kgq(struct amdgpu_ring *ring, unsigned int vmid)
+static int gfx_v12_0_reset_kgq(struct amdgpu_ring *ring,
+ unsigned int vmid,
+ struct amdgpu_fence *timedout_fence)
{
struct amdgpu_device *adev = ring->adev;
int r;
@@ -5421,7 +5423,9 @@ static int gfx_v12_0_reset_compute_pipe(struct amdgpu_ring *ring)
return 0;
}
-static int gfx_v12_0_reset_kcq(struct amdgpu_ring *ring, unsigned int vmid)
+static int gfx_v12_0_reset_kcq(struct amdgpu_ring *ring,
+ unsigned int vmid,
+ struct amdgpu_fence *timedout_fence)
{
struct amdgpu_device *adev = ring->adev;
int r;
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
index 866e39f6fab3f..d91e0423c4820 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
@@ -7172,7 +7172,8 @@ static void gfx_v9_ring_insert_nop(struct amdgpu_ring *ring, uint32_t num_nop)
}
static int gfx_v9_0_reset_kcq(struct amdgpu_ring *ring,
- unsigned int vmid)
+ unsigned int vmid,
+ struct amdgpu_fence *timedout_fence)
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_kiq *kiq = &adev->gfx.kiq[0];
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
index c233edf605694..272f0f8e41d45 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
@@ -3552,7 +3552,8 @@ static int gfx_v9_4_3_reset_hw_pipe(struct amdgpu_ring *ring)
}
static int gfx_v9_4_3_reset_kcq(struct amdgpu_ring *ring,
- unsigned int vmid)
+ unsigned int vmid,
+ struct amdgpu_fence *timedout_fence)
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_kiq *kiq = &adev->gfx.kiq[ring->xcc_id];
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
index 4cde8a8bcc837..93eb71d2ce304 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
@@ -764,7 +764,9 @@ static int jpeg_v2_0_process_interrupt(struct amdgpu_device *adev,
return 0;
}
-static int jpeg_v2_0_ring_reset(struct amdgpu_ring *ring, unsigned int vmid)
+static int jpeg_v2_0_ring_reset(struct amdgpu_ring *ring,
+ unsigned int vmid,
+ struct amdgpu_fence *timedout_fence)
{
jpeg_v2_0_stop(ring->adev);
jpeg_v2_0_start(ring->adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
index 8b39e114f3be1..45b8702d20ad9 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
@@ -643,7 +643,9 @@ static int jpeg_v2_5_process_interrupt(struct amdgpu_device *adev,
return 0;
}
-static int jpeg_v2_5_ring_reset(struct amdgpu_ring *ring, unsigned int vmid)
+static int jpeg_v2_5_ring_reset(struct amdgpu_ring *ring,
+ unsigned int vmid,
+ struct amdgpu_fence *timedout_fence)
{
jpeg_v2_5_stop_inst(ring->adev, ring->me);
jpeg_v2_5_start_inst(ring->adev, ring->me);
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
index 2f8510c2986b9..9bd0ae4a24a1a 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
@@ -555,7 +555,9 @@ static int jpeg_v3_0_process_interrupt(struct amdgpu_device *adev,
return 0;
}
-static int jpeg_v3_0_ring_reset(struct amdgpu_ring *ring, unsigned int vmid)
+static int jpeg_v3_0_ring_reset(struct amdgpu_ring *ring,
+ unsigned int vmid,
+ struct amdgpu_fence *timedout_fence)
{
jpeg_v3_0_stop(ring->adev);
jpeg_v3_0_start(ring->adev);
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
index f17ec5414fd69..4fc1ef85b2945 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
@@ -720,7 +720,9 @@ static int jpeg_v4_0_process_interrupt(struct amdgpu_device *adev,
return 0;
}
-static int jpeg_v4_0_ring_reset(struct amdgpu_ring *ring, unsigned int vmid)
+static int jpeg_v4_0_ring_reset(struct amdgpu_ring *ring,
+ unsigned int vmid,
+ struct amdgpu_fence *timedout_fence)
{
if (amdgpu_sriov_vf(ring->adev))
return -EINVAL;
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
index 79e342d5ab28d..bdc7612ba56a5 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
@@ -1143,7 +1143,9 @@ static void jpeg_v4_0_3_core_stall_reset(struct amdgpu_ring *ring)
WREG32_SOC15(JPEG, jpeg_inst, regJPEG_CORE_RST_CTRL, 0x00);
}
-static int jpeg_v4_0_3_ring_reset(struct amdgpu_ring *ring, unsigned int vmid)
+static int jpeg_v4_0_3_ring_reset(struct amdgpu_ring *ring,
+ unsigned int vmid,
+ struct amdgpu_fence *timedout_fence)
{
if (amdgpu_sriov_vf(ring->adev))
return -EOPNOTSUPP;
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c
index 3b6f65a256464..aee4f50a0f52e 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c
@@ -834,7 +834,9 @@ static void jpeg_v5_0_1_core_stall_reset(struct amdgpu_ring *ring)
WREG32_SOC15(JPEG, jpeg_inst, regJPEG_CORE_RST_CTRL, 0x00);
}
-static int jpeg_v5_0_1_ring_reset(struct amdgpu_ring *ring, unsigned int vmid)
+static int jpeg_v5_0_1_ring_reset(struct amdgpu_ring *ring,
+ unsigned int vmid,
+ struct amdgpu_fence *timedout_fence)
{
if (amdgpu_sriov_vf(ring->adev))
return -EOPNOTSUPP;
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
index 08ddef027f21f..b8828432c98a3 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
@@ -1675,7 +1675,9 @@ static bool sdma_v4_4_2_page_ring_is_guilty(struct amdgpu_ring *ring)
return sdma_v4_4_2_is_queue_selected(adev, instance_id, true);
}
-static int sdma_v4_4_2_reset_queue(struct amdgpu_ring *ring, unsigned int vmid)
+static int sdma_v4_4_2_reset_queue(struct amdgpu_ring *ring,
+ unsigned int vmid,
+ struct amdgpu_fence *timedout_fence)
{
struct amdgpu_device *adev = ring->adev;
u32 id = ring->me;
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
index 37f4b5b4a098f..2fd72c85cf014 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
@@ -1539,7 +1539,9 @@ static int sdma_v5_0_soft_reset(struct amdgpu_ip_block *ip_block)
return 0;
}
-static int sdma_v5_0_reset_queue(struct amdgpu_ring *ring, unsigned int vmid)
+static int sdma_v5_0_reset_queue(struct amdgpu_ring *ring,
+ unsigned int vmid,
+ struct amdgpu_fence *timedout_fence)
{
struct amdgpu_device *adev = ring->adev;
u32 inst_id = ring->me;
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
index 0b40411b92a0b..21421f1bd2095 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
@@ -1452,7 +1452,9 @@ static int sdma_v5_2_wait_for_idle(struct amdgpu_ip_block *ip_block)
return -ETIMEDOUT;
}
-static int sdma_v5_2_reset_queue(struct amdgpu_ring *ring, unsigned int vmid)
+static int sdma_v5_2_reset_queue(struct amdgpu_ring *ring,
+ unsigned int vmid,
+ struct amdgpu_fence *timedout_fence)
{
struct amdgpu_device *adev = ring->adev;
u32 inst_id = ring->me;
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
index 2f3250d30bb01..2cd5f60aef859 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
@@ -1566,7 +1566,9 @@ static int sdma_v6_0_ring_preempt_ib(struct amdgpu_ring *ring)
return r;
}
-static int sdma_v6_0_reset_queue(struct amdgpu_ring *ring, unsigned int vmid)
+static int sdma_v6_0_reset_queue(struct amdgpu_ring *ring,
+ unsigned int vmid,
+ struct amdgpu_fence *timedout_fence)
{
struct amdgpu_device *adev = ring->adev;
int i, r;
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c
index 86903eccbd4e5..6210be7e4a52f 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c
@@ -802,7 +802,9 @@ static bool sdma_v7_0_check_soft_reset(struct amdgpu_ip_block *ip_block)
return false;
}
-static int sdma_v7_0_reset_queue(struct amdgpu_ring *ring, unsigned int vmid)
+static int sdma_v7_0_reset_queue(struct amdgpu_ring *ring,
+ unsigned int vmid,
+ struct amdgpu_fence *timedout_fence)
{
struct amdgpu_device *adev = ring->adev;
int i, r;
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
index b5071f77f78d2..244359fa4aacb 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
@@ -1967,7 +1967,9 @@ static int vcn_v4_0_ring_patch_cs_in_place(struct amdgpu_cs_parser *p,
return 0;
}
-static int vcn_v4_0_ring_reset(struct amdgpu_ring *ring, unsigned int vmid)
+static int vcn_v4_0_ring_reset(struct amdgpu_ring *ring,
+ unsigned int vmid,
+ struct amdgpu_fence *timedout_fence)
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me];
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
index 5a33140f57235..75c07ebf7fe4b 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
@@ -1594,7 +1594,9 @@ static void vcn_v4_0_3_unified_ring_set_wptr(struct amdgpu_ring *ring)
}
}
-static int vcn_v4_0_3_ring_reset(struct amdgpu_ring *ring, unsigned int vmid)
+static int vcn_v4_0_3_ring_reset(struct amdgpu_ring *ring,
+ unsigned int vmid,
+ struct amdgpu_fence *timedout_fence)
{
int r = 0;
int vcn_inst;
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
index 16ade84facc78..731f7762c3e0a 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
@@ -1465,7 +1465,9 @@ static void vcn_v4_0_5_unified_ring_set_wptr(struct amdgpu_ring *ring)
}
}
-static int vcn_v4_0_5_ring_reset(struct amdgpu_ring *ring, unsigned int vmid)
+static int vcn_v4_0_5_ring_reset(struct amdgpu_ring *ring,
+ unsigned int vmid,
+ struct amdgpu_fence *timedout_fence)
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me];
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
index f8e3f0b882da5..f975994b3ff44 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
@@ -1192,7 +1192,9 @@ static void vcn_v5_0_0_unified_ring_set_wptr(struct amdgpu_ring *ring)
}
}
-static int vcn_v5_0_0_ring_reset(struct amdgpu_ring *ring, unsigned int vmid)
+static int vcn_v5_0_0_ring_reset(struct amdgpu_ring *ring,
+ unsigned int vmid,
+ struct amdgpu_fence *timedout_fence)
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me];
--
2.50.0
^ permalink raw reply related [flat|nested] 35+ messages in thread* [PATCH 03/30] drm/amdgpu: rework queue reset scheduler interaction
2025-06-25 21:06 [PATCH V11 00/30] Reset improvements Alex Deucher
2025-06-25 21:06 ` [PATCH 01/30] drm/amdgpu: remove job parameter from amdgpu_fence_emit() Alex Deucher
2025-06-25 21:06 ` [PATCH 02/30] drm/amdgpu: update ring reset function signature Alex Deucher
@ 2025-06-25 21:06 ` Alex Deucher
2025-06-25 21:06 ` [PATCH 04/30] drm/amdgpu: move force completion into ring resets Alex Deucher
` (26 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Alex Deucher @ 2025-06-25 21:06 UTC (permalink / raw)
To: amd-gfx, christian.koenig, sasundar; +Cc: Christian König, Alex Deucher
From: Christian König <ckoenig.leichtzumerken@gmail.com>
Stopping the scheduler for queue reset is generally a good idea because
it prevents any worker from touching the ring buffer.
Reviewed-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 35 ++++++++++++++-----------
1 file changed, 20 insertions(+), 15 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
index a7ff1fa4c778e..93413be59e08f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
@@ -91,8 +91,8 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
struct amdgpu_job *job = to_amdgpu_job(s_job);
struct amdgpu_task_info *ti;
struct amdgpu_device *adev = ring->adev;
- int idx;
- int r;
+ bool set_error = false;
+ int idx, r;
if (!drm_dev_enter(adev_to_drm(adev), &idx)) {
dev_info(adev->dev, "%s - device unplugged skipping recovery on scheduler:%s",
@@ -136,10 +136,12 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
} else if (amdgpu_gpu_recovery && ring->funcs->reset) {
bool is_guilty;
- dev_err(adev->dev, "Starting %s ring reset\n", s_job->sched->name);
- /* stop the scheduler, but don't mess with the
- * bad job yet because if ring reset fails
- * we'll fall back to full GPU reset.
+ dev_err(adev->dev, "Starting %s ring reset\n",
+ s_job->sched->name);
+
+ /*
+ * Stop the scheduler to prevent anybody else from touching the
+ * ring buffer.
*/
drm_sched_wqueue_stop(&ring->sched);
@@ -152,26 +154,29 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
else
is_guilty = true;
- if (is_guilty)
+ if (is_guilty) {
dma_fence_set_error(&s_job->s_fence->finished, -ETIME);
+ set_error = true;
+ }
r = amdgpu_ring_reset(ring, job->vmid, NULL);
if (!r) {
- if (amdgpu_ring_sched_ready(ring))
- drm_sched_stop(&ring->sched, s_job);
if (is_guilty) {
atomic_inc(&ring->adev->gpu_reset_counter);
amdgpu_fence_driver_force_completion(ring);
}
- if (amdgpu_ring_sched_ready(ring))
- drm_sched_start(&ring->sched, 0);
- dev_err(adev->dev, "Ring %s reset succeeded\n", ring->sched.name);
- drm_dev_wedged_event(adev_to_drm(adev), DRM_WEDGE_RECOVERY_NONE);
+ drm_sched_wqueue_start(&ring->sched);
+ dev_err(adev->dev, "Ring %s reset succeeded\n",
+ ring->sched.name);
+ drm_dev_wedged_event(adev_to_drm(adev),
+ DRM_WEDGE_RECOVERY_NONE);
goto exit;
}
- dev_err(adev->dev, "Ring %s reset failure\n", ring->sched.name);
+ dev_err(adev->dev, "Ring %s reset failed\n", ring->sched.name);
}
- dma_fence_set_error(&s_job->s_fence->finished, -ETIME);
+
+ if (!set_error)
+ dma_fence_set_error(&s_job->s_fence->finished, -ETIME);
if (amdgpu_device_should_recover_gpu(ring->adev)) {
struct amdgpu_reset_context reset_context;
--
2.50.0
^ permalink raw reply related [flat|nested] 35+ messages in thread* [PATCH 04/30] drm/amdgpu: move force completion into ring resets
2025-06-25 21:06 [PATCH V11 00/30] Reset improvements Alex Deucher
` (2 preceding siblings ...)
2025-06-25 21:06 ` [PATCH 03/30] drm/amdgpu: rework queue reset scheduler interaction Alex Deucher
@ 2025-06-25 21:06 ` Alex Deucher
2025-06-25 21:06 ` [PATCH 05/30] drm/amdgpu: move guilty handling " Alex Deucher
` (25 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Alex Deucher @ 2025-06-25 21:06 UTC (permalink / raw)
To: amd-gfx, christian.koenig, sasundar; +Cc: Alex Deucher
Move the force completion handling into each ring
reset function so that each engine can determine
whether or not it needs to force completion on the
jobs in the ring.
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 4 +--
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 12 +++++++--
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 12 +++++++--
drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c | 12 +++++++--
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 7 +++++-
drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c | 7 +++++-
drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c | 8 +++++-
drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c | 8 +++++-
drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c | 8 +++++-
drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c | 8 +++++-
drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c | 8 +++++-
drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c | 8 +++++-
drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c | 31 +++++++++++++++++++++---
drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c | 5 +++-
drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c | 5 +++-
drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c | 6 ++++-
drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c | 6 ++++-
drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 7 +++++-
drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 6 +++--
drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c | 7 +++++-
drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c | 7 +++++-
21 files changed, 152 insertions(+), 30 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
index 93413be59e08f..177f04491a11b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
@@ -161,10 +161,8 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
r = amdgpu_ring_reset(ring, job->vmid, NULL);
if (!r) {
- if (is_guilty) {
+ if (is_guilty)
atomic_inc(&ring->adev->gpu_reset_counter);
- amdgpu_fence_driver_force_completion(ring);
- }
drm_sched_wqueue_start(&ring->sched);
dev_err(adev->dev, "Ring %s reset succeeded\n",
ring->sched.name);
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
index 4b2af95203b26..4d0ee3ffe9858 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
@@ -9577,7 +9577,11 @@ static int gfx_v10_0_reset_kgq(struct amdgpu_ring *ring,
return r;
}
- return amdgpu_ring_test_ring(ring);
+ r = amdgpu_ring_test_ring(ring);
+ if (r)
+ return r;
+ amdgpu_fence_driver_force_completion(ring);
+ return 0;
}
static int gfx_v10_0_reset_kcq(struct amdgpu_ring *ring,
@@ -9650,7 +9654,11 @@ static int gfx_v10_0_reset_kcq(struct amdgpu_ring *ring,
if (r)
return r;
- return amdgpu_ring_test_ring(ring);
+ r = amdgpu_ring_test_ring(ring);
+ if (r)
+ return r;
+ amdgpu_fence_driver_force_completion(ring);
+ return 0;
}
static void gfx_v10_ip_print(struct amdgpu_ip_block *ip_block, struct drm_printer *p)
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
index 8d5c0ab016d2b..39f4dd18c277b 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -6842,7 +6842,11 @@ static int gfx_v11_0_reset_kgq(struct amdgpu_ring *ring,
return r;
}
- return amdgpu_ring_test_ring(ring);
+ r = amdgpu_ring_test_ring(ring);
+ if (r)
+ return r;
+ amdgpu_fence_driver_force_completion(ring);
+ return 0;
}
static int gfx_v11_0_reset_compute_pipe(struct amdgpu_ring *ring)
@@ -7004,7 +7008,11 @@ static int gfx_v11_0_reset_kcq(struct amdgpu_ring *ring,
return r;
}
- return amdgpu_ring_test_ring(ring);
+ r = amdgpu_ring_test_ring(ring);
+ if (r)
+ return r;
+ amdgpu_fence_driver_force_completion(ring);
+ return 0;
}
static void gfx_v11_ip_print(struct amdgpu_ip_block *ip_block, struct drm_printer *p)
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
index 795bd353a9cea..964fa3f2e2719 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
@@ -5337,7 +5337,11 @@ static int gfx_v12_0_reset_kgq(struct amdgpu_ring *ring,
return r;
}
- return amdgpu_ring_test_ring(ring);
+ r = amdgpu_ring_test_ring(ring);
+ if (r)
+ return r;
+ amdgpu_fence_driver_force_completion(ring);
+ return 0;
}
static int gfx_v12_0_reset_compute_pipe(struct amdgpu_ring *ring)
@@ -5452,7 +5456,11 @@ static int gfx_v12_0_reset_kcq(struct amdgpu_ring *ring,
return r;
}
- return amdgpu_ring_test_ring(ring);
+ r = amdgpu_ring_test_ring(ring);
+ if (r)
+ return r;
+ amdgpu_fence_driver_force_completion(ring);
+ return 0;
}
static void gfx_v12_0_ring_begin_use(struct amdgpu_ring *ring)
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
index d91e0423c4820..95e319974f221 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
@@ -7242,7 +7242,12 @@ static int gfx_v9_0_reset_kcq(struct amdgpu_ring *ring,
DRM_ERROR("fail to remap queue\n");
return r;
}
- return amdgpu_ring_test_ring(ring);
+
+ r = amdgpu_ring_test_ring(ring);
+ if (r)
+ return r;
+ amdgpu_fence_driver_force_completion(ring);
+ return 0;
}
static void gfx_v9_ip_print(struct amdgpu_ip_block *ip_block, struct drm_printer *p)
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
index 272f0f8e41d45..8bfee17a826e2 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
@@ -3620,7 +3620,12 @@ static int gfx_v9_4_3_reset_kcq(struct amdgpu_ring *ring,
dev_err(adev->dev, "fail to remap queue\n");
return r;
}
- return amdgpu_ring_test_ring(ring);
+
+ r = amdgpu_ring_test_ring(ring);
+ if (r)
+ return r;
+ amdgpu_fence_driver_force_completion(ring);
+ return 0;
}
enum amdgpu_gfx_cp_ras_mem_id {
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
index 93eb71d2ce304..6621a7b1f29fc 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
@@ -768,9 +768,15 @@ static int jpeg_v2_0_ring_reset(struct amdgpu_ring *ring,
unsigned int vmid,
struct amdgpu_fence *timedout_fence)
{
+ int r;
+
jpeg_v2_0_stop(ring->adev);
jpeg_v2_0_start(ring->adev);
- return amdgpu_ring_test_helper(ring);
+ r = amdgpu_ring_test_helper(ring);
+ if (r)
+ return r;
+ amdgpu_fence_driver_force_completion(ring);
+ return 0;
}
static const struct amd_ip_funcs jpeg_v2_0_ip_funcs = {
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
index 45b8702d20ad9..44a5c0e82ca43 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
@@ -647,9 +647,15 @@ static int jpeg_v2_5_ring_reset(struct amdgpu_ring *ring,
unsigned int vmid,
struct amdgpu_fence *timedout_fence)
{
+ int r;
+
jpeg_v2_5_stop_inst(ring->adev, ring->me);
jpeg_v2_5_start_inst(ring->adev, ring->me);
- return amdgpu_ring_test_helper(ring);
+ r = amdgpu_ring_test_helper(ring);
+ if (r)
+ return r;
+ amdgpu_fence_driver_force_completion(ring);
+ return 0;
}
static const struct amd_ip_funcs jpeg_v2_5_ip_funcs = {
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
index 9bd0ae4a24a1a..e813af4eedd21 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
@@ -559,9 +559,15 @@ static int jpeg_v3_0_ring_reset(struct amdgpu_ring *ring,
unsigned int vmid,
struct amdgpu_fence *timedout_fence)
{
+ int r;
+
jpeg_v3_0_stop(ring->adev);
jpeg_v3_0_start(ring->adev);
- return amdgpu_ring_test_helper(ring);
+ r = amdgpu_ring_test_helper(ring);
+ if (r)
+ return r;
+ amdgpu_fence_driver_force_completion(ring);
+ return 0;
}
static const struct amd_ip_funcs jpeg_v3_0_ip_funcs = {
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
index 4fc1ef85b2945..190f0742d7016 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
@@ -724,12 +724,18 @@ static int jpeg_v4_0_ring_reset(struct amdgpu_ring *ring,
unsigned int vmid,
struct amdgpu_fence *timedout_fence)
{
+ int r;
+
if (amdgpu_sriov_vf(ring->adev))
return -EINVAL;
jpeg_v4_0_stop(ring->adev);
jpeg_v4_0_start(ring->adev);
- return amdgpu_ring_test_helper(ring);
+ r = amdgpu_ring_test_helper(ring);
+ if (r)
+ return r;
+ amdgpu_fence_driver_force_completion(ring);
+ return 0;
}
static const struct amd_ip_funcs jpeg_v4_0_ip_funcs = {
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
index bdc7612ba56a5..04755b7a62d9b 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
@@ -1147,12 +1147,18 @@ static int jpeg_v4_0_3_ring_reset(struct amdgpu_ring *ring,
unsigned int vmid,
struct amdgpu_fence *timedout_fence)
{
+ int r;
+
if (amdgpu_sriov_vf(ring->adev))
return -EOPNOTSUPP;
jpeg_v4_0_3_core_stall_reset(ring);
jpeg_v4_0_3_start_jrbc(ring);
- return amdgpu_ring_test_helper(ring);
+ r = amdgpu_ring_test_helper(ring);
+ if (r)
+ return r;
+ amdgpu_fence_driver_force_completion(ring);
+ return 0;
}
static const struct amd_ip_funcs jpeg_v4_0_3_ip_funcs = {
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c
index aee4f50a0f52e..e7f942dc714a7 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c
@@ -838,12 +838,18 @@ static int jpeg_v5_0_1_ring_reset(struct amdgpu_ring *ring,
unsigned int vmid,
struct amdgpu_fence *timedout_fence)
{
+ int r;
+
if (amdgpu_sriov_vf(ring->adev))
return -EOPNOTSUPP;
jpeg_v5_0_1_core_stall_reset(ring);
jpeg_v5_0_1_init_jrbc(ring);
- return amdgpu_ring_test_helper(ring);
+ r = amdgpu_ring_test_helper(ring);
+ if (r)
+ return r;
+ amdgpu_fence_driver_force_completion(ring);
+ return 0;
}
static const struct amd_ip_funcs jpeg_v5_0_1_ip_funcs = {
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
index b8828432c98a3..c13ae87d4e648 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
@@ -1679,6 +1679,7 @@ static int sdma_v4_4_2_reset_queue(struct amdgpu_ring *ring,
unsigned int vmid,
struct amdgpu_fence *timedout_fence)
{
+ bool is_guilty = ring->funcs->is_guilty(ring);
struct amdgpu_device *adev = ring->adev;
u32 id = ring->me;
int r;
@@ -1689,8 +1690,13 @@ static int sdma_v4_4_2_reset_queue(struct amdgpu_ring *ring,
amdgpu_amdkfd_suspend(adev, true);
r = amdgpu_sdma_reset_engine(adev, id);
amdgpu_amdkfd_resume(adev, true);
+ if (r)
+ return r;
- return r;
+ if (is_guilty)
+ amdgpu_fence_driver_force_completion(ring);
+
+ return 0;
}
static int sdma_v4_4_2_stop_queue(struct amdgpu_ring *ring)
@@ -1734,8 +1740,8 @@ static int sdma_v4_4_2_stop_queue(struct amdgpu_ring *ring)
static int sdma_v4_4_2_restore_queue(struct amdgpu_ring *ring)
{
struct amdgpu_device *adev = ring->adev;
- u32 inst_mask;
- int i;
+ u32 inst_mask, tmp_mask;
+ int i, r;
inst_mask = 1 << ring->me;
udelay(50);
@@ -1752,7 +1758,24 @@ static int sdma_v4_4_2_restore_queue(struct amdgpu_ring *ring)
return -ETIMEDOUT;
}
- return sdma_v4_4_2_inst_start(adev, inst_mask, true);
+ r = sdma_v4_4_2_inst_start(adev, inst_mask, true);
+ if (r)
+ return r;
+
+ tmp_mask = inst_mask;
+ for_each_inst(i, tmp_mask) {
+ ring = &adev->sdma.instance[i].ring;
+
+ amdgpu_fence_driver_force_completion(ring);
+
+ if (adev->sdma.has_page_queue) {
+ struct amdgpu_ring *page = &adev->sdma.instance[i].page;
+
+ amdgpu_fence_driver_force_completion(page);
+ }
+ }
+
+ return r;
}
static int sdma_v4_4_2_soft_reset_engine(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
index 2fd72c85cf014..4d72b085b3dd7 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_0.c
@@ -1618,7 +1618,10 @@ static int sdma_v5_0_restore_queue(struct amdgpu_ring *ring)
r = sdma_v5_0_gfx_resume_instance(adev, inst_id, true);
amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
- return r;
+ if (r)
+ return r;
+ amdgpu_fence_driver_force_completion(ring);
+ return 0;
}
static int sdma_v5_0_ring_preempt_ib(struct amdgpu_ring *ring)
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
index 21421f1bd2095..42a25150f83ac 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v5_2.c
@@ -1534,7 +1534,10 @@ static int sdma_v5_2_restore_queue(struct amdgpu_ring *ring)
r = sdma_v5_2_gfx_resume_instance(adev, inst_id, true);
amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
- return r;
+ if (r)
+ return r;
+ amdgpu_fence_driver_force_completion(ring);
+ return 0;
}
static int sdma_v5_2_ring_preempt_ib(struct amdgpu_ring *ring)
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
index 2cd5f60aef859..4b6a799704f1f 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
@@ -1590,7 +1590,11 @@ static int sdma_v6_0_reset_queue(struct amdgpu_ring *ring,
if (r)
return r;
- return sdma_v6_0_gfx_resume_instance(adev, i, true);
+ r = sdma_v6_0_gfx_resume_instance(adev, i, true);
+ if (r)
+ return r;
+ amdgpu_fence_driver_force_completion(ring);
+ return 0;
}
static int sdma_v6_0_set_trap_irq_state(struct amdgpu_device *adev,
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c
index 6210be7e4a52f..b00c63812899d 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c
@@ -826,7 +826,11 @@ static int sdma_v7_0_reset_queue(struct amdgpu_ring *ring,
if (r)
return r;
- return sdma_v7_0_gfx_resume_instance(adev, i, true);
+ r = sdma_v7_0_gfx_resume_instance(adev, i, true);
+ if (r)
+ return r;
+ amdgpu_fence_driver_force_completion(ring);
+ return 0;
}
/**
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
index 244359fa4aacb..6c25e9fc4f0f9 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
@@ -1973,6 +1973,7 @@ static int vcn_v4_0_ring_reset(struct amdgpu_ring *ring,
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me];
+ int r;
if (!(adev->vcn.supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE))
return -EOPNOTSUPP;
@@ -1980,7 +1981,11 @@ static int vcn_v4_0_ring_reset(struct amdgpu_ring *ring,
vcn_v4_0_stop(vinst);
vcn_v4_0_start(vinst);
- return amdgpu_ring_test_helper(ring);
+ r = amdgpu_ring_test_helper(ring);
+ if (r)
+ return r;
+ amdgpu_fence_driver_force_completion(ring);
+ return 0;
}
static struct amdgpu_ring_funcs vcn_v4_0_unified_ring_vm_funcs = {
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
index 75c07ebf7fe4b..1e1dd61b774ec 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
@@ -1623,8 +1623,10 @@ static int vcn_v4_0_3_ring_reset(struct amdgpu_ring *ring,
vcn_v4_0_3_hw_init_inst(vinst);
vcn_v4_0_3_start_dpg_mode(vinst, adev->vcn.inst[ring->me].indirect_sram);
r = amdgpu_ring_test_helper(ring);
-
- return r;
+ if (r)
+ return r;
+ amdgpu_fence_driver_force_completion(ring);
+ return 0;
}
static const struct amdgpu_ring_funcs vcn_v4_0_3_unified_ring_vm_funcs = {
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
index 731f7762c3e0a..9c02446bb1a54 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
@@ -1471,6 +1471,7 @@ static int vcn_v4_0_5_ring_reset(struct amdgpu_ring *ring,
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me];
+ int r;
if (!(adev->vcn.supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE))
return -EOPNOTSUPP;
@@ -1478,7 +1479,11 @@ static int vcn_v4_0_5_ring_reset(struct amdgpu_ring *ring,
vcn_v4_0_5_stop(vinst);
vcn_v4_0_5_start(vinst);
- return amdgpu_ring_test_helper(ring);
+ r = amdgpu_ring_test_helper(ring);
+ if (r)
+ return r;
+ amdgpu_fence_driver_force_completion(ring);
+ return 0;
}
static struct amdgpu_ring_funcs vcn_v4_0_5_unified_ring_vm_funcs = {
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
index f975994b3ff44..c8924f97cf58a 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
@@ -1198,6 +1198,7 @@ static int vcn_v5_0_0_ring_reset(struct amdgpu_ring *ring,
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me];
+ int r;
if (!(adev->vcn.supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE))
return -EOPNOTSUPP;
@@ -1205,7 +1206,11 @@ static int vcn_v5_0_0_ring_reset(struct amdgpu_ring *ring,
vcn_v5_0_0_stop(vinst);
vcn_v5_0_0_start(vinst);
- return amdgpu_ring_test_helper(ring);
+ r = amdgpu_ring_test_helper(ring);
+ if (r)
+ return r;
+ amdgpu_fence_driver_force_completion(ring);
+ return 0;
}
static const struct amdgpu_ring_funcs vcn_v5_0_0_unified_ring_vm_funcs = {
--
2.50.0
^ permalink raw reply related [flat|nested] 35+ messages in thread* [PATCH 05/30] drm/amdgpu: move guilty handling into ring resets
2025-06-25 21:06 [PATCH V11 00/30] Reset improvements Alex Deucher
` (3 preceding siblings ...)
2025-06-25 21:06 ` [PATCH 04/30] drm/amdgpu: move force completion into ring resets Alex Deucher
@ 2025-06-25 21:06 ` Alex Deucher
2025-06-25 21:06 ` [PATCH 06/30] drm/amdgpu: move scheduler wqueue handling into callbacks Alex Deucher
` (24 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Alex Deucher @ 2025-06-25 21:06 UTC (permalink / raw)
To: amd-gfx, christian.koenig, sasundar; +Cc: Alex Deucher
Move guilty logic into the ring reset callbacks. This
allows each ring reset callback to better handle fence
errors and force completions in line with the reset
behavior for each IP. It also allows us to remove
the ring guilty callback since that logic now lives
in the reset callback.
Acked-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 23 ++----------------
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 1 -
drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c | 30 +-----------------------
3 files changed, 3 insertions(+), 51 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
index 177f04491a11b..3b7d3844a74bc 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
@@ -91,7 +91,6 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
struct amdgpu_job *job = to_amdgpu_job(s_job);
struct amdgpu_task_info *ti;
struct amdgpu_device *adev = ring->adev;
- bool set_error = false;
int idx, r;
if (!drm_dev_enter(adev_to_drm(adev), &idx)) {
@@ -134,8 +133,6 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
if (unlikely(adev->debug_disable_gpu_ring_reset)) {
dev_err(adev->dev, "Ring reset disabled by debug mask\n");
} else if (amdgpu_gpu_recovery && ring->funcs->reset) {
- bool is_guilty;
-
dev_err(adev->dev, "Starting %s ring reset\n",
s_job->sched->name);
@@ -145,24 +142,9 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
*/
drm_sched_wqueue_stop(&ring->sched);
- /* for engine resets, we need to reset the engine,
- * but individual queues may be unaffected.
- * check here to make sure the accounting is correct.
- */
- if (ring->funcs->is_guilty)
- is_guilty = ring->funcs->is_guilty(ring);
- else
- is_guilty = true;
-
- if (is_guilty) {
- dma_fence_set_error(&s_job->s_fence->finished, -ETIME);
- set_error = true;
- }
-
r = amdgpu_ring_reset(ring, job->vmid, NULL);
if (!r) {
- if (is_guilty)
- atomic_inc(&ring->adev->gpu_reset_counter);
+ atomic_inc(&ring->adev->gpu_reset_counter);
drm_sched_wqueue_start(&ring->sched);
dev_err(adev->dev, "Ring %s reset succeeded\n",
ring->sched.name);
@@ -173,8 +155,7 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
dev_err(adev->dev, "Ring %s reset failed\n", ring->sched.name);
}
- if (!set_error)
- dma_fence_set_error(&s_job->s_fence->finished, -ETIME);
+ dma_fence_set_error(&s_job->s_fence->finished, -ETIME);
if (amdgpu_device_should_recover_gpu(ring->adev)) {
struct amdgpu_reset_context reset_context;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
index de972f69d96e7..784ba2ec354c7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
@@ -271,7 +271,6 @@ struct amdgpu_ring_funcs {
int (*reset)(struct amdgpu_ring *ring, unsigned int vmid,
struct amdgpu_fence *timedout_fence);
void (*emit_cleaner_shader)(struct amdgpu_ring *ring);
- bool (*is_guilty)(struct amdgpu_ring *ring);
};
/**
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
index c13ae87d4e648..d3072bca43e3f 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v4_4_2.c
@@ -1656,30 +1656,10 @@ static bool sdma_v4_4_2_is_queue_selected(struct amdgpu_device *adev, uint32_t i
return (context_status & SDMA_GFX_CONTEXT_STATUS__SELECTED_MASK) != 0;
}
-static bool sdma_v4_4_2_ring_is_guilty(struct amdgpu_ring *ring)
-{
- struct amdgpu_device *adev = ring->adev;
- uint32_t instance_id = ring->me;
-
- return sdma_v4_4_2_is_queue_selected(adev, instance_id, false);
-}
-
-static bool sdma_v4_4_2_page_ring_is_guilty(struct amdgpu_ring *ring)
-{
- struct amdgpu_device *adev = ring->adev;
- uint32_t instance_id = ring->me;
-
- if (!adev->sdma.has_page_queue)
- return false;
-
- return sdma_v4_4_2_is_queue_selected(adev, instance_id, true);
-}
-
static int sdma_v4_4_2_reset_queue(struct amdgpu_ring *ring,
unsigned int vmid,
struct amdgpu_fence *timedout_fence)
{
- bool is_guilty = ring->funcs->is_guilty(ring);
struct amdgpu_device *adev = ring->adev;
u32 id = ring->me;
int r;
@@ -1690,13 +1670,7 @@ static int sdma_v4_4_2_reset_queue(struct amdgpu_ring *ring,
amdgpu_amdkfd_suspend(adev, true);
r = amdgpu_sdma_reset_engine(adev, id);
amdgpu_amdkfd_resume(adev, true);
- if (r)
- return r;
-
- if (is_guilty)
- amdgpu_fence_driver_force_completion(ring);
-
- return 0;
+ return r;
}
static int sdma_v4_4_2_stop_queue(struct amdgpu_ring *ring)
@@ -2181,7 +2155,6 @@ static const struct amdgpu_ring_funcs sdma_v4_4_2_ring_funcs = {
.emit_reg_wait = sdma_v4_4_2_ring_emit_reg_wait,
.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
.reset = sdma_v4_4_2_reset_queue,
- .is_guilty = sdma_v4_4_2_ring_is_guilty,
};
static const struct amdgpu_ring_funcs sdma_v4_4_2_page_ring_funcs = {
@@ -2214,7 +2187,6 @@ static const struct amdgpu_ring_funcs sdma_v4_4_2_page_ring_funcs = {
.emit_reg_wait = sdma_v4_4_2_ring_emit_reg_wait,
.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
.reset = sdma_v4_4_2_reset_queue,
- .is_guilty = sdma_v4_4_2_page_ring_is_guilty,
};
static void sdma_v4_4_2_set_ring_funcs(struct amdgpu_device *adev)
--
2.50.0
^ permalink raw reply related [flat|nested] 35+ messages in thread* [PATCH 06/30] drm/amdgpu: move scheduler wqueue handling into callbacks
2025-06-25 21:06 [PATCH V11 00/30] Reset improvements Alex Deucher
` (4 preceding siblings ...)
2025-06-25 21:06 ` [PATCH 05/30] drm/amdgpu: move guilty handling " Alex Deucher
@ 2025-06-25 21:06 ` Alex Deucher
2025-06-26 9:33 ` Christian König
2025-06-25 21:06 ` [PATCH 07/30] drm/amdgpu: track ring state associated with a fence Alex Deucher
` (23 subsequent siblings)
29 siblings, 1 reply; 35+ messages in thread
From: Alex Deucher @ 2025-06-25 21:06 UTC (permalink / raw)
To: amd-gfx, christian.koenig, sasundar; +Cc: Alex Deucher
Move the scheduler wqueue stopping and starting into
the ring reset callbacks. On some IPs we have to reset
an engine which may have multiple queues. Move the wqueue
handling into the backend so we can handle them as needed
based on the type of reset available.
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 8 --------
drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c | 17 ++++-------------
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 6 ++++++
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 6 ++++++
drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c | 6 ++++++
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 3 +++
drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c | 3 +++
drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c | 2 ++
drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c | 2 ++
drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c | 2 ++
drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c | 2 ++
drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c | 2 ++
drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c | 2 ++
drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c | 3 +++
drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c | 3 +++
drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 2 ++
drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 3 +++
drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c | 2 ++
drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c | 2 ++
19 files changed, 55 insertions(+), 21 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
index 3b7d3844a74bc..f0b7080dccb8d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
@@ -135,17 +135,9 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
} else if (amdgpu_gpu_recovery && ring->funcs->reset) {
dev_err(adev->dev, "Starting %s ring reset\n",
s_job->sched->name);
-
- /*
- * Stop the scheduler to prevent anybody else from touching the
- * ring buffer.
- */
- drm_sched_wqueue_stop(&ring->sched);
-
r = amdgpu_ring_reset(ring, job->vmid, NULL);
if (!r) {
atomic_inc(&ring->adev->gpu_reset_counter);
- drm_sched_wqueue_start(&ring->sched);
dev_err(adev->dev, "Ring %s reset succeeded\n",
ring->sched.name);
drm_dev_wedged_event(adev_to_drm(adev),
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
index cf5733d5d26dd..7e26a44dcc1fd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
@@ -554,22 +554,16 @@ int amdgpu_sdma_reset_engine(struct amdgpu_device *adev, uint32_t instance_id)
struct amdgpu_sdma_instance *sdma_instance = &adev->sdma.instance[instance_id];
struct amdgpu_ring *gfx_ring = &sdma_instance->ring;
struct amdgpu_ring *page_ring = &sdma_instance->page;
- bool gfx_sched_stopped = false, page_sched_stopped = false;
mutex_lock(&sdma_instance->engine_reset_mutex);
/* Stop the scheduler's work queue for the GFX and page rings if they are running.
* This ensures that no new tasks are submitted to the queues while
* the reset is in progress.
*/
- if (!amdgpu_ring_sched_ready(gfx_ring)) {
- drm_sched_wqueue_stop(&gfx_ring->sched);
- gfx_sched_stopped = true;
- }
+ drm_sched_wqueue_stop(&gfx_ring->sched);
- if (adev->sdma.has_page_queue && !amdgpu_ring_sched_ready(page_ring)) {
+ if (adev->sdma.has_page_queue)
drm_sched_wqueue_stop(&page_ring->sched);
- page_sched_stopped = true;
- }
if (sdma_instance->funcs->stop_kernel_queue) {
sdma_instance->funcs->stop_kernel_queue(gfx_ring);
@@ -596,12 +590,9 @@ 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) {
- if (gfx_sched_stopped && amdgpu_ring_sched_ready(gfx_ring)) {
- drm_sched_wqueue_start(&gfx_ring->sched);
- }
- if (page_sched_stopped && amdgpu_ring_sched_ready(page_ring)) {
+ drm_sched_wqueue_start(&gfx_ring->sched);
+ if (adev->sdma.has_page_queue)
drm_sched_wqueue_start(&page_ring->sched);
- }
}
mutex_unlock(&sdma_instance->engine_reset_mutex);
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
index 4d0ee3ffe9858..8c377ecbb8a75 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
@@ -9540,6 +9540,8 @@ static int gfx_v10_0_reset_kgq(struct amdgpu_ring *ring,
if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
return -EINVAL;
+ drm_sched_wqueue_stop(&ring->sched);
+
spin_lock_irqsave(&kiq->ring_lock, flags);
if (amdgpu_ring_alloc(kiq_ring, 5 + 7 + 7 + kiq->pmf->map_queues_size)) {
@@ -9581,6 +9583,7 @@ static int gfx_v10_0_reset_kgq(struct amdgpu_ring *ring,
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
+ drm_sched_wqueue_start(&ring->sched);
return 0;
}
@@ -9600,6 +9603,8 @@ static int gfx_v10_0_reset_kcq(struct amdgpu_ring *ring,
if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
return -EINVAL;
+ drm_sched_wqueue_stop(&ring->sched);
+
spin_lock_irqsave(&kiq->ring_lock, flags);
if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->unmap_queues_size)) {
@@ -9658,6 +9663,7 @@ static int gfx_v10_0_reset_kcq(struct amdgpu_ring *ring,
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
+ drm_sched_wqueue_start(&ring->sched);
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
index 39f4dd18c277b..37dcec2d07841 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -6821,6 +6821,8 @@ static int gfx_v11_0_reset_kgq(struct amdgpu_ring *ring,
if (amdgpu_sriov_vf(adev))
return -EINVAL;
+ drm_sched_wqueue_stop(&ring->sched);
+
r = amdgpu_mes_reset_legacy_queue(ring->adev, ring, vmid, false);
if (r) {
@@ -6846,6 +6848,7 @@ static int gfx_v11_0_reset_kgq(struct amdgpu_ring *ring,
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
+ drm_sched_wqueue_start(&ring->sched);
return 0;
}
@@ -6989,6 +6992,8 @@ static int gfx_v11_0_reset_kcq(struct amdgpu_ring *ring,
if (amdgpu_sriov_vf(adev))
return -EINVAL;
+ drm_sched_wqueue_stop(&ring->sched);
+
r = amdgpu_mes_reset_legacy_queue(ring->adev, ring, vmid, true);
if (r) {
dev_warn(adev->dev, "fail(%d) to reset kcq and try pipe reset\n", r);
@@ -7012,6 +7017,7 @@ static int gfx_v11_0_reset_kcq(struct amdgpu_ring *ring,
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
+ drm_sched_wqueue_start(&ring->sched);
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
index 964fa3f2e2719..e4fc42470cf3e 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
@@ -5317,6 +5317,8 @@ static int gfx_v12_0_reset_kgq(struct amdgpu_ring *ring,
if (amdgpu_sriov_vf(adev))
return -EINVAL;
+ drm_sched_wqueue_stop(&ring->sched);
+
r = amdgpu_mes_reset_legacy_queue(ring->adev, ring, vmid, false);
if (r) {
dev_warn(adev->dev, "reset via MES failed and try pipe reset %d\n", r);
@@ -5341,6 +5343,7 @@ static int gfx_v12_0_reset_kgq(struct amdgpu_ring *ring,
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
+ drm_sched_wqueue_start(&ring->sched);
return 0;
}
@@ -5437,6 +5440,8 @@ static int gfx_v12_0_reset_kcq(struct amdgpu_ring *ring,
if (amdgpu_sriov_vf(adev))
return -EINVAL;
+ drm_sched_wqueue_stop(&ring->sched);
+
r = amdgpu_mes_reset_legacy_queue(ring->adev, ring, vmid, true);
if (r) {
dev_warn(adev->dev, "fail(%d) to reset kcq and try pipe reset\n", r);
@@ -5460,6 +5465,7 @@ static int gfx_v12_0_reset_kcq(struct amdgpu_ring *ring,
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
+ drm_sched_wqueue_start(&ring->sched);
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
index 95e319974f221..76ba664efecb3 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
@@ -7187,6 +7187,8 @@ static int gfx_v9_0_reset_kcq(struct amdgpu_ring *ring,
if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
return -EINVAL;
+ drm_sched_wqueue_stop(&ring->sched);
+
spin_lock_irqsave(&kiq->ring_lock, flags);
if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->unmap_queues_size)) {
@@ -7247,6 +7249,7 @@ static int gfx_v9_0_reset_kcq(struct amdgpu_ring *ring,
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
+ drm_sched_wqueue_start(&ring->sched);
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
index 8bfee17a826e2..daed0f187bda5 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
@@ -3567,6 +3567,8 @@ static int gfx_v9_4_3_reset_kcq(struct amdgpu_ring *ring,
if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
return -EINVAL;
+ drm_sched_wqueue_stop(&ring->sched);
+
spin_lock_irqsave(&kiq->ring_lock, flags);
if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->unmap_queues_size)) {
@@ -3625,6 +3627,7 @@ static int gfx_v9_4_3_reset_kcq(struct amdgpu_ring *ring,
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
+ drm_sched_wqueue_start(&ring->sched);
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
index 6621a7b1f29fc..781a5a8a83614 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
@@ -770,12 +770,14 @@ static int jpeg_v2_0_ring_reset(struct amdgpu_ring *ring,
{
int r;
+ drm_sched_wqueue_stop(&ring->sched);
jpeg_v2_0_stop(ring->adev);
jpeg_v2_0_start(ring->adev);
r = amdgpu_ring_test_helper(ring);
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
+ drm_sched_wqueue_start(&ring->sched);
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
index 44a5c0e82ca43..5be9cdcae32c1 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
@@ -649,12 +649,14 @@ static int jpeg_v2_5_ring_reset(struct amdgpu_ring *ring,
{
int r;
+ drm_sched_wqueue_stop(&ring->sched);
jpeg_v2_5_stop_inst(ring->adev, ring->me);
jpeg_v2_5_start_inst(ring->adev, ring->me);
r = amdgpu_ring_test_helper(ring);
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
+ drm_sched_wqueue_start(&ring->sched);
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
index e813af4eedd21..a24bd833d6442 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
@@ -561,12 +561,14 @@ static int jpeg_v3_0_ring_reset(struct amdgpu_ring *ring,
{
int r;
+ drm_sched_wqueue_stop(&ring->sched);
jpeg_v3_0_stop(ring->adev);
jpeg_v3_0_start(ring->adev);
r = amdgpu_ring_test_helper(ring);
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
+ drm_sched_wqueue_start(&ring->sched);
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
index 190f0742d7016..1d4edd77837d0 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
@@ -729,12 +729,14 @@ static int jpeg_v4_0_ring_reset(struct amdgpu_ring *ring,
if (amdgpu_sriov_vf(ring->adev))
return -EINVAL;
+ drm_sched_wqueue_stop(&ring->sched);
jpeg_v4_0_stop(ring->adev);
jpeg_v4_0_start(ring->adev);
r = amdgpu_ring_test_helper(ring);
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
+ drm_sched_wqueue_start(&ring->sched);
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
index 04755b7a62d9b..78441f8fce972 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
@@ -1152,12 +1152,14 @@ static int jpeg_v4_0_3_ring_reset(struct amdgpu_ring *ring,
if (amdgpu_sriov_vf(ring->adev))
return -EOPNOTSUPP;
+ drm_sched_wqueue_stop(&ring->sched);
jpeg_v4_0_3_core_stall_reset(ring);
jpeg_v4_0_3_start_jrbc(ring);
r = amdgpu_ring_test_helper(ring);
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
+ drm_sched_wqueue_start(&ring->sched);
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c
index e7f942dc714a7..6f8a16da9d608 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c
@@ -843,12 +843,14 @@ static int jpeg_v5_0_1_ring_reset(struct amdgpu_ring *ring,
if (amdgpu_sriov_vf(ring->adev))
return -EOPNOTSUPP;
+ drm_sched_wqueue_stop(&ring->sched);
jpeg_v5_0_1_core_stall_reset(ring);
jpeg_v5_0_1_init_jrbc(ring);
r = amdgpu_ring_test_helper(ring);
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
+ drm_sched_wqueue_start(&ring->sched);
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
index 4b6a799704f1f..103e5ec7aa63b 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
@@ -1586,6 +1586,8 @@ static int sdma_v6_0_reset_queue(struct amdgpu_ring *ring,
return -EINVAL;
}
+ drm_sched_wqueue_stop(&ring->sched);
+
r = amdgpu_mes_reset_legacy_queue(adev, ring, vmid, true);
if (r)
return r;
@@ -1594,6 +1596,7 @@ static int sdma_v6_0_reset_queue(struct amdgpu_ring *ring,
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
+ drm_sched_wqueue_start(&ring->sched);
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c
index b00c63812899d..99a080bad2a3d 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c
@@ -822,6 +822,8 @@ static int sdma_v7_0_reset_queue(struct amdgpu_ring *ring,
return -EINVAL;
}
+ drm_sched_wqueue_stop(&ring->sched);
+
r = amdgpu_mes_reset_legacy_queue(adev, ring, vmid, true);
if (r)
return r;
@@ -830,6 +832,7 @@ static int sdma_v7_0_reset_queue(struct amdgpu_ring *ring,
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
+ drm_sched_wqueue_start(&ring->sched);
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
index 6c25e9fc4f0f9..eec9133e1b2c4 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
@@ -1978,6 +1978,7 @@ static int vcn_v4_0_ring_reset(struct amdgpu_ring *ring,
if (!(adev->vcn.supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE))
return -EOPNOTSUPP;
+ drm_sched_wqueue_stop(&ring->sched);
vcn_v4_0_stop(vinst);
vcn_v4_0_start(vinst);
@@ -1985,6 +1986,7 @@ static int vcn_v4_0_ring_reset(struct amdgpu_ring *ring,
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
+ drm_sched_wqueue_start(&ring->sched);
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
index 1e1dd61b774ec..d8fd32c1e38ec 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
@@ -1609,6 +1609,8 @@ static int vcn_v4_0_3_ring_reset(struct amdgpu_ring *ring,
if (!(adev->vcn.supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE))
return -EOPNOTSUPP;
+ drm_sched_wqueue_stop(&ring->sched);
+
vcn_inst = GET_INST(VCN, ring->me);
r = amdgpu_dpm_reset_vcn(adev, 1 << vcn_inst);
@@ -1626,6 +1628,7 @@ static int vcn_v4_0_3_ring_reset(struct amdgpu_ring *ring,
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
+ drm_sched_wqueue_start(&ring->sched);
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
index 9c02446bb1a54..7e37ddea63550 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
@@ -1476,6 +1476,7 @@ static int vcn_v4_0_5_ring_reset(struct amdgpu_ring *ring,
if (!(adev->vcn.supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE))
return -EOPNOTSUPP;
+ drm_sched_wqueue_stop(&ring->sched);
vcn_v4_0_5_stop(vinst);
vcn_v4_0_5_start(vinst);
@@ -1483,6 +1484,7 @@ static int vcn_v4_0_5_ring_reset(struct amdgpu_ring *ring,
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
+ drm_sched_wqueue_start(&ring->sched);
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
index c8924f97cf58a..47c0bcc9e7d80 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
@@ -1203,6 +1203,7 @@ static int vcn_v5_0_0_ring_reset(struct amdgpu_ring *ring,
if (!(adev->vcn.supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE))
return -EOPNOTSUPP;
+ drm_sched_wqueue_stop(&ring->sched);
vcn_v5_0_0_stop(vinst);
vcn_v5_0_0_start(vinst);
@@ -1210,6 +1211,7 @@ static int vcn_v5_0_0_ring_reset(struct amdgpu_ring *ring,
if (r)
return r;
amdgpu_fence_driver_force_completion(ring);
+ drm_sched_wqueue_start(&ring->sched);
return 0;
}
--
2.50.0
^ permalink raw reply related [flat|nested] 35+ messages in thread* Re: [PATCH 06/30] drm/amdgpu: move scheduler wqueue handling into callbacks
2025-06-25 21:06 ` [PATCH 06/30] drm/amdgpu: move scheduler wqueue handling into callbacks Alex Deucher
@ 2025-06-26 9:33 ` Christian König
0 siblings, 0 replies; 35+ messages in thread
From: Christian König @ 2025-06-26 9:33 UTC (permalink / raw)
To: Alex Deucher, amd-gfx, sasundar
On 25.06.25 23:06, Alex Deucher wrote:
> Move the scheduler wqueue stopping and starting into
> the ring reset callbacks. On some IPs we have to reset
> an engine which may have multiple queues. Move the wqueue
> handling into the backend so we can handle them as needed
> based on the type of reset available.
>
> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Reviewed-by: Christian König <christian.koenig@amd.com>
> ---
> drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 8 --------
> drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c | 17 ++++-------------
> drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 6 ++++++
> drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 6 ++++++
> drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c | 6 ++++++
> drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 3 +++
> drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c | 3 +++
> drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c | 2 ++
> drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c | 2 ++
> drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c | 2 ++
> drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c | 2 ++
> drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c | 2 ++
> drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c | 2 ++
> drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c | 3 +++
> drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c | 3 +++
> drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 2 ++
> drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 3 +++
> drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c | 2 ++
> drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c | 2 ++
> 19 files changed, 55 insertions(+), 21 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
> index 3b7d3844a74bc..f0b7080dccb8d 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
> @@ -135,17 +135,9 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
> } else if (amdgpu_gpu_recovery && ring->funcs->reset) {
> dev_err(adev->dev, "Starting %s ring reset\n",
> s_job->sched->name);
> -
> - /*
> - * Stop the scheduler to prevent anybody else from touching the
> - * ring buffer.
> - */
> - drm_sched_wqueue_stop(&ring->sched);
> -
> r = amdgpu_ring_reset(ring, job->vmid, NULL);
> if (!r) {
> atomic_inc(&ring->adev->gpu_reset_counter);
> - drm_sched_wqueue_start(&ring->sched);
> dev_err(adev->dev, "Ring %s reset succeeded\n",
> ring->sched.name);
> drm_dev_wedged_event(adev_to_drm(adev),
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
> index cf5733d5d26dd..7e26a44dcc1fd 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_sdma.c
> @@ -554,22 +554,16 @@ int amdgpu_sdma_reset_engine(struct amdgpu_device *adev, uint32_t instance_id)
> struct amdgpu_sdma_instance *sdma_instance = &adev->sdma.instance[instance_id];
> struct amdgpu_ring *gfx_ring = &sdma_instance->ring;
> struct amdgpu_ring *page_ring = &sdma_instance->page;
> - bool gfx_sched_stopped = false, page_sched_stopped = false;
>
> mutex_lock(&sdma_instance->engine_reset_mutex);
> /* Stop the scheduler's work queue for the GFX and page rings if they are running.
> * This ensures that no new tasks are submitted to the queues while
> * the reset is in progress.
> */
> - if (!amdgpu_ring_sched_ready(gfx_ring)) {
> - drm_sched_wqueue_stop(&gfx_ring->sched);
> - gfx_sched_stopped = true;
> - }
> + drm_sched_wqueue_stop(&gfx_ring->sched);
>
> - if (adev->sdma.has_page_queue && !amdgpu_ring_sched_ready(page_ring)) {
> + if (adev->sdma.has_page_queue)
> drm_sched_wqueue_stop(&page_ring->sched);
> - page_sched_stopped = true;
> - }
>
> if (sdma_instance->funcs->stop_kernel_queue) {
> sdma_instance->funcs->stop_kernel_queue(gfx_ring);
> @@ -596,12 +590,9 @@ 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) {
> - if (gfx_sched_stopped && amdgpu_ring_sched_ready(gfx_ring)) {
> - drm_sched_wqueue_start(&gfx_ring->sched);
> - }
> - if (page_sched_stopped && amdgpu_ring_sched_ready(page_ring)) {
> + drm_sched_wqueue_start(&gfx_ring->sched);
> + if (adev->sdma.has_page_queue)
> drm_sched_wqueue_start(&page_ring->sched);
> - }
> }
> mutex_unlock(&sdma_instance->engine_reset_mutex);
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
> index 4d0ee3ffe9858..8c377ecbb8a75 100644
> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
> @@ -9540,6 +9540,8 @@ static int gfx_v10_0_reset_kgq(struct amdgpu_ring *ring,
> if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
> return -EINVAL;
>
> + drm_sched_wqueue_stop(&ring->sched);
> +
> spin_lock_irqsave(&kiq->ring_lock, flags);
>
> if (amdgpu_ring_alloc(kiq_ring, 5 + 7 + 7 + kiq->pmf->map_queues_size)) {
> @@ -9581,6 +9583,7 @@ static int gfx_v10_0_reset_kgq(struct amdgpu_ring *ring,
> if (r)
> return r;
> amdgpu_fence_driver_force_completion(ring);
> + drm_sched_wqueue_start(&ring->sched);
> return 0;
> }
>
> @@ -9600,6 +9603,8 @@ static int gfx_v10_0_reset_kcq(struct amdgpu_ring *ring,
> if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
> return -EINVAL;
>
> + drm_sched_wqueue_stop(&ring->sched);
> +
> spin_lock_irqsave(&kiq->ring_lock, flags);
>
> if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->unmap_queues_size)) {
> @@ -9658,6 +9663,7 @@ static int gfx_v10_0_reset_kcq(struct amdgpu_ring *ring,
> if (r)
> return r;
> amdgpu_fence_driver_force_completion(ring);
> + drm_sched_wqueue_start(&ring->sched);
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> index 39f4dd18c277b..37dcec2d07841 100644
> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
> @@ -6821,6 +6821,8 @@ static int gfx_v11_0_reset_kgq(struct amdgpu_ring *ring,
> if (amdgpu_sriov_vf(adev))
> return -EINVAL;
>
> + drm_sched_wqueue_stop(&ring->sched);
> +
> r = amdgpu_mes_reset_legacy_queue(ring->adev, ring, vmid, false);
> if (r) {
>
> @@ -6846,6 +6848,7 @@ static int gfx_v11_0_reset_kgq(struct amdgpu_ring *ring,
> if (r)
> return r;
> amdgpu_fence_driver_force_completion(ring);
> + drm_sched_wqueue_start(&ring->sched);
> return 0;
> }
>
> @@ -6989,6 +6992,8 @@ static int gfx_v11_0_reset_kcq(struct amdgpu_ring *ring,
> if (amdgpu_sriov_vf(adev))
> return -EINVAL;
>
> + drm_sched_wqueue_stop(&ring->sched);
> +
> r = amdgpu_mes_reset_legacy_queue(ring->adev, ring, vmid, true);
> if (r) {
> dev_warn(adev->dev, "fail(%d) to reset kcq and try pipe reset\n", r);
> @@ -7012,6 +7017,7 @@ static int gfx_v11_0_reset_kcq(struct amdgpu_ring *ring,
> if (r)
> return r;
> amdgpu_fence_driver_force_completion(ring);
> + drm_sched_wqueue_start(&ring->sched);
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
> index 964fa3f2e2719..e4fc42470cf3e 100644
> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
> @@ -5317,6 +5317,8 @@ static int gfx_v12_0_reset_kgq(struct amdgpu_ring *ring,
> if (amdgpu_sriov_vf(adev))
> return -EINVAL;
>
> + drm_sched_wqueue_stop(&ring->sched);
> +
> r = amdgpu_mes_reset_legacy_queue(ring->adev, ring, vmid, false);
> if (r) {
> dev_warn(adev->dev, "reset via MES failed and try pipe reset %d\n", r);
> @@ -5341,6 +5343,7 @@ static int gfx_v12_0_reset_kgq(struct amdgpu_ring *ring,
> if (r)
> return r;
> amdgpu_fence_driver_force_completion(ring);
> + drm_sched_wqueue_start(&ring->sched);
> return 0;
> }
>
> @@ -5437,6 +5440,8 @@ static int gfx_v12_0_reset_kcq(struct amdgpu_ring *ring,
> if (amdgpu_sriov_vf(adev))
> return -EINVAL;
>
> + drm_sched_wqueue_stop(&ring->sched);
> +
> r = amdgpu_mes_reset_legacy_queue(ring->adev, ring, vmid, true);
> if (r) {
> dev_warn(adev->dev, "fail(%d) to reset kcq and try pipe reset\n", r);
> @@ -5460,6 +5465,7 @@ static int gfx_v12_0_reset_kcq(struct amdgpu_ring *ring,
> if (r)
> return r;
> amdgpu_fence_driver_force_completion(ring);
> + drm_sched_wqueue_start(&ring->sched);
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
> index 95e319974f221..76ba664efecb3 100644
> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
> @@ -7187,6 +7187,8 @@ static int gfx_v9_0_reset_kcq(struct amdgpu_ring *ring,
> if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
> return -EINVAL;
>
> + drm_sched_wqueue_stop(&ring->sched);
> +
> spin_lock_irqsave(&kiq->ring_lock, flags);
>
> if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->unmap_queues_size)) {
> @@ -7247,6 +7249,7 @@ static int gfx_v9_0_reset_kcq(struct amdgpu_ring *ring,
> if (r)
> return r;
> amdgpu_fence_driver_force_completion(ring);
> + drm_sched_wqueue_start(&ring->sched);
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
> index 8bfee17a826e2..daed0f187bda5 100644
> --- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
> +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
> @@ -3567,6 +3567,8 @@ static int gfx_v9_4_3_reset_kcq(struct amdgpu_ring *ring,
> if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
> return -EINVAL;
>
> + drm_sched_wqueue_stop(&ring->sched);
> +
> spin_lock_irqsave(&kiq->ring_lock, flags);
>
> if (amdgpu_ring_alloc(kiq_ring, kiq->pmf->unmap_queues_size)) {
> @@ -3625,6 +3627,7 @@ static int gfx_v9_4_3_reset_kcq(struct amdgpu_ring *ring,
> if (r)
> return r;
> amdgpu_fence_driver_force_completion(ring);
> + drm_sched_wqueue_start(&ring->sched);
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
> index 6621a7b1f29fc..781a5a8a83614 100644
> --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
> @@ -770,12 +770,14 @@ static int jpeg_v2_0_ring_reset(struct amdgpu_ring *ring,
> {
> int r;
>
> + drm_sched_wqueue_stop(&ring->sched);
> jpeg_v2_0_stop(ring->adev);
> jpeg_v2_0_start(ring->adev);
> r = amdgpu_ring_test_helper(ring);
> if (r)
> return r;
> amdgpu_fence_driver_force_completion(ring);
> + drm_sched_wqueue_start(&ring->sched);
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
> index 44a5c0e82ca43..5be9cdcae32c1 100644
> --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
> +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
> @@ -649,12 +649,14 @@ static int jpeg_v2_5_ring_reset(struct amdgpu_ring *ring,
> {
> int r;
>
> + drm_sched_wqueue_stop(&ring->sched);
> jpeg_v2_5_stop_inst(ring->adev, ring->me);
> jpeg_v2_5_start_inst(ring->adev, ring->me);
> r = amdgpu_ring_test_helper(ring);
> if (r)
> return r;
> amdgpu_fence_driver_force_completion(ring);
> + drm_sched_wqueue_start(&ring->sched);
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
> index e813af4eedd21..a24bd833d6442 100644
> --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
> @@ -561,12 +561,14 @@ static int jpeg_v3_0_ring_reset(struct amdgpu_ring *ring,
> {
> int r;
>
> + drm_sched_wqueue_stop(&ring->sched);
> jpeg_v3_0_stop(ring->adev);
> jpeg_v3_0_start(ring->adev);
> r = amdgpu_ring_test_helper(ring);
> if (r)
> return r;
> amdgpu_fence_driver_force_completion(ring);
> + drm_sched_wqueue_start(&ring->sched);
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
> index 190f0742d7016..1d4edd77837d0 100644
> --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
> @@ -729,12 +729,14 @@ static int jpeg_v4_0_ring_reset(struct amdgpu_ring *ring,
> if (amdgpu_sriov_vf(ring->adev))
> return -EINVAL;
>
> + drm_sched_wqueue_stop(&ring->sched);
> jpeg_v4_0_stop(ring->adev);
> jpeg_v4_0_start(ring->adev);
> r = amdgpu_ring_test_helper(ring);
> if (r)
> return r;
> amdgpu_fence_driver_force_completion(ring);
> + drm_sched_wqueue_start(&ring->sched);
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
> index 04755b7a62d9b..78441f8fce972 100644
> --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
> +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
> @@ -1152,12 +1152,14 @@ static int jpeg_v4_0_3_ring_reset(struct amdgpu_ring *ring,
> if (amdgpu_sriov_vf(ring->adev))
> return -EOPNOTSUPP;
>
> + drm_sched_wqueue_stop(&ring->sched);
> jpeg_v4_0_3_core_stall_reset(ring);
> jpeg_v4_0_3_start_jrbc(ring);
> r = amdgpu_ring_test_helper(ring);
> if (r)
> return r;
> amdgpu_fence_driver_force_completion(ring);
> + drm_sched_wqueue_start(&ring->sched);
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c
> index e7f942dc714a7..6f8a16da9d608 100644
> --- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c
> +++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c
> @@ -843,12 +843,14 @@ static int jpeg_v5_0_1_ring_reset(struct amdgpu_ring *ring,
> if (amdgpu_sriov_vf(ring->adev))
> return -EOPNOTSUPP;
>
> + drm_sched_wqueue_stop(&ring->sched);
> jpeg_v5_0_1_core_stall_reset(ring);
> jpeg_v5_0_1_init_jrbc(ring);
> r = amdgpu_ring_test_helper(ring);
> if (r)
> return r;
> amdgpu_fence_driver_force_completion(ring);
> + drm_sched_wqueue_start(&ring->sched);
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
> index 4b6a799704f1f..103e5ec7aa63b 100644
> --- a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
> @@ -1586,6 +1586,8 @@ static int sdma_v6_0_reset_queue(struct amdgpu_ring *ring,
> return -EINVAL;
> }
>
> + drm_sched_wqueue_stop(&ring->sched);
> +
> r = amdgpu_mes_reset_legacy_queue(adev, ring, vmid, true);
> if (r)
> return r;
> @@ -1594,6 +1596,7 @@ static int sdma_v6_0_reset_queue(struct amdgpu_ring *ring,
> if (r)
> return r;
> amdgpu_fence_driver_force_completion(ring);
> + drm_sched_wqueue_start(&ring->sched);
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c
> index b00c63812899d..99a080bad2a3d 100644
> --- a/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c
> @@ -822,6 +822,8 @@ static int sdma_v7_0_reset_queue(struct amdgpu_ring *ring,
> return -EINVAL;
> }
>
> + drm_sched_wqueue_stop(&ring->sched);
> +
> r = amdgpu_mes_reset_legacy_queue(adev, ring, vmid, true);
> if (r)
> return r;
> @@ -830,6 +832,7 @@ static int sdma_v7_0_reset_queue(struct amdgpu_ring *ring,
> if (r)
> return r;
> amdgpu_fence_driver_force_completion(ring);
> + drm_sched_wqueue_start(&ring->sched);
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> index 6c25e9fc4f0f9..eec9133e1b2c4 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
> @@ -1978,6 +1978,7 @@ static int vcn_v4_0_ring_reset(struct amdgpu_ring *ring,
> if (!(adev->vcn.supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE))
> return -EOPNOTSUPP;
>
> + drm_sched_wqueue_stop(&ring->sched);
> vcn_v4_0_stop(vinst);
> vcn_v4_0_start(vinst);
>
> @@ -1985,6 +1986,7 @@ static int vcn_v4_0_ring_reset(struct amdgpu_ring *ring,
> if (r)
> return r;
> amdgpu_fence_driver_force_completion(ring);
> + drm_sched_wqueue_start(&ring->sched);
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> index 1e1dd61b774ec..d8fd32c1e38ec 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
> @@ -1609,6 +1609,8 @@ static int vcn_v4_0_3_ring_reset(struct amdgpu_ring *ring,
> if (!(adev->vcn.supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE))
> return -EOPNOTSUPP;
>
> + drm_sched_wqueue_stop(&ring->sched);
> +
> vcn_inst = GET_INST(VCN, ring->me);
> r = amdgpu_dpm_reset_vcn(adev, 1 << vcn_inst);
>
> @@ -1626,6 +1628,7 @@ static int vcn_v4_0_3_ring_reset(struct amdgpu_ring *ring,
> if (r)
> return r;
> amdgpu_fence_driver_force_completion(ring);
> + drm_sched_wqueue_start(&ring->sched);
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> index 9c02446bb1a54..7e37ddea63550 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
> @@ -1476,6 +1476,7 @@ static int vcn_v4_0_5_ring_reset(struct amdgpu_ring *ring,
> if (!(adev->vcn.supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE))
> return -EOPNOTSUPP;
>
> + drm_sched_wqueue_stop(&ring->sched);
> vcn_v4_0_5_stop(vinst);
> vcn_v4_0_5_start(vinst);
>
> @@ -1483,6 +1484,7 @@ static int vcn_v4_0_5_ring_reset(struct amdgpu_ring *ring,
> if (r)
> return r;
> amdgpu_fence_driver_force_completion(ring);
> + drm_sched_wqueue_start(&ring->sched);
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> index c8924f97cf58a..47c0bcc9e7d80 100644
> --- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> +++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
> @@ -1203,6 +1203,7 @@ static int vcn_v5_0_0_ring_reset(struct amdgpu_ring *ring,
> if (!(adev->vcn.supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE))
> return -EOPNOTSUPP;
>
> + drm_sched_wqueue_stop(&ring->sched);
> vcn_v5_0_0_stop(vinst);
> vcn_v5_0_0_start(vinst);
>
> @@ -1210,6 +1211,7 @@ static int vcn_v5_0_0_ring_reset(struct amdgpu_ring *ring,
> if (r)
> return r;
> amdgpu_fence_driver_force_completion(ring);
> + drm_sched_wqueue_start(&ring->sched);
> return 0;
> }
>
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 07/30] drm/amdgpu: track ring state associated with a fence
2025-06-25 21:06 [PATCH V11 00/30] Reset improvements Alex Deucher
` (5 preceding siblings ...)
2025-06-25 21:06 ` [PATCH 06/30] drm/amdgpu: move scheduler wqueue handling into callbacks Alex Deucher
@ 2025-06-25 21:06 ` Alex Deucher
2025-06-26 11:02 ` Christian König
2025-06-25 21:06 ` [PATCH 08/30] drm/amdgpu/gfx9: re-emit unprocessed state on kcq reset Alex Deucher
` (22 subsequent siblings)
29 siblings, 1 reply; 35+ messages in thread
From: Alex Deucher @ 2025-06-25 21:06 UTC (permalink / raw)
To: amd-gfx, christian.koenig, sasundar; +Cc: Alex Deucher
We need to know the wptr and sequence number associated
with a fence so that we can re-emit the unprocessed state
after a ring reset. Pre-allocate storage space for
the ring buffer contents and add helpers to save off
and re-emit the unprocessed state so that it can be
re-emitted after the queue is reset.
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c | 99 +++++++++++++++++++++++
drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 15 +++-
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 4 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 59 ++++++++++++++
drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 17 ++++
5 files changed, 191 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
index 2d6b2b486baf7..db14bdc7053ca 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
@@ -120,11 +120,13 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f,
am_fence = kzalloc(sizeof(*am_fence), GFP_KERNEL);
if (!am_fence)
return -ENOMEM;
+ am_fence->context = 0;
} else {
am_fence = af;
}
fence = &am_fence->base;
am_fence->ring = ring;
+ am_fence->wptr = 0;
seq = ++ring->fence_drv.sync_seq;
if (af) {
@@ -253,6 +255,7 @@ bool amdgpu_fence_process(struct amdgpu_ring *ring)
do {
struct dma_fence *fence, **ptr;
+ struct amdgpu_fence *am_fence;
++last_seq;
last_seq &= drv->num_fences_mask;
@@ -265,6 +268,13 @@ bool amdgpu_fence_process(struct amdgpu_ring *ring)
if (!fence)
continue;
+ /* Save the wptr in the fence driver so we know what the last processed
+ * wptr was. This is required for re-emitting the ring state for
+ * queues that are reset but are not guilty and thus have no guilty fence.
+ */
+ am_fence = container_of(fence, struct amdgpu_fence, base);
+ if (am_fence->wptr)
+ drv->last_wptr = am_fence->wptr;
dma_fence_signal(fence);
dma_fence_put(fence);
pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
@@ -727,6 +737,95 @@ void amdgpu_fence_driver_force_completion(struct amdgpu_ring *ring)
amdgpu_fence_process(ring);
}
+
+/**
+ * Kernel queue reset handling
+ *
+ * The driver can reset individual queues for most engines, but those queues
+ * may contain work from multiple contexts. Resetting the queue will reset
+ * lose all of that state. In order to minimize the collatoral damage, the
+ * driver will save the ring contents which are not associated with the guilty
+ * context prior to resetting the queue. After resetting the queue the queue
+ * contents from the other contexts is re-emitted to the rings so that it can
+ * be processed by the engine. To handle this, we save the queue's write
+ * pointer (wptr) in the fences associated with each context. If we get a
+ * queue timeout, we can then use the wptrs from the fences to determine
+ * which data needs to be saved out of the queue's ring buffer.
+ */
+
+/**
+ * amdgpu_fence_driver_guilty_force_completion - force signal of specified sequence
+ *
+ * @fence: fence of the ring to signal
+ *
+ */
+void amdgpu_fence_driver_guilty_force_completion(struct amdgpu_fence *fence)
+{
+ dma_fence_set_error(&fence->base, -ETIME);
+ amdgpu_fence_write(fence->ring, fence->base.seqno);
+ amdgpu_fence_process(fence->ring);
+}
+
+void amdgpu_fence_save_wptr(struct dma_fence *fence)
+{
+ struct amdgpu_fence *am_fence = container_of(fence, struct amdgpu_fence, base);
+
+ am_fence->wptr = am_fence->ring->wptr;
+}
+
+static void amdgpu_ring_backup_unprocessed_command(struct amdgpu_ring *ring,
+ unsigned int idx,
+ u64 start_wptr, u32 end_wptr)
+{
+ unsigned int first_idx = start_wptr & ring->buf_mask;
+ unsigned int last_idx = end_wptr & ring->buf_mask;
+ unsigned int i, count;
+
+ /* Backup the contents of the ring buffer. */
+ for (i = first_idx, count = 0; i != last_idx; ++i, i &= ring->buf_mask, ++count)
+ ring->ring_backup[count] = ring->ring[i];
+ ring->ring_backup_entries_to_copy = count;
+}
+
+void amdgpu_ring_backup_unprocessed_commands(struct amdgpu_ring *ring,
+ struct amdgpu_fence *guilty_fence)
+{
+ struct amdgpu_fence *fence;
+ struct dma_fence *unprocessed, **ptr;
+ u64 wptr, i, seqno;
+
+ if (guilty_fence) {
+ seqno = guilty_fence->base.seqno;
+ wptr = guilty_fence->wptr;
+ } else {
+ seqno = amdgpu_fence_read(ring);
+ wptr = ring->fence_drv.last_wptr;
+ }
+ ring->ring_backup_entries_to_copy = 0;
+ for (i = seqno + 1; i <= ring->fence_drv.sync_seq; ++i) {
+ ptr = &ring->fence_drv.fences[i & ring->fence_drv.num_fences_mask];
+ rcu_read_lock();
+ unprocessed = rcu_dereference(*ptr);
+
+ if (unprocessed && !dma_fence_is_signaled(unprocessed)) {
+ fence = container_of(unprocessed, struct amdgpu_fence, base);
+
+ /* save everything if the ring is not guilty, otherwise
+ * just save the content from other contexts.
+ */
+ if (fence->wptr &&
+ (!guilty_fence || (fence->context != guilty_fence->context))) {
+ amdgpu_ring_backup_unprocessed_command(ring,
+ ring->ring_backup_entries_to_copy,
+ wptr,
+ fence->wptr);
+ wptr = fence->wptr;
+ }
+ }
+ rcu_read_unlock();
+ }
+}
+
/*
* Common fence implementation
*/
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
index 206b70acb29a0..d0f838fde2ae5 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
@@ -139,7 +139,6 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
int vmid = AMDGPU_JOB_GET_VMID(job);
bool need_pipe_sync = false;
unsigned int cond_exec;
-
unsigned int i;
int r = 0;
@@ -156,6 +155,11 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
gds_va = job->gds_va;
init_shadow = job->init_shadow;
af = &job->hw_fence;
+ /* Save the context of the job for reset handling.
+ * The driver needs this so it can skip the ring
+ * contents for guilty contexts.
+ */
+ af->context = job->base.s_fence ? job->base.s_fence->finished.context : 0;
} else {
vm = NULL;
fence_ctx = 0;
@@ -309,6 +313,15 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
amdgpu_ring_ib_end(ring);
amdgpu_ring_commit(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
+ * fence so we know what rings contents to backup
+ * after we reset the queue.
+ */
+ amdgpu_fence_save_wptr(*f);
+
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
index f0b7080dccb8d..45febdc2f3493 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
@@ -89,8 +89,8 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
{
struct amdgpu_ring *ring = to_amdgpu_ring(s_job->sched);
struct amdgpu_job *job = to_amdgpu_job(s_job);
- struct amdgpu_task_info *ti;
struct amdgpu_device *adev = ring->adev;
+ struct amdgpu_task_info *ti;
int idx, r;
if (!drm_dev_enter(adev_to_drm(adev), &idx)) {
@@ -135,7 +135,7 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
} else if (amdgpu_gpu_recovery && ring->funcs->reset) {
dev_err(adev->dev, "Starting %s ring reset\n",
s_job->sched->name);
- r = amdgpu_ring_reset(ring, job->vmid, NULL);
+ r = amdgpu_ring_reset(ring, job->vmid, &job->hw_fence);
if (!r) {
atomic_inc(&ring->adev->gpu_reset_counter);
dev_err(adev->dev, "Ring %s reset succeeded\n",
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
index 426834806fbf2..0985eba010e17 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
@@ -333,6 +333,12 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
/* Initialize cached_rptr to 0 */
ring->cached_rptr = 0;
+ if (!ring->ring_backup) {
+ ring->ring_backup = kvzalloc(ring->ring_size, GFP_KERNEL);
+ if (!ring->ring_backup)
+ return -ENOMEM;
+ }
+
/* Allocate ring buffer */
if (ring->ring_obj == NULL) {
r = amdgpu_bo_create_kernel(adev, ring->ring_size + ring->funcs->extra_dw, PAGE_SIZE,
@@ -342,6 +348,7 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
(void **)&ring->ring);
if (r) {
dev_err(adev->dev, "(%d) ring create failed\n", r);
+ kvfree(ring->ring_backup);
return r;
}
amdgpu_ring_clear_ring(ring);
@@ -385,6 +392,8 @@ void amdgpu_ring_fini(struct amdgpu_ring *ring)
amdgpu_bo_free_kernel(&ring->ring_obj,
&ring->gpu_addr,
(void **)&ring->ring);
+ kvfree(ring->ring_backup);
+ ring->ring_backup = NULL;
dma_fence_put(ring->vmid_wait);
ring->vmid_wait = NULL;
@@ -753,3 +762,53 @@ bool amdgpu_ring_sched_ready(struct amdgpu_ring *ring)
return true;
}
+
+static int amdgpu_ring_reemit_unprocessed_commands(struct amdgpu_ring *ring)
+{
+ unsigned int i;
+ int r;
+
+ /* re-emit the unprocessed ring contents */
+ if (ring->ring_backup_entries_to_copy) {
+ r = amdgpu_ring_alloc(ring, ring->ring_backup_entries_to_copy);
+ if (r)
+ return r;
+ for (i = 0; i < ring->ring_backup_entries_to_copy; i++)
+ amdgpu_ring_write(ring, ring->ring_backup[i]);
+ amdgpu_ring_commit(ring);
+ }
+
+ return 0;
+}
+
+void amdgpu_ring_reset_helper_begin(struct amdgpu_ring *ring,
+ struct amdgpu_fence *guilty_fence)
+{
+ /* Stop the scheduler to prevent anybody else from touching the ring buffer. */
+ drm_sched_wqueue_stop(&ring->sched);
+ /* back up the non-guilty commands */
+ amdgpu_ring_backup_unprocessed_commands(ring, guilty_fence);
+}
+
+int amdgpu_ring_reset_helper_end(struct amdgpu_ring *ring,
+ struct amdgpu_fence *guilty_fence)
+{
+ int r;
+
+ /* verify that the ring is functional */
+ r = amdgpu_ring_test_ring(ring);
+ if (r)
+ return r;
+
+ /* signal the fence of the bad job */
+ if (guilty_fence)
+ amdgpu_fence_driver_guilty_force_completion(guilty_fence);
+ /* Re-emit the non-guilty commands */
+ r = amdgpu_ring_reemit_unprocessed_commands(ring);
+ if (r)
+ /* if we fail to reemit, force complete all fences */
+ amdgpu_fence_driver_force_completion(ring);
+ /* Start the scheduler again */
+ drm_sched_wqueue_start(&ring->sched);
+ return 0;
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
index 784ba2ec354c7..2b5546d15a6be 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
@@ -118,6 +118,7 @@ struct amdgpu_fence_driver {
/* sync_seq is protected by ring emission lock */
uint32_t sync_seq;
atomic_t last_seq;
+ u64 last_wptr;
bool initialized;
struct amdgpu_irq_src *irq_src;
unsigned irq_type;
@@ -141,6 +142,11 @@ struct amdgpu_fence {
/* RB, DMA, etc. */
struct amdgpu_ring *ring;
ktime_t start_timestamp;
+
+ /* wptr for the fence for resets */
+ u64 wptr;
+ /* fence context for resets */
+ u64 context;
};
extern const struct drm_sched_backend_ops amdgpu_sched_ops;
@@ -148,6 +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_guilty_force_completion(struct amdgpu_fence *fence);
+void amdgpu_fence_save_wptr(struct dma_fence *fence);
int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring);
int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring,
@@ -284,6 +292,9 @@ struct amdgpu_ring {
struct amdgpu_bo *ring_obj;
uint32_t *ring;
+ /* backups for resets */
+ uint32_t *ring_backup;
+ unsigned int ring_backup_entries_to_copy;
unsigned rptr_offs;
u64 rptr_gpu_addr;
volatile u32 *rptr_cpu_addr;
@@ -550,4 +561,10 @@ int amdgpu_ib_pool_init(struct amdgpu_device *adev);
void amdgpu_ib_pool_fini(struct amdgpu_device *adev);
int amdgpu_ib_ring_tests(struct amdgpu_device *adev);
bool amdgpu_ring_sched_ready(struct amdgpu_ring *ring);
+void amdgpu_ring_backup_unprocessed_commands(struct amdgpu_ring *ring,
+ struct amdgpu_fence *guilty_fence);
+void amdgpu_ring_reset_helper_begin(struct amdgpu_ring *ring,
+ struct amdgpu_fence *guilty_fence);
+int amdgpu_ring_reset_helper_end(struct amdgpu_ring *ring,
+ struct amdgpu_fence *guilty_fence);
#endif
--
2.50.0
^ permalink raw reply related [flat|nested] 35+ messages in thread* Re: [PATCH 07/30] drm/amdgpu: track ring state associated with a fence
2025-06-25 21:06 ` [PATCH 07/30] drm/amdgpu: track ring state associated with a fence Alex Deucher
@ 2025-06-26 11:02 ` Christian König
2025-06-26 17:25 ` Alex Deucher
0 siblings, 1 reply; 35+ messages in thread
From: Christian König @ 2025-06-26 11:02 UTC (permalink / raw)
To: Alex Deucher, amd-gfx, sasundar
On 25.06.25 23:06, Alex Deucher wrote:
> We need to know the wptr and sequence number associated
> with a fence so that we can re-emit the unprocessed state
> after a ring reset. Pre-allocate storage space for
> the ring buffer contents and add helpers to save off
> and re-emit the unprocessed state so that it can be
> re-emitted after the queue is reset.
>
> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
> ---
> drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c | 99 +++++++++++++++++++++++
> drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 15 +++-
> drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 4 +-
> drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 59 ++++++++++++++
> drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 17 ++++
> 5 files changed, 191 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
> index 2d6b2b486baf7..db14bdc7053ca 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
> @@ -120,11 +120,13 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f,
> am_fence = kzalloc(sizeof(*am_fence), GFP_KERNEL);
> if (!am_fence)
> return -ENOMEM;
> + am_fence->context = 0;
> } else {
> am_fence = af;
> }
> fence = &am_fence->base;
> am_fence->ring = ring;
> + am_fence->wptr = 0;
>
> seq = ++ring->fence_drv.sync_seq;
> if (af) {
> @@ -253,6 +255,7 @@ bool amdgpu_fence_process(struct amdgpu_ring *ring)
>
> do {
> struct dma_fence *fence, **ptr;
> + struct amdgpu_fence *am_fence;
>
> ++last_seq;
> last_seq &= drv->num_fences_mask;
> @@ -265,6 +268,13 @@ bool amdgpu_fence_process(struct amdgpu_ring *ring)
> if (!fence)
> continue;
>
> + /* Save the wptr in the fence driver so we know what the last processed
> + * wptr was. This is required for re-emitting the ring state for
> + * queues that are reset but are not guilty and thus have no guilty fence.
> + */
> + am_fence = container_of(fence, struct amdgpu_fence, base);
> + if (am_fence->wptr)
> + drv->last_wptr = am_fence->wptr;
That looks fishy. We don't need the last wptr, but the first processed one.
> dma_fence_signal(fence);
> dma_fence_put(fence);
> pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
> @@ -727,6 +737,95 @@ void amdgpu_fence_driver_force_completion(struct amdgpu_ring *ring)
> amdgpu_fence_process(ring);
> }
>
> +
> +/**
> + * Kernel queue reset handling
> + *
> + * The driver can reset individual queues for most engines, but those queues
> + * may contain work from multiple contexts. Resetting the queue will reset
> + * lose all of that state. In order to minimize the collatoral damage, the
Typo "collateral".
> + * driver will save the ring contents which are not associated with the guilty
> + * context prior to resetting the queue. After resetting the queue the queue
> + * contents from the other contexts is re-emitted to the rings so that it can
> + * be processed by the engine. To handle this, we save the queue's write
> + * pointer (wptr) in the fences associated with each context. If we get a
> + * queue timeout, we can then use the wptrs from the fences to determine
> + * which data needs to be saved out of the queue's ring buffer.
> + */
> +
> +/**
> + * amdgpu_fence_driver_guilty_force_completion - force signal of specified sequence
> + *
> + * @fence: fence of the ring to signal
> + *
> + */
> +void amdgpu_fence_driver_guilty_force_completion(struct amdgpu_fence *fence)
> +{
> + dma_fence_set_error(&fence->base, -ETIME);
> + amdgpu_fence_write(fence->ring, fence->base.seqno);
> + amdgpu_fence_process(fence->ring);
> +}
> +
> +void amdgpu_fence_save_wptr(struct dma_fence *fence)
> +{
> + struct amdgpu_fence *am_fence = container_of(fence, struct amdgpu_fence, base);
> +
> + am_fence->wptr = am_fence->ring->wptr;
> +}
> +
> +static void amdgpu_ring_backup_unprocessed_command(struct amdgpu_ring *ring,
> + unsigned int idx,
idx is unused.
> + u64 start_wptr, u32 end_wptr)
> +{
> + unsigned int first_idx = start_wptr & ring->buf_mask;
> + unsigned int last_idx = end_wptr & ring->buf_mask;
> + unsigned int i, count;
> +
> + /* Backup the contents of the ring buffer. */
> + for (i = first_idx, count = 0; i != last_idx; ++i, i &= ring->buf_mask, ++count)
count should start at ring->ring_backup_entries_to_copy.
> + ring->ring_backup[count] = ring->ring[i];
> + ring->ring_backup_entries_to_copy = count;
> +}
> +
> +void amdgpu_ring_backup_unprocessed_commands(struct amdgpu_ring *ring,
> + struct amdgpu_fence *guilty_fence)
> +{
> + struct amdgpu_fence *fence;
> + struct dma_fence *unprocessed, **ptr;
ptr need an __rcu annotation or otherwise the automated tools will start complaining.
> + u64 wptr, i, seqno;
> +
> + if (guilty_fence) {
> + seqno = guilty_fence->base.seqno;
> + wptr = guilty_fence->wptr;
I think we can just always go over the whole ring buffer here. E.g. dropping this if branch.
> + } else {
> + seqno = amdgpu_fence_read(ring);
> + wptr = ring->fence_drv.last_wptr;
Again that looks fishy. We shouldn't start at the last wptr, but the first.
> + }
> + ring->ring_backup_entries_to_copy = 0;
> + for (i = seqno + 1; i <= ring->fence_drv.sync_seq; ++i) {
> + ptr = &ring->fence_drv.fences[i & ring->fence_drv.num_fences_mask];
> + rcu_read_lock();
> + unprocessed = rcu_dereference(*ptr);
> +
> + if (unprocessed && !dma_fence_is_signaled(unprocessed)) {
> + fence = container_of(unprocessed, struct amdgpu_fence, base);
We should probably make ring->fence_drv.fences an array of amdgpu_fences.
> +
> + /* save everything if the ring is not guilty, otherwise
> + * just save the content from other contexts.
> + */
> + if (fence->wptr &&
> + (!guilty_fence || (fence->context != guilty_fence->context))) {
> + amdgpu_ring_backup_unprocessed_command(ring,
> + ring->ring_backup_entries_to_copy,
> + wptr,
> + fence->wptr);
> + wptr = fence->wptr;
Wptr also needs to be updated for already signaled fences and fences which are skipped because they belong to the guilty context.
Christian.
> + }
> + }
> + rcu_read_unlock();
> + }
> +}
> +
> /*
> * Common fence implementation
> */
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
> index 206b70acb29a0..d0f838fde2ae5 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
> @@ -139,7 +139,6 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
> int vmid = AMDGPU_JOB_GET_VMID(job);
> bool need_pipe_sync = false;
> unsigned int cond_exec;
> -
> unsigned int i;
> int r = 0;
>
> @@ -156,6 +155,11 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
> gds_va = job->gds_va;
> init_shadow = job->init_shadow;
> af = &job->hw_fence;
> + /* Save the context of the job for reset handling.
> + * The driver needs this so it can skip the ring
> + * contents for guilty contexts.
> + */
> + af->context = job->base.s_fence ? job->base.s_fence->finished.context : 0;
> } else {
> vm = NULL;
> fence_ctx = 0;
> @@ -309,6 +313,15 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
>
> amdgpu_ring_ib_end(ring);
> amdgpu_ring_commit(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
> + * fence so we know what rings contents to backup
> + * after we reset the queue.
> + */
> + amdgpu_fence_save_wptr(*f);
> +
> return 0;
> }
>
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
> index f0b7080dccb8d..45febdc2f3493 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
> @@ -89,8 +89,8 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
> {
> struct amdgpu_ring *ring = to_amdgpu_ring(s_job->sched);
> struct amdgpu_job *job = to_amdgpu_job(s_job);
> - struct amdgpu_task_info *ti;
> struct amdgpu_device *adev = ring->adev;
> + struct amdgpu_task_info *ti;
> int idx, r;
>
> if (!drm_dev_enter(adev_to_drm(adev), &idx)) {
> @@ -135,7 +135,7 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
> } else if (amdgpu_gpu_recovery && ring->funcs->reset) {
> dev_err(adev->dev, "Starting %s ring reset\n",
> s_job->sched->name);
> - r = amdgpu_ring_reset(ring, job->vmid, NULL);
> + r = amdgpu_ring_reset(ring, job->vmid, &job->hw_fence);
> if (!r) {
> atomic_inc(&ring->adev->gpu_reset_counter);
> dev_err(adev->dev, "Ring %s reset succeeded\n",
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
> index 426834806fbf2..0985eba010e17 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
> @@ -333,6 +333,12 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
> /* Initialize cached_rptr to 0 */
> ring->cached_rptr = 0;
>
> + if (!ring->ring_backup) {
> + ring->ring_backup = kvzalloc(ring->ring_size, GFP_KERNEL);
> + if (!ring->ring_backup)
> + return -ENOMEM;
> + }
> +
> /* Allocate ring buffer */
> if (ring->ring_obj == NULL) {
> r = amdgpu_bo_create_kernel(adev, ring->ring_size + ring->funcs->extra_dw, PAGE_SIZE,
> @@ -342,6 +348,7 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
> (void **)&ring->ring);
> if (r) {
> dev_err(adev->dev, "(%d) ring create failed\n", r);
> + kvfree(ring->ring_backup);
> return r;
> }
> amdgpu_ring_clear_ring(ring);
> @@ -385,6 +392,8 @@ void amdgpu_ring_fini(struct amdgpu_ring *ring)
> amdgpu_bo_free_kernel(&ring->ring_obj,
> &ring->gpu_addr,
> (void **)&ring->ring);
> + kvfree(ring->ring_backup);
> + ring->ring_backup = NULL;
>
> dma_fence_put(ring->vmid_wait);
> ring->vmid_wait = NULL;
> @@ -753,3 +762,53 @@ bool amdgpu_ring_sched_ready(struct amdgpu_ring *ring)
>
> return true;
> }
> +
> +static int amdgpu_ring_reemit_unprocessed_commands(struct amdgpu_ring *ring)
> +{
> + unsigned int i;
> + int r;
> +
> + /* re-emit the unprocessed ring contents */
> + if (ring->ring_backup_entries_to_copy) {
> + r = amdgpu_ring_alloc(ring, ring->ring_backup_entries_to_copy);
> + if (r)
> + return r;
> + for (i = 0; i < ring->ring_backup_entries_to_copy; i++)
> + amdgpu_ring_write(ring, ring->ring_backup[i]);
> + amdgpu_ring_commit(ring);
> + }
> +
> + return 0;
> +}
> +
> +void amdgpu_ring_reset_helper_begin(struct amdgpu_ring *ring,
> + struct amdgpu_fence *guilty_fence)
> +{
> + /* Stop the scheduler to prevent anybody else from touching the ring buffer. */
> + drm_sched_wqueue_stop(&ring->sched);
> + /* back up the non-guilty commands */
> + amdgpu_ring_backup_unprocessed_commands(ring, guilty_fence);
> +}
> +
> +int amdgpu_ring_reset_helper_end(struct amdgpu_ring *ring,
> + struct amdgpu_fence *guilty_fence)
> +{
> + int r;
> +
> + /* verify that the ring is functional */
> + r = amdgpu_ring_test_ring(ring);
> + if (r)
> + return r;
> +
> + /* signal the fence of the bad job */
> + if (guilty_fence)
> + amdgpu_fence_driver_guilty_force_completion(guilty_fence);
> + /* Re-emit the non-guilty commands */
> + r = amdgpu_ring_reemit_unprocessed_commands(ring);
> + if (r)
> + /* if we fail to reemit, force complete all fences */
> + amdgpu_fence_driver_force_completion(ring);
> + /* Start the scheduler again */
> + drm_sched_wqueue_start(&ring->sched);
> + return 0;
> +}
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
> index 784ba2ec354c7..2b5546d15a6be 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
> @@ -118,6 +118,7 @@ struct amdgpu_fence_driver {
> /* sync_seq is protected by ring emission lock */
> uint32_t sync_seq;
> atomic_t last_seq;
> + u64 last_wptr;
> bool initialized;
> struct amdgpu_irq_src *irq_src;
> unsigned irq_type;
> @@ -141,6 +142,11 @@ struct amdgpu_fence {
> /* RB, DMA, etc. */
> struct amdgpu_ring *ring;
> ktime_t start_timestamp;
> +
> + /* wptr for the fence for resets */
> + u64 wptr;
> + /* fence context for resets */
> + u64 context;
> };
>
> extern const struct drm_sched_backend_ops amdgpu_sched_ops;
> @@ -148,6 +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_guilty_force_completion(struct amdgpu_fence *fence);
> +void amdgpu_fence_save_wptr(struct dma_fence *fence);
>
> int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring);
> int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring,
> @@ -284,6 +292,9 @@ struct amdgpu_ring {
>
> struct amdgpu_bo *ring_obj;
> uint32_t *ring;
> + /* backups for resets */
> + uint32_t *ring_backup;
> + unsigned int ring_backup_entries_to_copy;
> unsigned rptr_offs;
> u64 rptr_gpu_addr;
> volatile u32 *rptr_cpu_addr;
> @@ -550,4 +561,10 @@ int amdgpu_ib_pool_init(struct amdgpu_device *adev);
> void amdgpu_ib_pool_fini(struct amdgpu_device *adev);
> int amdgpu_ib_ring_tests(struct amdgpu_device *adev);
> bool amdgpu_ring_sched_ready(struct amdgpu_ring *ring);
> +void amdgpu_ring_backup_unprocessed_commands(struct amdgpu_ring *ring,
> + struct amdgpu_fence *guilty_fence);
> +void amdgpu_ring_reset_helper_begin(struct amdgpu_ring *ring,
> + struct amdgpu_fence *guilty_fence);
> +int amdgpu_ring_reset_helper_end(struct amdgpu_ring *ring,
> + struct amdgpu_fence *guilty_fence);
> #endif
^ permalink raw reply [flat|nested] 35+ messages in thread* Re: [PATCH 07/30] drm/amdgpu: track ring state associated with a fence
2025-06-26 11:02 ` Christian König
@ 2025-06-26 17:25 ` Alex Deucher
0 siblings, 0 replies; 35+ messages in thread
From: Alex Deucher @ 2025-06-26 17:25 UTC (permalink / raw)
To: Christian König; +Cc: Alex Deucher, amd-gfx, sasundar
On Thu, Jun 26, 2025 at 7:03 AM Christian König
<christian.koenig@amd.com> wrote:
>
>
>
> On 25.06.25 23:06, Alex Deucher wrote:
> > We need to know the wptr and sequence number associated
> > with a fence so that we can re-emit the unprocessed state
> > after a ring reset. Pre-allocate storage space for
> > the ring buffer contents and add helpers to save off
> > and re-emit the unprocessed state so that it can be
> > re-emitted after the queue is reset.
> >
> > Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
> > ---
> > drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c | 99 +++++++++++++++++++++++
> > drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c | 15 +++-
> > drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 4 +-
> > drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c | 59 ++++++++++++++
> > drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h | 17 ++++
> > 5 files changed, 191 insertions(+), 3 deletions(-)
> >
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
> > index 2d6b2b486baf7..db14bdc7053ca 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fence.c
> > @@ -120,11 +120,13 @@ int amdgpu_fence_emit(struct amdgpu_ring *ring, struct dma_fence **f,
> > am_fence = kzalloc(sizeof(*am_fence), GFP_KERNEL);
> > if (!am_fence)
> > return -ENOMEM;
> > + am_fence->context = 0;
> > } else {
> > am_fence = af;
> > }
> > fence = &am_fence->base;
> > am_fence->ring = ring;
> > + am_fence->wptr = 0;
> >
> > seq = ++ring->fence_drv.sync_seq;
> > if (af) {
> > @@ -253,6 +255,7 @@ bool amdgpu_fence_process(struct amdgpu_ring *ring)
> >
> > do {
> > struct dma_fence *fence, **ptr;
> > + struct amdgpu_fence *am_fence;
> >
> > ++last_seq;
> > last_seq &= drv->num_fences_mask;
> > @@ -265,6 +268,13 @@ bool amdgpu_fence_process(struct amdgpu_ring *ring)
> > if (!fence)
> > continue;
> >
> > + /* Save the wptr in the fence driver so we know what the last processed
> > + * wptr was. This is required for re-emitting the ring state for
> > + * queues that are reset but are not guilty and thus have no guilty fence.
> > + */
> > + am_fence = container_of(fence, struct amdgpu_fence, base);
> > + if (am_fence->wptr)
> > + drv->last_wptr = am_fence->wptr;
>
> That looks fishy. We don't need the last wptr, but the first processed one.
I will rename it to signalled_wptr, but I think it is correct. This
is the wptr associated with the last fence that signalled. That is
the starting point for saving the ring contents.
Alex
>
> > dma_fence_signal(fence);
> > dma_fence_put(fence);
> > pm_runtime_mark_last_busy(adev_to_drm(adev)->dev);
> > @@ -727,6 +737,95 @@ void amdgpu_fence_driver_force_completion(struct amdgpu_ring *ring)
> > amdgpu_fence_process(ring);
> > }
> >
> > +
> > +/**
> > + * Kernel queue reset handling
> > + *
> > + * The driver can reset individual queues for most engines, but those queues
> > + * may contain work from multiple contexts. Resetting the queue will reset
> > + * lose all of that state. In order to minimize the collatoral damage, the
>
> Typo "collateral".
>
> > + * driver will save the ring contents which are not associated with the guilty
> > + * context prior to resetting the queue. After resetting the queue the queue
> > + * contents from the other contexts is re-emitted to the rings so that it can
> > + * be processed by the engine. To handle this, we save the queue's write
> > + * pointer (wptr) in the fences associated with each context. If we get a
> > + * queue timeout, we can then use the wptrs from the fences to determine
> > + * which data needs to be saved out of the queue's ring buffer.
> > + */
> > +
> > +/**
> > + * amdgpu_fence_driver_guilty_force_completion - force signal of specified sequence
> > + *
> > + * @fence: fence of the ring to signal
> > + *
> > + */
> > +void amdgpu_fence_driver_guilty_force_completion(struct amdgpu_fence *fence)
> > +{
> > + dma_fence_set_error(&fence->base, -ETIME);
> > + amdgpu_fence_write(fence->ring, fence->base.seqno);
> > + amdgpu_fence_process(fence->ring);
> > +}
> > +
> > +void amdgpu_fence_save_wptr(struct dma_fence *fence)
> > +{
> > + struct amdgpu_fence *am_fence = container_of(fence, struct amdgpu_fence, base);
> > +
> > + am_fence->wptr = am_fence->ring->wptr;
> > +}
> > +
> > +static void amdgpu_ring_backup_unprocessed_command(struct amdgpu_ring *ring,
> > + unsigned int idx,
>
> idx is unused.
>
> > + u64 start_wptr, u32 end_wptr)
> > +{
> > + unsigned int first_idx = start_wptr & ring->buf_mask;
> > + unsigned int last_idx = end_wptr & ring->buf_mask;
> > + unsigned int i, count;
> > +
> > + /* Backup the contents of the ring buffer. */
> > + for (i = first_idx, count = 0; i != last_idx; ++i, i &= ring->buf_mask, ++count)
>
> count should start at ring->ring_backup_entries_to_copy.
>
> > + ring->ring_backup[count] = ring->ring[i];
> > + ring->ring_backup_entries_to_copy = count;
> > +}
> > +
> > +void amdgpu_ring_backup_unprocessed_commands(struct amdgpu_ring *ring,
> > + struct amdgpu_fence *guilty_fence)
> > +{
> > + struct amdgpu_fence *fence;
> > + struct dma_fence *unprocessed, **ptr;
>
> ptr need an __rcu annotation or otherwise the automated tools will start complaining.
>
> > + u64 wptr, i, seqno;
> > +
> > + if (guilty_fence) {
> > + seqno = guilty_fence->base.seqno;
> > + wptr = guilty_fence->wptr;
>
> I think we can just always go over the whole ring buffer here. E.g. dropping this if branch.
>
>
> > + } else {
> > + seqno = amdgpu_fence_read(ring);
> > + wptr = ring->fence_drv.last_wptr;
>
> Again that looks fishy. We shouldn't start at the last wptr, but the first.
>
> > + }
> > + ring->ring_backup_entries_to_copy = 0;
> > + for (i = seqno + 1; i <= ring->fence_drv.sync_seq; ++i) {
> > + ptr = &ring->fence_drv.fences[i & ring->fence_drv.num_fences_mask];
> > + rcu_read_lock();
> > + unprocessed = rcu_dereference(*ptr);
> > +
> > + if (unprocessed && !dma_fence_is_signaled(unprocessed)) {
> > + fence = container_of(unprocessed, struct amdgpu_fence, base);
>
> We should probably make ring->fence_drv.fences an array of amdgpu_fences.
>
> > +
> > + /* save everything if the ring is not guilty, otherwise
> > + * just save the content from other contexts.
> > + */
> > + if (fence->wptr &&
> > + (!guilty_fence || (fence->context != guilty_fence->context))) {
> > + amdgpu_ring_backup_unprocessed_command(ring,
> > + ring->ring_backup_entries_to_copy,
> > + wptr,
> > + fence->wptr);
> > + wptr = fence->wptr;
>
> Wptr also needs to be updated for already signaled fences and fences which are skipped because they belong to the guilty context.
>
> Christian.
>
> > + }
> > + }
> > + rcu_read_unlock();
> > + }
> > +}
> > +
> > /*
> > * Common fence implementation
> > */
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
> > index 206b70acb29a0..d0f838fde2ae5 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ib.c
> > @@ -139,7 +139,6 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
> > int vmid = AMDGPU_JOB_GET_VMID(job);
> > bool need_pipe_sync = false;
> > unsigned int cond_exec;
> > -
> > unsigned int i;
> > int r = 0;
> >
> > @@ -156,6 +155,11 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
> > gds_va = job->gds_va;
> > init_shadow = job->init_shadow;
> > af = &job->hw_fence;
> > + /* Save the context of the job for reset handling.
> > + * The driver needs this so it can skip the ring
> > + * contents for guilty contexts.
> > + */
> > + af->context = job->base.s_fence ? job->base.s_fence->finished.context : 0;
> > } else {
> > vm = NULL;
> > fence_ctx = 0;
> > @@ -309,6 +313,15 @@ int amdgpu_ib_schedule(struct amdgpu_ring *ring, unsigned int num_ibs,
> >
> > amdgpu_ring_ib_end(ring);
> > amdgpu_ring_commit(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
> > + * fence so we know what rings contents to backup
> > + * after we reset the queue.
> > + */
> > + amdgpu_fence_save_wptr(*f);
> > +
> > return 0;
> > }
> >
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
> > index f0b7080dccb8d..45febdc2f3493 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
> > @@ -89,8 +89,8 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
> > {
> > struct amdgpu_ring *ring = to_amdgpu_ring(s_job->sched);
> > struct amdgpu_job *job = to_amdgpu_job(s_job);
> > - struct amdgpu_task_info *ti;
> > struct amdgpu_device *adev = ring->adev;
> > + struct amdgpu_task_info *ti;
> > int idx, r;
> >
> > if (!drm_dev_enter(adev_to_drm(adev), &idx)) {
> > @@ -135,7 +135,7 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
> > } else if (amdgpu_gpu_recovery && ring->funcs->reset) {
> > dev_err(adev->dev, "Starting %s ring reset\n",
> > s_job->sched->name);
> > - r = amdgpu_ring_reset(ring, job->vmid, NULL);
> > + r = amdgpu_ring_reset(ring, job->vmid, &job->hw_fence);
> > if (!r) {
> > atomic_inc(&ring->adev->gpu_reset_counter);
> > dev_err(adev->dev, "Ring %s reset succeeded\n",
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
> > index 426834806fbf2..0985eba010e17 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.c
> > @@ -333,6 +333,12 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
> > /* Initialize cached_rptr to 0 */
> > ring->cached_rptr = 0;
> >
> > + if (!ring->ring_backup) {
> > + ring->ring_backup = kvzalloc(ring->ring_size, GFP_KERNEL);
> > + if (!ring->ring_backup)
> > + return -ENOMEM;
> > + }
> > +
> > /* Allocate ring buffer */
> > if (ring->ring_obj == NULL) {
> > r = amdgpu_bo_create_kernel(adev, ring->ring_size + ring->funcs->extra_dw, PAGE_SIZE,
> > @@ -342,6 +348,7 @@ int amdgpu_ring_init(struct amdgpu_device *adev, struct amdgpu_ring *ring,
> > (void **)&ring->ring);
> > if (r) {
> > dev_err(adev->dev, "(%d) ring create failed\n", r);
> > + kvfree(ring->ring_backup);
> > return r;
> > }
> > amdgpu_ring_clear_ring(ring);
> > @@ -385,6 +392,8 @@ void amdgpu_ring_fini(struct amdgpu_ring *ring)
> > amdgpu_bo_free_kernel(&ring->ring_obj,
> > &ring->gpu_addr,
> > (void **)&ring->ring);
> > + kvfree(ring->ring_backup);
> > + ring->ring_backup = NULL;
> >
> > dma_fence_put(ring->vmid_wait);
> > ring->vmid_wait = NULL;
> > @@ -753,3 +762,53 @@ bool amdgpu_ring_sched_ready(struct amdgpu_ring *ring)
> >
> > return true;
> > }
> > +
> > +static int amdgpu_ring_reemit_unprocessed_commands(struct amdgpu_ring *ring)
> > +{
> > + unsigned int i;
> > + int r;
> > +
> > + /* re-emit the unprocessed ring contents */
> > + if (ring->ring_backup_entries_to_copy) {
> > + r = amdgpu_ring_alloc(ring, ring->ring_backup_entries_to_copy);
> > + if (r)
> > + return r;
> > + for (i = 0; i < ring->ring_backup_entries_to_copy; i++)
> > + amdgpu_ring_write(ring, ring->ring_backup[i]);
> > + amdgpu_ring_commit(ring);
> > + }
> > +
> > + return 0;
> > +}
> > +
> > +void amdgpu_ring_reset_helper_begin(struct amdgpu_ring *ring,
> > + struct amdgpu_fence *guilty_fence)
> > +{
> > + /* Stop the scheduler to prevent anybody else from touching the ring buffer. */
> > + drm_sched_wqueue_stop(&ring->sched);
> > + /* back up the non-guilty commands */
> > + amdgpu_ring_backup_unprocessed_commands(ring, guilty_fence);
> > +}
> > +
> > +int amdgpu_ring_reset_helper_end(struct amdgpu_ring *ring,
> > + struct amdgpu_fence *guilty_fence)
> > +{
> > + int r;
> > +
> > + /* verify that the ring is functional */
> > + r = amdgpu_ring_test_ring(ring);
> > + if (r)
> > + return r;
> > +
> > + /* signal the fence of the bad job */
> > + if (guilty_fence)
> > + amdgpu_fence_driver_guilty_force_completion(guilty_fence);
> > + /* Re-emit the non-guilty commands */
> > + r = amdgpu_ring_reemit_unprocessed_commands(ring);
> > + if (r)
> > + /* if we fail to reemit, force complete all fences */
> > + amdgpu_fence_driver_force_completion(ring);
> > + /* Start the scheduler again */
> > + drm_sched_wqueue_start(&ring->sched);
> > + return 0;
> > +}
> > diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
> > index 784ba2ec354c7..2b5546d15a6be 100644
> > --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
> > +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ring.h
> > @@ -118,6 +118,7 @@ struct amdgpu_fence_driver {
> > /* sync_seq is protected by ring emission lock */
> > uint32_t sync_seq;
> > atomic_t last_seq;
> > + u64 last_wptr;
> > bool initialized;
> > struct amdgpu_irq_src *irq_src;
> > unsigned irq_type;
> > @@ -141,6 +142,11 @@ struct amdgpu_fence {
> > /* RB, DMA, etc. */
> > struct amdgpu_ring *ring;
> > ktime_t start_timestamp;
> > +
> > + /* wptr for the fence for resets */
> > + u64 wptr;
> > + /* fence context for resets */
> > + u64 context;
> > };
> >
> > extern const struct drm_sched_backend_ops amdgpu_sched_ops;
> > @@ -148,6 +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_guilty_force_completion(struct amdgpu_fence *fence);
> > +void amdgpu_fence_save_wptr(struct dma_fence *fence);
> >
> > int amdgpu_fence_driver_init_ring(struct amdgpu_ring *ring);
> > int amdgpu_fence_driver_start_ring(struct amdgpu_ring *ring,
> > @@ -284,6 +292,9 @@ struct amdgpu_ring {
> >
> > struct amdgpu_bo *ring_obj;
> > uint32_t *ring;
> > + /* backups for resets */
> > + uint32_t *ring_backup;
> > + unsigned int ring_backup_entries_to_copy;
> > unsigned rptr_offs;
> > u64 rptr_gpu_addr;
> > volatile u32 *rptr_cpu_addr;
> > @@ -550,4 +561,10 @@ int amdgpu_ib_pool_init(struct amdgpu_device *adev);
> > void amdgpu_ib_pool_fini(struct amdgpu_device *adev);
> > int amdgpu_ib_ring_tests(struct amdgpu_device *adev);
> > bool amdgpu_ring_sched_ready(struct amdgpu_ring *ring);
> > +void amdgpu_ring_backup_unprocessed_commands(struct amdgpu_ring *ring,
> > + struct amdgpu_fence *guilty_fence);
> > +void amdgpu_ring_reset_helper_begin(struct amdgpu_ring *ring,
> > + struct amdgpu_fence *guilty_fence);
> > +int amdgpu_ring_reset_helper_end(struct amdgpu_ring *ring,
> > + struct amdgpu_fence *guilty_fence);
> > #endif
>
^ permalink raw reply [flat|nested] 35+ messages in thread
* [PATCH 08/30] drm/amdgpu/gfx9: re-emit unprocessed state on kcq reset
2025-06-25 21:06 [PATCH V11 00/30] Reset improvements Alex Deucher
` (6 preceding siblings ...)
2025-06-25 21:06 ` [PATCH 07/30] drm/amdgpu: track ring state associated with a fence Alex Deucher
@ 2025-06-25 21:06 ` Alex Deucher
2025-06-25 21:06 ` [PATCH 09/30] drm/amdgpu/gfx9.4.3: " Alex Deucher
` (21 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Alex Deucher @ 2025-06-25 21:06 UTC (permalink / raw)
To: amd-gfx, christian.koenig, sasundar; +Cc: Alex Deucher
Re-emit the unprocessed state after resetting the queue.
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c | 12 +++---------
1 file changed, 3 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
index 76ba664efecb3..30f6b04cf82e4 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_0.c
@@ -7187,7 +7187,7 @@ static int gfx_v9_0_reset_kcq(struct amdgpu_ring *ring,
if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
return -EINVAL;
- drm_sched_wqueue_stop(&ring->sched);
+ amdgpu_ring_reset_helper_begin(ring, timedout_fence);
spin_lock_irqsave(&kiq->ring_lock, flags);
@@ -7238,19 +7238,13 @@ static int gfx_v9_0_reset_kcq(struct amdgpu_ring *ring,
}
kiq->pmf->kiq_map_queues(kiq_ring, ring);
amdgpu_ring_commit(kiq_ring);
- spin_unlock_irqrestore(&kiq->ring_lock, flags);
r = amdgpu_ring_test_ring(kiq_ring);
+ spin_unlock_irqrestore(&kiq->ring_lock, flags);
if (r) {
DRM_ERROR("fail to remap queue\n");
return r;
}
-
- r = amdgpu_ring_test_ring(ring);
- if (r)
- return r;
- amdgpu_fence_driver_force_completion(ring);
- drm_sched_wqueue_start(&ring->sched);
- return 0;
+ return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static void gfx_v9_ip_print(struct amdgpu_ip_block *ip_block, struct drm_printer *p)
--
2.50.0
^ permalink raw reply related [flat|nested] 35+ messages in thread* [PATCH 09/30] drm/amdgpu/gfx9.4.3: re-emit unprocessed state on kcq reset
2025-06-25 21:06 [PATCH V11 00/30] Reset improvements Alex Deucher
` (7 preceding siblings ...)
2025-06-25 21:06 ` [PATCH 08/30] drm/amdgpu/gfx9: re-emit unprocessed state on kcq reset Alex Deucher
@ 2025-06-25 21:06 ` Alex Deucher
2025-06-25 21:06 ` [PATCH 10/30] drm/amdgpu/gfx10: re-emit unprocessed state on ring reset Alex Deucher
` (20 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Alex Deucher @ 2025-06-25 21:06 UTC (permalink / raw)
To: amd-gfx, christian.koenig, sasundar; +Cc: Alex Deucher
Re-emit the unprocessed state after resetting the queue.
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c | 12 +++---------
1 file changed, 3 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
index daed0f187bda5..21bdf9746db7a 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v9_4_3.c
@@ -3567,7 +3567,7 @@ static int gfx_v9_4_3_reset_kcq(struct amdgpu_ring *ring,
if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
return -EINVAL;
- drm_sched_wqueue_stop(&ring->sched);
+ amdgpu_ring_reset_helper_begin(ring, timedout_fence);
spin_lock_irqsave(&kiq->ring_lock, flags);
@@ -3615,20 +3615,14 @@ static int gfx_v9_4_3_reset_kcq(struct amdgpu_ring *ring,
}
kiq->pmf->kiq_map_queues(kiq_ring, ring);
amdgpu_ring_commit(kiq_ring);
- spin_unlock_irqrestore(&kiq->ring_lock, flags);
-
r = amdgpu_ring_test_ring(kiq_ring);
+ spin_unlock_irqrestore(&kiq->ring_lock, flags);
if (r) {
dev_err(adev->dev, "fail to remap queue\n");
return r;
}
- r = amdgpu_ring_test_ring(ring);
- if (r)
- return r;
- amdgpu_fence_driver_force_completion(ring);
- drm_sched_wqueue_start(&ring->sched);
- return 0;
+ return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
enum amdgpu_gfx_cp_ras_mem_id {
--
2.50.0
^ permalink raw reply related [flat|nested] 35+ messages in thread* [PATCH 10/30] drm/amdgpu/gfx10: re-emit unprocessed state on ring reset
2025-06-25 21:06 [PATCH V11 00/30] Reset improvements Alex Deucher
` (8 preceding siblings ...)
2025-06-25 21:06 ` [PATCH 09/30] drm/amdgpu/gfx9.4.3: " Alex Deucher
@ 2025-06-25 21:06 ` Alex Deucher
2025-06-25 21:06 ` [PATCH 11/30] drm/amdgpu/gfx11: " Alex Deucher
` (19 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Alex Deucher @ 2025-06-25 21:06 UTC (permalink / raw)
To: amd-gfx, christian.koenig, sasundar; +Cc: Alex Deucher
Re-emit the unprocessed state after resetting the queue.
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c | 45 ++++----------------------
1 file changed, 7 insertions(+), 38 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
index 8c377ecbb8a75..89010d9c9d5ee 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v10_0.c
@@ -9046,21 +9046,6 @@ static void gfx_v10_0_ring_emit_reg_write_reg_wait(struct amdgpu_ring *ring,
ref, mask);
}
-static void gfx_v10_0_ring_soft_recovery(struct amdgpu_ring *ring,
- unsigned int vmid)
-{
- struct amdgpu_device *adev = ring->adev;
- uint32_t value = 0;
-
- value = REG_SET_FIELD(value, SQ_CMD, CMD, 0x03);
- value = REG_SET_FIELD(value, SQ_CMD, MODE, 0x01);
- value = REG_SET_FIELD(value, SQ_CMD, CHECK_VMID, 1);
- value = REG_SET_FIELD(value, SQ_CMD, VM_ID, vmid);
- amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
- WREG32_SOC15(GC, 0, mmSQ_CMD, value);
- amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
-}
-
static void
gfx_v10_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev,
uint32_t me, uint32_t pipe,
@@ -9540,7 +9525,7 @@ static int gfx_v10_0_reset_kgq(struct amdgpu_ring *ring,
if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
return -EINVAL;
- drm_sched_wqueue_stop(&ring->sched);
+ amdgpu_ring_reset_helper_begin(ring, timedout_fence);
spin_lock_irqsave(&kiq->ring_lock, flags);
@@ -9566,10 +9551,8 @@ static int gfx_v10_0_reset_kgq(struct amdgpu_ring *ring,
SOC15_REG_OFFSET(GC, 0, mmCP_VMID_RESET), 0, 0xffffffff);
kiq->pmf->kiq_map_queues(kiq_ring, ring);
amdgpu_ring_commit(kiq_ring);
-
- spin_unlock_irqrestore(&kiq->ring_lock, flags);
-
r = amdgpu_ring_test_ring(kiq_ring);
+ spin_unlock_irqrestore(&kiq->ring_lock, flags);
if (r)
return r;
@@ -9579,12 +9562,7 @@ static int gfx_v10_0_reset_kgq(struct amdgpu_ring *ring,
return r;
}
- r = amdgpu_ring_test_ring(ring);
- if (r)
- return r;
- amdgpu_fence_driver_force_completion(ring);
- drm_sched_wqueue_start(&ring->sched);
- return 0;
+ return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static int gfx_v10_0_reset_kcq(struct amdgpu_ring *ring,
@@ -9603,7 +9581,7 @@ static int gfx_v10_0_reset_kcq(struct amdgpu_ring *ring,
if (!kiq->pmf || !kiq->pmf->kiq_unmap_queues)
return -EINVAL;
- drm_sched_wqueue_stop(&ring->sched);
+ amdgpu_ring_reset_helper_begin(ring, timedout_fence);
spin_lock_irqsave(&kiq->ring_lock, flags);
@@ -9615,9 +9593,8 @@ static int gfx_v10_0_reset_kcq(struct amdgpu_ring *ring,
kiq->pmf->kiq_unmap_queues(kiq_ring, ring, RESET_QUEUES,
0, 0);
amdgpu_ring_commit(kiq_ring);
- spin_unlock_irqrestore(&kiq->ring_lock, flags);
-
r = amdgpu_ring_test_ring(kiq_ring);
+ spin_unlock_irqrestore(&kiq->ring_lock, flags);
if (r)
return r;
@@ -9653,18 +9630,12 @@ static int gfx_v10_0_reset_kcq(struct amdgpu_ring *ring,
}
kiq->pmf->kiq_map_queues(kiq_ring, ring);
amdgpu_ring_commit(kiq_ring);
- spin_unlock_irqrestore(&kiq->ring_lock, flags);
-
r = amdgpu_ring_test_ring(kiq_ring);
+ spin_unlock_irqrestore(&kiq->ring_lock, flags);
if (r)
return r;
- r = amdgpu_ring_test_ring(ring);
- if (r)
- return r;
- amdgpu_fence_driver_force_completion(ring);
- drm_sched_wqueue_start(&ring->sched);
- return 0;
+ return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static void gfx_v10_ip_print(struct amdgpu_ip_block *ip_block, struct drm_printer *p)
@@ -9899,7 +9870,6 @@ static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_gfx = {
.emit_wreg = gfx_v10_0_ring_emit_wreg,
.emit_reg_wait = gfx_v10_0_ring_emit_reg_wait,
.emit_reg_write_reg_wait = gfx_v10_0_ring_emit_reg_write_reg_wait,
- .soft_recovery = gfx_v10_0_ring_soft_recovery,
.emit_mem_sync = gfx_v10_0_emit_mem_sync,
.reset = gfx_v10_0_reset_kgq,
.emit_cleaner_shader = gfx_v10_0_ring_emit_cleaner_shader,
@@ -9940,7 +9910,6 @@ static const struct amdgpu_ring_funcs gfx_v10_0_ring_funcs_compute = {
.emit_wreg = gfx_v10_0_ring_emit_wreg,
.emit_reg_wait = gfx_v10_0_ring_emit_reg_wait,
.emit_reg_write_reg_wait = gfx_v10_0_ring_emit_reg_write_reg_wait,
- .soft_recovery = gfx_v10_0_ring_soft_recovery,
.emit_mem_sync = gfx_v10_0_emit_mem_sync,
.reset = gfx_v10_0_reset_kcq,
.emit_cleaner_shader = gfx_v10_0_ring_emit_cleaner_shader,
--
2.50.0
^ permalink raw reply related [flat|nested] 35+ messages in thread* [PATCH 11/30] drm/amdgpu/gfx11: re-emit unprocessed state on ring reset
2025-06-25 21:06 [PATCH V11 00/30] Reset improvements Alex Deucher
` (9 preceding siblings ...)
2025-06-25 21:06 ` [PATCH 10/30] drm/amdgpu/gfx10: re-emit unprocessed state on ring reset Alex Deucher
@ 2025-06-25 21:06 ` Alex Deucher
2025-06-25 21:06 ` [PATCH 12/30] drm/amdgpu/gfx12: " Alex Deucher
` (18 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Alex Deucher @ 2025-06-25 21:06 UTC (permalink / raw)
To: amd-gfx, christian.koenig, sasundar; +Cc: Alex Deucher
Re-emit the unprocessed state after resetting the queue.
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c | 35 +++-----------------------
1 file changed, 4 insertions(+), 31 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
index 37dcec2d07841..04b2e3def5098 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v11_0.c
@@ -6283,21 +6283,6 @@ static void gfx_v11_0_ring_emit_reg_write_reg_wait(struct amdgpu_ring *ring,
ref, mask, 0x20);
}
-static void gfx_v11_0_ring_soft_recovery(struct amdgpu_ring *ring,
- unsigned vmid)
-{
- struct amdgpu_device *adev = ring->adev;
- uint32_t value = 0;
-
- value = REG_SET_FIELD(value, SQ_CMD, CMD, 0x03);
- value = REG_SET_FIELD(value, SQ_CMD, MODE, 0x01);
- value = REG_SET_FIELD(value, SQ_CMD, CHECK_VMID, 1);
- value = REG_SET_FIELD(value, SQ_CMD, VM_ID, vmid);
- amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
- WREG32_SOC15(GC, 0, regSQ_CMD, value);
- amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
-}
-
static void
gfx_v11_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev,
uint32_t me, uint32_t pipe,
@@ -6821,7 +6806,7 @@ static int gfx_v11_0_reset_kgq(struct amdgpu_ring *ring,
if (amdgpu_sriov_vf(adev))
return -EINVAL;
- drm_sched_wqueue_stop(&ring->sched);
+ amdgpu_ring_reset_helper_begin(ring, timedout_fence);
r = amdgpu_mes_reset_legacy_queue(ring->adev, ring, vmid, false);
if (r) {
@@ -6844,12 +6829,7 @@ static int gfx_v11_0_reset_kgq(struct amdgpu_ring *ring,
return r;
}
- r = amdgpu_ring_test_ring(ring);
- if (r)
- return r;
- amdgpu_fence_driver_force_completion(ring);
- drm_sched_wqueue_start(&ring->sched);
- return 0;
+ return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static int gfx_v11_0_reset_compute_pipe(struct amdgpu_ring *ring)
@@ -6992,7 +6972,7 @@ static int gfx_v11_0_reset_kcq(struct amdgpu_ring *ring,
if (amdgpu_sriov_vf(adev))
return -EINVAL;
- drm_sched_wqueue_stop(&ring->sched);
+ amdgpu_ring_reset_helper_begin(ring, timedout_fence);
r = amdgpu_mes_reset_legacy_queue(ring->adev, ring, vmid, true);
if (r) {
@@ -7013,12 +6993,7 @@ static int gfx_v11_0_reset_kcq(struct amdgpu_ring *ring,
return r;
}
- r = amdgpu_ring_test_ring(ring);
- if (r)
- return r;
- amdgpu_fence_driver_force_completion(ring);
- drm_sched_wqueue_start(&ring->sched);
- return 0;
+ return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static void gfx_v11_ip_print(struct amdgpu_ip_block *ip_block, struct drm_printer *p)
@@ -7254,7 +7229,6 @@ static const struct amdgpu_ring_funcs gfx_v11_0_ring_funcs_gfx = {
.emit_wreg = gfx_v11_0_ring_emit_wreg,
.emit_reg_wait = gfx_v11_0_ring_emit_reg_wait,
.emit_reg_write_reg_wait = gfx_v11_0_ring_emit_reg_write_reg_wait,
- .soft_recovery = gfx_v11_0_ring_soft_recovery,
.emit_mem_sync = gfx_v11_0_emit_mem_sync,
.reset = gfx_v11_0_reset_kgq,
.emit_cleaner_shader = gfx_v11_0_ring_emit_cleaner_shader,
@@ -7296,7 +7270,6 @@ static const struct amdgpu_ring_funcs gfx_v11_0_ring_funcs_compute = {
.emit_wreg = gfx_v11_0_ring_emit_wreg,
.emit_reg_wait = gfx_v11_0_ring_emit_reg_wait,
.emit_reg_write_reg_wait = gfx_v11_0_ring_emit_reg_write_reg_wait,
- .soft_recovery = gfx_v11_0_ring_soft_recovery,
.emit_mem_sync = gfx_v11_0_emit_mem_sync,
.reset = gfx_v11_0_reset_kcq,
.emit_cleaner_shader = gfx_v11_0_ring_emit_cleaner_shader,
--
2.50.0
^ permalink raw reply related [flat|nested] 35+ messages in thread* [PATCH 12/30] drm/amdgpu/gfx12: re-emit unprocessed state on ring reset
2025-06-25 21:06 [PATCH V11 00/30] Reset improvements Alex Deucher
` (10 preceding siblings ...)
2025-06-25 21:06 ` [PATCH 11/30] drm/amdgpu/gfx11: " Alex Deucher
@ 2025-06-25 21:06 ` Alex Deucher
2025-06-25 21:06 ` [PATCH 13/30] drm/amdgpu/sdma6: " Alex Deucher
` (17 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Alex Deucher @ 2025-06-25 21:06 UTC (permalink / raw)
To: amd-gfx, christian.koenig, sasundar; +Cc: Alex Deucher
Re-emit the unprocessed state after resetting the queue.
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c | 35 +++-----------------------
1 file changed, 4 insertions(+), 31 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
index e4fc42470cf3e..a3be2b46177c3 100644
--- a/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/gfx_v12_0.c
@@ -4690,21 +4690,6 @@ static void gfx_v12_0_ring_emit_reg_write_reg_wait(struct amdgpu_ring *ring,
ref, mask, 0x20);
}
-static void gfx_v12_0_ring_soft_recovery(struct amdgpu_ring *ring,
- unsigned vmid)
-{
- struct amdgpu_device *adev = ring->adev;
- uint32_t value = 0;
-
- value = REG_SET_FIELD(value, SQ_CMD, CMD, 0x03);
- value = REG_SET_FIELD(value, SQ_CMD, MODE, 0x01);
- value = REG_SET_FIELD(value, SQ_CMD, CHECK_VMID, 1);
- value = REG_SET_FIELD(value, SQ_CMD, VM_ID, vmid);
- amdgpu_gfx_rlc_enter_safe_mode(adev, 0);
- WREG32_SOC15(GC, 0, regSQ_CMD, value);
- amdgpu_gfx_rlc_exit_safe_mode(adev, 0);
-}
-
static void
gfx_v12_0_set_gfx_eop_interrupt_state(struct amdgpu_device *adev,
uint32_t me, uint32_t pipe,
@@ -5317,7 +5302,7 @@ static int gfx_v12_0_reset_kgq(struct amdgpu_ring *ring,
if (amdgpu_sriov_vf(adev))
return -EINVAL;
- drm_sched_wqueue_stop(&ring->sched);
+ amdgpu_ring_reset_helper_begin(ring, timedout_fence);
r = amdgpu_mes_reset_legacy_queue(ring->adev, ring, vmid, false);
if (r) {
@@ -5339,12 +5324,7 @@ static int gfx_v12_0_reset_kgq(struct amdgpu_ring *ring,
return r;
}
- r = amdgpu_ring_test_ring(ring);
- if (r)
- return r;
- amdgpu_fence_driver_force_completion(ring);
- drm_sched_wqueue_start(&ring->sched);
- return 0;
+ return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static int gfx_v12_0_reset_compute_pipe(struct amdgpu_ring *ring)
@@ -5440,7 +5420,7 @@ static int gfx_v12_0_reset_kcq(struct amdgpu_ring *ring,
if (amdgpu_sriov_vf(adev))
return -EINVAL;
- drm_sched_wqueue_stop(&ring->sched);
+ amdgpu_ring_reset_helper_begin(ring, timedout_fence);
r = amdgpu_mes_reset_legacy_queue(ring->adev, ring, vmid, true);
if (r) {
@@ -5461,12 +5441,7 @@ static int gfx_v12_0_reset_kcq(struct amdgpu_ring *ring,
return r;
}
- r = amdgpu_ring_test_ring(ring);
- if (r)
- return r;
- amdgpu_fence_driver_force_completion(ring);
- drm_sched_wqueue_start(&ring->sched);
- return 0;
+ return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static void gfx_v12_0_ring_begin_use(struct amdgpu_ring *ring)
@@ -5544,7 +5519,6 @@ static const struct amdgpu_ring_funcs gfx_v12_0_ring_funcs_gfx = {
.emit_wreg = gfx_v12_0_ring_emit_wreg,
.emit_reg_wait = gfx_v12_0_ring_emit_reg_wait,
.emit_reg_write_reg_wait = gfx_v12_0_ring_emit_reg_write_reg_wait,
- .soft_recovery = gfx_v12_0_ring_soft_recovery,
.emit_mem_sync = gfx_v12_0_emit_mem_sync,
.reset = gfx_v12_0_reset_kgq,
.emit_cleaner_shader = gfx_v12_0_ring_emit_cleaner_shader,
@@ -5583,7 +5557,6 @@ static const struct amdgpu_ring_funcs gfx_v12_0_ring_funcs_compute = {
.emit_wreg = gfx_v12_0_ring_emit_wreg,
.emit_reg_wait = gfx_v12_0_ring_emit_reg_wait,
.emit_reg_write_reg_wait = gfx_v12_0_ring_emit_reg_write_reg_wait,
- .soft_recovery = gfx_v12_0_ring_soft_recovery,
.emit_mem_sync = gfx_v12_0_emit_mem_sync,
.reset = gfx_v12_0_reset_kcq,
.emit_cleaner_shader = gfx_v12_0_ring_emit_cleaner_shader,
--
2.50.0
^ permalink raw reply related [flat|nested] 35+ messages in thread* [PATCH 13/30] drm/amdgpu/sdma6: re-emit unprocessed state on ring reset
2025-06-25 21:06 [PATCH V11 00/30] Reset improvements Alex Deucher
` (11 preceding siblings ...)
2025-06-25 21:06 ` [PATCH 12/30] drm/amdgpu/gfx12: " Alex Deucher
@ 2025-06-25 21:06 ` Alex Deucher
2025-06-25 21:06 ` [PATCH 14/30] drm/amdgpu/sdma7: " Alex Deucher
` (16 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Alex Deucher @ 2025-06-25 21:06 UTC (permalink / raw)
To: amd-gfx, christian.koenig, sasundar; +Cc: Alex Deucher
Re-emit the unprocessed state after resetting the queue.
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c | 18 ++++++------------
1 file changed, 6 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
index 103e5ec7aa63b..a9f3aa8194051 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v6_0.c
@@ -1571,33 +1571,27 @@ static int sdma_v6_0_reset_queue(struct amdgpu_ring *ring,
struct amdgpu_fence *timedout_fence)
{
struct amdgpu_device *adev = ring->adev;
- int i, r;
+ int r;
if (amdgpu_sriov_vf(adev))
return -EINVAL;
- for (i = 0; i < adev->sdma.num_instances; i++) {
- if (ring == &adev->sdma.instance[i].ring)
- break;
- }
-
- if (i == adev->sdma.num_instances) {
+ if (ring->me >= adev->sdma.num_instances) {
DRM_ERROR("sdma instance not found\n");
return -EINVAL;
}
- drm_sched_wqueue_stop(&ring->sched);
+ amdgpu_ring_reset_helper_begin(ring, timedout_fence);
r = amdgpu_mes_reset_legacy_queue(adev, ring, vmid, true);
if (r)
return r;
- r = sdma_v6_0_gfx_resume_instance(adev, i, true);
+ r = sdma_v6_0_gfx_resume_instance(adev, ring->me, true);
if (r)
return r;
- amdgpu_fence_driver_force_completion(ring);
- drm_sched_wqueue_start(&ring->sched);
- return 0;
+
+ return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static int sdma_v6_0_set_trap_irq_state(struct amdgpu_device *adev,
--
2.50.0
^ permalink raw reply related [flat|nested] 35+ messages in thread* [PATCH 14/30] drm/amdgpu/sdma7: re-emit unprocessed state on ring reset
2025-06-25 21:06 [PATCH V11 00/30] Reset improvements Alex Deucher
` (12 preceding siblings ...)
2025-06-25 21:06 ` [PATCH 13/30] drm/amdgpu/sdma6: " Alex Deucher
@ 2025-06-25 21:06 ` Alex Deucher
2025-06-25 21:06 ` [PATCH 15/30] drm/amdgpu/jpeg2: " Alex Deucher
` (15 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Alex Deucher @ 2025-06-25 21:06 UTC (permalink / raw)
To: amd-gfx, christian.koenig, sasundar; +Cc: Alex Deucher
Re-emit the unprocessed state after resetting the queue.
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c | 18 ++++++------------
1 file changed, 6 insertions(+), 12 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c
index 99a080bad2a3d..64322a836ebbe 100644
--- a/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/sdma_v7_0.c
@@ -807,33 +807,27 @@ static int sdma_v7_0_reset_queue(struct amdgpu_ring *ring,
struct amdgpu_fence *timedout_fence)
{
struct amdgpu_device *adev = ring->adev;
- int i, r;
+ int r;
if (amdgpu_sriov_vf(adev))
return -EINVAL;
- for (i = 0; i < adev->sdma.num_instances; i++) {
- if (ring == &adev->sdma.instance[i].ring)
- break;
- }
-
- if (i == adev->sdma.num_instances) {
+ if (ring->me >= adev->sdma.num_instances) {
DRM_ERROR("sdma instance not found\n");
return -EINVAL;
}
- drm_sched_wqueue_stop(&ring->sched);
+ amdgpu_ring_reset_helper_begin(ring, timedout_fence);
r = amdgpu_mes_reset_legacy_queue(adev, ring, vmid, true);
if (r)
return r;
- r = sdma_v7_0_gfx_resume_instance(adev, i, true);
+ r = sdma_v7_0_gfx_resume_instance(adev, ring->me, true);
if (r)
return r;
- amdgpu_fence_driver_force_completion(ring);
- drm_sched_wqueue_start(&ring->sched);
- return 0;
+
+ return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
/**
--
2.50.0
^ permalink raw reply related [flat|nested] 35+ messages in thread* [PATCH 15/30] drm/amdgpu/jpeg2: re-emit unprocessed state on ring reset
2025-06-25 21:06 [PATCH V11 00/30] Reset improvements Alex Deucher
` (13 preceding siblings ...)
2025-06-25 21:06 ` [PATCH 14/30] drm/amdgpu/sdma7: " Alex Deucher
@ 2025-06-25 21:06 ` Alex Deucher
2025-06-25 21:06 ` [PATCH 16/30] drm/amdgpu/jpeg2.5: " Alex Deucher
` (14 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Alex Deucher @ 2025-06-25 21:06 UTC (permalink / raw)
To: amd-gfx, christian.koenig, sasundar; +Cc: Alex Deucher, Sathishkumar S
Re-emit the unprocessed state after resetting the queue.
Reviewed-by: Sathishkumar S <sathishkumar.sundararaju@amd.com>
Tested-by: Sathishkumar S <sathishkumar.sundararaju@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
index 781a5a8a83614..cb66eff499662 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_0.c
@@ -768,17 +768,10 @@ static int jpeg_v2_0_ring_reset(struct amdgpu_ring *ring,
unsigned int vmid,
struct amdgpu_fence *timedout_fence)
{
- int r;
-
- drm_sched_wqueue_stop(&ring->sched);
+ amdgpu_ring_reset_helper_begin(ring, timedout_fence);
jpeg_v2_0_stop(ring->adev);
jpeg_v2_0_start(ring->adev);
- r = amdgpu_ring_test_helper(ring);
- if (r)
- return r;
- amdgpu_fence_driver_force_completion(ring);
- drm_sched_wqueue_start(&ring->sched);
- return 0;
+ return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static const struct amd_ip_funcs jpeg_v2_0_ip_funcs = {
--
2.50.0
^ permalink raw reply related [flat|nested] 35+ messages in thread* [PATCH 16/30] drm/amdgpu/jpeg2.5: re-emit unprocessed state on ring reset
2025-06-25 21:06 [PATCH V11 00/30] Reset improvements Alex Deucher
` (14 preceding siblings ...)
2025-06-25 21:06 ` [PATCH 15/30] drm/amdgpu/jpeg2: " Alex Deucher
@ 2025-06-25 21:06 ` Alex Deucher
2025-06-25 21:06 ` [PATCH 17/30] drm/amdgpu/jpeg3: " Alex Deucher
` (13 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Alex Deucher @ 2025-06-25 21:06 UTC (permalink / raw)
To: amd-gfx, christian.koenig, sasundar; +Cc: Alex Deucher, Sathishkumar S
Re-emit the unprocessed state after resetting the queue.
Reviewed-by: Sathishkumar S <sathishkumar.sundararaju@amd.com>
Tested-by: Sathishkumar S <sathishkumar.sundararaju@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
index 5be9cdcae32c1..7432990f77507 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v2_5.c
@@ -647,17 +647,10 @@ static int jpeg_v2_5_ring_reset(struct amdgpu_ring *ring,
unsigned int vmid,
struct amdgpu_fence *timedout_fence)
{
- int r;
-
- drm_sched_wqueue_stop(&ring->sched);
+ amdgpu_ring_reset_helper_begin(ring, timedout_fence);
jpeg_v2_5_stop_inst(ring->adev, ring->me);
jpeg_v2_5_start_inst(ring->adev, ring->me);
- r = amdgpu_ring_test_helper(ring);
- if (r)
- return r;
- amdgpu_fence_driver_force_completion(ring);
- drm_sched_wqueue_start(&ring->sched);
- return 0;
+ return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static const struct amd_ip_funcs jpeg_v2_5_ip_funcs = {
--
2.50.0
^ permalink raw reply related [flat|nested] 35+ messages in thread* [PATCH 17/30] drm/amdgpu/jpeg3: re-emit unprocessed state on ring reset
2025-06-25 21:06 [PATCH V11 00/30] Reset improvements Alex Deucher
` (15 preceding siblings ...)
2025-06-25 21:06 ` [PATCH 16/30] drm/amdgpu/jpeg2.5: " Alex Deucher
@ 2025-06-25 21:06 ` Alex Deucher
2025-06-25 21:06 ` [PATCH 18/30] drm/amdgpu/jpeg4: " Alex Deucher
` (12 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Alex Deucher @ 2025-06-25 21:06 UTC (permalink / raw)
To: amd-gfx, christian.koenig, sasundar; +Cc: Alex Deucher, Sathishkumar S
Re-emit the unprocessed state after resetting the queue.
Reviewed-by: Sathishkumar S <sathishkumar.sundararaju@amd.com>
Tested-by: Sathishkumar S <sathishkumar.sundararaju@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
index a24bd833d6442..5598fa40764a7 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v3_0.c
@@ -559,17 +559,10 @@ static int jpeg_v3_0_ring_reset(struct amdgpu_ring *ring,
unsigned int vmid,
struct amdgpu_fence *timedout_fence)
{
- int r;
-
- drm_sched_wqueue_stop(&ring->sched);
+ amdgpu_ring_reset_helper_begin(ring, timedout_fence);
jpeg_v3_0_stop(ring->adev);
jpeg_v3_0_start(ring->adev);
- r = amdgpu_ring_test_helper(ring);
- if (r)
- return r;
- amdgpu_fence_driver_force_completion(ring);
- drm_sched_wqueue_start(&ring->sched);
- return 0;
+ return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static const struct amd_ip_funcs jpeg_v3_0_ip_funcs = {
--
2.50.0
^ permalink raw reply related [flat|nested] 35+ messages in thread* [PATCH 18/30] drm/amdgpu/jpeg4: re-emit unprocessed state on ring reset
2025-06-25 21:06 [PATCH V11 00/30] Reset improvements Alex Deucher
` (16 preceding siblings ...)
2025-06-25 21:06 ` [PATCH 17/30] drm/amdgpu/jpeg3: " Alex Deucher
@ 2025-06-25 21:06 ` Alex Deucher
2025-06-25 21:06 ` [PATCH 19/30] drm/amdgpu/jpeg4.0.3: " Alex Deucher
` (11 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Alex Deucher @ 2025-06-25 21:06 UTC (permalink / raw)
To: amd-gfx, christian.koenig, sasundar; +Cc: Alex Deucher, Sathishkumar S
Re-emit the unprocessed state after resetting the queue.
Reviewed-by: Sathishkumar S <sathishkumar.sundararaju@amd.com>
Tested-by: Sathishkumar S <sathishkumar.sundararaju@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
index 1d4edd77837d0..e9acbd5afbb7b 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0.c
@@ -724,20 +724,13 @@ static int jpeg_v4_0_ring_reset(struct amdgpu_ring *ring,
unsigned int vmid,
struct amdgpu_fence *timedout_fence)
{
- int r;
-
if (amdgpu_sriov_vf(ring->adev))
return -EINVAL;
- drm_sched_wqueue_stop(&ring->sched);
+ amdgpu_ring_reset_helper_begin(ring, timedout_fence);
jpeg_v4_0_stop(ring->adev);
jpeg_v4_0_start(ring->adev);
- r = amdgpu_ring_test_helper(ring);
- if (r)
- return r;
- amdgpu_fence_driver_force_completion(ring);
- drm_sched_wqueue_start(&ring->sched);
- return 0;
+ return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static const struct amd_ip_funcs jpeg_v4_0_ip_funcs = {
--
2.50.0
^ permalink raw reply related [flat|nested] 35+ messages in thread* [PATCH 19/30] drm/amdgpu/jpeg4.0.3: re-emit unprocessed state on ring reset
2025-06-25 21:06 [PATCH V11 00/30] Reset improvements Alex Deucher
` (17 preceding siblings ...)
2025-06-25 21:06 ` [PATCH 18/30] drm/amdgpu/jpeg4: " Alex Deucher
@ 2025-06-25 21:06 ` Alex Deucher
2025-06-25 21:06 ` [PATCH 20/30] drm/amdgpu/jpeg4.0.5: add queue reset Alex Deucher
` (10 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Alex Deucher @ 2025-06-25 21:06 UTC (permalink / raw)
To: amd-gfx, christian.koenig, sasundar; +Cc: Alex Deucher, Sathishkumar S
Re-emit the unprocessed state after resetting the queue.
Reviewed-by: Sathishkumar S <sathishkumar.sundararaju@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
index 78441f8fce972..c3f73a2a911b4 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_3.c
@@ -1147,20 +1147,13 @@ static int jpeg_v4_0_3_ring_reset(struct amdgpu_ring *ring,
unsigned int vmid,
struct amdgpu_fence *timedout_fence)
{
- int r;
-
if (amdgpu_sriov_vf(ring->adev))
return -EOPNOTSUPP;
- drm_sched_wqueue_stop(&ring->sched);
+ amdgpu_ring_reset_helper_begin(ring, timedout_fence);
jpeg_v4_0_3_core_stall_reset(ring);
jpeg_v4_0_3_start_jrbc(ring);
- r = amdgpu_ring_test_helper(ring);
- if (r)
- return r;
- amdgpu_fence_driver_force_completion(ring);
- drm_sched_wqueue_start(&ring->sched);
- return 0;
+ return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static const struct amd_ip_funcs jpeg_v4_0_3_ip_funcs = {
--
2.50.0
^ permalink raw reply related [flat|nested] 35+ messages in thread* [PATCH 20/30] drm/amdgpu/jpeg4.0.5: add queue reset
2025-06-25 21:06 [PATCH V11 00/30] Reset improvements Alex Deucher
` (18 preceding siblings ...)
2025-06-25 21:06 ` [PATCH 19/30] drm/amdgpu/jpeg4.0.3: " Alex Deucher
@ 2025-06-25 21:06 ` Alex Deucher
2025-06-25 21:06 ` [PATCH 21/30] drm/amdgpu/jpeg5: " Alex Deucher
` (9 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Alex Deucher @ 2025-06-25 21:06 UTC (permalink / raw)
To: amd-gfx, christian.koenig, sasundar; +Cc: Alex Deucher, Sathishkumar S
Add queue reset support for jpeg 4.0.5.
Use the new helpers to re-emit the unprocessed state
after resetting the queue.
Reviewed-by: Sathishkumar S <sathishkumar.sundararaju@amd.com>
Tested-by: Sathishkumar S <sathishkumar.sundararaju@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c
index 974030a5c03c9..e6e90496135b6 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v4_0_5.c
@@ -767,6 +767,16 @@ static int jpeg_v4_0_5_process_interrupt(struct amdgpu_device *adev,
return 0;
}
+static int jpeg_v4_0_5_ring_reset(struct amdgpu_ring *ring,
+ unsigned int vmid,
+ struct amdgpu_fence *timedout_fence)
+{
+ amdgpu_ring_reset_helper_begin(ring, timedout_fence);
+ jpeg_v4_0_5_stop(ring->adev);
+ jpeg_v4_0_5_start(ring->adev);
+ return amdgpu_ring_reset_helper_end(ring, timedout_fence);
+}
+
static const struct amd_ip_funcs jpeg_v4_0_5_ip_funcs = {
.name = "jpeg_v4_0_5",
.early_init = jpeg_v4_0_5_early_init,
@@ -812,6 +822,7 @@ static const struct amdgpu_ring_funcs jpeg_v4_0_5_dec_ring_vm_funcs = {
.emit_wreg = jpeg_v2_0_dec_ring_emit_wreg,
.emit_reg_wait = jpeg_v2_0_dec_ring_emit_reg_wait,
.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
+ .reset = jpeg_v4_0_5_ring_reset,
};
static void jpeg_v4_0_5_set_dec_ring_funcs(struct amdgpu_device *adev)
--
2.50.0
^ permalink raw reply related [flat|nested] 35+ messages in thread* [PATCH 21/30] drm/amdgpu/jpeg5: add queue reset
2025-06-25 21:06 [PATCH V11 00/30] Reset improvements Alex Deucher
` (19 preceding siblings ...)
2025-06-25 21:06 ` [PATCH 20/30] drm/amdgpu/jpeg4.0.5: add queue reset Alex Deucher
@ 2025-06-25 21:06 ` Alex Deucher
2025-06-25 21:06 ` [PATCH 22/30] drm/amdgpu/jpeg5.0.1: re-emit unprocessed state on ring reset Alex Deucher
` (8 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Alex Deucher @ 2025-06-25 21:06 UTC (permalink / raw)
To: amd-gfx, christian.koenig, sasundar; +Cc: Alex Deucher, Sathishkumar S
Add queue reset support for jpeg 5.0.0.
Use the new helpers to re-emit the unprocessed state
after resetting the queue.
Reviewed-by: Sathishkumar S <sathishkumar.sundararaju@amd.com>
Tested-by: Sathishkumar S <sathishkumar.sundararaju@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c
index 31d213ccbe0a8..351e21494365d 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_0.c
@@ -644,6 +644,19 @@ static int jpeg_v5_0_0_process_interrupt(struct amdgpu_device *adev,
return 0;
}
+static int jpeg_v5_0_0_ring_reset(struct amdgpu_ring *ring,
+ unsigned int vmid,
+ struct amdgpu_fence *timedout_fence)
+{
+ if (amdgpu_sriov_vf(ring->adev))
+ return -EINVAL;
+
+ amdgpu_ring_reset_helper_begin(ring, timedout_fence);
+ jpeg_v5_0_0_stop(ring->adev);
+ jpeg_v5_0_0_start(ring->adev);
+ return amdgpu_ring_reset_helper_end(ring, timedout_fence);
+}
+
static const struct amd_ip_funcs jpeg_v5_0_0_ip_funcs = {
.name = "jpeg_v5_0_0",
.early_init = jpeg_v5_0_0_early_init,
@@ -689,6 +702,7 @@ static const struct amdgpu_ring_funcs jpeg_v5_0_0_dec_ring_vm_funcs = {
.emit_wreg = jpeg_v4_0_3_dec_ring_emit_wreg,
.emit_reg_wait = jpeg_v4_0_3_dec_ring_emit_reg_wait,
.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
+ .reset = jpeg_v5_0_0_ring_reset,
};
static void jpeg_v5_0_0_set_dec_ring_funcs(struct amdgpu_device *adev)
--
2.50.0
^ permalink raw reply related [flat|nested] 35+ messages in thread* [PATCH 22/30] drm/amdgpu/jpeg5.0.1: re-emit unprocessed state on ring reset
2025-06-25 21:06 [PATCH V11 00/30] Reset improvements Alex Deucher
` (20 preceding siblings ...)
2025-06-25 21:06 ` [PATCH 21/30] drm/amdgpu/jpeg5: " Alex Deucher
@ 2025-06-25 21:06 ` Alex Deucher
2025-06-25 21:06 ` [PATCH 23/30] drm/amdgpu/vcn4: " Alex Deucher
` (7 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Alex Deucher @ 2025-06-25 21:06 UTC (permalink / raw)
To: amd-gfx, christian.koenig, sasundar; +Cc: Alex Deucher, Sathishkumar S
Re-emit the unprocessed state after resetting the queue.
Reviewed-by: Sathishkumar S <sathishkumar.sundararaju@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c
index 6f8a16da9d608..5473cbaa5c0e8 100644
--- a/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c
+++ b/drivers/gpu/drm/amd/amdgpu/jpeg_v5_0_1.c
@@ -838,20 +838,13 @@ static int jpeg_v5_0_1_ring_reset(struct amdgpu_ring *ring,
unsigned int vmid,
struct amdgpu_fence *timedout_fence)
{
- int r;
-
if (amdgpu_sriov_vf(ring->adev))
return -EOPNOTSUPP;
- drm_sched_wqueue_stop(&ring->sched);
+ amdgpu_ring_reset_helper_begin(ring, timedout_fence);
jpeg_v5_0_1_core_stall_reset(ring);
jpeg_v5_0_1_init_jrbc(ring);
- r = amdgpu_ring_test_helper(ring);
- if (r)
- return r;
- amdgpu_fence_driver_force_completion(ring);
- drm_sched_wqueue_start(&ring->sched);
- return 0;
+ return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static const struct amd_ip_funcs jpeg_v5_0_1_ip_funcs = {
--
2.50.0
^ permalink raw reply related [flat|nested] 35+ messages in thread* [PATCH 23/30] drm/amdgpu/vcn4: re-emit unprocessed state on ring reset
2025-06-25 21:06 [PATCH V11 00/30] Reset improvements Alex Deucher
` (21 preceding siblings ...)
2025-06-25 21:06 ` [PATCH 22/30] drm/amdgpu/jpeg5.0.1: re-emit unprocessed state on ring reset Alex Deucher
@ 2025-06-25 21:06 ` Alex Deucher
2025-06-25 21:06 ` [PATCH 24/30] drm/amdgpu/vcn4.0.3: " Alex Deucher
` (6 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Alex Deucher @ 2025-06-25 21:06 UTC (permalink / raw)
To: amd-gfx, christian.koenig, sasundar; +Cc: Alex Deucher, Sathishkumar S
Re-emit the unprocessed state after resetting the queue.
Reviewed-by: Sathishkumar S <sathishkumar.sundararaju@amd.com>
Tested-by: Sathishkumar S <sathishkumar.sundararaju@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
index eec9133e1b2c4..9bf1a345ac2cf 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0.c
@@ -1973,21 +1973,14 @@ static int vcn_v4_0_ring_reset(struct amdgpu_ring *ring,
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me];
- int r;
if (!(adev->vcn.supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE))
return -EOPNOTSUPP;
- drm_sched_wqueue_stop(&ring->sched);
+ amdgpu_ring_reset_helper_begin(ring, timedout_fence);
vcn_v4_0_stop(vinst);
vcn_v4_0_start(vinst);
-
- r = amdgpu_ring_test_helper(ring);
- if (r)
- return r;
- amdgpu_fence_driver_force_completion(ring);
- drm_sched_wqueue_start(&ring->sched);
- return 0;
+ return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static struct amdgpu_ring_funcs vcn_v4_0_unified_ring_vm_funcs = {
--
2.50.0
^ permalink raw reply related [flat|nested] 35+ messages in thread* [PATCH 24/30] drm/amdgpu/vcn4.0.3: re-emit unprocessed state on ring reset
2025-06-25 21:06 [PATCH V11 00/30] Reset improvements Alex Deucher
` (22 preceding siblings ...)
2025-06-25 21:06 ` [PATCH 23/30] drm/amdgpu/vcn4: " Alex Deucher
@ 2025-06-25 21:06 ` Alex Deucher
2025-06-25 21:06 ` [PATCH 25/30] drm/amdgpu/vcn4.0.5: " Alex Deucher
` (5 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Alex Deucher @ 2025-06-25 21:06 UTC (permalink / raw)
To: amd-gfx, christian.koenig, sasundar; +Cc: Alex Deucher, Sathishkumar S
Re-emit the unprocessed state after resetting the queue.
Reviewed-by: Sathishkumar S <sathishkumar.sundararaju@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
index d8fd32c1e38ec..3bda19b92cde7 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_3.c
@@ -1609,7 +1609,7 @@ static int vcn_v4_0_3_ring_reset(struct amdgpu_ring *ring,
if (!(adev->vcn.supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE))
return -EOPNOTSUPP;
- drm_sched_wqueue_stop(&ring->sched);
+ amdgpu_ring_reset_helper_begin(ring, timedout_fence);
vcn_inst = GET_INST(VCN, ring->me);
r = amdgpu_dpm_reset_vcn(adev, 1 << vcn_inst);
@@ -1624,12 +1624,8 @@ static int vcn_v4_0_3_ring_reset(struct amdgpu_ring *ring,
adev->vcn.caps |= AMDGPU_VCN_CAPS(RRMT_ENABLED);
vcn_v4_0_3_hw_init_inst(vinst);
vcn_v4_0_3_start_dpg_mode(vinst, adev->vcn.inst[ring->me].indirect_sram);
- r = amdgpu_ring_test_helper(ring);
- if (r)
- return r;
- amdgpu_fence_driver_force_completion(ring);
- drm_sched_wqueue_start(&ring->sched);
- return 0;
+
+ return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static const struct amdgpu_ring_funcs vcn_v4_0_3_unified_ring_vm_funcs = {
--
2.50.0
^ permalink raw reply related [flat|nested] 35+ messages in thread* [PATCH 25/30] drm/amdgpu/vcn4.0.5: re-emit unprocessed state on ring reset
2025-06-25 21:06 [PATCH V11 00/30] Reset improvements Alex Deucher
` (23 preceding siblings ...)
2025-06-25 21:06 ` [PATCH 24/30] drm/amdgpu/vcn4.0.3: " Alex Deucher
@ 2025-06-25 21:06 ` Alex Deucher
2025-06-25 21:06 ` [PATCH 26/30] drm/amdgpu/vcn5: " Alex Deucher
` (4 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Alex Deucher @ 2025-06-25 21:06 UTC (permalink / raw)
To: amd-gfx, christian.koenig, sasundar; +Cc: Alex Deucher, Sathishkumar S
Re-emit the unprocessed state after resetting the queue.
Reviewed-by: Sathishkumar S <sathishkumar.sundararaju@amd.com>
Tested-by: Sathishkumar S <sathishkumar.sundararaju@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
index 7e37ddea63550..faf2df7ed3fd3 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v4_0_5.c
@@ -1471,21 +1471,14 @@ static int vcn_v4_0_5_ring_reset(struct amdgpu_ring *ring,
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me];
- int r;
if (!(adev->vcn.supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE))
return -EOPNOTSUPP;
- drm_sched_wqueue_stop(&ring->sched);
+ amdgpu_ring_reset_helper_begin(ring, timedout_fence);
vcn_v4_0_5_stop(vinst);
vcn_v4_0_5_start(vinst);
-
- r = amdgpu_ring_test_helper(ring);
- if (r)
- return r;
- amdgpu_fence_driver_force_completion(ring);
- drm_sched_wqueue_start(&ring->sched);
- return 0;
+ return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static struct amdgpu_ring_funcs vcn_v4_0_5_unified_ring_vm_funcs = {
--
2.50.0
^ permalink raw reply related [flat|nested] 35+ messages in thread* [PATCH 26/30] drm/amdgpu/vcn5: re-emit unprocessed state on ring reset
2025-06-25 21:06 [PATCH V11 00/30] Reset improvements Alex Deucher
` (24 preceding siblings ...)
2025-06-25 21:06 ` [PATCH 25/30] drm/amdgpu/vcn4.0.5: " Alex Deucher
@ 2025-06-25 21:06 ` Alex Deucher
2025-06-25 21:06 ` [PATCH 27/30] drm/amdgpu/vcn: add a helper framework for engine resets Alex Deucher
` (3 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Alex Deucher @ 2025-06-25 21:06 UTC (permalink / raw)
To: amd-gfx, christian.koenig, sasundar; +Cc: Alex Deucher, Sathishkumar S
Re-emit the unprocessed state after resetting the queue.
Reviewed-by: Sathishkumar S <sathishkumar.sundararaju@amd.com>
Tested-by: Sathishkumar S <sathishkumar.sundararaju@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c | 11 ++---------
1 file changed, 2 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
index 47c0bcc9e7d80..5997927ac6db1 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v5_0_0.c
@@ -1198,21 +1198,14 @@ static int vcn_v5_0_0_ring_reset(struct amdgpu_ring *ring,
{
struct amdgpu_device *adev = ring->adev;
struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[ring->me];
- int r;
if (!(adev->vcn.supported_reset & AMDGPU_RESET_TYPE_PER_QUEUE))
return -EOPNOTSUPP;
- drm_sched_wqueue_stop(&ring->sched);
+ amdgpu_ring_reset_helper_begin(ring, timedout_fence);
vcn_v5_0_0_stop(vinst);
vcn_v5_0_0_start(vinst);
-
- r = amdgpu_ring_test_helper(ring);
- if (r)
- return r;
- amdgpu_fence_driver_force_completion(ring);
- drm_sched_wqueue_start(&ring->sched);
- return 0;
+ return amdgpu_ring_reset_helper_end(ring, timedout_fence);
}
static const struct amdgpu_ring_funcs vcn_v5_0_0_unified_ring_vm_funcs = {
--
2.50.0
^ permalink raw reply related [flat|nested] 35+ messages in thread* [PATCH 27/30] drm/amdgpu/vcn: add a helper framework for engine resets
2025-06-25 21:06 [PATCH V11 00/30] Reset improvements Alex Deucher
` (25 preceding siblings ...)
2025-06-25 21:06 ` [PATCH 26/30] drm/amdgpu/vcn5: " Alex Deucher
@ 2025-06-25 21:06 ` Alex Deucher
2025-06-25 21:06 ` [PATCH 28/30] drm/amdgpu/vcn2: implement ring reset Alex Deucher
` (2 subsequent siblings)
29 siblings, 0 replies; 35+ messages in thread
From: Alex Deucher @ 2025-06-25 21:06 UTC (permalink / raw)
To: amd-gfx, christian.koenig, sasundar; +Cc: Alex Deucher, Sathishkumar S
With engine resets we reset all queues on the engine rather
than just a single queue. Add a framework to handle this
similar to SDMA.
Reviewed-by: Sathishkumar S <sathishkumar.sundararaju@amd.com>
Tested-by: Sathishkumar S <sathishkumar.sundararaju@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c | 76 +++++++++++++++++++++++++
drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h | 6 +-
2 files changed, 81 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
index c8885c3d54b33..f1f67521c29ca 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.c
@@ -134,6 +134,7 @@ int amdgpu_vcn_sw_init(struct amdgpu_device *adev, int i)
mutex_init(&adev->vcn.inst[i].vcn1_jpeg1_workaround);
mutex_init(&adev->vcn.inst[i].vcn_pg_lock);
+ mutex_init(&adev->vcn.inst[i].engine_reset_mutex);
atomic_set(&adev->vcn.inst[i].total_submission_cnt, 0);
INIT_DELAYED_WORK(&adev->vcn.inst[i].idle_work, amdgpu_vcn_idle_work_handler);
atomic_set(&adev->vcn.inst[i].dpg_enc_submission_cnt, 0);
@@ -1451,3 +1452,78 @@ int vcn_set_powergating_state(struct amdgpu_ip_block *ip_block,
return ret;
}
+
+/**
+ * amdgpu_vcn_reset_engine - Reset a specific VCN engine
+ * @adev: Pointer to the AMDGPU device
+ * @instance_id: VCN engine instance to reset
+ *
+ * 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)
+{
+ struct amdgpu_vcn_inst *vinst = &adev->vcn.inst[instance_id];
+ int r, i;
+
+ mutex_lock(&vinst->engine_reset_mutex);
+ /* Stop the scheduler's work queue for the dec and enc rings if they are running.
+ * This ensures that no new tasks are submitted to the queues while
+ * the reset is in progress.
+ */
+ drm_sched_wqueue_stop(&vinst->ring_dec.sched);
+ for (i = 0; i < vinst->num_enc_rings; i++)
+ drm_sched_wqueue_stop(&vinst->ring_enc[i].sched);
+
+ /* Perform the VCN reset for the specified instance */
+ r = vinst->reset(vinst);
+ if (r)
+ goto unlock;
+ r = amdgpu_ring_test_ring(&vinst->ring_dec);
+ if (r)
+ goto unlock;
+ for (i = 0; i < vinst->num_enc_rings; i++) {
+ r = amdgpu_ring_test_ring(&vinst->ring_enc[i]);
+ if (r)
+ goto unlock;
+ }
+ amdgpu_fence_driver_force_completion(&vinst->ring_dec);
+ for (i = 0; i < vinst->num_enc_rings; i++)
+ amdgpu_fence_driver_force_completion(&vinst->ring_enc[i]);
+
+ /* Restart the scheduler's work queue for the dec and enc rings
+ * if they were stopped by this function. This allows new tasks
+ * to be submitted to the queues after the reset is complete.
+ */
+ drm_sched_wqueue_start(&vinst->ring_dec.sched);
+ for (i = 0; i < vinst->num_enc_rings; i++)
+ drm_sched_wqueue_start(&vinst->ring_enc[i].sched);
+
+unlock:
+ mutex_unlock(&vinst->engine_reset_mutex);
+
+ return r;
+}
+
+/**
+ * amdgpu_vcn_ring_reset - Reset a VCN ring
+ * @ring: ring to reset
+ * @vmid: vmid of guilty job
+ * @timedout_fence: fence of timed out job
+ *
+ * This helper is for VCN blocks without unified queues because
+ * resetting the engine resets all queues in that case. With
+ * unified queues we have one queue per engine.
+ * Returns: 0 on success, or a negative error code on failure.
+ */
+int amdgpu_vcn_ring_reset(struct amdgpu_ring *ring,
+ unsigned int vmid,
+ struct amdgpu_fence *timedout_fence)
+{
+ struct amdgpu_device *adev = ring->adev;
+
+ if (adev->vcn.inst[ring->me].using_unified_queue)
+ return -EINVAL;
+
+ return amdgpu_vcn_reset_engine(adev, ring->me);
+}
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
index 83adf81defc71..0bc0a94d7cf0f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vcn.h
@@ -330,7 +330,9 @@ struct amdgpu_vcn_inst {
struct dpg_pause_state *new_state);
int (*set_pg_state)(struct amdgpu_vcn_inst *vinst,
enum amd_powergating_state state);
+ int (*reset)(struct amdgpu_vcn_inst *vinst);
bool using_unified_queue;
+ struct mutex engine_reset_mutex;
};
struct amdgpu_vcn_ras {
@@ -552,5 +554,7 @@ void amdgpu_debugfs_vcn_sched_mask_init(struct amdgpu_device *adev);
int vcn_set_powergating_state(struct amdgpu_ip_block *ip_block,
enum amd_powergating_state state);
-
+int amdgpu_vcn_ring_reset(struct amdgpu_ring *ring,
+ unsigned int vmid,
+ struct amdgpu_fence *guilty_fence);
#endif
--
2.50.0
^ permalink raw reply related [flat|nested] 35+ messages in thread* [PATCH 28/30] drm/amdgpu/vcn2: implement ring reset
2025-06-25 21:06 [PATCH V11 00/30] Reset improvements Alex Deucher
` (26 preceding siblings ...)
2025-06-25 21:06 ` [PATCH 27/30] drm/amdgpu/vcn: add a helper framework for engine resets Alex Deucher
@ 2025-06-25 21:06 ` Alex Deucher
2025-06-25 21:06 ` [PATCH 29/30] drm/amdgpu/vcn2.5: " Alex Deucher
2025-06-25 21:06 ` [PATCH 30/30] drm/amdgpu/vcn3: " Alex Deucher
29 siblings, 0 replies; 35+ messages in thread
From: Alex Deucher @ 2025-06-25 21:06 UTC (permalink / raw)
To: amd-gfx, christian.koenig, sasundar; +Cc: Alex Deucher, Sathishkumar S
Use the new helpers to handle engine resets for VCN.
Reviewed-by: Sathishkumar S <sathishkumar.sundararaju@amd.com>
Tested-by: Sathishkumar S <sathishkumar.sundararaju@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
index 148b651be7ca7..33d210a61483f 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_0.c
@@ -98,6 +98,8 @@ static int vcn_v2_0_set_pg_state(struct amdgpu_vcn_inst *vinst,
static int vcn_v2_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
struct dpg_pause_state *new_state);
static int vcn_v2_0_start_sriov(struct amdgpu_device *adev);
+static int vcn_v2_0_reset(struct amdgpu_vcn_inst *vinst);
+
/**
* vcn_v2_0_early_init - set function pointers and load microcode
*
@@ -213,6 +215,7 @@ static int vcn_v2_0_sw_init(struct amdgpu_ip_block *ip_block)
}
adev->vcn.inst[0].pause_dpg_mode = vcn_v2_0_pause_dpg_mode;
+ adev->vcn.inst[0].reset = vcn_v2_0_reset;
r = amdgpu_virt_alloc_mm_table(adev);
if (r)
@@ -1355,6 +1358,13 @@ static int vcn_v2_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
return 0;
}
+static int vcn_v2_0_reset(struct amdgpu_vcn_inst *vinst)
+{
+ vcn_v2_0_stop(vinst);
+ vcn_v2_0_start(vinst);
+ return 0;
+}
+
static bool vcn_v2_0_is_idle(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
@@ -2176,6 +2186,7 @@ static const struct amdgpu_ring_funcs vcn_v2_0_dec_ring_vm_funcs = {
.emit_wreg = vcn_v2_0_dec_ring_emit_wreg,
.emit_reg_wait = vcn_v2_0_dec_ring_emit_reg_wait,
.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
+ .reset = amdgpu_vcn_ring_reset,
};
static const struct amdgpu_ring_funcs vcn_v2_0_enc_ring_vm_funcs = {
@@ -2205,6 +2216,7 @@ static const struct amdgpu_ring_funcs vcn_v2_0_enc_ring_vm_funcs = {
.emit_wreg = vcn_v2_0_enc_ring_emit_wreg,
.emit_reg_wait = vcn_v2_0_enc_ring_emit_reg_wait,
.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
+ .reset = amdgpu_vcn_ring_reset,
};
static void vcn_v2_0_set_dec_ring_funcs(struct amdgpu_device *adev)
--
2.50.0
^ permalink raw reply related [flat|nested] 35+ messages in thread* [PATCH 29/30] drm/amdgpu/vcn2.5: implement ring reset
2025-06-25 21:06 [PATCH V11 00/30] Reset improvements Alex Deucher
` (27 preceding siblings ...)
2025-06-25 21:06 ` [PATCH 28/30] drm/amdgpu/vcn2: implement ring reset Alex Deucher
@ 2025-06-25 21:06 ` Alex Deucher
2025-06-25 21:06 ` [PATCH 30/30] drm/amdgpu/vcn3: " Alex Deucher
29 siblings, 0 replies; 35+ messages in thread
From: Alex Deucher @ 2025-06-25 21:06 UTC (permalink / raw)
To: amd-gfx, christian.koenig, sasundar; +Cc: Alex Deucher, Sathishkumar S
Use the new helpers to handle engine resets for VCN.
Reviewed-by: Sathishkumar S <sathishkumar.sundararaju@amd.com>
Tested-by: Sathishkumar S <sathishkumar.sundararaju@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
index 58b527a6b795f..49ec4a7775f90 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v2_5.c
@@ -102,6 +102,7 @@ static int vcn_v2_5_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
struct dpg_pause_state *new_state);
static int vcn_v2_5_sriov_start(struct amdgpu_device *adev);
static void vcn_v2_5_set_ras_funcs(struct amdgpu_device *adev);
+static int vcn_v2_5_reset(struct amdgpu_vcn_inst *vinst);
static int amdgpu_ih_clientid_vcns[] = {
SOC15_IH_CLIENTID_VCN,
@@ -404,6 +405,7 @@ static int vcn_v2_5_sw_init(struct amdgpu_ip_block *ip_block)
if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
adev->vcn.inst[j].pause_dpg_mode = vcn_v2_5_pause_dpg_mode;
+ adev->vcn.inst[j].reset = vcn_v2_5_reset;
}
if (amdgpu_sriov_vf(adev)) {
@@ -1816,6 +1818,7 @@ static const struct amdgpu_ring_funcs vcn_v2_5_dec_ring_vm_funcs = {
.emit_wreg = vcn_v2_0_dec_ring_emit_wreg,
.emit_reg_wait = vcn_v2_0_dec_ring_emit_reg_wait,
.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
+ .reset = amdgpu_vcn_ring_reset,
};
/**
@@ -1914,6 +1917,7 @@ static const struct amdgpu_ring_funcs vcn_v2_5_enc_ring_vm_funcs = {
.emit_wreg = vcn_v2_0_enc_ring_emit_wreg,
.emit_reg_wait = vcn_v2_0_enc_ring_emit_reg_wait,
.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
+ .reset = amdgpu_vcn_ring_reset,
};
static void vcn_v2_5_set_dec_ring_funcs(struct amdgpu_device *adev)
@@ -1942,6 +1946,13 @@ static void vcn_v2_5_set_enc_ring_funcs(struct amdgpu_device *adev)
}
}
+static int vcn_v2_5_reset(struct amdgpu_vcn_inst *vinst)
+{
+ vcn_v2_5_stop(vinst);
+ vcn_v2_5_start(vinst);
+ return 0;
+}
+
static bool vcn_v2_5_is_idle(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
--
2.50.0
^ permalink raw reply related [flat|nested] 35+ messages in thread* [PATCH 30/30] drm/amdgpu/vcn3: implement ring reset
2025-06-25 21:06 [PATCH V11 00/30] Reset improvements Alex Deucher
` (28 preceding siblings ...)
2025-06-25 21:06 ` [PATCH 29/30] drm/amdgpu/vcn2.5: " Alex Deucher
@ 2025-06-25 21:06 ` Alex Deucher
29 siblings, 0 replies; 35+ messages in thread
From: Alex Deucher @ 2025-06-25 21:06 UTC (permalink / raw)
To: amd-gfx, christian.koenig, sasundar; +Cc: Alex Deucher, Sathishkumar S
Use the new helpers to handle engine resets for VCN.
Reviewed-by: Sathishkumar S <sathishkumar.sundararaju@amd.com>
Tested-by: Sathishkumar S <sathishkumar.sundararaju@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
---
drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c | 13 +++++++++++++
1 file changed, 13 insertions(+)
diff --git a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
index 9fb0d53805892..dd015bc6fd0ee 100644
--- a/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
+++ b/drivers/gpu/drm/amd/amdgpu/vcn_v3_0.c
@@ -110,6 +110,7 @@ static int vcn_v3_0_set_pg_state(struct amdgpu_vcn_inst *vinst,
enum amd_powergating_state state);
static int vcn_v3_0_pause_dpg_mode(struct amdgpu_vcn_inst *vinst,
struct dpg_pause_state *new_state);
+static int vcn_v3_0_reset(struct amdgpu_vcn_inst *vinst);
static void vcn_v3_0_dec_ring_set_wptr(struct amdgpu_ring *ring);
static void vcn_v3_0_enc_ring_set_wptr(struct amdgpu_ring *ring);
@@ -289,6 +290,7 @@ static int vcn_v3_0_sw_init(struct amdgpu_ip_block *ip_block)
if (adev->pg_flags & AMD_PG_SUPPORT_VCN_DPG)
adev->vcn.inst[i].pause_dpg_mode = vcn_v3_0_pause_dpg_mode;
+ adev->vcn.inst[i].reset = vcn_v3_0_reset;
}
if (amdgpu_sriov_vf(adev)) {
@@ -2033,6 +2035,7 @@ static const struct amdgpu_ring_funcs vcn_v3_0_dec_ring_vm_funcs = {
.emit_wreg = vcn_v2_0_dec_ring_emit_wreg,
.emit_reg_wait = vcn_v2_0_dec_ring_emit_reg_wait,
.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
+ .reset = amdgpu_vcn_ring_reset,
};
/**
@@ -2131,6 +2134,7 @@ static const struct amdgpu_ring_funcs vcn_v3_0_enc_ring_vm_funcs = {
.emit_wreg = vcn_v2_0_enc_ring_emit_wreg,
.emit_reg_wait = vcn_v2_0_enc_ring_emit_reg_wait,
.emit_reg_write_reg_wait = amdgpu_ring_emit_reg_write_reg_wait_helper,
+ .reset = amdgpu_vcn_ring_reset,
};
static void vcn_v3_0_set_dec_ring_funcs(struct amdgpu_device *adev)
@@ -2164,6 +2168,15 @@ static void vcn_v3_0_set_enc_ring_funcs(struct amdgpu_device *adev)
}
}
+static int vcn_v3_0_reset(struct amdgpu_vcn_inst *vinst)
+{
+ vcn_v3_0_stop(vinst);
+ vcn_v3_0_enable_clock_gating(vinst);
+ vcn_v3_0_enable_static_power_gating(vinst);
+ vcn_v3_0_start(vinst);
+ return 0;
+}
+
static bool vcn_v3_0_is_idle(struct amdgpu_ip_block *ip_block)
{
struct amdgpu_device *adev = ip_block->adev;
--
2.50.0
^ permalink raw reply related [flat|nested] 35+ messages in thread