diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c index 6d3ed55e9ab4..bcfbd7213dd6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c @@ -1070,6 +1070,16 @@ amdgpu_userq_vm_validate_and_restore_queue(struct amdgpu_userq_mgr *uq_mgr) if (ret) goto unlock_all; + /* + * PRT/sparse mappings are kept off the vm_bo state lists, so + * amdgpu_vm_handle_moved() does not touch them. Refresh their PTEs + * explicitly here (as the CS path does) so sparse mappings survive a + * VRAM-lost reset. + */ + ret = amdgpu_vm_bo_update(adev, fpriv->prt_va, false); + if (ret) + goto unlock_all; + key = 0; /* Validate User Ptr BOs */ list_for_each_entry(bo_va, &vm->always_valid.idle, base.vm_status) { @@ -1127,6 +1137,12 @@ amdgpu_userq_vm_validate_and_restore_queue(struct amdgpu_userq_mgr *uq_mgr) */ list_for_each_entry(bo_va, &vm->always_valid.idle, base.vm_status) dma_fence_wait(bo_va->last_pt_update, false); + /* + * The PRT bo_va is kept off the state lists, so its PTE update fence + * lands in prt_va->last_pt_update rather than vm->last_update; wait on + * it explicitly (as the CS path syncs it) before restarting queues. + */ + dma_fence_wait(fpriv->prt_va->last_pt_update, false); dma_fence_wait(vm->last_update, false); xa_for_each(&uq_mgr->userq_xa, tmp_key, queue) { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 86aab37cbdc4..71050a86bcc3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -1408,7 +1408,13 @@ int amdgpu_vm_bo_update(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va, amdgpu_vm_bo_evicted(&bo_va->base); else amdgpu_vm_bo_idle(&bo_va->base); - } else { + } else if (bo) { + /* + * A PRT/sparse mapping has no BO and is kept off the vm_bo + * state lists (see amdgpu_vm_bo_base_init()); putting it on the + * idle list here would let amdgpu_vm_handle_moved() dereference + * the NULL bo after a reset. + */ amdgpu_vm_bo_idle(&bo_va->base); }