It needs to drop the old userq fence dereference, otherwise
it can't be walked during freeing the queue.

Signed-off-by: Prike Liang <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c | 16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
index 9df62f71f27c..f1acd785c27d 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
@@ -105,9 +105,21 @@ int amdgpu_userq_fence_driver_alloc(struct amdgpu_device 
*adev,
        get_task_comm(fence_drv->timeline_name, current);
 
        xa_lock_irqsave(&adev->userq_xa, flags);
-       r = xa_err(__xa_store(&adev->userq_xa, userq->doorbell_index,
-                             fence_drv, GFP_KERNEL));
+       struct amdgpu_userq_fence_driver *old;
+
+       old = __xa_store(&adev->userq_xa, userq->doorbell_index,
+                             fence_drv, GFP_KERNEL);
        xa_unlock_irqrestore(&adev->userq_xa, flags);
+
+       if (xa_is_err(old)) {
+               r = xa_err(old);
+       } else if (old) {
+               /* Doorbell index was reused: drop the replaced driver's ref */
+               amdgpu_userq_fence_driver_put(old);
+               r = 0;
+       } else {
+               r = 0;
+       }
        if (r)
                goto free_seq64;
 
-- 
2.34.1

Reply via email to