* [PATCH v2 0/8] drm/sched: Allow drivers to skip the reset with DRM_GPU_SCHED_STAT_NO_HANG
@ 2025-05-30 14:01 Maíra Canal
2025-05-30 14:01 ` [PATCH v2 1/8] drm/sched: Rename DRM_GPU_SCHED_STAT_NOMINAL to DRM_GPU_SCHED_STAT_RESET Maíra Canal
` (7 more replies)
0 siblings, 8 replies; 19+ messages in thread
From: Maíra Canal @ 2025-05-30 14:01 UTC (permalink / raw)
To: Matthew Brost, Danilo Krummrich, Philipp Stanner,
Christian König, Tvrtko Ursulin, Simona Vetter, David Airlie,
Melissa Wen, Lucas Stach, Russell King, Christian Gmeiner,
Lucas De Marchi, Thomas Hellström, Rodrigo Vivi,
Boris Brezillon, Rob Herring, Steven Price, Liviu Dudau
Cc: kernel-dev, dri-devel, etnaviv, intel-xe, Maíra Canal,
Min Ma, Lizhi Hou, Oded Gabbay, Frank Binns, Matt Coster,
Qiang Yu, Lyude Paul, Alex Deucher, Christian König
When the DRM scheduler times out, it's possible that the GPU isn't hung;
instead, a job may still be running, and there may be no valid reason to
reset the hardware. This can occur in two situations:
1. The GPU exposes some mechanism that ensures the GPU is still making
progress. By checking this mechanism, the driver can safely skip the
reset, re-arm the timeout, and allow the job to continue running until
completion. This is the case for v3d, Etnaviv, and Xe.
2. Timeout has fired before the free-job worker. Consequently, the
scheduler calls `timedout_job()` for a job that isn't timed out.
These two scenarios are problematic because the job was removed from the
`sched->pending_list` before calling `sched->ops->timedout_job()`, which
means that when the job finishes, it won't be freed by the scheduler
though `sched->ops->free_job()`. As a result, the job and its resources
won't be freed, leading to a memory leak.
For v3d specifically, we have observed that these memory leaks can be
significant in certain scenarios, as reported by users in [1][2]. To
address this situation, I submitted a patch similar to commit 704d3d60fec4
("drm/etnaviv: don't block scheduler when GPU is still active") for v3d [3].
This patch has already landed in drm-misc-fixes and successfully resolved
the users' issues.
However, as I mentioned in [3], exposing the scheduler's internals within
the drivers isn't ideal and I believe this specific situation can be
addressed within the DRM scheduler framework.
This series aims to resolve this issue by adding a new DRM sched status
that allows a driver to skip the reset. This new status will indicate that
the job should be reinserted into the pending list, and the driver will
still signal its completion.
[1] https://gitlab.freedesktop.org/mesa/mesa/-/issues/12227
[2] https://github.com/raspberrypi/linux/issues/6817
[3] https://lore.kernel.org/dri-devel/20250430210643.57924-1-mcanal@igalia.com/T/
Best Regards,
- Maíra
---
v1 -> v2:
- Fix several grammar nits across the documentation and commit messages.
- Drop "drm/sched: Always free the job after the timeout" (Tvrtko Ursulin)
- [1/8] NEW PATCH: Rename DRM_GPU_SCHED_STAT_NOMINAL to a more semantic
name (Tvrtko Ursulin, Philipp Stanner)
- [2/8] Rename DRM_GPU_SCHED_STAT_RUNNING to DRM_GPU_SCHED_STAT_NO_HANG (Tvrtko Ursulin, Philipp Stanner)
- [2/8] Requeue free-job work after reinserting the job to the pending list (Matthew Brost)
- [2/8] Create a helper function to reinsert the job (Philipp Stanner)
- [2/8] Rewrite the commit message (Philipp Stanner)
- [2/8] Add a comment to `drm_sched_start()` documentation, similar to what
was commented in `drm_sched_stop()` (Philipp Stanner)
- [3/8] Keep HZ as timeout for `drm_mock_sched_job_wait_scheduled()` (Tvrtko Ursulin)
- [4/8] Use a job flag to indicate that `timedout_job()` should skip the
reset (Tvrtko Ursulin)
- [7/8] Use DRM_GPU_SCHED_STAT_NO_HANG to re-arm the timer in other cases
as well (Matthew Brost)
- Link to v1: https://lore.kernel.org/r/20250503-sched-skip-reset-v1-0-ed0d6701a3fe@igalia.com
---
Maíra Canal (8):
drm/sched: Rename DRM_GPU_SCHED_STAT_NOMINAL to DRM_GPU_SCHED_STAT_RESET
drm/sched: Allow drivers to skip the reset and keep on running
drm/sched: Reduce scheduler's timeout for timeout tests
drm/sched: Add new test for DRM_GPU_SCHED_STAT_NO_HANG
drm/v3d: Use DRM_GPU_SCHED_STAT_NO_HANG to skip the reset
drm/etnaviv: Use DRM_GPU_SCHED_STAT_NO_HANG to skip the reset
drm/xe: Use DRM_GPU_SCHED_STAT_NO_HANG to skip the reset
drm/panfrost: Use DRM_GPU_SCHED_STAT_NO_HANG to skip the reset
drivers/accel/amdxdna/aie2_ctx.c | 2 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 2 +-
drivers/gpu/drm/etnaviv/etnaviv_sched.c | 13 +++---
drivers/gpu/drm/imagination/pvr_queue.c | 4 +-
drivers/gpu/drm/lima/lima_sched.c | 6 +--
drivers/gpu/drm/nouveau/nouveau_exec.c | 2 +-
drivers/gpu/drm/nouveau/nouveau_sched.c | 2 +-
drivers/gpu/drm/panfrost/panfrost_job.c | 10 ++---
drivers/gpu/drm/panthor/panthor_mmu.c | 2 +-
drivers/gpu/drm/panthor/panthor_sched.c | 2 +-
drivers/gpu/drm/scheduler/sched_main.c | 51 ++++++++++++++++++++++--
drivers/gpu/drm/scheduler/tests/mock_scheduler.c | 7 +++-
drivers/gpu/drm/scheduler/tests/sched_tests.h | 1 +
drivers/gpu/drm/scheduler/tests/tests_basic.c | 51 ++++++++++++++++++++++--
drivers/gpu/drm/v3d/v3d_sched.c | 6 +--
drivers/gpu/drm/xe/xe_guc_submit.c | 14 ++-----
include/drm/gpu_scheduler.h | 7 +++-
17 files changed, 136 insertions(+), 46 deletions(-)
---
base-commit: df1c3093aee3daee4d56a5cb8cdba75c1ef6962f
change-id: 20250502-sched-skip-reset-bf7c163233da
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v2 1/8] drm/sched: Rename DRM_GPU_SCHED_STAT_NOMINAL to DRM_GPU_SCHED_STAT_RESET
2025-05-30 14:01 [PATCH v2 0/8] drm/sched: Allow drivers to skip the reset with DRM_GPU_SCHED_STAT_NO_HANG Maíra Canal
@ 2025-05-30 14:01 ` Maíra Canal
2025-05-30 14:01 ` [PATCH v2 2/8] drm/sched: Allow drivers to skip the reset and keep on running Maíra Canal
` (6 subsequent siblings)
7 siblings, 0 replies; 19+ messages in thread
From: Maíra Canal @ 2025-05-30 14:01 UTC (permalink / raw)
To: Matthew Brost, Danilo Krummrich, Philipp Stanner,
Christian König, Tvrtko Ursulin, Simona Vetter, David Airlie,
Melissa Wen, Lucas Stach, Russell King, Christian Gmeiner,
Lucas De Marchi, Thomas Hellström, Rodrigo Vivi,
Boris Brezillon, Rob Herring, Steven Price, Liviu Dudau
Cc: kernel-dev, dri-devel, etnaviv, intel-xe, Maíra Canal,
Min Ma, Lizhi Hou, Oded Gabbay, Frank Binns, Matt Coster,
Qiang Yu, Lyude Paul, Alex Deucher, Christian König
Among the scheduler's statuses, the only one that indicates an error is
DRM_GPU_SCHED_STAT_ENODEV. Any status other than DRM_GPU_SCHED_STAT_ENODEV
signifies that the operation succeeded and the GPU is in a nominal state.
However, to provide more information about the GPU's status, it is needed
to convey more information than just "OK".
Therefore, rename DRM_GPU_SCHED_STAT_NOMINAL to
DRM_GPU_SCHED_STAT_RESET, which betters communicates the meaning of this
status. The status DRM_GPU_SCHED_STAT_RESET indicates that the GPU has
hung, but it has been successfully reset and is now in a nominal state
again.
Signed-off-by: Maíra Canal <mcanal@igalia.com>
---
To: Min Ma <min.ma@amd.com>
To: Lizhi Hou <lizhi.hou@amd.com>
To: Oded Gabbay <ogabbay@kernel.org>
To: Frank Binns <frank.binns@imgtec.com>
To: Matt Coster <matt.coster@imgtec.com>
To: Qiang Yu <yuq825@gmail.com>
To: Lyude Paul <lyude@redhat.com>
To: Alex Deucher <alexander.deucher@amd.com>
To: Christian König <christian.koenig@amd.com>
---
drivers/accel/amdxdna/aie2_ctx.c | 2 +-
drivers/gpu/drm/amd/amdgpu/amdgpu_job.c | 2 +-
drivers/gpu/drm/etnaviv/etnaviv_sched.c | 4 ++--
drivers/gpu/drm/imagination/pvr_queue.c | 4 ++--
drivers/gpu/drm/lima/lima_sched.c | 6 +++---
drivers/gpu/drm/nouveau/nouveau_exec.c | 2 +-
drivers/gpu/drm/nouveau/nouveau_sched.c | 2 +-
drivers/gpu/drm/panfrost/panfrost_job.c | 6 +++---
drivers/gpu/drm/panthor/panthor_mmu.c | 2 +-
drivers/gpu/drm/panthor/panthor_sched.c | 2 +-
drivers/gpu/drm/scheduler/sched_main.c | 2 +-
drivers/gpu/drm/scheduler/tests/mock_scheduler.c | 2 +-
drivers/gpu/drm/v3d/v3d_sched.c | 6 +++---
drivers/gpu/drm/xe/xe_guc_submit.c | 6 +++---
include/drm/gpu_scheduler.h | 4 ++--
15 files changed, 26 insertions(+), 26 deletions(-)
diff --git a/drivers/accel/amdxdna/aie2_ctx.c b/drivers/accel/amdxdna/aie2_ctx.c
index 3e38a5f637ea049c9b8f08dc270482377a4fc4f3..756f817cc8fe523041ab11a6454e0f42d9781f9e 100644
--- a/drivers/accel/amdxdna/aie2_ctx.c
+++ b/drivers/accel/amdxdna/aie2_ctx.c
@@ -361,7 +361,7 @@ aie2_sched_job_timedout(struct drm_sched_job *sched_job)
aie2_hwctx_restart(xdna, hwctx);
mutex_unlock(&xdna->dev_lock);
- return DRM_GPU_SCHED_STAT_NOMINAL;
+ return DRM_GPU_SCHED_STAT_RESET;
}
static const struct drm_sched_backend_ops sched_ops = {
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
index 75262ce8db27fad4a1f1af00639031b040f21c87..863e1158196cc0db0296abadd2302de1c700649b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_job.c
@@ -199,7 +199,7 @@ static enum drm_gpu_sched_stat amdgpu_job_timedout(struct drm_sched_job *s_job)
exit:
drm_dev_exit(idx);
- return DRM_GPU_SCHED_STAT_NOMINAL;
+ return DRM_GPU_SCHED_STAT_RESET;
}
int amdgpu_job_alloc(struct amdgpu_device *adev, struct amdgpu_vm *vm,
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c b/drivers/gpu/drm/etnaviv/etnaviv_sched.c
index 76a3a3e517d8d9f654fb6b9e98e72910795cfc7a..7146069a98492f5fab2a49d96e2054f649e1fe3d 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c
@@ -86,11 +86,11 @@ static enum drm_gpu_sched_stat etnaviv_sched_timedout_job(struct drm_sched_job
drm_sched_resubmit_jobs(&gpu->sched);
drm_sched_start(&gpu->sched, 0);
- return DRM_GPU_SCHED_STAT_NOMINAL;
+ return DRM_GPU_SCHED_STAT_RESET;
out_no_timeout:
list_add(&sched_job->list, &sched_job->sched->pending_list);
- return DRM_GPU_SCHED_STAT_NOMINAL;
+ return DRM_GPU_SCHED_STAT_RESET;
}
static void etnaviv_sched_free_job(struct drm_sched_job *sched_job)
diff --git a/drivers/gpu/drm/imagination/pvr_queue.c b/drivers/gpu/drm/imagination/pvr_queue.c
index 5a41ee79fed646a86344cd16e78efdb45ff02e43..fc415dd0d7a73631bd4144c9f35b9b294c625a12 100644
--- a/drivers/gpu/drm/imagination/pvr_queue.c
+++ b/drivers/gpu/drm/imagination/pvr_queue.c
@@ -803,7 +803,7 @@ static void pvr_queue_start(struct pvr_queue *queue)
* the scheduler, and re-assign parent fences in the middle.
*
* Return:
- * * DRM_GPU_SCHED_STAT_NOMINAL.
+ * * DRM_GPU_SCHED_STAT_RESET.
*/
static enum drm_gpu_sched_stat
pvr_queue_timedout_job(struct drm_sched_job *s_job)
@@ -854,7 +854,7 @@ pvr_queue_timedout_job(struct drm_sched_job *s_job)
drm_sched_start(sched, 0);
- return DRM_GPU_SCHED_STAT_NOMINAL;
+ return DRM_GPU_SCHED_STAT_RESET;
}
/**
diff --git a/drivers/gpu/drm/lima/lima_sched.c b/drivers/gpu/drm/lima/lima_sched.c
index 954f4325b859b2977a2cc608a99a6ebb642f1000..739e8c6c6d909aa4263bad8a12ec07f0c6607bb2 100644
--- a/drivers/gpu/drm/lima/lima_sched.c
+++ b/drivers/gpu/drm/lima/lima_sched.c
@@ -412,7 +412,7 @@ static enum drm_gpu_sched_stat lima_sched_timedout_job(struct drm_sched_job *job
*/
if (dma_fence_is_signaled(task->fence)) {
DRM_WARN("%s spurious timeout\n", lima_ip_name(ip));
- return DRM_GPU_SCHED_STAT_NOMINAL;
+ return DRM_GPU_SCHED_STAT_RESET;
}
/*
@@ -429,7 +429,7 @@ static enum drm_gpu_sched_stat lima_sched_timedout_job(struct drm_sched_job *job
if (dma_fence_is_signaled(task->fence)) {
DRM_WARN("%s unexpectedly high interrupt latency\n", lima_ip_name(ip));
- return DRM_GPU_SCHED_STAT_NOMINAL;
+ return DRM_GPU_SCHED_STAT_RESET;
}
/*
@@ -467,7 +467,7 @@ static enum drm_gpu_sched_stat lima_sched_timedout_job(struct drm_sched_job *job
drm_sched_resubmit_jobs(&pipe->base);
drm_sched_start(&pipe->base, 0);
- return DRM_GPU_SCHED_STAT_NOMINAL;
+ return DRM_GPU_SCHED_STAT_RESET;
}
static void lima_sched_free_job(struct drm_sched_job *job)
diff --git a/drivers/gpu/drm/nouveau/nouveau_exec.c b/drivers/gpu/drm/nouveau/nouveau_exec.c
index a0b5f1b16e8b39a84e3e79429a532b10fbffd066..1b89f1b36b89c7ea4f4ca2f3ea799511858fc068 100644
--- a/drivers/gpu/drm/nouveau/nouveau_exec.c
+++ b/drivers/gpu/drm/nouveau/nouveau_exec.c
@@ -185,7 +185,7 @@ nouveau_exec_job_timeout(struct nouveau_job *job)
NV_PRINTK(warn, job->cli, "job timeout, channel %d killed!\n",
chan->chid);
- return DRM_GPU_SCHED_STAT_NOMINAL;
+ return DRM_GPU_SCHED_STAT_RESET;
}
static const struct nouveau_job_ops nouveau_exec_job_ops = {
diff --git a/drivers/gpu/drm/nouveau/nouveau_sched.c b/drivers/gpu/drm/nouveau/nouveau_sched.c
index 460a5fb024129a0557f2b55008278e1378019d89..e60f7892f5ce9aff0c5fa1908c1a0445891927ed 100644
--- a/drivers/gpu/drm/nouveau/nouveau_sched.c
+++ b/drivers/gpu/drm/nouveau/nouveau_sched.c
@@ -371,7 +371,7 @@ nouveau_sched_timedout_job(struct drm_sched_job *sched_job)
{
struct drm_gpu_scheduler *sched = sched_job->sched;
struct nouveau_job *job = to_nouveau_job(sched_job);
- enum drm_gpu_sched_stat stat = DRM_GPU_SCHED_STAT_NOMINAL;
+ enum drm_gpu_sched_stat stat = DRM_GPU_SCHED_STAT_RESET;
drm_sched_stop(sched, sched_job);
diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c
index 5657106c2f7d0a0ca6162850767f58f3200cce13..afcffe7f8fe9e11f84e4ab7e8f5a72f7bf583690 100644
--- a/drivers/gpu/drm/panfrost/panfrost_job.c
+++ b/drivers/gpu/drm/panfrost/panfrost_job.c
@@ -755,7 +755,7 @@ static enum drm_gpu_sched_stat panfrost_job_timedout(struct drm_sched_job
* spurious. Bail out.
*/
if (dma_fence_is_signaled(job->done_fence))
- return DRM_GPU_SCHED_STAT_NOMINAL;
+ return DRM_GPU_SCHED_STAT_RESET;
/*
* Panfrost IRQ handler may take a long time to process an interrupt
@@ -770,7 +770,7 @@ static enum drm_gpu_sched_stat panfrost_job_timedout(struct drm_sched_job
if (dma_fence_is_signaled(job->done_fence)) {
dev_warn(pfdev->dev, "unexpectedly high interrupt latency\n");
- return DRM_GPU_SCHED_STAT_NOMINAL;
+ return DRM_GPU_SCHED_STAT_RESET;
}
dev_err(pfdev->dev, "gpu sched timeout, js=%d, config=0x%x, status=0x%x, head=0x%x, tail=0x%x, sched_job=%p",
@@ -786,7 +786,7 @@ static enum drm_gpu_sched_stat panfrost_job_timedout(struct drm_sched_job
atomic_set(&pfdev->reset.pending, 1);
panfrost_reset(pfdev, sched_job);
- return DRM_GPU_SCHED_STAT_NOMINAL;
+ return DRM_GPU_SCHED_STAT_RESET;
}
static void panfrost_reset_work(struct work_struct *work)
diff --git a/drivers/gpu/drm/panthor/panthor_mmu.c b/drivers/gpu/drm/panthor/panthor_mmu.c
index 4ae72b2117937f609593e47686d944854111edd7..96bad928a7ceb3993aefb423a792145c8aa9fb92 100644
--- a/drivers/gpu/drm/panthor/panthor_mmu.c
+++ b/drivers/gpu/drm/panthor/panthor_mmu.c
@@ -2282,7 +2282,7 @@ static enum drm_gpu_sched_stat
panthor_vm_bind_timedout_job(struct drm_sched_job *sched_job)
{
WARN(1, "VM_BIND ops are synchronous for now, there should be no timeout!");
- return DRM_GPU_SCHED_STAT_NOMINAL;
+ return DRM_GPU_SCHED_STAT_RESET;
}
static const struct drm_sched_backend_ops panthor_vm_bind_ops = {
diff --git a/drivers/gpu/drm/panthor/panthor_sched.c b/drivers/gpu/drm/panthor/panthor_sched.c
index a2248f692a030c1c84869b9a1948ad1cb0c0b490..8f17394cc82aad9eaf01e473cd9d3dea46fa3d61 100644
--- a/drivers/gpu/drm/panthor/panthor_sched.c
+++ b/drivers/gpu/drm/panthor/panthor_sched.c
@@ -3241,7 +3241,7 @@ queue_timedout_job(struct drm_sched_job *sched_job)
queue_start(queue);
- return DRM_GPU_SCHED_STAT_NOMINAL;
+ return DRM_GPU_SCHED_STAT_RESET;
}
static void queue_free_job(struct drm_sched_job *sched_job)
diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c
index d20726d7adf0212a3651a3f64544f308e7412b4a..3b0760dfa4fe2fc63e893cda733e78d08dd451d5 100644
--- a/drivers/gpu/drm/scheduler/sched_main.c
+++ b/drivers/gpu/drm/scheduler/sched_main.c
@@ -540,7 +540,7 @@ static void drm_sched_job_timedout(struct work_struct *work)
{
struct drm_gpu_scheduler *sched;
struct drm_sched_job *job;
- enum drm_gpu_sched_stat status = DRM_GPU_SCHED_STAT_NOMINAL;
+ enum drm_gpu_sched_stat status = DRM_GPU_SCHED_STAT_RESET;
sched = container_of(work, struct drm_gpu_scheduler, work_tdr.work);
diff --git a/drivers/gpu/drm/scheduler/tests/mock_scheduler.c b/drivers/gpu/drm/scheduler/tests/mock_scheduler.c
index fcddaeaa921760715a344b81ebbed6cc921231ac..fdf5f34b39e02c8a8648d8bea566a27fd3251516 100644
--- a/drivers/gpu/drm/scheduler/tests/mock_scheduler.c
+++ b/drivers/gpu/drm/scheduler/tests/mock_scheduler.c
@@ -208,7 +208,7 @@ mock_sched_timedout_job(struct drm_sched_job *sched_job)
job->flags |= DRM_MOCK_SCHED_JOB_TIMEDOUT;
- return DRM_GPU_SCHED_STAT_NOMINAL;
+ return DRM_GPU_SCHED_STAT_RESET;
}
static void mock_sched_free_job(struct drm_sched_job *sched_job)
diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c
index 466d28ceee28d6c173197b07c0d5f73c8db53e2c..e1997387831541fb053e472672004cf511c25558 100644
--- a/drivers/gpu/drm/v3d/v3d_sched.c
+++ b/drivers/gpu/drm/v3d/v3d_sched.c
@@ -741,7 +741,7 @@ v3d_gpu_reset_for_timeout(struct v3d_dev *v3d, struct drm_sched_job *sched_job)
mutex_unlock(&v3d->reset_lock);
- return DRM_GPU_SCHED_STAT_NOMINAL;
+ return DRM_GPU_SCHED_STAT_RESET;
}
/* If the current address or return address have changed, then the GPU
@@ -761,7 +761,7 @@ v3d_cl_job_timedout(struct drm_sched_job *sched_job, enum v3d_queue q,
if (*timedout_ctca != ctca || *timedout_ctra != ctra) {
*timedout_ctca = ctca;
*timedout_ctra = ctra;
- return DRM_GPU_SCHED_STAT_NOMINAL;
+ return DRM_GPU_SCHED_STAT_RESET;
}
return v3d_gpu_reset_for_timeout(v3d, sched_job);
@@ -805,7 +805,7 @@ v3d_csd_job_timedout(struct drm_sched_job *sched_job)
*/
if (job->timedout_batches != batches) {
job->timedout_batches = batches;
- return DRM_GPU_SCHED_STAT_NOMINAL;
+ return DRM_GPU_SCHED_STAT_RESET;
}
return v3d_gpu_reset_for_timeout(v3d, sched_job);
diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
index 813c3c0bb2500722b03831d9815e83400460c9e2..98363d688cbbf884e17e6610366202a3372f5fe0 100644
--- a/drivers/gpu/drm/xe/xe_guc_submit.c
+++ b/drivers/gpu/drm/xe/xe_guc_submit.c
@@ -1071,7 +1071,7 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
xe_sched_add_pending_job(sched, job);
xe_sched_submission_start(sched);
- return DRM_GPU_SCHED_STAT_NOMINAL;
+ return DRM_GPU_SCHED_STAT_RESET;
}
/* Kill the run_job entry point */
@@ -1237,7 +1237,7 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
/* Start fence signaling */
xe_hw_fence_irq_start(q->fence_irq);
- return DRM_GPU_SCHED_STAT_NOMINAL;
+ return DRM_GPU_SCHED_STAT_RESET;
sched_enable:
enable_scheduling(q);
@@ -1250,7 +1250,7 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
xe_sched_add_pending_job(sched, job);
xe_sched_submission_start(sched);
- return DRM_GPU_SCHED_STAT_NOMINAL;
+ return DRM_GPU_SCHED_STAT_RESET;
}
static void __guc_exec_queue_fini_async(struct work_struct *w)
diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h
index e62a7214e05217d72de5c6e5168544d47099090a..83e5c00d8dd9a83ab20547a93d6fc572de97616e 100644
--- a/include/drm/gpu_scheduler.h
+++ b/include/drm/gpu_scheduler.h
@@ -391,12 +391,12 @@ struct drm_sched_job {
* enum drm_gpu_sched_stat - the scheduler's status
*
* @DRM_GPU_SCHED_STAT_NONE: Reserved. Do not use.
- * @DRM_GPU_SCHED_STAT_NOMINAL: Operation succeeded.
+ * @DRM_GPU_SCHED_STAT_RESET: The GPU hung and successfully reset.
* @DRM_GPU_SCHED_STAT_ENODEV: Error: Device is not available anymore.
*/
enum drm_gpu_sched_stat {
DRM_GPU_SCHED_STAT_NONE,
- DRM_GPU_SCHED_STAT_NOMINAL,
+ DRM_GPU_SCHED_STAT_RESET,
DRM_GPU_SCHED_STAT_ENODEV,
};
--
2.49.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 2/8] drm/sched: Allow drivers to skip the reset and keep on running
2025-05-30 14:01 [PATCH v2 0/8] drm/sched: Allow drivers to skip the reset with DRM_GPU_SCHED_STAT_NO_HANG Maíra Canal
2025-05-30 14:01 ` [PATCH v2 1/8] drm/sched: Rename DRM_GPU_SCHED_STAT_NOMINAL to DRM_GPU_SCHED_STAT_RESET Maíra Canal
@ 2025-05-30 14:01 ` Maíra Canal
2025-06-02 7:06 ` Philipp Stanner
2025-05-30 14:01 ` [PATCH v2 3/8] drm/sched: Reduce scheduler's timeout for timeout tests Maíra Canal
` (5 subsequent siblings)
7 siblings, 1 reply; 19+ messages in thread
From: Maíra Canal @ 2025-05-30 14:01 UTC (permalink / raw)
To: Matthew Brost, Danilo Krummrich, Philipp Stanner,
Christian König, Tvrtko Ursulin, Simona Vetter, David Airlie,
Melissa Wen, Lucas Stach, Russell King, Christian Gmeiner,
Lucas De Marchi, Thomas Hellström, Rodrigo Vivi,
Boris Brezillon, Rob Herring, Steven Price, Liviu Dudau
Cc: kernel-dev, dri-devel, etnaviv, intel-xe, Maíra Canal
When the DRM scheduler times out, it's possible that the GPU isn't hung;
instead, a job may still be running, and there may be no valid reason to
reset the hardware. This can occur in two situations:
1. The GPU exposes some mechanism that ensures the GPU is still making
progress. By checking this mechanism, the driver can safely skip the
reset, re-arm the timeout, and allow the job to continue running until
completion. This is the case for v3d, Etnaviv, and Xe.
2. Timeout has fired before the free-job worker. Consequently, the
scheduler calls `timedout_job()` for a job that isn't timed out.
These two scenarios are problematic because the job was removed from the
`sched->pending_list` before calling `sched->ops->timedout_job()`, which
means that when the job finishes, it won't be freed by the scheduler
though `sched->ops->free_job()`. As a result, the job and its resources
won't be freed, leading to a memory leak.
To resolve those scenarios, create a new `drm_gpu_sched_stat`, called
DRM_GPU_SCHED_STAT_NO_HANG, that allows a driver to skip the reset. The
new status will indicate that the job should be reinserted into the
pending list, and the hardware / driver is still responsible to
signal job completion.
Signed-off-by: Maíra Canal <mcanal@igalia.com>
---
drivers/gpu/drm/scheduler/sched_main.c | 49 ++++++++++++++++++++++++++++++++--
include/drm/gpu_scheduler.h | 3 +++
2 files changed, 50 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/scheduler/sched_main.c b/drivers/gpu/drm/scheduler/sched_main.c
index 3b0760dfa4fe2fc63e893cda733e78d08dd451d5..ddc53eadab7bb6a15109f43989afa1f7a95a3b41 100644
--- a/drivers/gpu/drm/scheduler/sched_main.c
+++ b/drivers/gpu/drm/scheduler/sched_main.c
@@ -379,11 +379,16 @@ static void drm_sched_run_free_queue(struct drm_gpu_scheduler *sched)
{
struct drm_sched_job *job;
- spin_lock(&sched->job_list_lock);
job = list_first_entry_or_null(&sched->pending_list,
struct drm_sched_job, list);
if (job && dma_fence_is_signaled(&job->s_fence->finished))
__drm_sched_run_free_queue(sched);
+}
+
+static void drm_sched_run_free_queue_unlocked(struct drm_gpu_scheduler *sched)
+{
+ spin_lock(&sched->job_list_lock);
+ drm_sched_run_free_queue(sched);
spin_unlock(&sched->job_list_lock);
}
@@ -536,6 +541,32 @@ static void drm_sched_job_begin(struct drm_sched_job *s_job)
spin_unlock(&sched->job_list_lock);
}
+/**
+ * drm_sched_job_reinsert_on_false_timeout - Reinsert the job on a false timeout
+ *
+ * @sched: scheduler instance
+ * @job: job to be reinserted on the pending list
+ *
+ * In the case of a "false timeout" - when a timeout occurs but the GPU isn't
+ * hung and the job is making progress, the scheduler must reinsert the job back
+ * into the pending list. Otherwise, the job and its resources won't be freed
+ * through the &drm_sched_backend_ops.free_job callback.
+ *
+ * Note that after reinserting the job, the scheduler enqueues the free-job
+ * work again if ready. Otherwise, a signaled job could be added to the pending
+ * list, but never freed.
+ *
+ * This function must be used in "false timeout" cases only.
+ */
+static void drm_sched_job_reinsert_on_false_timeout(struct drm_gpu_scheduler *sched,
+ struct drm_sched_job *job)
+{
+ spin_lock(&sched->job_list_lock);
+ list_add(&job->list, &sched->pending_list);
+ drm_sched_run_free_queue(sched);
+ spin_unlock(&sched->job_list_lock);
+}
+
static void drm_sched_job_timedout(struct work_struct *work)
{
struct drm_gpu_scheduler *sched;
@@ -569,6 +600,14 @@ static void drm_sched_job_timedout(struct work_struct *work)
job->sched->ops->free_job(job);
sched->free_guilty = false;
}
+
+ /*
+ * If the driver indicated that the GPU is still running and wants
+ * to skip the reset, reinsert the job back into the pending list
+ * and re-arm the timeout.
+ */
+ if (status == DRM_GPU_SCHED_STAT_NO_HANG)
+ drm_sched_job_reinsert_on_false_timeout(sched, job);
} else {
spin_unlock(&sched->job_list_lock);
}
@@ -591,6 +630,9 @@ static void drm_sched_job_timedout(struct work_struct *work)
* This function is typically used for reset recovery (see the docu of
* drm_sched_backend_ops.timedout_job() for details). Do not call it for
* scheduler teardown, i.e., before calling drm_sched_fini().
+ *
+ * As it's used for reset recovery, drm_sched_stop() shouldn't be called
+ * if the driver skipped the timeout (DRM_GPU_SCHED_STAT_NO_HANG).
*/
void drm_sched_stop(struct drm_gpu_scheduler *sched, struct drm_sched_job *bad)
{
@@ -676,6 +718,9 @@ EXPORT_SYMBOL(drm_sched_stop);
* drm_sched_backend_ops.timedout_job() for details). Do not call it for
* scheduler startup. The scheduler itself is fully operational after
* drm_sched_init() succeeded.
+ *
+ * As it's used for reset recovery, drm_sched_start() shouldn't be called
+ * if the driver skipped the timeout (DRM_GPU_SCHED_STAT_NO_HANG).
*/
void drm_sched_start(struct drm_gpu_scheduler *sched, int errno)
{
@@ -1197,7 +1242,7 @@ static void drm_sched_free_job_work(struct work_struct *w)
if (job)
sched->ops->free_job(job);
- drm_sched_run_free_queue(sched);
+ drm_sched_run_free_queue_unlocked(sched);
drm_sched_run_job_queue(sched);
}
diff --git a/include/drm/gpu_scheduler.h b/include/drm/gpu_scheduler.h
index 83e5c00d8dd9a83ab20547a93d6fc572de97616e..063c1915841aa54a0859bdccd3c1ef6028105bec 100644
--- a/include/drm/gpu_scheduler.h
+++ b/include/drm/gpu_scheduler.h
@@ -393,11 +393,14 @@ struct drm_sched_job {
* @DRM_GPU_SCHED_STAT_NONE: Reserved. Do not use.
* @DRM_GPU_SCHED_STAT_RESET: The GPU hung and successfully reset.
* @DRM_GPU_SCHED_STAT_ENODEV: Error: Device is not available anymore.
+ * @DRM_GPU_SCHED_STAT_NO_HANG: Contrary to scheduler's belief, the GPU
+ * did not hang and it's operational.
*/
enum drm_gpu_sched_stat {
DRM_GPU_SCHED_STAT_NONE,
DRM_GPU_SCHED_STAT_RESET,
DRM_GPU_SCHED_STAT_ENODEV,
+ DRM_GPU_SCHED_STAT_NO_HANG,
};
/**
--
2.49.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 3/8] drm/sched: Reduce scheduler's timeout for timeout tests
2025-05-30 14:01 [PATCH v2 0/8] drm/sched: Allow drivers to skip the reset with DRM_GPU_SCHED_STAT_NO_HANG Maíra Canal
2025-05-30 14:01 ` [PATCH v2 1/8] drm/sched: Rename DRM_GPU_SCHED_STAT_NOMINAL to DRM_GPU_SCHED_STAT_RESET Maíra Canal
2025-05-30 14:01 ` [PATCH v2 2/8] drm/sched: Allow drivers to skip the reset and keep on running Maíra Canal
@ 2025-05-30 14:01 ` Maíra Canal
2025-06-02 8:54 ` Philipp Stanner
2025-06-02 9:06 ` Tvrtko Ursulin
2025-05-30 14:01 ` [PATCH v2 4/8] drm/sched: Add new test for DRM_GPU_SCHED_STAT_NO_HANG Maíra Canal
` (4 subsequent siblings)
7 siblings, 2 replies; 19+ messages in thread
From: Maíra Canal @ 2025-05-30 14:01 UTC (permalink / raw)
To: Matthew Brost, Danilo Krummrich, Philipp Stanner,
Christian König, Tvrtko Ursulin, Simona Vetter, David Airlie,
Melissa Wen, Lucas Stach, Russell King, Christian Gmeiner,
Lucas De Marchi, Thomas Hellström, Rodrigo Vivi,
Boris Brezillon, Rob Herring, Steven Price, Liviu Dudau
Cc: kernel-dev, dri-devel, etnaviv, intel-xe, Maíra Canal
As more KUnit tests are introduced to evaluate the basic capabilities of
the `timedout_job()` hook, the test suite will continue to increase in
duration. To reduce the overall running time of the test suite, decrease
the scheduler's timeout for the timeout tests.
Before this commit:
[15:42:26] Elapsed time: 15.637s total, 0.002s configuring, 10.387s building, 5.229s running
After this commit:
[15:45:26] Elapsed time: 9.263s total, 0.002s configuring, 5.168s building, 4.037s running
Signed-off-by: Maíra Canal <mcanal@igalia.com>
---
drivers/gpu/drm/scheduler/tests/tests_basic.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/scheduler/tests/tests_basic.c b/drivers/gpu/drm/scheduler/tests/tests_basic.c
index 7230057e0594c6246f02608f07fcb1f8d738ac75..41c648782f4548e202bd8711b45d28eead9bd0b2 100644
--- a/drivers/gpu/drm/scheduler/tests/tests_basic.c
+++ b/drivers/gpu/drm/scheduler/tests/tests_basic.c
@@ -5,6 +5,8 @@
#include "sched_tests.h"
+#define MOCK_TIMEOUT (HZ / 5)
+
/*
* DRM scheduler basic tests should check the basic functional correctness of
* the scheduler, including some very light smoke testing. More targeted tests,
@@ -28,7 +30,7 @@ static void drm_sched_basic_exit(struct kunit *test)
static int drm_sched_timeout_init(struct kunit *test)
{
- test->priv = drm_mock_sched_new(test, HZ);
+ test->priv = drm_mock_sched_new(test, MOCK_TIMEOUT);
return 0;
}
@@ -227,14 +229,14 @@ static void drm_sched_basic_timeout(struct kunit *test)
done = drm_mock_sched_job_wait_scheduled(job, HZ);
KUNIT_ASSERT_TRUE(test, done);
- done = drm_mock_sched_job_wait_finished(job, HZ / 2);
+ done = drm_mock_sched_job_wait_finished(job, MOCK_TIMEOUT / 2);
KUNIT_ASSERT_FALSE(test, done);
KUNIT_ASSERT_EQ(test,
job->flags & DRM_MOCK_SCHED_JOB_TIMEDOUT,
0);
- done = drm_mock_sched_job_wait_finished(job, HZ);
+ done = drm_mock_sched_job_wait_finished(job, MOCK_TIMEOUT);
KUNIT_ASSERT_FALSE(test, done);
KUNIT_ASSERT_EQ(test,
--
2.49.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 4/8] drm/sched: Add new test for DRM_GPU_SCHED_STAT_NO_HANG
2025-05-30 14:01 [PATCH v2 0/8] drm/sched: Allow drivers to skip the reset with DRM_GPU_SCHED_STAT_NO_HANG Maíra Canal
` (2 preceding siblings ...)
2025-05-30 14:01 ` [PATCH v2 3/8] drm/sched: Reduce scheduler's timeout for timeout tests Maíra Canal
@ 2025-05-30 14:01 ` Maíra Canal
2025-06-02 9:34 ` Tvrtko Ursulin
2025-05-30 14:01 ` [PATCH v2 5/8] drm/v3d: Use DRM_GPU_SCHED_STAT_NO_HANG to skip the reset Maíra Canal
` (3 subsequent siblings)
7 siblings, 1 reply; 19+ messages in thread
From: Maíra Canal @ 2025-05-30 14:01 UTC (permalink / raw)
To: Matthew Brost, Danilo Krummrich, Philipp Stanner,
Christian König, Tvrtko Ursulin, Simona Vetter, David Airlie,
Melissa Wen, Lucas Stach, Russell King, Christian Gmeiner,
Lucas De Marchi, Thomas Hellström, Rodrigo Vivi,
Boris Brezillon, Rob Herring, Steven Price, Liviu Dudau
Cc: kernel-dev, dri-devel, etnaviv, intel-xe, Maíra Canal
Add a test to submit a single job against a scheduler with the timeout
configured and verify that if the job is still running, the timeout
handler will skip the reset and allow the job to complete.
Signed-off-by: Maíra Canal <mcanal@igalia.com>
---
drivers/gpu/drm/scheduler/tests/mock_scheduler.c | 5 +++
drivers/gpu/drm/scheduler/tests/sched_tests.h | 1 +
drivers/gpu/drm/scheduler/tests/tests_basic.c | 43 ++++++++++++++++++++++++
3 files changed, 49 insertions(+)
diff --git a/drivers/gpu/drm/scheduler/tests/mock_scheduler.c b/drivers/gpu/drm/scheduler/tests/mock_scheduler.c
index fdf5f34b39e02c8a8648d8bea566a27fd3251516..39429f5cd19ee3c23816f257d566b47d3daa4baa 100644
--- a/drivers/gpu/drm/scheduler/tests/mock_scheduler.c
+++ b/drivers/gpu/drm/scheduler/tests/mock_scheduler.c
@@ -208,6 +208,11 @@ mock_sched_timedout_job(struct drm_sched_job *sched_job)
job->flags |= DRM_MOCK_SCHED_JOB_TIMEDOUT;
+ if (job->flags & DRM_MOCK_SCHED_JOB_DONT_RESET) {
+ job->flags &= ~DRM_MOCK_SCHED_JOB_DONT_RESET;
+ return DRM_GPU_SCHED_STAT_NO_HANG;
+ }
+
return DRM_GPU_SCHED_STAT_RESET;
}
diff --git a/drivers/gpu/drm/scheduler/tests/sched_tests.h b/drivers/gpu/drm/scheduler/tests/sched_tests.h
index 27caf8285fb74b9f3c9ce2daa1c44d4a0c967e92..5259f181e55387c41efbcd3f6addc9465331d787 100644
--- a/drivers/gpu/drm/scheduler/tests/sched_tests.h
+++ b/drivers/gpu/drm/scheduler/tests/sched_tests.h
@@ -98,6 +98,7 @@ struct drm_mock_sched_job {
#define DRM_MOCK_SCHED_JOB_DONE 0x1
#define DRM_MOCK_SCHED_JOB_TIMEDOUT 0x2
+#define DRM_MOCK_SCHED_JOB_DONT_RESET 0x4
unsigned long flags;
struct list_head link;
diff --git a/drivers/gpu/drm/scheduler/tests/tests_basic.c b/drivers/gpu/drm/scheduler/tests/tests_basic.c
index 41c648782f4548e202bd8711b45d28eead9bd0b2..2ba2d1b0c3cad9626ab9d89cfae05244c670a826 100644
--- a/drivers/gpu/drm/scheduler/tests/tests_basic.c
+++ b/drivers/gpu/drm/scheduler/tests/tests_basic.c
@@ -246,8 +246,51 @@ static void drm_sched_basic_timeout(struct kunit *test)
drm_mock_sched_entity_free(entity);
}
+static void drm_sched_skip_reset(struct kunit *test)
+{
+ struct drm_mock_scheduler *sched = test->priv;
+ struct drm_mock_sched_entity *entity;
+ struct drm_mock_sched_job *job;
+ bool done;
+
+ /*
+ * Submit a single job against a scheduler with the timeout configured
+ * and verify that if the job is still running, the timeout handler
+ * will skip the reset and allow the job to complete.
+ */
+
+ entity = drm_mock_sched_entity_new(test,
+ DRM_SCHED_PRIORITY_NORMAL,
+ sched);
+ job = drm_mock_sched_job_new(test, entity);
+
+ job->flags = DRM_MOCK_SCHED_JOB_DONT_RESET;
+
+ drm_mock_sched_job_set_duration_us(job, jiffies_to_usecs(2 * MOCK_TIMEOUT));
+ drm_mock_sched_job_submit(job);
+
+ done = drm_mock_sched_job_wait_finished(job, MOCK_TIMEOUT);
+ KUNIT_ASSERT_FALSE(test, done);
+
+ KUNIT_ASSERT_EQ(test,
+ job->flags & DRM_MOCK_SCHED_JOB_TIMEDOUT,
+ DRM_MOCK_SCHED_JOB_TIMEDOUT);
+
+ KUNIT_ASSERT_EQ(test,
+ job->flags & DRM_MOCK_SCHED_JOB_DONT_RESET,
+ 0);
+
+ KUNIT_ASSERT_FALSE(test, list_empty(&sched->job_list));
+
+ done = drm_mock_sched_job_wait_finished(job, MOCK_TIMEOUT);
+ KUNIT_ASSERT_TRUE(test, done);
+
+ drm_mock_sched_entity_free(entity);
+}
+
static struct kunit_case drm_sched_timeout_tests[] = {
KUNIT_CASE(drm_sched_basic_timeout),
+ KUNIT_CASE(drm_sched_skip_reset),
{}
};
--
2.49.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 5/8] drm/v3d: Use DRM_GPU_SCHED_STAT_NO_HANG to skip the reset
2025-05-30 14:01 [PATCH v2 0/8] drm/sched: Allow drivers to skip the reset with DRM_GPU_SCHED_STAT_NO_HANG Maíra Canal
` (3 preceding siblings ...)
2025-05-30 14:01 ` [PATCH v2 4/8] drm/sched: Add new test for DRM_GPU_SCHED_STAT_NO_HANG Maíra Canal
@ 2025-05-30 14:01 ` Maíra Canal
2025-06-02 7:13 ` Philipp Stanner
2025-05-30 14:01 ` [PATCH v2 6/8] drm/etnaviv: " Maíra Canal
` (2 subsequent siblings)
7 siblings, 1 reply; 19+ messages in thread
From: Maíra Canal @ 2025-05-30 14:01 UTC (permalink / raw)
To: Matthew Brost, Danilo Krummrich, Philipp Stanner,
Christian König, Tvrtko Ursulin, Simona Vetter, David Airlie,
Melissa Wen, Lucas Stach, Russell King, Christian Gmeiner,
Lucas De Marchi, Thomas Hellström, Rodrigo Vivi,
Boris Brezillon, Rob Herring, Steven Price, Liviu Dudau
Cc: kernel-dev, dri-devel, etnaviv, intel-xe, Maíra Canal
When a CL/CSD job times out, we check if the GPU has made any progress
since the last timeout. If so, instead of resetting the hardware, we skip
the reset and allow the timer to be rearmed. This gives long-running jobs
a chance to complete.
Use the DRM_GPU_SCHED_STAT_NO_HANG status to skip the reset and re-arm
the timer.
Signed-off-by: Maíra Canal <mcanal@igalia.com>
---
drivers/gpu/drm/v3d/v3d_sched.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/gpu/drm/v3d/v3d_sched.c b/drivers/gpu/drm/v3d/v3d_sched.c
index e1997387831541fb053e472672004cf511c25558..fbb09a8aff3740b5cd59573b5f2e26b2ee352dfb 100644
--- a/drivers/gpu/drm/v3d/v3d_sched.c
+++ b/drivers/gpu/drm/v3d/v3d_sched.c
@@ -761,7 +761,7 @@ v3d_cl_job_timedout(struct drm_sched_job *sched_job, enum v3d_queue q,
if (*timedout_ctca != ctca || *timedout_ctra != ctra) {
*timedout_ctca = ctca;
*timedout_ctra = ctra;
- return DRM_GPU_SCHED_STAT_RESET;
+ return DRM_GPU_SCHED_STAT_NO_HANG;
}
return v3d_gpu_reset_for_timeout(v3d, sched_job);
@@ -805,7 +805,7 @@ v3d_csd_job_timedout(struct drm_sched_job *sched_job)
*/
if (job->timedout_batches != batches) {
job->timedout_batches = batches;
- return DRM_GPU_SCHED_STAT_RESET;
+ return DRM_GPU_SCHED_STAT_NO_HANG;
}
return v3d_gpu_reset_for_timeout(v3d, sched_job);
--
2.49.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 6/8] drm/etnaviv: Use DRM_GPU_SCHED_STAT_NO_HANG to skip the reset
2025-05-30 14:01 [PATCH v2 0/8] drm/sched: Allow drivers to skip the reset with DRM_GPU_SCHED_STAT_NO_HANG Maíra Canal
` (4 preceding siblings ...)
2025-05-30 14:01 ` [PATCH v2 5/8] drm/v3d: Use DRM_GPU_SCHED_STAT_NO_HANG to skip the reset Maíra Canal
@ 2025-05-30 14:01 ` Maíra Canal
2025-06-02 7:28 ` Philipp Stanner
2025-05-30 14:01 ` [PATCH v2 7/8] drm/xe: " Maíra Canal
2025-05-30 14:01 ` [PATCH v2 8/8] drm/panfrost: " Maíra Canal
7 siblings, 1 reply; 19+ messages in thread
From: Maíra Canal @ 2025-05-30 14:01 UTC (permalink / raw)
To: Matthew Brost, Danilo Krummrich, Philipp Stanner,
Christian König, Tvrtko Ursulin, Simona Vetter, David Airlie,
Melissa Wen, Lucas Stach, Russell King, Christian Gmeiner,
Lucas De Marchi, Thomas Hellström, Rodrigo Vivi,
Boris Brezillon, Rob Herring, Steven Price, Liviu Dudau
Cc: kernel-dev, dri-devel, etnaviv, intel-xe, Maíra Canal
Etnaviv can skip a hardware reset in two situations:
1. TDR has fired before the free-job worker and the timeout is spurious.
2. The GPU is still making progress on the front-end and we can give
the job a chance to complete.
Instead of relying on the scheduler internals, use the
DRM_GPU_SCHED_STAT_NO_HANG status to skip the reset and re-arm the timer.
Signed-off-by: Maíra Canal <mcanal@igalia.com>
---
drivers/gpu/drm/etnaviv/etnaviv_sched.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c b/drivers/gpu/drm/etnaviv/etnaviv_sched.c
index 7146069a98492f5fab2a49d96e2054f649e1fe3d..46f5391e84a12232b247886cf1311f8e09f42f04 100644
--- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c
+++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c
@@ -40,11 +40,11 @@ static enum drm_gpu_sched_stat etnaviv_sched_timedout_job(struct drm_sched_job
int change;
/*
- * If the GPU managed to complete this jobs fence, the timout is
- * spurious. Bail out.
+ * If the GPU managed to complete this jobs fence, the timeout has
+ * fired before free-job worker. The timeout is spurious, so bail out.
*/
if (dma_fence_is_signaled(submit->out_fence))
- goto out_no_timeout;
+ return DRM_GPU_SCHED_STAT_NO_HANG;
/*
* If the GPU is still making forward progress on the front-end (which
@@ -70,7 +70,7 @@ static enum drm_gpu_sched_stat etnaviv_sched_timedout_job(struct drm_sched_job
gpu->hangcheck_dma_addr = dma_addr;
gpu->hangcheck_primid = primid;
gpu->hangcheck_fence = gpu->completed_fence;
- goto out_no_timeout;
+ return DRM_GPU_SCHED_STAT_NO_HANG;
}
/* block scheduler */
@@ -86,10 +86,7 @@ static enum drm_gpu_sched_stat etnaviv_sched_timedout_job(struct drm_sched_job
drm_sched_resubmit_jobs(&gpu->sched);
drm_sched_start(&gpu->sched, 0);
- return DRM_GPU_SCHED_STAT_RESET;
-out_no_timeout:
- list_add(&sched_job->list, &sched_job->sched->pending_list);
return DRM_GPU_SCHED_STAT_RESET;
}
--
2.49.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 7/8] drm/xe: Use DRM_GPU_SCHED_STAT_NO_HANG to skip the reset
2025-05-30 14:01 [PATCH v2 0/8] drm/sched: Allow drivers to skip the reset with DRM_GPU_SCHED_STAT_NO_HANG Maíra Canal
` (5 preceding siblings ...)
2025-05-30 14:01 ` [PATCH v2 6/8] drm/etnaviv: " Maíra Canal
@ 2025-05-30 14:01 ` Maíra Canal
2025-06-02 7:47 ` Philipp Stanner
2025-05-30 14:01 ` [PATCH v2 8/8] drm/panfrost: " Maíra Canal
7 siblings, 1 reply; 19+ messages in thread
From: Maíra Canal @ 2025-05-30 14:01 UTC (permalink / raw)
To: Matthew Brost, Danilo Krummrich, Philipp Stanner,
Christian König, Tvrtko Ursulin, Simona Vetter, David Airlie,
Melissa Wen, Lucas Stach, Russell King, Christian Gmeiner,
Lucas De Marchi, Thomas Hellström, Rodrigo Vivi,
Boris Brezillon, Rob Herring, Steven Price, Liviu Dudau
Cc: kernel-dev, dri-devel, etnaviv, intel-xe, Maíra Canal
Xe can skip the reset if TDR has fired before the free job worker and can
also re-arm the timeout timer in some scenarios. Instead of using the
scheduler internals to add the job to the pending list, use the
DRM_GPU_SCHED_STAT_NO_HANG status to skip the reset and re-arm the timer.
Note that, in the first case, there is no need to restart submission if it
hasn't been stopped.
Signed-off-by: Maíra Canal <mcanal@igalia.com>
---
drivers/gpu/drm/xe/xe_guc_submit.c | 12 +++---------
1 file changed, 3 insertions(+), 9 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
index 98363d688cbbf884e17e6610366202a3372f5fe0..0149c85aa1a85b2b2e739774310d7b3265e33228 100644
--- a/drivers/gpu/drm/xe/xe_guc_submit.c
+++ b/drivers/gpu/drm/xe/xe_guc_submit.c
@@ -1067,12 +1067,8 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
* list so job can be freed and kick scheduler ensuring free job is not
* lost.
*/
- if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &job->fence->flags)) {
- xe_sched_add_pending_job(sched, job);
- xe_sched_submission_start(sched);
-
- return DRM_GPU_SCHED_STAT_RESET;
- }
+ if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &job->fence->flags))
+ return DRM_GPU_SCHED_STAT_NO_HANG;
/* Kill the run_job entry point */
xe_sched_submission_stop(sched);
@@ -1247,10 +1243,8 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
* but there is not currently an easy way to do in DRM scheduler. With
* some thought, do this in a follow up.
*/
- xe_sched_add_pending_job(sched, job);
xe_sched_submission_start(sched);
-
- return DRM_GPU_SCHED_STAT_RESET;
+ return DRM_GPU_SCHED_STAT_NO_HANG;
}
static void __guc_exec_queue_fini_async(struct work_struct *w)
--
2.49.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* [PATCH v2 8/8] drm/panfrost: Use DRM_GPU_SCHED_STAT_NO_HANG to skip the reset
2025-05-30 14:01 [PATCH v2 0/8] drm/sched: Allow drivers to skip the reset with DRM_GPU_SCHED_STAT_NO_HANG Maíra Canal
` (6 preceding siblings ...)
2025-05-30 14:01 ` [PATCH v2 7/8] drm/xe: " Maíra Canal
@ 2025-05-30 14:01 ` Maíra Canal
7 siblings, 0 replies; 19+ messages in thread
From: Maíra Canal @ 2025-05-30 14:01 UTC (permalink / raw)
To: Matthew Brost, Danilo Krummrich, Philipp Stanner,
Christian König, Tvrtko Ursulin, Simona Vetter, David Airlie,
Melissa Wen, Lucas Stach, Russell King, Christian Gmeiner,
Lucas De Marchi, Thomas Hellström, Rodrigo Vivi,
Boris Brezillon, Rob Herring, Steven Price, Liviu Dudau
Cc: kernel-dev, dri-devel, etnaviv, intel-xe, Maíra Canal
Panfrost can skip the reset if TDR has fired before the free-job worker.
Currently, since Panfrost doesn't take any action on these scenarios, the
job is being leaked, considering that `free_job()` won't be called.
To avoid such leaks, use the DRM_GPU_SCHED_STAT_NO_STAT status to skip the
reset and re-arm the timer.
Signed-off-by: Maíra Canal <mcanal@igalia.com>
Reviewed-by: Steven Price <steven.price@arm.com>
---
drivers/gpu/drm/panfrost/panfrost_job.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/gpu/drm/panfrost/panfrost_job.c b/drivers/gpu/drm/panfrost/panfrost_job.c
index afcffe7f8fe9e11f84e4ab7e8f5a72f7bf583690..842e012cdc68e130a13e08ffae3b7fdf5f8e1acc 100644
--- a/drivers/gpu/drm/panfrost/panfrost_job.c
+++ b/drivers/gpu/drm/panfrost/panfrost_job.c
@@ -751,11 +751,11 @@ static enum drm_gpu_sched_stat panfrost_job_timedout(struct drm_sched_job
int js = panfrost_job_get_slot(job);
/*
- * If the GPU managed to complete this jobs fence, the timeout is
- * spurious. Bail out.
+ * If the GPU managed to complete this jobs fence, the timeout has
+ * fired before free-job worker. The timeout is spurious, so bail out.
*/
if (dma_fence_is_signaled(job->done_fence))
- return DRM_GPU_SCHED_STAT_RESET;
+ return DRM_GPU_SCHED_STAT_NO_HANG;
/*
* Panfrost IRQ handler may take a long time to process an interrupt
@@ -770,7 +770,7 @@ static enum drm_gpu_sched_stat panfrost_job_timedout(struct drm_sched_job
if (dma_fence_is_signaled(job->done_fence)) {
dev_warn(pfdev->dev, "unexpectedly high interrupt latency\n");
- return DRM_GPU_SCHED_STAT_RESET;
+ return DRM_GPU_SCHED_STAT_NO_HANG;
}
dev_err(pfdev->dev, "gpu sched timeout, js=%d, config=0x%x, status=0x%x, head=0x%x, tail=0x%x, sched_job=%p",
--
2.49.0
^ permalink raw reply related [flat|nested] 19+ messages in thread
* Re: [PATCH v2 2/8] drm/sched: Allow drivers to skip the reset and keep on running
2025-05-30 14:01 ` [PATCH v2 2/8] drm/sched: Allow drivers to skip the reset and keep on running Maíra Canal
@ 2025-06-02 7:06 ` Philipp Stanner
0 siblings, 0 replies; 19+ messages in thread
From: Philipp Stanner @ 2025-06-02 7:06 UTC (permalink / raw)
To: Maíra Canal, Matthew Brost, Danilo Krummrich,
Philipp Stanner, Christian König, Tvrtko Ursulin,
Simona Vetter, David Airlie, Melissa Wen, Lucas Stach,
Russell King, Christian Gmeiner, Lucas De Marchi,
Thomas Hellström, Rodrigo Vivi, Boris Brezillon, Rob Herring,
Steven Price, Liviu Dudau
Cc: kernel-dev, dri-devel, etnaviv, intel-xe
Hi,
thx for the update. Seems to be developing nicely. Some comments below.
On Fri, 2025-05-30 at 11:01 -0300, Maíra Canal wrote:
> When the DRM scheduler times out, it's possible that the GPU isn't
> hung;
> instead, a job may still be running, and there may be no valid reason
> to
> reset the hardware. This can occur in two situations:
>
> 1. The GPU exposes some mechanism that ensures the GPU is still
> making
> progress. By checking this mechanism, the driver can safely skip
> the
> reset, re-arm the timeout, and allow the job to continue running
> until
> completion. This is the case for v3d, Etnaviv, and Xe.
> 2. Timeout has fired before the free-job worker. Consequently, the
> scheduler calls `timedout_job()` for a job that isn't timed out.
>
> These two scenarios are problematic because the job was removed from
> the
> `sched->pending_list` before calling `sched->ops->timedout_job()`,
> which
> means that when the job finishes, it won't be freed by the scheduler
> though `sched->ops->free_job()`. As a result, the job and its
> resources
> won't be freed, leading to a memory leak.
nit: redundant "won't bee freed"
>
> To resolve those scenarios, create a new `drm_gpu_sched_stat`, called
nit:
s/resolve those scenarios/solve those problems
> DRM_GPU_SCHED_STAT_NO_HANG, that allows a driver to skip the reset.
> The
> new status will indicate that the job should be reinserted into the
nit:
s/should/must
> pending list, and the hardware / driver is still responsible to
> signal job completion.
The driver is *always* responsible for signaling, well, "the hardware
fence". We could have a discussion about whether a job is "completed"
if the driver signals its hardware fence through the timedout_job()
callback, but I think it's safer to just change this sentence to:
"and the hardware / driver will still complete that job."
>
> Signed-off-by: Maíra Canal <mcanal@igalia.com>
> ---
> drivers/gpu/drm/scheduler/sched_main.c | 49
> ++++++++++++++++++++++++++++++++--
> include/drm/gpu_scheduler.h | 3 +++
> 2 files changed, 50 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/scheduler/sched_main.c
> b/drivers/gpu/drm/scheduler/sched_main.c
> index
> 3b0760dfa4fe2fc63e893cda733e78d08dd451d5..ddc53eadab7bb6a15109f43989a
> fa1f7a95a3b41 100644
> --- a/drivers/gpu/drm/scheduler/sched_main.c
> +++ b/drivers/gpu/drm/scheduler/sched_main.c
> @@ -379,11 +379,16 @@ static void drm_sched_run_free_queue(struct
> drm_gpu_scheduler *sched)
> {
> struct drm_sched_job *job;
>
> - spin_lock(&sched->job_list_lock);
> job = list_first_entry_or_null(&sched->pending_list,
> struct drm_sched_job, list);
> if (job && dma_fence_is_signaled(&job->s_fence->finished))
> __drm_sched_run_free_queue(sched);
> +}
> +
> +static void drm_sched_run_free_queue_unlocked(struct
> drm_gpu_scheduler *sched)
> +{
> + spin_lock(&sched->job_list_lock);
> + drm_sched_run_free_queue(sched);
> spin_unlock(&sched->job_list_lock);
> }
nit:
Took me a few seconds to realize why that's necessary. A sentence in
the commit message might have been good. But no big thing, up to you
>
> @@ -536,6 +541,32 @@ static void drm_sched_job_begin(struct
> drm_sched_job *s_job)
> spin_unlock(&sched->job_list_lock);
> }
>
> +/**
> + * drm_sched_job_reinsert_on_false_timeout - Reinsert the job on a
> false timeout
> + *
Please remove this empty line. Our docu style in those files is not
consistent, and I'd like to move towards a more unified style.
> + * @sched: scheduler instance
> + * @job: job to be reinserted on the pending list
> + *
> + * In the case of a "false timeout" - when a timeout occurs but the
> GPU isn't
> + * hung and the job is making progress, the scheduler must reinsert
> the job back
> + * into the pending list. Otherwise, the job and its resources won't
> be freed
> + * through the &drm_sched_backend_ops.free_job callback.
> + *
> + * Note that after reinserting the job, the scheduler enqueues the
> free-job
> + * work again if ready. Otherwise, a signaled job could be added to
> the pending
> + * list, but never freed.
> + *
> + * This function must be used in "false timeout" cases only.
> + */
> +static void drm_sched_job_reinsert_on_false_timeout(struct
> drm_gpu_scheduler *sched,
> + struct
> drm_sched_job *job)
> +{
> + spin_lock(&sched->job_list_lock);
> + list_add(&job->list, &sched->pending_list);
> + drm_sched_run_free_queue(sched);
> + spin_unlock(&sched->job_list_lock);
> +}
> +
> static void drm_sched_job_timedout(struct work_struct *work)
> {
> struct drm_gpu_scheduler *sched;
> @@ -569,6 +600,14 @@ static void drm_sched_job_timedout(struct
> work_struct *work)
> job->sched->ops->free_job(job);
> sched->free_guilty = false;
> }
> +
> + /*
> + * If the driver indicated that the GPU is still
> running and wants
> + * to skip the reset, reinsert the job back into the
> pending list
> + * and re-arm the timeout.
Doesn't sound entirely correct to me – at this point, the driver itself
did already skip the reset. The scheduler has no control over that.
You might also just drop the comment, I think the function name and the
function's docstring make what's happening perfectly clear.
> + */
> + if (status == DRM_GPU_SCHED_STAT_NO_HANG)
> + drm_sched_job_reinsert_on_false_timeout(sche
> d, job);
> } else {
> spin_unlock(&sched->job_list_lock);
> }
> @@ -591,6 +630,9 @@ static void drm_sched_job_timedout(struct
> work_struct *work)
> * This function is typically used for reset recovery (see the docu
> of
> * drm_sched_backend_ops.timedout_job() for details). Do not call it
> for
> * scheduler teardown, i.e., before calling drm_sched_fini().
> + *
> + * As it's used for reset recovery, drm_sched_stop() shouldn't be
> called
> + * if the driver skipped the timeout (DRM_GPU_SCHED_STAT_NO_HANG).
s/timeout/reset
> */
> void drm_sched_stop(struct drm_gpu_scheduler *sched, struct
> drm_sched_job *bad)
> {
> @@ -676,6 +718,9 @@ EXPORT_SYMBOL(drm_sched_stop);
> * drm_sched_backend_ops.timedout_job() for details). Do not call it
> for
> * scheduler startup. The scheduler itself is fully operational
> after
> * drm_sched_init() succeeded.
> + *
> + * As it's used for reset recovery, drm_sched_start() shouldn't be
> called
> + * if the driver skipped the timeout (DRM_GPU_SCHED_STAT_NO_HANG).
same
> */
> void drm_sched_start(struct drm_gpu_scheduler *sched, int errno)
> {
> @@ -1197,7 +1242,7 @@ static void drm_sched_free_job_work(struct
> work_struct *w)
> if (job)
> sched->ops->free_job(job);
>
> - drm_sched_run_free_queue(sched);
> + drm_sched_run_free_queue_unlocked(sched);
> drm_sched_run_job_queue(sched);
> }
>
> diff --git a/include/drm/gpu_scheduler.h
> b/include/drm/gpu_scheduler.h
> index
> 83e5c00d8dd9a83ab20547a93d6fc572de97616e..063c1915841aa54a0859bdccd3c
> 1ef6028105bec 100644
> --- a/include/drm/gpu_scheduler.h
> +++ b/include/drm/gpu_scheduler.h
> @@ -393,11 +393,14 @@ struct drm_sched_job {
> * @DRM_GPU_SCHED_STAT_NONE: Reserved. Do not use.
> * @DRM_GPU_SCHED_STAT_RESET: The GPU hung and successfully reset.
> * @DRM_GPU_SCHED_STAT_ENODEV: Error: Device is not available
> anymore.
> + * @DRM_GPU_SCHED_STAT_NO_HANG: Contrary to scheduler's belief, the
> GPU
> + * did not hang and it's operational.
s/it's/is
> */
> enum drm_gpu_sched_stat {
> DRM_GPU_SCHED_STAT_NONE,
> DRM_GPU_SCHED_STAT_RESET,
> DRM_GPU_SCHED_STAT_ENODEV,
> + DRM_GPU_SCHED_STAT_NO_HANG,
> };
>
> /**
>
Thx, I'll look through the other ones soonish, too
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 5/8] drm/v3d: Use DRM_GPU_SCHED_STAT_NO_HANG to skip the reset
2025-05-30 14:01 ` [PATCH v2 5/8] drm/v3d: Use DRM_GPU_SCHED_STAT_NO_HANG to skip the reset Maíra Canal
@ 2025-06-02 7:13 ` Philipp Stanner
2025-06-02 11:27 ` Maíra Canal
0 siblings, 1 reply; 19+ messages in thread
From: Philipp Stanner @ 2025-06-02 7:13 UTC (permalink / raw)
To: Maíra Canal, Matthew Brost, Danilo Krummrich,
Philipp Stanner, Christian König, Tvrtko Ursulin,
Simona Vetter, David Airlie, Melissa Wen, Lucas Stach,
Russell King, Christian Gmeiner, Lucas De Marchi,
Thomas Hellström, Rodrigo Vivi, Boris Brezillon, Rob Herring,
Steven Price, Liviu Dudau
Cc: kernel-dev, dri-devel, etnaviv, intel-xe
On Fri, 2025-05-30 at 11:01 -0300, Maíra Canal wrote:
> When a CL/CSD job times out, we check if the GPU has made any
> progress
> since the last timeout. If so, instead of resetting the hardware, we
> skip
> the reset and allow the timer to be rearmed. This gives long-running
> jobs
> a chance to complete.
>
> Use the DRM_GPU_SCHED_STAT_NO_HANG status to skip the reset and re-
> arm
> the timer.
>
> Signed-off-by: Maíra Canal <mcanal@igalia.com>
> ---
> drivers/gpu/drm/v3d/v3d_sched.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/gpu/drm/v3d/v3d_sched.c
> b/drivers/gpu/drm/v3d/v3d_sched.c
> index
> e1997387831541fb053e472672004cf511c25558..fbb09a8aff3740b5cd59573b5f2
> e26b2ee352dfb 100644
> --- a/drivers/gpu/drm/v3d/v3d_sched.c
> +++ b/drivers/gpu/drm/v3d/v3d_sched.c
> @@ -761,7 +761,7 @@ v3d_cl_job_timedout(struct drm_sched_job
> *sched_job, enum v3d_queue q,
> if (*timedout_ctca != ctca || *timedout_ctra != ctra) {
> *timedout_ctca = ctca;
> *timedout_ctra = ctra;
> - return DRM_GPU_SCHED_STAT_RESET;
> + return DRM_GPU_SCHED_STAT_NO_HANG;
> }
>
> return v3d_gpu_reset_for_timeout(v3d, sched_job);
> @@ -805,7 +805,7 @@ v3d_csd_job_timedout(struct drm_sched_job
> *sched_job)
> */
> if (job->timedout_batches != batches) {
> job->timedout_batches = batches;
> - return DRM_GPU_SCHED_STAT_RESET;
> + return DRM_GPU_SCHED_STAT_NO_HANG;
> }
Wait a second, help me out here quickly. You already added workaround
stuff where you manipulate the scheduler's pending_list, as you state
in the cover letter. That code here [1].
Don't you have to remove the very same code in this series again to
still have correct behavior in your driver?
As I see it, all drm branches end up in Linus's tree ultimately. So I'd
think about potential branch-races in case you didn't already.
P.
[1] https://lore.kernel.org/dri-devel/20250430210643.57924-1-mcanal@igalia.com/T/
>
> return v3d_gpu_reset_for_timeout(v3d, sched_job);
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 6/8] drm/etnaviv: Use DRM_GPU_SCHED_STAT_NO_HANG to skip the reset
2025-05-30 14:01 ` [PATCH v2 6/8] drm/etnaviv: " Maíra Canal
@ 2025-06-02 7:28 ` Philipp Stanner
2025-06-02 11:36 ` Maíra Canal
0 siblings, 1 reply; 19+ messages in thread
From: Philipp Stanner @ 2025-06-02 7:28 UTC (permalink / raw)
To: Maíra Canal, Matthew Brost, Danilo Krummrich,
Philipp Stanner, Christian König, Tvrtko Ursulin,
Simona Vetter, David Airlie, Melissa Wen, Lucas Stach,
Russell King, Christian Gmeiner, Lucas De Marchi,
Thomas Hellström, Rodrigo Vivi, Boris Brezillon, Rob Herring,
Steven Price, Liviu Dudau
Cc: kernel-dev, dri-devel, etnaviv, intel-xe
On Fri, 2025-05-30 at 11:01 -0300, Maíra Canal wrote:
> Etnaviv can skip a hardware reset in two situations:
>
> 1. TDR has fired before the free-job worker and the timeout is
> spurious.
> 2. The GPU is still making progress on the front-end and we can
> give
> the job a chance to complete.
>
> Instead of relying on the scheduler internals, use the
> DRM_GPU_SCHED_STAT_NO_HANG status to skip the reset and re-arm the
In the four patches adjusting the drivers, I rather recommend to write:
"Instead of manipulating scheduler internals, inform the scheduler that
this job did not actually time out and no reset was performed through
the new status code DRM_GPU_SCHED_STAT_NO_HANG."
> timer.
>
> Signed-off-by: Maíra Canal <mcanal@igalia.com>
> ---
> drivers/gpu/drm/etnaviv/etnaviv_sched.c | 11 ++++-------
> 1 file changed, 4 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c
> b/drivers/gpu/drm/etnaviv/etnaviv_sched.c
> index
> 7146069a98492f5fab2a49d96e2054f649e1fe3d..46f5391e84a12232b247886cf13
> 11f8e09f42f04 100644
> --- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c
> +++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c
> @@ -40,11 +40,11 @@ static enum drm_gpu_sched_stat
> etnaviv_sched_timedout_job(struct drm_sched_job
> int change;
>
> /*
> - * If the GPU managed to complete this jobs fence, the
> timout is
> - * spurious. Bail out.
> + * If the GPU managed to complete this jobs fence, the
> timeout has
> + * fired before free-job worker. The timeout is spurious, so
> bail out.
> */
> if (dma_fence_is_signaled(submit->out_fence))
> - goto out_no_timeout;
> + return DRM_GPU_SCHED_STAT_NO_HANG;
>
> /*
> * If the GPU is still making forward progress on the front-
> end (which
> @@ -70,7 +70,7 @@ static enum drm_gpu_sched_stat
> etnaviv_sched_timedout_job(struct drm_sched_job
> gpu->hangcheck_dma_addr = dma_addr;
> gpu->hangcheck_primid = primid;
> gpu->hangcheck_fence = gpu->completed_fence;
> - goto out_no_timeout;
> + return DRM_GPU_SCHED_STAT_NO_HANG;
> }
>
> /* block scheduler */
> @@ -86,10 +86,7 @@ static enum drm_gpu_sched_stat
> etnaviv_sched_timedout_job(struct drm_sched_job
> drm_sched_resubmit_jobs(&gpu->sched);
>
> drm_sched_start(&gpu->sched, 0);
> - return DRM_GPU_SCHED_STAT_RESET;
>
> -out_no_timeout:
> - list_add(&sched_job->list, &sched_job->sched->pending_list);
Here you actually remove the manipulation of the scheduler internals,
but you didn't in v3d. Just to point that out.
And BTW I'm just seeing that the pending_list gets manipulated here
with the scheduler's workqueues running and no locks being hold.
Oh man :(
That is most certainly a bug, and I recommend that the etnaviv
maintainers at least add the appropriate lock here and backport that
since it can race any time.
But thx for working on that, Maíra. Good that we can remove the stuff
this way.
Thinking about it, this patch even fixes a bug. So could contain a
Fixes: tag. But I'm not sure if it's worth it to mark the entire series
for Stable. Opinions?
P.
> return DRM_GPU_SCHED_STAT_RESET;
> }
>
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 7/8] drm/xe: Use DRM_GPU_SCHED_STAT_NO_HANG to skip the reset
2025-05-30 14:01 ` [PATCH v2 7/8] drm/xe: " Maíra Canal
@ 2025-06-02 7:47 ` Philipp Stanner
0 siblings, 0 replies; 19+ messages in thread
From: Philipp Stanner @ 2025-06-02 7:47 UTC (permalink / raw)
To: Maíra Canal, Matthew Brost, Danilo Krummrich,
Philipp Stanner, Christian König, Tvrtko Ursulin,
Simona Vetter, David Airlie, Melissa Wen, Lucas Stach,
Russell King, Christian Gmeiner, Lucas De Marchi,
Thomas Hellström, Rodrigo Vivi, Boris Brezillon, Rob Herring,
Steven Price, Liviu Dudau
Cc: kernel-dev, dri-devel, etnaviv, intel-xe
On Fri, 2025-05-30 at 11:01 -0300, Maíra Canal wrote:
> Xe can skip the reset if TDR has fired before the free job worker and
> can
> also re-arm the timeout timer in some scenarios. Instead of using the
> scheduler internals to add the job to the pending list, use the
> DRM_GPU_SCHED_STAT_NO_HANG status to skip the reset and re-arm the
> timer.
>
> Note that, in the first case, there is no need to restart submission
> if it
> hasn't been stopped.
>
> Signed-off-by: Maíra Canal <mcanal@igalia.com>
> ---
> drivers/gpu/drm/xe/xe_guc_submit.c | 12 +++---------
> 1 file changed, 3 insertions(+), 9 deletions(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c
> b/drivers/gpu/drm/xe/xe_guc_submit.c
> index
> 98363d688cbbf884e17e6610366202a3372f5fe0..0149c85aa1a85b2b2e739774310
> d7b3265e33228 100644
> --- a/drivers/gpu/drm/xe/xe_guc_submit.c
> +++ b/drivers/gpu/drm/xe/xe_guc_submit.c
> @@ -1067,12 +1067,8 @@ guc_exec_queue_timedout_job(struct
> drm_sched_job *drm_job)
> * list so job can be freed and kick scheduler ensuring free
> job is not
> * lost.
> */
> - if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &job->fence-
> >flags)) {
> - xe_sched_add_pending_job(sched, job);
> - xe_sched_submission_start(sched);
> -
> - return DRM_GPU_SCHED_STAT_RESET;
> - }
> + if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &job->fence-
> >flags))
> + return DRM_GPU_SCHED_STAT_NO_HANG;
>
> /* Kill the run_job entry point */
> xe_sched_submission_stop(sched);
> @@ -1247,10 +1243,8 @@ guc_exec_queue_timedout_job(struct
> drm_sched_job *drm_job)
> * but there is not currently an easy way to do in DRM
> scheduler. With
> * some thought, do this in a follow up.
> */
> - xe_sched_add_pending_job(sched, job);
> xe_sched_submission_start(sched);
> -
> - return DRM_GPU_SCHED_STAT_RESET;
> + return DRM_GPU_SCHED_STAT_NO_HANG;
> }
This patch removes two of three uses of xe_sched_add_pending_job().
There's now only one left, in the same function, slightly above.
@Matthew, can that call be removed, too? Should that be done in this
patch or seperately?
P.
>
> static void __guc_exec_queue_fini_async(struct work_struct *w)
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 3/8] drm/sched: Reduce scheduler's timeout for timeout tests
2025-05-30 14:01 ` [PATCH v2 3/8] drm/sched: Reduce scheduler's timeout for timeout tests Maíra Canal
@ 2025-06-02 8:54 ` Philipp Stanner
2025-06-02 9:06 ` Tvrtko Ursulin
1 sibling, 0 replies; 19+ messages in thread
From: Philipp Stanner @ 2025-06-02 8:54 UTC (permalink / raw)
To: Maíra Canal, Matthew Brost, Danilo Krummrich,
Philipp Stanner, Christian König, Tvrtko Ursulin,
Simona Vetter, David Airlie, Melissa Wen, Lucas Stach,
Russell King, Christian Gmeiner, Lucas De Marchi,
Thomas Hellström, Rodrigo Vivi, Boris Brezillon, Rob Herring,
Steven Price, Liviu Dudau
Cc: kernel-dev, dri-devel, etnaviv, intel-xe
I'd call that patch sth like "Make timeout unit tests faster". Makes
more obvious what it's about.
P.
On Fri, 2025-05-30 at 11:01 -0300, Maíra Canal wrote:
> As more KUnit tests are introduced to evaluate the basic capabilities
> of
> the `timedout_job()` hook, the test suite will continue to increase
> in
> duration. To reduce the overall running time of the test suite,
> decrease
> the scheduler's timeout for the timeout tests.
>
> Before this commit:
>
> [15:42:26] Elapsed time: 15.637s total, 0.002s configuring, 10.387s
> building, 5.229s running
>
> After this commit:
>
> [15:45:26] Elapsed time: 9.263s total, 0.002s configuring, 5.168s
> building, 4.037s running
>
> Signed-off-by: Maíra Canal <mcanal@igalia.com>
> ---
> drivers/gpu/drm/scheduler/tests/tests_basic.c | 8 +++++---
> 1 file changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/scheduler/tests/tests_basic.c
> b/drivers/gpu/drm/scheduler/tests/tests_basic.c
> index
> 7230057e0594c6246f02608f07fcb1f8d738ac75..41c648782f4548e202bd8711b45
> d28eead9bd0b2 100644
> --- a/drivers/gpu/drm/scheduler/tests/tests_basic.c
> +++ b/drivers/gpu/drm/scheduler/tests/tests_basic.c
> @@ -5,6 +5,8 @@
>
> #include "sched_tests.h"
>
> +#define MOCK_TIMEOUT (HZ / 5)
> +
> /*
> * DRM scheduler basic tests should check the basic functional
> correctness of
> * the scheduler, including some very light smoke testing. More
> targeted tests,
> @@ -28,7 +30,7 @@ static void drm_sched_basic_exit(struct kunit
> *test)
>
> static int drm_sched_timeout_init(struct kunit *test)
> {
> - test->priv = drm_mock_sched_new(test, HZ);
> + test->priv = drm_mock_sched_new(test, MOCK_TIMEOUT);
>
> return 0;
> }
> @@ -227,14 +229,14 @@ static void drm_sched_basic_timeout(struct
> kunit *test)
> done = drm_mock_sched_job_wait_scheduled(job, HZ);
> KUNIT_ASSERT_TRUE(test, done);
>
> - done = drm_mock_sched_job_wait_finished(job, HZ / 2);
> + done = drm_mock_sched_job_wait_finished(job, MOCK_TIMEOUT /
> 2);
> KUNIT_ASSERT_FALSE(test, done);
>
> KUNIT_ASSERT_EQ(test,
> job->flags & DRM_MOCK_SCHED_JOB_TIMEDOUT,
> 0);
>
> - done = drm_mock_sched_job_wait_finished(job, HZ);
> + done = drm_mock_sched_job_wait_finished(job, MOCK_TIMEOUT);
> KUNIT_ASSERT_FALSE(test, done);
>
> KUNIT_ASSERT_EQ(test,
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 3/8] drm/sched: Reduce scheduler's timeout for timeout tests
2025-05-30 14:01 ` [PATCH v2 3/8] drm/sched: Reduce scheduler's timeout for timeout tests Maíra Canal
2025-06-02 8:54 ` Philipp Stanner
@ 2025-06-02 9:06 ` Tvrtko Ursulin
1 sibling, 0 replies; 19+ messages in thread
From: Tvrtko Ursulin @ 2025-06-02 9:06 UTC (permalink / raw)
To: Maíra Canal, Matthew Brost, Danilo Krummrich,
Philipp Stanner, Christian König, Simona Vetter,
David Airlie, Melissa Wen, Lucas Stach, Russell King,
Christian Gmeiner, Lucas De Marchi, Thomas Hellström,
Rodrigo Vivi, Boris Brezillon, Rob Herring, Steven Price,
Liviu Dudau
Cc: kernel-dev, dri-devel, etnaviv, intel-xe
On 30/05/2025 15:01, Maíra Canal wrote:
> As more KUnit tests are introduced to evaluate the basic capabilities of
> the `timedout_job()` hook, the test suite will continue to increase in
> duration. To reduce the overall running time of the test suite, decrease
> the scheduler's timeout for the timeout tests.
>
> Before this commit:
>
> [15:42:26] Elapsed time: 15.637s total, 0.002s configuring, 10.387s building, 5.229s running
>
> After this commit:
>
> [15:45:26] Elapsed time: 9.263s total, 0.002s configuring, 5.168s building, 4.037s running
>
> Signed-off-by: Maíra Canal <mcanal@igalia.com>
> ---
> drivers/gpu/drm/scheduler/tests/tests_basic.c | 8 +++++---
> 1 file changed, 5 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/scheduler/tests/tests_basic.c b/drivers/gpu/drm/scheduler/tests/tests_basic.c
> index 7230057e0594c6246f02608f07fcb1f8d738ac75..41c648782f4548e202bd8711b45d28eead9bd0b2 100644
> --- a/drivers/gpu/drm/scheduler/tests/tests_basic.c
> +++ b/drivers/gpu/drm/scheduler/tests/tests_basic.c
> @@ -5,6 +5,8 @@
>
> #include "sched_tests.h"
>
> +#define MOCK_TIMEOUT (HZ / 5)
> +
> /*
> * DRM scheduler basic tests should check the basic functional correctness of
> * the scheduler, including some very light smoke testing. More targeted tests,
> @@ -28,7 +30,7 @@ static void drm_sched_basic_exit(struct kunit *test)
>
> static int drm_sched_timeout_init(struct kunit *test)
> {
> - test->priv = drm_mock_sched_new(test, HZ);
> + test->priv = drm_mock_sched_new(test, MOCK_TIMEOUT);
>
> return 0;
> }
> @@ -227,14 +229,14 @@ static void drm_sched_basic_timeout(struct kunit *test)
> done = drm_mock_sched_job_wait_scheduled(job, HZ);
> KUNIT_ASSERT_TRUE(test, done);
>
> - done = drm_mock_sched_job_wait_finished(job, HZ / 2);
> + done = drm_mock_sched_job_wait_finished(job, MOCK_TIMEOUT / 2);
> KUNIT_ASSERT_FALSE(test, done);
>
> KUNIT_ASSERT_EQ(test,
> job->flags & DRM_MOCK_SCHED_JOB_TIMEDOUT,
> 0);
>
> - done = drm_mock_sched_job_wait_finished(job, HZ);
> + done = drm_mock_sched_job_wait_finished(job, MOCK_TIMEOUT);
> KUNIT_ASSERT_FALSE(test, done);
Thinking about the potential for false negatives - scheduler timeout is
set to 200ms and total wait is 300ms before checking if the timeout hook
was executed by the scheduler core. So false negative only if scheduler
core would be lax with the timed out work handling. Or the lax delayed
work mechanism. Probably fine until we learn otherwise.
Reviewed-by: Tvrtko Ursulin <tvrtko.ursulin@igalia.com>
Regards,
Tvrtko
>
> KUNIT_ASSERT_EQ(test,
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 4/8] drm/sched: Add new test for DRM_GPU_SCHED_STAT_NO_HANG
2025-05-30 14:01 ` [PATCH v2 4/8] drm/sched: Add new test for DRM_GPU_SCHED_STAT_NO_HANG Maíra Canal
@ 2025-06-02 9:34 ` Tvrtko Ursulin
0 siblings, 0 replies; 19+ messages in thread
From: Tvrtko Ursulin @ 2025-06-02 9:34 UTC (permalink / raw)
To: Maíra Canal, Matthew Brost, Danilo Krummrich,
Philipp Stanner, Christian König, Simona Vetter,
David Airlie, Melissa Wen, Lucas Stach, Russell King,
Christian Gmeiner, Lucas De Marchi, Thomas Hellström,
Rodrigo Vivi, Boris Brezillon, Rob Herring, Steven Price,
Liviu Dudau
Cc: kernel-dev, dri-devel, etnaviv, intel-xe
On 30/05/2025 15:01, Maíra Canal wrote:
> Add a test to submit a single job against a scheduler with the timeout
> configured and verify that if the job is still running, the timeout
> handler will skip the reset and allow the job to complete.
>
> Signed-off-by: Maíra Canal <mcanal@igalia.com>
> ---
> drivers/gpu/drm/scheduler/tests/mock_scheduler.c | 5 +++
> drivers/gpu/drm/scheduler/tests/sched_tests.h | 1 +
> drivers/gpu/drm/scheduler/tests/tests_basic.c | 43 ++++++++++++++++++++++++
> 3 files changed, 49 insertions(+)
>
> diff --git a/drivers/gpu/drm/scheduler/tests/mock_scheduler.c b/drivers/gpu/drm/scheduler/tests/mock_scheduler.c
> index fdf5f34b39e02c8a8648d8bea566a27fd3251516..39429f5cd19ee3c23816f257d566b47d3daa4baa 100644
> --- a/drivers/gpu/drm/scheduler/tests/mock_scheduler.c
> +++ b/drivers/gpu/drm/scheduler/tests/mock_scheduler.c
> @@ -208,6 +208,11 @@ mock_sched_timedout_job(struct drm_sched_job *sched_job)
>
> job->flags |= DRM_MOCK_SCHED_JOB_TIMEDOUT;
>
> + if (job->flags & DRM_MOCK_SCHED_JOB_DONT_RESET) {
> + job->flags &= ~DRM_MOCK_SCHED_JOB_DONT_RESET;
If it isn't important to clear the flag I would consider omitting it.
> + return DRM_GPU_SCHED_STAT_NO_HANG;
> + }
> +
> return DRM_GPU_SCHED_STAT_RESET;
> }
>
> diff --git a/drivers/gpu/drm/scheduler/tests/sched_tests.h b/drivers/gpu/drm/scheduler/tests/sched_tests.h
> index 27caf8285fb74b9f3c9ce2daa1c44d4a0c967e92..5259f181e55387c41efbcd3f6addc9465331d787 100644
> --- a/drivers/gpu/drm/scheduler/tests/sched_tests.h
> +++ b/drivers/gpu/drm/scheduler/tests/sched_tests.h
> @@ -98,6 +98,7 @@ struct drm_mock_sched_job {
>
> #define DRM_MOCK_SCHED_JOB_DONE 0x1
> #define DRM_MOCK_SCHED_JOB_TIMEDOUT 0x2
> +#define DRM_MOCK_SCHED_JOB_DONT_RESET 0x4
> unsigned long flags;
>
> struct list_head link;
> diff --git a/drivers/gpu/drm/scheduler/tests/tests_basic.c b/drivers/gpu/drm/scheduler/tests/tests_basic.c
> index 41c648782f4548e202bd8711b45d28eead9bd0b2..2ba2d1b0c3cad9626ab9d89cfae05244c670a826 100644
> --- a/drivers/gpu/drm/scheduler/tests/tests_basic.c
> +++ b/drivers/gpu/drm/scheduler/tests/tests_basic.c
> @@ -246,8 +246,51 @@ static void drm_sched_basic_timeout(struct kunit *test)
> drm_mock_sched_entity_free(entity);
> }
>
> +static void drm_sched_skip_reset(struct kunit *test)
> +{
> + struct drm_mock_scheduler *sched = test->priv;
> + struct drm_mock_sched_entity *entity;
> + struct drm_mock_sched_job *job;
> + bool done;
> +
> + /*
> + * Submit a single job against a scheduler with the timeout configured
> + * and verify that if the job is still running, the timeout handler
> + * will skip the reset and allow the job to complete.
> + */
> +
> + entity = drm_mock_sched_entity_new(test,
> + DRM_SCHED_PRIORITY_NORMAL,
> + sched);
> + job = drm_mock_sched_job_new(test, entity);
> +
> + job->flags = DRM_MOCK_SCHED_JOB_DONT_RESET;
> +
> + drm_mock_sched_job_set_duration_us(job, jiffies_to_usecs(2 * MOCK_TIMEOUT));
Might be easier to not set the duration but advance the job manually
after the timeout assert. One time based interaction less.
> + drm_mock_sched_job_submit(job);
> +
> + done = drm_mock_sched_job_wait_finished(job, MOCK_TIMEOUT);
> + KUNIT_ASSERT_FALSE(test, done);
> +
> + KUNIT_ASSERT_EQ(test,
> + job->flags & DRM_MOCK_SCHED_JOB_TIMEDOUT,
> + DRM_MOCK_SCHED_JOB_TIMEDOUT);
> +
> + KUNIT_ASSERT_EQ(test,
> + job->flags & DRM_MOCK_SCHED_JOB_DONT_RESET,
> + 0);
Wait_finished for 200ms is equal to the configured job timeout so could
this be a bit racy? Safer to wait for 2 * MOCK_TIMEOUT I think.
(I also wonder whether I should have made the flags bit operations
atomic so the visibility between CPU cores running different threads is
guaranteed. I might follow up with that tweak.)
> +
> + KUNIT_ASSERT_FALSE(test, list_empty(&sched->job_list));
Going back to my first comment - if you remove the set_duration and
instead of this assert have do KUNIT_ASSERT_EQ(drm_mock_sched_advance(),
1) I think that should be good enough and simpler.
Regards,
Tvrtko
> +
> + done = drm_mock_sched_job_wait_finished(job, MOCK_TIMEOUT);
> + KUNIT_ASSERT_TRUE(test, done);
> +
> + drm_mock_sched_entity_free(entity);
> +}
> +
> static struct kunit_case drm_sched_timeout_tests[] = {
> KUNIT_CASE(drm_sched_basic_timeout),
> + KUNIT_CASE(drm_sched_skip_reset),
> {}
> };
>
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 5/8] drm/v3d: Use DRM_GPU_SCHED_STAT_NO_HANG to skip the reset
2025-06-02 7:13 ` Philipp Stanner
@ 2025-06-02 11:27 ` Maíra Canal
0 siblings, 0 replies; 19+ messages in thread
From: Maíra Canal @ 2025-06-02 11:27 UTC (permalink / raw)
To: phasta, Matthew Brost, Danilo Krummrich, Christian König,
Tvrtko Ursulin, Simona Vetter, David Airlie, Melissa Wen,
Lucas Stach, Russell King, Christian Gmeiner, Lucas De Marchi,
Thomas Hellström, Rodrigo Vivi, Boris Brezillon, Rob Herring,
Steven Price, Liviu Dudau
Cc: kernel-dev, dri-devel, etnaviv, intel-xe
Hi Philipp,
On 02/06/25 04:13, Philipp Stanner wrote:
> On Fri, 2025-05-30 at 11:01 -0300, Maíra Canal wrote:
>> When a CL/CSD job times out, we check if the GPU has made any
>> progress
>> since the last timeout. If so, instead of resetting the hardware, we
>> skip
>> the reset and allow the timer to be rearmed. This gives long-running
>> jobs
>> a chance to complete.
>>
>> Use the DRM_GPU_SCHED_STAT_NO_HANG status to skip the reset and re-
>> arm
>> the timer.
>>
>> Signed-off-by: Maíra Canal <mcanal@igalia.com>
>> ---
>> drivers/gpu/drm/v3d/v3d_sched.c | 4 ++--
>> 1 file changed, 2 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/gpu/drm/v3d/v3d_sched.c
>> b/drivers/gpu/drm/v3d/v3d_sched.c
>> index
>> e1997387831541fb053e472672004cf511c25558..fbb09a8aff3740b5cd59573b5f2
>> e26b2ee352dfb 100644
>> --- a/drivers/gpu/drm/v3d/v3d_sched.c
>> +++ b/drivers/gpu/drm/v3d/v3d_sched.c
>> @@ -761,7 +761,7 @@ v3d_cl_job_timedout(struct drm_sched_job
>> *sched_job, enum v3d_queue q,
>> if (*timedout_ctca != ctca || *timedout_ctra != ctra) {
>> *timedout_ctca = ctca;
>> *timedout_ctra = ctra;
>> - return DRM_GPU_SCHED_STAT_RESET;
>> + return DRM_GPU_SCHED_STAT_NO_HANG;
>> }
>>
>> return v3d_gpu_reset_for_timeout(v3d, sched_job);
>> @@ -805,7 +805,7 @@ v3d_csd_job_timedout(struct drm_sched_job
>> *sched_job)
>> */
>> if (job->timedout_batches != batches) {
>> job->timedout_batches = batches;
>> - return DRM_GPU_SCHED_STAT_RESET;
>> + return DRM_GPU_SCHED_STAT_NO_HANG;
>> }
>
> Wait a second, help me out here quickly. You already added workaround
> stuff where you manipulate the scheduler's pending_list, as you state
> in the cover letter. That code here [1].
>
> Don't you have to remove the very same code in this series again to
> still have correct behavior in your driver?
>
> As I see it, all drm branches end up in Linus's tree ultimately. So I'd
> think about potential branch-races in case you didn't already.
>
I always base my patches in drm-misc-next, which didn't backported
Linus' tree yet and still doesn't have the v3d fix. Hopefully, it will
be backported before I send v3.
Best Regards,
- Maíra
>
> P.
>
>
>
> [1] https://lore.kernel.org/dri-devel/20250430210643.57924-1-mcanal@igalia.com/T/
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 6/8] drm/etnaviv: Use DRM_GPU_SCHED_STAT_NO_HANG to skip the reset
2025-06-02 7:28 ` Philipp Stanner
@ 2025-06-02 11:36 ` Maíra Canal
2025-06-02 11:59 ` Philipp Stanner
0 siblings, 1 reply; 19+ messages in thread
From: Maíra Canal @ 2025-06-02 11:36 UTC (permalink / raw)
To: phasta, Matthew Brost, Danilo Krummrich, Christian König,
Tvrtko Ursulin, Simona Vetter, David Airlie, Melissa Wen,
Lucas Stach, Russell King, Christian Gmeiner, Lucas De Marchi,
Thomas Hellström, Rodrigo Vivi, Boris Brezillon, Rob Herring,
Steven Price, Liviu Dudau
Cc: kernel-dev, dri-devel, etnaviv, intel-xe
Hi Philipp,
On 02/06/25 04:28, Philipp Stanner wrote:
> On Fri, 2025-05-30 at 11:01 -0300, Maíra Canal wrote:
[...]
>> diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c
>> b/drivers/gpu/drm/etnaviv/etnaviv_sched.c
>> index
>> 7146069a98492f5fab2a49d96e2054f649e1fe3d..46f5391e84a12232b247886cf13
>> 11f8e09f42f04 100644
>> --- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c
>> +++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c
>> @@ -40,11 +40,11 @@ static enum drm_gpu_sched_stat
>> etnaviv_sched_timedout_job(struct drm_sched_job
>> int change;
>>
>> /*
>> - * If the GPU managed to complete this jobs fence, the
>> timout is
>> - * spurious. Bail out.
>> + * If the GPU managed to complete this jobs fence, the
>> timeout has
>> + * fired before free-job worker. The timeout is spurious, so
>> bail out.
>> */
>> if (dma_fence_is_signaled(submit->out_fence))
>> - goto out_no_timeout;
>> + return DRM_GPU_SCHED_STAT_NO_HANG;
>>
>> /*
>> * If the GPU is still making forward progress on the front-
>> end (which
>> @@ -70,7 +70,7 @@ static enum drm_gpu_sched_stat
>> etnaviv_sched_timedout_job(struct drm_sched_job
>> gpu->hangcheck_dma_addr = dma_addr;
>> gpu->hangcheck_primid = primid;
>> gpu->hangcheck_fence = gpu->completed_fence;
>> - goto out_no_timeout;
>> + return DRM_GPU_SCHED_STAT_NO_HANG;
>> }
>>
>> /* block scheduler */
>> @@ -86,10 +86,7 @@ static enum drm_gpu_sched_stat
>> etnaviv_sched_timedout_job(struct drm_sched_job
>> drm_sched_resubmit_jobs(&gpu->sched);
>>
>> drm_sched_start(&gpu->sched, 0);
>> - return DRM_GPU_SCHED_STAT_RESET;
>>
>> -out_no_timeout:
>> - list_add(&sched_job->list, &sched_job->sched->pending_list);
>
> Here you actually remove the manipulation of the scheduler internals,
> but you didn't in v3d. Just to point that out.
>
>
> And BTW I'm just seeing that the pending_list gets manipulated here
> with the scheduler's workqueues running and no locks being hold.
>
> Oh man :(
>
> That is most certainly a bug, and I recommend that the etnaviv
> maintainers at least add the appropriate lock here and backport that
> since it can race any time.
>
>
> But thx for working on that, Maíra. Good that we can remove the stuff
> this way.
>
> Thinking about it, this patch even fixes a bug. So could contain a
> Fixes: tag. But I'm not sure if it's worth it to mark the entire series
> for Stable. Opinions?
I believe the best way to fix this bug would be doing something similar
to what I did to v3d: send a temporary fix adding the locks, which will
be backported to stable. I'll send a fix to Etnaviv today.
Thanks for the review, Phillip!
Best Regards,
- Maíra
>
>
> P.
>
>
>> return DRM_GPU_SCHED_STAT_RESET;
>> }
>>
>>
>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2 6/8] drm/etnaviv: Use DRM_GPU_SCHED_STAT_NO_HANG to skip the reset
2025-06-02 11:36 ` Maíra Canal
@ 2025-06-02 11:59 ` Philipp Stanner
0 siblings, 0 replies; 19+ messages in thread
From: Philipp Stanner @ 2025-06-02 11:59 UTC (permalink / raw)
To: Maíra Canal, phasta, Matthew Brost, Danilo Krummrich,
Christian König, Tvrtko Ursulin, Simona Vetter, David Airlie,
Melissa Wen, Lucas Stach, Russell King, Christian Gmeiner,
Lucas De Marchi, Thomas Hellström, Rodrigo Vivi,
Boris Brezillon, Rob Herring, Steven Price, Liviu Dudau
Cc: kernel-dev, dri-devel, etnaviv, intel-xe
On Mon, 2025-06-02 at 08:36 -0300, Maíra Canal wrote:
> Hi Philipp,
>
> On 02/06/25 04:28, Philipp Stanner wrote:
> > On Fri, 2025-05-30 at 11:01 -0300, Maíra Canal wrote:
>
> [...]
>
> > > diff --git a/drivers/gpu/drm/etnaviv/etnaviv_sched.c
> > > b/drivers/gpu/drm/etnaviv/etnaviv_sched.c
> > > index
> > > 7146069a98492f5fab2a49d96e2054f649e1fe3d..46f5391e84a12232b247886
> > > cf13
> > > 11f8e09f42f04 100644
> > > --- a/drivers/gpu/drm/etnaviv/etnaviv_sched.c
> > > +++ b/drivers/gpu/drm/etnaviv/etnaviv_sched.c
> > > @@ -40,11 +40,11 @@ static enum drm_gpu_sched_stat
> > > etnaviv_sched_timedout_job(struct drm_sched_job
> > > int change;
> > >
> > > /*
> > > - * If the GPU managed to complete this jobs fence, the
> > > timout is
> > > - * spurious. Bail out.
> > > + * If the GPU managed to complete this jobs fence, the
> > > timeout has
> > > + * fired before free-job worker. The timeout is
> > > spurious, so
> > > bail out.
> > > */
> > > if (dma_fence_is_signaled(submit->out_fence))
> > > - goto out_no_timeout;
> > > + return DRM_GPU_SCHED_STAT_NO_HANG;
> > >
> > > /*
> > > * If the GPU is still making forward progress on the
> > > front-
> > > end (which
> > > @@ -70,7 +70,7 @@ static enum drm_gpu_sched_stat
> > > etnaviv_sched_timedout_job(struct drm_sched_job
> > > gpu->hangcheck_dma_addr = dma_addr;
> > > gpu->hangcheck_primid = primid;
> > > gpu->hangcheck_fence = gpu->completed_fence;
> > > - goto out_no_timeout;
> > > + return DRM_GPU_SCHED_STAT_NO_HANG;
> > > }
> > >
> > > /* block scheduler */
> > > @@ -86,10 +86,7 @@ static enum drm_gpu_sched_stat
> > > etnaviv_sched_timedout_job(struct drm_sched_job
> > > drm_sched_resubmit_jobs(&gpu->sched);
> > >
> > > drm_sched_start(&gpu->sched, 0);
> > > - return DRM_GPU_SCHED_STAT_RESET;
> > >
> > > -out_no_timeout:
> > > - list_add(&sched_job->list, &sched_job->sched-
> > > >pending_list);
> >
> > Here you actually remove the manipulation of the scheduler
> > internals,
> > but you didn't in v3d. Just to point that out.
> >
> >
> > And BTW I'm just seeing that the pending_list gets manipulated here
> > with the scheduler's workqueues running and no locks being hold.
> >
> > Oh man :(
> >
> > That is most certainly a bug, and I recommend that the etnaviv
> > maintainers at least add the appropriate lock here and backport
> > that
> > since it can race any time.
> >
> >
> > But thx for working on that, Maíra. Good that we can remove the
> > stuff
> > this way.
> >
> > Thinking about it, this patch even fixes a bug. So could contain a
> > Fixes: tag. But I'm not sure if it's worth it to mark the entire
> > series
> > for Stable. Opinions?
>
> I believe the best way to fix this bug would be doing something
> similar
> to what I did to v3d: send a temporary fix adding the locks, which
> will
> be backported to stable. I'll send a fix to Etnaviv today.
Having the locking is significantly better than not having it, and
adding it gets my blessing, but it still doesn't solve all issues.
As Matt pointed out and as you address in your patch №2, a job could
still leak if no one makes sure that free_job_work gets kicked off. And
exposing yet another scheduler function publicly is obviously
unacceptable, so it's either live with the potential leak, or use the
new status code.
P.
>
> Thanks for the review, Phillip!
>
> Best Regards,
> - Maíra
>
> >
> >
> > P.
> >
> >
> > > return DRM_GPU_SCHED_STAT_RESET;
> > > }
> > >
> > >
> >
>
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2025-06-02 11:59 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-30 14:01 [PATCH v2 0/8] drm/sched: Allow drivers to skip the reset with DRM_GPU_SCHED_STAT_NO_HANG Maíra Canal
2025-05-30 14:01 ` [PATCH v2 1/8] drm/sched: Rename DRM_GPU_SCHED_STAT_NOMINAL to DRM_GPU_SCHED_STAT_RESET Maíra Canal
2025-05-30 14:01 ` [PATCH v2 2/8] drm/sched: Allow drivers to skip the reset and keep on running Maíra Canal
2025-06-02 7:06 ` Philipp Stanner
2025-05-30 14:01 ` [PATCH v2 3/8] drm/sched: Reduce scheduler's timeout for timeout tests Maíra Canal
2025-06-02 8:54 ` Philipp Stanner
2025-06-02 9:06 ` Tvrtko Ursulin
2025-05-30 14:01 ` [PATCH v2 4/8] drm/sched: Add new test for DRM_GPU_SCHED_STAT_NO_HANG Maíra Canal
2025-06-02 9:34 ` Tvrtko Ursulin
2025-05-30 14:01 ` [PATCH v2 5/8] drm/v3d: Use DRM_GPU_SCHED_STAT_NO_HANG to skip the reset Maíra Canal
2025-06-02 7:13 ` Philipp Stanner
2025-06-02 11:27 ` Maíra Canal
2025-05-30 14:01 ` [PATCH v2 6/8] drm/etnaviv: " Maíra Canal
2025-06-02 7:28 ` Philipp Stanner
2025-06-02 11:36 ` Maíra Canal
2025-06-02 11:59 ` Philipp Stanner
2025-05-30 14:01 ` [PATCH v2 7/8] drm/xe: " Maíra Canal
2025-06-02 7:47 ` Philipp Stanner
2025-05-30 14:01 ` [PATCH v2 8/8] drm/panfrost: " Maíra Canal
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).