Hold the reset-domain semaphore for read around queue eviction. If it cannot be acquired immediately under userq_mutex, release the mutex, wait for recovery, and retry the queue and fence checks. Protect eviction-fence publication and hardware mapping with the same semaphore. BO validation can wait for evictions, so it must not hold the reset semaphore across those waits.
Signed-off-by: Prike Liang <[email protected]> --- drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c | 9 +++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c | 12 ++++++++++++ 2 files changed, 21 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c index 15897c3eacb7..f0cc49213c01 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c @@ -67,10 +67,18 @@ amdgpu_eviction_fence_suspend_worker(struct work_struct *work) bool cookie; int r; +retry: mutex_lock(&uq_mgr->userq_mutex); /* Fence waits are not allowed in a fence signalling critical section. */ amdgpu_userq_wait_for_signal(uq_mgr); + if (!down_read_trylock(&uq_mgr->adev->reset_domain->sem)) { + mutex_unlock(&uq_mgr->userq_mutex); + + down_read(&uq_mgr->adev->reset_domain->sem); + up_read(&uq_mgr->adev->reset_domain->sem); + goto retry; + } /* * This is intentionally after taking the userq_mutex since we do @@ -81,6 +89,7 @@ amdgpu_eviction_fence_suspend_worker(struct work_struct *work) ev_fence = amdgpu_evf_mgr_get_fence(evf_mgr); r = amdgpu_userq_evict(uq_mgr); + up_read(&uq_mgr->adev->reset_domain->sem); /* * Signaling the eviction fence must be done while holding the diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c index fa8ffa060fa5..322c95201494 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c @@ -1219,13 +1219,21 @@ amdgpu_userq_vm_validate_and_restore_queue(struct amdgpu_userq_mgr *uq_mgr) queue->wptr_obj.gpu_addr = amdgpu_bo_gpu_offset(bo); } + /* Back off without publishing a fence if recovery owns the hardware. */ + if (!down_read_trylock(&adev->reset_domain->sem)) { + ret = -EAGAIN; + goto unlock_all; + } + ret = amdgpu_evf_mgr_rearm(&fpriv->evf_mgr, &exec); if (ret) { + up_read(&adev->reset_domain->sem); drm_file_err(uq_mgr->file, "Failed to replace eviction fence\n"); goto unlock_all; } ret = amdgpu_userq_restore_all(uq_mgr); + up_read(&adev->reset_domain->sem); unlock_all: drm_exec_fini(&exec); @@ -1252,6 +1260,10 @@ static void amdgpu_userq_restore_worker(struct work_struct *work) goto put_fence; ret = amdgpu_userq_vm_validate_and_restore_queue(uq_mgr); + if (ret == -EAGAIN) { + schedule_delayed_work(&uq_mgr->resume_work, msecs_to_jiffies(10)); + goto put_fence; + } if (ret) { drm_file_err(uq_mgr->file, "Failed to validate BOs to restore ret=%d\n", ret); goto put_fence; -- 2.34.1
