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

Reply via email to