The system PM notifier runs before the PCI suspend callback and may
evict BOs or prepare pinned BOs.

Hold the common device I/O gate during preparation and skip it when
the device is blocked or unplugged. Track whether preparation ran so
the post callback only performs matching cleanup and releases the
runtime PM reference when needed.

Keep the gate held across BO eviction so isolation waits for
preparation admitted before the device was blocked.

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

v3:
- Replace the private I/O gate with the DRM device SRCU helper.

Cc: Matthew Brost <[email protected]>
Cc: Thomas Hellström <[email protected]>
Cc: Himal Prasad Ghimiray <[email protected]>
Cc: Rodrigo Vivi <[email protected]>
Assisted-by: LLM
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 1d3f72f6f315..983f0ce6062c 100644
--- a/drivers/gpu/drm/xe/xe_device_types.h
+++ b/drivers/gpu/drm/xe/xe_device_types.h
@@ -499,6 +499,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