Page-fault work may still be queued when PCI error recovery starts or
the device becomes permanently wedged. Servicing these faults can migrate
memory or update page tables after device I/O has been blocked.

Check the device state while popping queued faults. Release queued
entries instead of passing them to a worker when device I/O is blocked.

Hold the device I/O gate across fault servicing so wedge isolation waits
for faults already in progress. Faults that start after the block are
rejected at the gate.

v2:
- Move the blocked-device check into the queue pop path. (Matt)
- Drop queued faults while holding the queue lock. (Matt)
- Remove weak checks around fault servicing. (Matt)
- Hold the device I/O gate across fault servicing. (Thomas)

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_pagefault.c | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/xe/xe_pagefault.c 
b/drivers/gpu/drm/xe/xe_pagefault.c
index c4aafdbdb518..fdb77291a30f 100644
--- a/drivers/gpu/drm/xe/xe_pagefault.c
+++ b/drivers/gpu/drm/xe/xe_pagefault.c
@@ -267,8 +267,10 @@ static struct xe_vm *xe_pagefault_asid_to_vm(struct 
xe_pagefault *pf, u32 asid)
 static int xe_pagefault_service(struct xe_pagefault *pf)
 {
        struct xe_gt *gt = pf->gt;
+       struct xe_device *xe = gt_to_xe(gt);
        struct xe_vm *vm;
        struct xe_vma *vma = NULL;
+       int io_idx;
        int err;
        bool atomic;
        u32 asid = FIELD_GET(XE_PAGEFAULT_ASID_MASK, pf->consumer.id);
@@ -277,9 +279,15 @@ static int xe_pagefault_service(struct xe_pagefault *pf)
        if (pf->consumer.fault_type_level == XE_PAGEFAULT_TYPE_LEVEL_NACK)
                return -EFAULT;
 
+       err = xe_device_io_get(xe, &io_idx);
+       if (err)
+               return err;
+
        vm = xe_pagefault_asid_to_vm(pf, asid);
-       if (IS_ERR(vm))
-               return PTR_ERR(vm);
+       if (IS_ERR(vm)) {
+               err = PTR_ERR(vm);
+               goto out_io;
+       }
 
        down_read(&vm->lock);
 
@@ -315,6 +323,8 @@ static int xe_pagefault_service(struct xe_pagefault *pf)
        up_read(&vm->lock);
        xe_vm_put(vm);
 
+out_io:
+       xe_device_io_put(io_idx);
        return err;
 }
 
@@ -504,6 +514,12 @@ static bool xe_pagefault_queue_pop(struct 
xe_pagefault_queue *pf_queue,
                    XE_PAGEFAULT_ALLOC_STATE_QUEUED)
                        continue;
 
+               if (xe_device_io_blocked(xe)) {
+                       lpf->consumer.alloc_state =
+                               XE_PAGEFAULT_ALLOC_STATE_FREE;
+                       continue;
+               }
+
                if (xe_pagefault_try_chain(pf_queue, lpf))
                        continue;
 
-- 
2.43.0

Reply via email to