* [PATCH v5 1/3] drm/xe: Prevent VF memory IRQ from accessing a torn-down engine
2026-10-12 5:50 [PATCH v5 0/3] Fix kernel crash during driver teardown Satyanarayana K V P
@ 2026-10-12 5:50 ` Satyanarayana K V P
2026-10-12 6:07 ` sashiko-bot
2026-10-12 8:29 ` Piotr Piórkowski
2026-10-12 5:50 ` [PATCH v5 2/3] drm/xe/guc: Protect timeout handling from device unplug Satyanarayana K V P
2026-10-12 5:50 ` [PATCH v5 3/3] drm/xe/gt: Disable GT reset worker before engine teardown Satyanarayana K V P
2 siblings, 2 replies; 8+ messages in thread
From: Satyanarayana K V P @ 2026-10-12 5:50 UTC (permalink / raw)
To: intel-xe; +Cc: Satyanarayana K V P, Matthew Brost, Piotr Piórkowski
The VF memory IRQ handler iterates over HW engines whose names are set.
Engine teardown clears hwe->gt but leaves hwe->name set, so the handler
can select an engine whose GT has already been invalidated. This can
cause a NULL pointer dereference in xe_hw_engine_handle_irq().
Invalidate the engine name during teardown so subsequent engine scans
skip it.
Signed-off-by: Satyanarayana K V P <satyanarayana.k.v.p@intel.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Piotr Piórkowski <piotr.piorkowski@intel.com>
Fixes: 6eb2aad402cc ("drm/xe: Move hw_engine_fini to devm managed")
---
V3 -> V4:
- Fix issue with xe_execlist_port_destroy() with V3 version (Sashiko).
V2 -> V3:
- Updated spin_lock_irq() to spin_lock_irqsave().
V1 -> V2:
- Fix race with xe_memirq_handler() and hw_engine_fini() (Sashiko & Piotr).
---
drivers/gpu/drm/xe/xe_hw_engine.c | 17 ++++++++++++++---
drivers/gpu/drm/xe/xe_irq.c | 3 +++
drivers/gpu/drm/xe/xe_memirq.c | 3 +++
3 files changed, 20 insertions(+), 3 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c
index 265f95c0c899..55ee0c892c1e 100644
--- a/drivers/gpu/drm/xe/xe_hw_engine.c
+++ b/drivers/gpu/drm/xe/xe_hw_engine.c
@@ -275,11 +275,22 @@ static const struct engine_info engine_infos[] = {
static void hw_engine_fini(void *arg)
{
struct xe_hw_engine *hwe = arg;
+ struct xe_gt *gt = hwe->gt;
+
+ if (gt) {
+ struct xe_device *xe = gt_to_xe(gt);
+ unsigned long flags;
- if (hwe->exl_port)
- xe_execlist_port_destroy(hwe->exl_port);
+ if (hwe->exl_port)
+ xe_execlist_port_destroy(hwe->exl_port);
- hwe->gt = NULL;
+ spin_lock_irqsave(&xe->irq.lock, flags);
+ hwe->name = NULL;
+ hwe->gt = NULL;
+ spin_unlock_irqrestore(&xe->irq.lock, flags);
+ } else {
+ hwe->name = NULL;
+ }
}
/**
diff --git a/drivers/gpu/drm/xe/xe_irq.c b/drivers/gpu/drm/xe/xe_irq.c
index 9e49e2241da4..b394c8edf89c 100644
--- a/drivers/gpu/drm/xe/xe_irq.c
+++ b/drivers/gpu/drm/xe/xe_irq.c
@@ -908,6 +908,7 @@ static irqreturn_t xe_irq_msix_default_hwe_handler(int irq, void *arg)
struct xe_hw_engine *hwe;
enum xe_hw_engine_id id;
struct xe_tile *tile;
+ unsigned long flags;
struct xe_gt *gt;
if (!atomic_read(&xe->irq.enabled))
@@ -922,8 +923,10 @@ static irqreturn_t xe_irq_msix_default_hwe_handler(int irq, void *arg)
if (gt->tile != tile)
continue;
+ spin_lock_irqsave(&xe->irq.lock, flags);
for_each_hw_engine(hwe, gt, id)
xe_memirq_hwe_handler(memirq, hwe);
+ spin_unlock_irqrestore(&xe->irq.lock, flags);
}
}
diff --git a/drivers/gpu/drm/xe/xe_memirq.c b/drivers/gpu/drm/xe/xe_memirq.c
index 9dfe965cb46e..1073132f2ded 100644
--- a/drivers/gpu/drm/xe/xe_memirq.c
+++ b/drivers/gpu/drm/xe/xe_memirq.c
@@ -555,6 +555,7 @@ void xe_memirq_handler(struct xe_memirq *memirq)
struct xe_hw_engine *hwe;
enum xe_hw_engine_id id;
struct iosys_map map;
+ unsigned long flags;
unsigned int gtid;
struct xe_gt *gt;
@@ -568,8 +569,10 @@ void xe_memirq_handler(struct xe_memirq *memirq)
if (gt->tile != tile)
continue;
+ spin_lock_irqsave(&xe->irq.lock, flags);
for_each_hw_engine(hwe, gt, id)
xe_memirq_hwe_handler(memirq, hwe);
+ spin_unlock_irqrestore(&xe->irq.lock, flags);
}
/* GuC and media GuC (if present) must be checked separately */
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v5 1/3] drm/xe: Prevent VF memory IRQ from accessing a torn-down engine
2026-10-12 5:50 ` [PATCH v5 1/3] drm/xe: Prevent VF memory IRQ from accessing a torn-down engine Satyanarayana K V P
@ 2026-10-12 6:07 ` sashiko-bot
2026-10-12 8:29 ` Piotr Piórkowski
1 sibling, 0 replies; 8+ messages in thread
From: sashiko-bot @ 2026-10-12 6:07 UTC (permalink / raw)
To: Satyanarayana K V P; +Cc: intel-xe
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] drm/xe: NULL pointer dereference due to incomplete locking in hw_engine_fini
--
commit 888f9d1be166404e1216f8d0d23505412e283b23
Author: Satyanarayana K V P <satyanarayana.k.v.p@intel.com>
drm/xe: Prevent VF memory IRQ from accessing a torn-down engine
This commit fixes a NULL pointer dereference by invalidating the engine
name and GT pointer during teardown in hw_engine_fini() under the
irq.lock, preventing the VF memory IRQ handler from scanning it.
> diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c
> index 265f95c0c8993..55ee0c892c1e8 100644
> --- a/drivers/gpu/drm/xe/xe_hw_engine.c
> +++ b/drivers/gpu/drm/xe/xe_hw_engine.c
[ ... ]
> @@ -275,11 +275,22 @@ static const struct engine_info engine_infos[] = {
> static void hw_engine_fini(void *arg)
> {
> struct xe_hw_engine *hwe = arg;
> + struct xe_gt *gt = hwe->gt;
> +
> + if (gt) {
> + struct xe_device *xe = gt_to_xe(gt);
> + unsigned long flags;
>
> - if (hwe->exl_port)
> - xe_execlist_port_destroy(hwe->exl_port);
> + if (hwe->exl_port)
> + xe_execlist_port_destroy(hwe->exl_port);
>
> - hwe->gt = NULL;
> + spin_lock_irqsave(&xe->irq.lock, flags);
> + hwe->name = NULL;
> + hwe->gt = NULL;
[Severity: High]
Can this still cause a NULL pointer dereference for lockless IOCTL callers?
Unprivileged userspace can call the DRM_IOCTL_XE_DEVICE_QUERY ioctl
(specifically query_engine_cycles) concurrently with device unbind or unplug.
Since the ioctl is not guarded by drm_dev_enter(), it can proceed
concurrently with devres_release_all() and hw_engine_fini().
The ioctl looks up the hardware engine via xe_gt_hw_engine() in
query_engine_cycles():
drivers/gpu/drm/xe/xe_query.c:query_engine_cycles() {
...
hwe = xe_gt_hw_engine(gt, user_to_xe_engine_class[eci->engine_class],
eci->engine_instance, true);
if (!hwe)
return -EINVAL;
...
}
Immediately after this check, hw_engine_fini() can execute and clear
hwe->gt = NULL (guarded only by xe->irq.lock, which the ioctl does not hold).
The ioctl then calls hwe_read_timestamp(), which dereferences hwe->gt:
drivers/gpu/drm/xe/xe_query.c:hwe_read_timestamp() {
struct xe_mmio *mmio = &hwe->gt->mmio;
...
}
Does this lockless path need additional protection against concurrent
teardown?
> + spin_unlock_irqrestore(&xe->irq.lock, flags);
> + } else {
> + hwe->name = NULL;
> + }
> }
>
> /**
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261012055053.964468-5-satyanarayana.k.v.p@intel.com?part=1
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH v5 1/3] drm/xe: Prevent VF memory IRQ from accessing a torn-down engine
2026-10-12 5:50 ` [PATCH v5 1/3] drm/xe: Prevent VF memory IRQ from accessing a torn-down engine Satyanarayana K V P
2026-10-12 6:07 ` sashiko-bot
@ 2026-10-12 8:29 ` Piotr Piórkowski
1 sibling, 0 replies; 8+ messages in thread
From: Piotr Piórkowski @ 2026-10-12 8:29 UTC (permalink / raw)
To: Satyanarayana K V P; +Cc: intel-xe, Matthew Brost
Satyanarayana K V P <satyanarayana.k.v.p@intel.com> wrote on pon [2026-paź-12 05:50:55 +0000]:
> The VF memory IRQ handler iterates over HW engines whose names are set.
> Engine teardown clears hwe->gt but leaves hwe->name set, so the handler
> can select an engine whose GT has already been invalidated. This can
> cause a NULL pointer dereference in xe_hw_engine_handle_irq().
>
> Invalidate the engine name during teardown so subsequent engine scans
> skip it.
>
> Signed-off-by: Satyanarayana K V P <satyanarayana.k.v.p@intel.com>
> Cc: Matthew Brost <matthew.brost@intel.com>
> Cc: Piotr Piórkowski <piotr.piorkowski@intel.com>
> Fixes: 6eb2aad402cc ("drm/xe: Move hw_engine_fini to devm managed")
> ---
> V3 -> V4:
> - Fix issue with xe_execlist_port_destroy() with V3 version (Sashiko).
>
> V2 -> V3:
> - Updated spin_lock_irq() to spin_lock_irqsave().
>
> V1 -> V2:
> - Fix race with xe_memirq_handler() and hw_engine_fini() (Sashiko & Piotr).
> ---
> drivers/gpu/drm/xe/xe_hw_engine.c | 17 ++++++++++++++---
> drivers/gpu/drm/xe/xe_irq.c | 3 +++
> drivers/gpu/drm/xe/xe_memirq.c | 3 +++
> 3 files changed, 20 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_hw_engine.c b/drivers/gpu/drm/xe/xe_hw_engine.c
> index 265f95c0c899..55ee0c892c1e 100644
> --- a/drivers/gpu/drm/xe/xe_hw_engine.c
> +++ b/drivers/gpu/drm/xe/xe_hw_engine.c
> @@ -275,11 +275,22 @@ static const struct engine_info engine_infos[] = {
> static void hw_engine_fini(void *arg)
> {
> struct xe_hw_engine *hwe = arg;
> + struct xe_gt *gt = hwe->gt;
> +
> + if (gt) {
> + struct xe_device *xe = gt_to_xe(gt);
> + unsigned long flags;
>
> - if (hwe->exl_port)
> - xe_execlist_port_destroy(hwe->exl_port);
> + if (hwe->exl_port)
> + xe_execlist_port_destroy(hwe->exl_port);
>
> - hwe->gt = NULL;
> + spin_lock_irqsave(&xe->irq.lock, flags);
> + hwe->name = NULL;
> + hwe->gt = NULL;
> + spin_unlock_irqrestore(&xe->irq.lock, flags);
> + } else {
> + hwe->name = NULL;
> + }
NIT: I don't think the !gt branch can ever be taken. hwe->gt is set in
hw_engine_init_early(), long before hw_engine_init() registers
hw_engine_fini() via devm_add_action_or_reset(). Both the normal devm
release and the _or_reset error path therefore always see a valid
hwe->gt, and the original code relied on that as well
(xe_execlist_port_destroy() dereferences port->hwe->gt unconditionally).
> }
>
> /**
> diff --git a/drivers/gpu/drm/xe/xe_irq.c b/drivers/gpu/drm/xe/xe_irq.c
> index 9e49e2241da4..b394c8edf89c 100644
> --- a/drivers/gpu/drm/xe/xe_irq.c
> +++ b/drivers/gpu/drm/xe/xe_irq.c
> @@ -908,6 +908,7 @@ static irqreturn_t xe_irq_msix_default_hwe_handler(int irq, void *arg)
> struct xe_hw_engine *hwe;
> enum xe_hw_engine_id id;
> struct xe_tile *tile;
> + unsigned long flags;
> struct xe_gt *gt;
>
> if (!atomic_read(&xe->irq.enabled))
> @@ -922,8 +923,10 @@ static irqreturn_t xe_irq_msix_default_hwe_handler(int irq, void *arg)
> if (gt->tile != tile)
> continue;
>
> + spin_lock_irqsave(&xe->irq.lock, flags);
> for_each_hw_engine(hwe, gt, id)
> xe_memirq_hwe_handler(memirq, hwe);
> + spin_unlock_irqrestore(&xe->irq.lock, flags);
> }
> }
>
> diff --git a/drivers/gpu/drm/xe/xe_memirq.c b/drivers/gpu/drm/xe/xe_memirq.c
> index 9dfe965cb46e..1073132f2ded 100644
> --- a/drivers/gpu/drm/xe/xe_memirq.c
> +++ b/drivers/gpu/drm/xe/xe_memirq.c
> @@ -555,6 +555,7 @@ void xe_memirq_handler(struct xe_memirq *memirq)
> struct xe_hw_engine *hwe;
> enum xe_hw_engine_id id;
> struct iosys_map map;
> + unsigned long flags;
> unsigned int gtid;
> struct xe_gt *gt;
>
> @@ -568,8 +569,10 @@ void xe_memirq_handler(struct xe_memirq *memirq)
> if (gt->tile != tile)
> continue;
>
> + spin_lock_irqsave(&xe->irq.lock, flags);
> for_each_hw_engine(hwe, gt, id)
> xe_memirq_hwe_handler(memirq, hwe);
> + spin_unlock_irqrestore(&xe->irq.lock, flags);
> }
>
> /* GuC and media GuC (if present) must be checked separately */
> --
> 2.43.0
>
LGTM, one NIT above:
Reviewed-by: Piotr Piórkowski <piotr.piorkowski@intel.com>
--
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v5 2/3] drm/xe/guc: Protect timeout handling from device unplug
2026-10-12 5:50 [PATCH v5 0/3] Fix kernel crash during driver teardown Satyanarayana K V P
2026-10-12 5:50 ` [PATCH v5 1/3] drm/xe: Prevent VF memory IRQ from accessing a torn-down engine Satyanarayana K V P
@ 2026-10-12 5:50 ` Satyanarayana K V P
2026-10-12 6:00 ` sashiko-bot
2026-10-12 5:50 ` [PATCH v5 3/3] drm/xe/gt: Disable GT reset worker before engine teardown Satyanarayana K V P
2 siblings, 1 reply; 8+ messages in thread
From: Satyanarayana K V P @ 2026-10-12 5:50 UTC (permalink / raw)
To: intel-xe; +Cc: Satyanarayana K V P, Matthew Brost, Piotr Piórkowski
The GuC scheduler timeout callback accesses device and GT state while
handling a timed-out job. Guard the callback with drm_dev_enter() and
drm_dev_exit() so device unplug waits for in-flight timeout handling.
If unplug has already started, mark the job with -ENODEV and return it
to the scheduler for cleanup.
Fixes: 6eb2aad402cc ("drm/xe: Move hw_engine_fini to devm managed")
Signed-off-by: Satyanarayana K V P <satyanarayana.k.v.p@intel.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Piotr Piórkowski <piotr.piorkowski@intel.com>
Assisted-by: LLM
---
V4 -> V5:
- Return DRM_GPU_SCHED_STAT_ENODEV instead of DRM_GPU_SCHED_STAT_NO_HANG
(Sashiko).
V3 -> V4:
- None.
V2 -> V3:
- Fixed race condition with guc_exec_queue_timedout_job(). (Sashiko).
---
drivers/gpu/drm/xe/xe_guc_submit.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
index 7ce73489c35f..082c94340b41 100644
--- a/drivers/gpu/drm/xe/xe_guc_submit.c
+++ b/drivers/gpu/drm/xe/xe_guc_submit.c
@@ -1599,6 +1599,12 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
int err = -ETIME;
pid_t pid = -1;
bool wedged = false, wedge_device = false, skip_timeout_check;
+ int idx;
+
+ if (!drm_dev_enter(&xe->drm, &idx)) {
+ xe_sched_job_set_error(job, -ENODEV);
+ return DRM_GPU_SCHED_STAT_ENODEV;
+ }
xe_gt_assert(guc_to_gt(guc), !exec_queue_destroyed(q));
@@ -1611,8 +1617,10 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
* lost.
*/
if (test_bit(DMA_FENCE_FLAG_SIGNALED_BIT, &job->fence->flags) ||
- vf_recovery(guc))
+ vf_recovery(guc)) {
+ drm_dev_exit(idx);
return DRM_GPU_SCHED_STAT_NO_HANG;
+ }
/* Kill the run_job entry point */
if (xe_exec_queue_is_multi_queue(q))
@@ -1786,6 +1794,7 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
* We want the job added back to the pending list so it gets freed; this
* is what DRM_GPU_SCHED_STAT_NO_HANG does.
*/
+ drm_dev_exit(idx);
return DRM_GPU_SCHED_STAT_NO_HANG;
rearm:
@@ -1799,6 +1808,7 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
else
xe_sched_submission_start(sched);
handle_vf_resume:
+ drm_dev_exit(idx);
return DRM_GPU_SCHED_STAT_NO_HANG;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v5 2/3] drm/xe/guc: Protect timeout handling from device unplug
2026-10-12 5:50 ` [PATCH v5 2/3] drm/xe/guc: Protect timeout handling from device unplug Satyanarayana K V P
@ 2026-10-12 6:00 ` sashiko-bot
0 siblings, 0 replies; 8+ messages in thread
From: sashiko-bot @ 2026-10-12 6:00 UTC (permalink / raw)
To: Satyanarayana K V P; +Cc: intel-xe
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] drm/scheduler: Memory leak of timed-out job when returning ENODEV
--
commit 17e9fcf9241e0bec8edf4a488366f62c46a0e6dc
Author: Satyanarayana K V P <satyanarayana.k.v.p@intel.com>
drm/xe/guc: Protect timeout handling from device unplug
This commit guards the GuC scheduler timeout callback with drm_dev_enter()
and drm_dev_exit() to handle concurrent device unplug. If an unplug has
started, it marks the job with -ENODEV and returns a corresponding status
to the scheduler.
> diff --git a/drivers/gpu/drm/xe/xe_guc_submit.c b/drivers/gpu/drm/xe/xe_guc_submit.c
> index 7ce73489c35fc..082c94340b41d 100644
> --- a/drivers/gpu/drm/xe/xe_guc_submit.c
> +++ b/drivers/gpu/drm/xe/xe_guc_submit.c
> @@ -1599,6 +1599,12 @@ guc_exec_queue_timedout_job(struct drm_sched_job *drm_job)
> int err = -ETIME;
> pid_t pid = -1;
> bool wedged = false, wedge_device = false, skip_timeout_check;
> + int idx;
> +
> + if (!drm_dev_enter(&xe->drm, &idx)) {
> + xe_sched_job_set_error(job, -ENODEV);
> + return DRM_GPU_SCHED_STAT_ENODEV;
[Severity: Medium]
Does returning DRM_GPU_SCHED_STAT_ENODEV here cause a memory leak of the
struct xe_sched_job and its associated resources?
When a job times out concurrently with device unplug, the DRM scheduler core
in drm_sched_job_timedout() explicitly drops the job from its pending list
before invoking this backend timeout callback. It only reinserts the job into
the pending list if the callback returns DRM_GPU_SCHED_STAT_NO_HANG.
By returning DRM_GPU_SCHED_STAT_ENODEV, the job remains unlinked. Even though
the fence is signaled via xe_sched_job_set_error(), the scheduler's cleanup
worker (drm_sched_free_job_work()) and teardown sequences only search
sched->pending_list.
Because the job is neither manually freed in this early return path nor
reinserted for automatic scheduler cleanup, the job structure appears to be
permanently orphaned.
> + }
>
> xe_gt_assert(guc_to_gt(guc), !exec_queue_destroyed(q));
>
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261012055053.964468-5-satyanarayana.k.v.p@intel.com?part=2
^ permalink raw reply [flat|nested] 8+ messages in thread
* [PATCH v5 3/3] drm/xe/gt: Disable GT reset worker before engine teardown
2026-10-12 5:50 [PATCH v5 0/3] Fix kernel crash during driver teardown Satyanarayana K V P
2026-10-12 5:50 ` [PATCH v5 1/3] drm/xe: Prevent VF memory IRQ from accessing a torn-down engine Satyanarayana K V P
2026-10-12 5:50 ` [PATCH v5 2/3] drm/xe/guc: Protect timeout handling from device unplug Satyanarayana K V P
@ 2026-10-12 5:50 ` Satyanarayana K V P
2026-10-12 8:40 ` Piotr Piórkowski
2 siblings, 1 reply; 8+ messages in thread
From: Satyanarayana K V P @ 2026-10-12 5:50 UTC (permalink / raw)
To: intel-xe
Cc: Satyanarayana K V P, Matthew Brost, Piotr Piórkowski,
Balasubramani Vivekanandan
During tear-down process, a reset queued from Guc timeout handler can
still access hwe after hwe is freed. Register a separate devm
action that disables and drains the reset worker, so it runs before
any engine is torn down.
Fixes: 09c452d1171f ("drm/xe/gt: Synchronize GT reset with device unbind")
Signed-off-by: Satyanarayana K V P <satyanarayana.k.v.p@intel.com>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Piotr Piórkowski <piotr.piorkowski@intel.com>
Cc: Balasubramani Vivekanandan <balasubramani.vivekanandan@intel.com>
Assisted-by: LLM
---
V3 -> V4:
- Fix race condition reported by LLM (Sashiko).
---
drivers/gpu/drm/xe/xe_gt.c | 29 ++++++++++++++++++++++-------
1 file changed, 22 insertions(+), 7 deletions(-)
diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c
index 775c826b68b4..bc9bf6f0b5a7 100644
--- a/drivers/gpu/drm/xe/xe_gt.c
+++ b/drivers/gpu/drm/xe/xe_gt.c
@@ -630,8 +630,21 @@ static int gt_init_with_gt_forcewake(struct xe_gt *gt)
return 0;
}
+static void gt_reset_worker_disable(void *arg)
+{
+ struct xe_gt *gt = arg;
+
+ if (disable_work_sync(>->reset.worker))
+ /*
+ * If gt_reset_worker was halted from executing, take care of
+ * releasing the rpm reference here.
+ */
+ xe_pm_runtime_put(gt_to_xe(gt));
+}
+
static int gt_init_with_all_forcewake(struct xe_gt *gt)
{
+ struct xe_device *xe = gt_to_xe(gt);
int err;
CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FORCEWAKE_ALL);
@@ -698,6 +711,11 @@ static int gt_init_with_all_forcewake(struct xe_gt *gt)
if (IS_SRIOV_PF(gt_to_xe(gt)))
xe_gt_sriov_pf_init_hw(gt);
+ /* Last action registered here so devres drains resets before teardown */
+ err = devm_add_action_or_reset(xe->drm.dev, gt_reset_worker_disable, gt);
+ if (err)
+ return err;
+
return 0;
}
@@ -706,12 +724,7 @@ static void xe_gt_fini(void *arg)
struct xe_gt *gt = arg;
int i;
- if (disable_work_sync(>->reset.worker))
- /*
- * If gt_reset_worker was halted from executing, take care of
- * releasing the rpm reference here.
- */
- xe_pm_runtime_put(gt_to_xe(gt));
+ gt_reset_worker_disable(gt);
for (i = 0; i < XE_ENGINE_CLASS_MAX; ++i)
xe_hw_fence_irq_finish(>->fence_irq[i]);
@@ -754,8 +767,10 @@ int xe_gt_init(struct xe_gt *gt)
xe_force_wake_init_engines(gt, gt_to_fw(gt));
err = gt_init_with_all_forcewake(gt);
- if (err)
+ if (err) {
+ gt_reset_worker_disable(gt);
return err;
+ }
xe_gt_record_user_engines(gt);
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH v5 3/3] drm/xe/gt: Disable GT reset worker before engine teardown
2026-10-12 5:50 ` [PATCH v5 3/3] drm/xe/gt: Disable GT reset worker before engine teardown Satyanarayana K V P
@ 2026-10-12 8:40 ` Piotr Piórkowski
0 siblings, 0 replies; 8+ messages in thread
From: Piotr Piórkowski @ 2026-10-12 8:40 UTC (permalink / raw)
To: Satyanarayana K V P; +Cc: intel-xe, Matthew Brost, Balasubramani Vivekanandan
Satyanarayana K V P <satyanarayana.k.v.p@intel.com> wrote on pon [2026-paź-12 05:50:57 +0000]:
> During tear-down process, a reset queued from Guc timeout handler can
> still access hwe after hwe is freed. Register a separate devm
> action that disables and drains the reset worker, so it runs before
> any engine is torn down.
>
> Fixes: 09c452d1171f ("drm/xe/gt: Synchronize GT reset with device unbind")
> Signed-off-by: Satyanarayana K V P <satyanarayana.k.v.p@intel.com>
> Cc: Matthew Brost <matthew.brost@intel.com>
> Cc: Piotr Piórkowski <piotr.piorkowski@intel.com>
> Cc: Balasubramani Vivekanandan <balasubramani.vivekanandan@intel.com>
> Assisted-by: LLM
> ---
> V3 -> V4:
> - Fix race condition reported by LLM (Sashiko).
> ---
> drivers/gpu/drm/xe/xe_gt.c | 29 ++++++++++++++++++++++-------
> 1 file changed, 22 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/gpu/drm/xe/xe_gt.c b/drivers/gpu/drm/xe/xe_gt.c
> index 775c826b68b4..bc9bf6f0b5a7 100644
> --- a/drivers/gpu/drm/xe/xe_gt.c
> +++ b/drivers/gpu/drm/xe/xe_gt.c
> @@ -630,8 +630,21 @@ static int gt_init_with_gt_forcewake(struct xe_gt *gt)
> return 0;
> }
>
> +static void gt_reset_worker_disable(void *arg)
> +{
> + struct xe_gt *gt = arg;
> +
> + if (disable_work_sync(>->reset.worker))
> + /*
> + * If gt_reset_worker was halted from executing, take care of
> + * releasing the rpm reference here.
> + */
> + xe_pm_runtime_put(gt_to_xe(gt));
> +}
> +
> static int gt_init_with_all_forcewake(struct xe_gt *gt)
> {
> + struct xe_device *xe = gt_to_xe(gt);
> int err;
>
> CLASS(xe_force_wake, fw_ref)(gt_to_fw(gt), XE_FORCEWAKE_ALL);
> @@ -698,6 +711,11 @@ static int gt_init_with_all_forcewake(struct xe_gt *gt)
> if (IS_SRIOV_PF(gt_to_xe(gt)))
> xe_gt_sriov_pf_init_hw(gt);
>
> + /* Last action registered here so devres drains resets before teardown */
> + err = devm_add_action_or_reset(xe->drm.dev, gt_reset_worker_disable, gt);
> + if (err)
> + return err;
> +
> return 0;
> }
>
> @@ -706,12 +724,7 @@ static void xe_gt_fini(void *arg)
> struct xe_gt *gt = arg;
> int i;
>
> - if (disable_work_sync(>->reset.worker))
> - /*
> - * If gt_reset_worker was halted from executing, take care of
> - * releasing the rpm reference here.
> - */
> - xe_pm_runtime_put(gt_to_xe(gt));
> + gt_reset_worker_disable(gt);
>
> for (i = 0; i < XE_ENGINE_CLASS_MAX; ++i)
> xe_hw_fence_irq_finish(>->fence_irq[i]);
> @@ -754,8 +767,10 @@ int xe_gt_init(struct xe_gt *gt)
> xe_force_wake_init_engines(gt, gt_to_fw(gt));
>
> err = gt_init_with_all_forcewake(gt);
> - if (err)
> + if (err) {
> + gt_reset_worker_disable(gt);
> return err;
> + }
>
> xe_gt_record_user_engines(gt);
>
LGTM:
Reviewed-by: Piotr Piórkowski <piotr.piorkowski@intel.com>
> --
> 2.43.0
>
--
^ permalink raw reply [flat|nested] 8+ messages in thread