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
