From: sashiko-bot@kernel.org
To: "Raag Jadav" <raag.jadav@intel.com>, intel-xe@lists.freedesktop.org
Subject: Re: [PATCH v12 08/10] drm/xe: Introduce temporary device wedging
Date: Tue, 03 Nov 2026 06:44:14 +0000 [thread overview]
Message-ID: <sashiko-outbox-194662@kernel.org> (raw)
In-Reply-To: <20261103060649.1015468-9-raag.jadav@intel.com>
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
- [High] drm/xe: unmatched xe_wedge_put() in xe_pci_error_resume()
- [High] drm/xe: leaked wedge and runtime PM ref after xe_pci_error_slot_reset()
- [Medium] drm/xe: premature wedged.perm set before PCI reset suppresses xe_wedge_declare()
--
commit 9aa7e09375e91e8cc39d736cc124e54fea45236b
Author: Raag Jadav <raag.jadav@intel.com>
drm/xe: Introduce temporary device wedging
This commit converts xe->wedged.flag into a reference count (xe->wedged.ref)
for temporary device wedging and adds xe->wedged.perm to track permanent
device wedging.
> diff --git a/drivers/gpu/drm/xe/xe_pci_error.c b/drivers/gpu/drm/xe/xe_pci_error.c
> index 9bf0da3a3d152..6a942cb6f69d9 100644
> --- a/drivers/gpu/drm/xe/xe_pci_error.c
> +++ b/drivers/gpu/drm/xe/xe_pci_error.c
> @@ -21,13 +21,8 @@ static void prepare_device_for_reset(struct pci_dev *pdev)
> struct xe_gt *gt;
> u8 id;
>
> - /*
> - * Wedge the device to prevent userspace access but do not send the uevent.
> - * xe_wedge_fini() releases runtime pm if wedged flag is set, so acquire a runtime
> - * pm reference to avoid underflow.
> - */
> - if (!atomic_xchg(&xe->wedged.flag, 1))
> - xe_pm_runtime_get_noresume(xe);
> + /* Wedge the device to prevent userspace access but do not send the uevent. */
> + xe_wedge_get(xe);
>
> xe_device_set_in_reset(xe);
>
> @@ -41,10 +36,16 @@ static void prepare_device_for_reset(struct pci_dev *pdev)
>
> static pci_ers_result_t ras_action_to_pci_result(struct pci_dev *pdev, u8 action)
> {
> + struct xe_device *xe = xe_any_to_xe(pdev);
> +
> switch (action) {
> case XE_RAS_RECOVERY_ACTION_RECOVERED:
> return PCI_ERS_RESULT_RECOVERED;
> case XE_RAS_RECOVERY_ACTION_RESET:
> + /* We should not be doing such ugly hacks, reuse FLR callbacks and drop this. */
> + if (atomic_xchg(&xe->wedged.perm, 1))
> + return PCI_ERS_RESULT_DISCONNECT;
> +
> prepare_device_for_reset(pdev);
> return PCI_ERS_RESULT_NEED_RESET;
> case XE_RAS_RECOVERY_ACTION_DISCONNECT:
> @@ -71,6 +72,10 @@ static pci_ers_result_t xe_pci_error_detected(struct pci_dev *pdev, pci_channel_
> case pci_channel_io_normal:
> return PCI_ERS_RESULT_CAN_RECOVER;
> case pci_channel_io_frozen:
> + /* We should not be doing such ugly hacks, reuse FLR callbacks and drop this. */
> + if (atomic_xchg(&xe->wedged.perm, 1))
> + return PCI_ERS_RESULT_DISCONNECT;
> +
> prepare_device_for_reset(pdev);
> return PCI_ERS_RESULT_NEED_RESET;
[Severity: Medium]
What happens if the PCI reset fails before xe_pci_error_slot_reset() removes
the old driver instance?
Both ras_action_to_pci_result() and xe_pci_error_detected() set
xe->wedged.perm to 1 via atomic_xchg() before calling
prepare_device_for_reset() -> xe_wedge_get().
If reset_subordinates() fails in pcie_do_recovery(), or if pci_enable_device()
fails in xe_pci_error_slot_reset():
drivers/gpu/drm/xe/xe_pci_error.c:xe_pci_error_slot_reset() {
...
err = pci_enable_device(pdev);
if (err) {
xe_log_err_fatal(xe, PCI, err, "Cannot re-enable PCI device after reset\n");
return PCI_ERS_RESULT_DISCONNECT;
}
xe_device_clear_in_reset(xe);
pdev->driver->remove(pdev);
...
}
the old xe_device remains bound with xe->wedged.perm == 1 and
xe->wedged.ref == 1.
Because xe->wedged.perm is already set to 1, xe_wedge_declare() was never
called and any subsequent call to xe_wedge_declare() will return early:
drivers/gpu/drm/xe/xe_wedge.c:xe_wedge_declare() {
...
if (atomic_xchg(&xe->wedged.perm, 1))
return;
xe_wedge_get(xe);
xe->needs_flr_on_fini = true;
...
schedule_work(&xe->wedged.work);
}
Wouldn't this leave the device permanently blocking IOCTLs and GuC CT
communication with -ENOTRECOVERABLE while suppressing the drm_dev_wedged_event
uevent to userspace and leaving xe->needs_flr_on_fini unset?
[ ... ]
> @@ -129,7 +134,7 @@ static pci_ers_result_t xe_pci_error_slot_reset(struct pci_dev *pdev)
> xe = pdev_to_xe_device(pdev);
>
> /* Wedge the device to prevent I/O operations till the resume callback */
> - atomic_set(&xe->wedged.flag, 1);
> + xe_wedge_get(xe);
>
> return PCI_ERS_RESULT_RECOVERED;
> }
[Severity: High]
As reported by Sashiko on v10 [1], does xe_pci_error_slot_reset() leak the
wedge reference and runtime PM reference if pcie_do_recovery() aborts before
calling xe_pci_error_resume()?
In xe_pci_error_slot_reset(), after removing the old device and probing a new
xe_device via pdev->driver->probe(), xe_wedge_get(xe) increments
xe->wedged.ref to 1 and acquires a runtime PM reference while xe->wedged.perm
remains 0.
In pcie_do_recovery(), pci_walk_bridge(bridge, report_slot_reset, &status)
walks all subordinate devices under the upstream bridge and merges their
results. If a sibling PCI device returns failure from slot_reset,
pcie_do_recovery() jumps to its failed path and broadcasts
report_perm_failure_detected() -> xe_pci_error_detected(pdev,
pci_channel_io_perm_failure) without calling report_resume(). Likewise,
report_slot_reset() releases device_lock(&pdev->dev) before report_resume()
re-acquires it, allowing driver unbind in between.
When the newly probed xe_device is later torn down, xe_wedge_fini() only puts
a reference if xe->wedged.perm is set:
drivers/gpu/drm/xe/xe_wedge.c:xe_wedge_fini() {
...
if (atomic_read(&xe->wedged.perm))
xe_wedge_put(xe);
xe_assert(xe, !xe_wedged(xe));
}
Wouldn't this leave the temporary reference from xe_pci_error_slot_reset()
unreleased, leaking the runtime PM reference and triggering the
xe_assert(xe, !xe_wedged(xe)) assertion on teardown?
Additionally, if pdev->driver->probe() in xe_pci_error_slot_reset() succeeds
by entering boot survivability mode in __xe_pci_probe(), it returns 0 before
xe_wedge_init() or xe_pm_init() are called, yet xe_pci_error_slot_reset()
unconditionally calls xe_wedge_get(xe).
> @@ -140,7 +145,8 @@ static void xe_pci_error_resume(struct pci_dev *pdev)
>
> xe_info(xe, "PCI error: resume\n");
>
> - atomic_set(&xe->wedged.flag, 0);
> + if (xe_wedged(xe))
> + xe_wedge_put(xe);
> }
[Severity: High]
Can xe_pci_error_resume() drop a wedge reference and runtime PM reference that
the PCI error recovery path never acquired?
When a non-fatal PCIe error occurs (state == pci_channel_io_normal),
pcie_do_recovery() runs:
report_normal_detected()
-> xe_pci_error_detected(pdev, pci_channel_io_normal)
returns PCI_ERS_RESULT_CAN_RECOVER (without calling xe_wedge_get())
report_mmio_enabled()
-> xe_pci_error_mmio_enabled()
-> xe_ras_process_errors()
-> ras_action_to_pci_result(pdev, XE_RAS_RECOVERY_ACTION_RECOVERED)
returns PCI_ERS_RESULT_RECOVERED (without calling xe_wedge_get())
report_resume()
-> xe_pci_error_resume()
Because xe_pci_error_detected() does not wedge the device or stop driver work
for pci_channel_io_normal, normal driver activity continues between
xe_pci_error_detected() and xe_pci_error_resume(). If a concurrent GT reset
failure, job timeout, or hardware error handler calls xe_wedge_declare() in
that window (or if xe_wedge_declare() was between atomic_xchg(&xe->wedged.perm,
1) and xe_wedge_get(xe) when xe_pci_error_detected() checked xe_wedged(xe)),
xe->wedged.ref becomes 1.
When xe_pci_error_resume() then checks xe_wedged(xe), it sees the global
xe->wedged.ref > 0 and calls xe_wedge_put(xe).
Wouldn't that consume the reference owned by xe_wedge_declare(), dropping
xe->wedged.ref back to 0 (unblocking IOCTLs on a permanently wedged device)
and later causing xe_wedge_fini() to underflow xe->wedged.ref to -1 and
underflow runtime PM when it sees xe->wedged.perm == 1?
[1] https://lore.kernel.org/r/20260821113758.006681F000E9@smtp.kernel.org
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261103060649.1015468-1-raag.jadav@intel.com?part=8
next prev parent reply other threads:[~2026-11-03 6:44 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-03 6:06 [PATCH v12 00/10] Introduce Xe PCIe FLR Raag Jadav
2026-11-03 6:06 ` [PATCH v12 01/10] drm/xe/uc_fw: Allow re-initializing firmware Raag Jadav
2026-11-03 6:06 ` [PATCH v12 02/10] drm/xe/guc_submit: Introduce guc_exec_queue_reinit_kernel() Raag Jadav
2026-11-03 6:06 ` [PATCH v12 03/10] drm/xe/gt: Introduce FLR helpers Raag Jadav
2026-11-03 6:39 ` sashiko-bot
2026-11-03 6:06 ` [PATCH v12 04/10] drm/xe/bo_evict: Introduce xe_bo_restore_map() Raag Jadav
2026-11-03 6:06 ` [PATCH v12 05/10] drm/xe/exec_queue: Introduce xe_exec_queue_reinit() Raag Jadav
2026-11-03 6:06 ` [PATCH v12 06/10] drm/xe/migrate: Introduce xe_migrate_reinit() Raag Jadav
2026-11-03 6:31 ` sashiko-bot
2026-11-03 6:06 ` [PATCH v12 07/10] drm/xe/pm: Introduce xe_device_suspend/resume() Raag Jadav
2026-11-03 6:48 ` sashiko-bot
2026-11-03 6:06 ` [PATCH v12 08/10] drm/xe: Introduce temporary device wedging Raag Jadav
2026-11-03 6:44 ` sashiko-bot [this message]
2026-11-03 6:06 ` [PATCH v12 09/10] drm/xe/pci: Introduce PCIe Function Level Reset Raag Jadav
2026-11-03 6:46 ` sashiko-bot
2026-11-03 6:06 ` [PATCH v12 10/10] drm/xe/doc: Wire up PCI Error Handling Raag Jadav
2026-11-03 6:51 ` ✗ CI.checkpatch: warning for Introduce Xe PCIe FLR (rev12) Patchwork
2026-11-03 6:53 ` ✓ CI.KUnit: success " Patchwork
2026-11-03 7:29 ` ✓ Xe.CI.BAT: " Patchwork
2026-11-03 12:43 ` ✓ Xe.CI.FULL: " Patchwork
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=sashiko-outbox-194662@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=intel-xe@lists.freedesktop.org \
--cc=raag.jadav@intel.com \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox