The system PM notifier runs before the PCI suspend callback and may evict
BOs or submit migration work. This work must not start after the device
has been declared wedged.

Skip PM preparation for a wedged device. Track whether preparation ran
so the post callback only performs matching cleanup and releases the
runtime PM reference when needed.

The gate is held across xe_bo_evict_all_user(), so wedge isolation waits
for eviction to finish. GTs are declared wedged before the gate is
drained, so pending fences are signalled and eviction can finish.

v2:
 - Protect PM preparation with the common SRCU gate.

Cc: Matthew Brost <[email protected]>
Cc: Thomas Hellström <[email protected]>
Cc: Himal Prasad Ghimiray <[email protected]>
Cc: Rodrigo Vivi <[email protected]>
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Arvind Yadav <[email protected]>
---
 drivers/gpu/drm/xe/xe_device_types.h |  2 ++
 drivers/gpu/drm/xe/xe_pm.c           | 12 ++++++++++++
 2 files changed, 14 insertions(+)

diff --git a/drivers/gpu/drm/xe/xe_device_types.h 
b/drivers/gpu/drm/xe/xe_device_types.h
index 93bb38ed5975..24e8cb5fc88a 100644
--- a/drivers/gpu/drm/xe/xe_device_types.h
+++ b/drivers/gpu/drm/xe/xe_device_types.h
@@ -484,6 +484,8 @@ struct xe_device {
 
        /** @pm_notifier: Our PM notifier to perform actions in response to 
various PM events. */
        struct notifier_block pm_notifier;
+       /** @pm_notifier_active: PM notifier prepare work was performed */
+       bool pm_notifier_active;
        /** @pm_block: Completion to block validating tasks on suspend / 
hibernate prepare */
        struct completion pm_block;
        /** @rebind_resume_list: List of wq items to kick on resume. */
diff --git a/drivers/gpu/drm/xe/xe_pm.c b/drivers/gpu/drm/xe/xe_pm.c
index daa7ba2df317..fd265f9135c6 100644
--- a/drivers/gpu/drm/xe/xe_pm.c
+++ b/drivers/gpu/drm/xe/xe_pm.c
@@ -459,10 +459,16 @@ static int xe_pm_notifier_callback(struct notifier_block 
*nb,
        case PM_SUSPEND_PREPARE:
        {
                struct xe_validation_ctx ctx;
+               int io_idx;
+
+               /* Do not start PM preparation while device I/O is blocked. */
+               if (xe_device_io_get(xe, &io_idx))
+                       break;
 
                reinit_completion(&xe->pm_block);
                xe_pm_block_begin_signalling();
                xe_pm_runtime_get(xe);
+               xe->pm_notifier_active = true;
                (void)xe_validation_ctx_init(&ctx, &xe->val, NULL,
                                             (struct xe_val_flags) {.exclusive 
= true});
                err = xe_bo_evict_all_user(xe);
@@ -479,10 +485,16 @@ static int xe_pm_notifier_callback(struct notifier_block 
*nb,
                 * allocations.
                 */
                xe_pm_block_end_signalling();
+               xe_device_io_put(io_idx);
                break;
        }
        case PM_POST_HIBERNATION:
        case PM_POST_SUSPEND:
+               if (!xe->pm_notifier_active)
+                       break;
+
+               xe->pm_notifier_active = false;
+
                complete_all(&xe->pm_block);
                xe_pm_wake_rebind_workers(xe);
                xe_bo_notifier_unprepare_all_pinned(xe);
-- 
2.43.0

Reply via email to