From: Vitaly Prosyak <[email protected]>

The eviction-fence worker must wait for reset before unmapping user queues,
but must not wait while inside dma_fence_begin_signalling(). Keep the
blocking reset_domain->sem serialization, and perform eviction and any
required reset-work flush before entering the signalling section. Signal the
eviction fence only after that work completes.

This removes the reset_domain->sem dependency from dma_fence_map while
preserving the eviction fence lifetime and reset serialization.

Changes in v2:
- Drop the v1 trylock and delayed-retry approach.
- Keep eviction blocked until reset completes, as Christian suggested.
- Move reset-work scheduling and flushing out of amdgpu_userq_evict_all().

Fixes: aebf196c550e ("drm/amdgpu/userq: wait for GPU reset before mapping or 
unmapping queues")
Suggested-by: Christian König <[email protected]>
Cc: Christian König <[email protected]>
Cc: Alex Deucher <[email protected]>
Cc: Prike Liang <[email protected]>
Signed-off-by: Vitaly Prosyak <[email protected]>
---
 .../gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c | 18 ++++++++++--------
 drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c      |  7 ++-----
 drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h      |  2 +-
 3 files changed, 13 insertions(+), 14 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c
index f8652fd0525d..c53ffcb35ddd 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_eviction_fence.c
@@ -65,21 +65,23 @@ amdgpu_eviction_fence_suspend_worker(struct work_struct 
*work)
        struct amdgpu_userq_mgr *uq_mgr = &fpriv->userq_mgr;
        struct dma_fence *ev_fence;
        bool cookie;
+       int ret;
 
        mutex_lock(&uq_mgr->userq_mutex);
 
        /* Fence waits are not allowed in a fence signalling critical section. 
*/
        amdgpu_userq_wait_for_signal(uq_mgr);
 
-       /*
-        * This is intentionally after taking the userq_mutex since we do
-        * allocate memory while holding this lock, but only after ensuring that
-        * the eviction fence is signaled.
-        */
-       cookie = dma_fence_begin_signalling();
-
        ev_fence = amdgpu_evf_mgr_get_fence(evf_mgr);
-       amdgpu_userq_evict(uq_mgr);
+       ret = amdgpu_userq_evict(uq_mgr);
+       if (ret) {
+               amdgpu_reset_domain_schedule(uq_mgr->adev->reset_domain,
+                                            &uq_mgr->reset_work);
+               flush_work(&uq_mgr->reset_work);
+       }
+
+       /* Don't enter the signalling section while waiting for GPU reset. */
+       cookie = dma_fence_begin_signalling();
 
        /*
         * 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 ccf0ff490ac2..9a0093bdb3be 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
@@ -1304,9 +1304,6 @@ amdgpu_userq_evict_all(struct amdgpu_userq_mgr *uq_mgr)
        if (ret) {
                drm_file_err(uq_mgr->file,
                             "Couldn't unmap all the queues, eviction failed 
ret=%d\n", ret);
-               amdgpu_reset_domain_schedule(uq_mgr->adev->reset_domain,
-                                            &uq_mgr->reset_work);
-               flush_work(&uq_mgr->reset_work);
        }
        return ret;
 }
@@ -1327,10 +1324,10 @@ amdgpu_userq_wait_for_signal(struct amdgpu_userq_mgr 
*uq_mgr)
        }
 }
 
-void
+int
 amdgpu_userq_evict(struct amdgpu_userq_mgr *uq_mgr)
 {
-       amdgpu_userq_evict_all(uq_mgr);
+       return amdgpu_userq_evict_all(uq_mgr);
 }
 
 int amdgpu_userq_mgr_init(struct amdgpu_userq_mgr *userq_mgr, struct drm_file 
*file_priv,
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
index 488dc21d7c81..4dcf6151de6a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.h
@@ -163,7 +163,7 @@ void amdgpu_userq_mgr_cancel_resume(struct amdgpu_userq_mgr 
*userq_mgr);
 void amdgpu_userq_mgr_fini(struct amdgpu_userq_mgr *userq_mgr);
 
 void amdgpu_userq_wait_for_signal(struct amdgpu_userq_mgr *uq_mgr);
-void amdgpu_userq_evict(struct amdgpu_userq_mgr *uq_mgr);
+int amdgpu_userq_evict(struct amdgpu_userq_mgr *uq_mgr);
 
 void amdgpu_userq_ensure_ev_fence(struct amdgpu_userq_mgr *userq_mgr,
                                  struct amdgpu_eviction_fence_mgr *evf_mgr);
-- 
2.55.0

Reply via email to