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) v3: - Hold the common 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: LLM Suggested-by: Thomas Hellström <[email protected]> Signed-off-by: Arvind Yadav <[email protected]> --- drivers/gpu/drm/xe/xe_pagefault.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/xe/xe_pagefault.c b/drivers/gpu/drm/xe/xe_pagefault.c index 5247321c805e..c9458688684b 100644 --- a/drivers/gpu/drm/xe/xe_pagefault.c +++ b/drivers/gpu/drm/xe/xe_pagefault.c @@ -270,6 +270,7 @@ static int xe_pagefault_service(struct xe_pagefault *pf) 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); @@ -278,13 +279,17 @@ 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)) { err = PTR_ERR(vm); trace_xe_pagefault_fail(xe, NULL, NULL, asid, xe_pagefault_addr(pf), xe_pagefault_get_error(pf), err); - return err; + goto out_io; } xe_migrate_ulls_enter(gt_to_tile(gt)->migrate); @@ -328,6 +333,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; } @@ -517,6 +524,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
