USERQ fence driver can outlive amdgpu_fpriv, so
it must not hold a raw pointer to fpriv.

Store a kref'd amdgpu_eventfd_mgr pointer in the fence driver instead.
The manager is owned by the drm_file but can be safely referenced by
longer-lived producer objects.

Cc: Harish Kasiviswanathan <[email protected]>
Cc: Felix Kuehling <[email protected]>
Cc: Alex Deucher <[email protected]>
Cc: Christian König <[email protected]>
Suggested-by: Christian König <[email protected]>
Signed-off-by: Srinivasan Shanmugam <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c     |  2 +-
 .../gpu/drm/amd/amdgpu/amdgpu_userq_fence.c   | 24 +++++++++++++++++--
 .../gpu/drm/amd/amdgpu/amdgpu_userq_fence.h   |  4 ++++
 3 files changed, 27 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
index e07b2082cf25..95b28816c298 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c
@@ -820,7 +820,7 @@ amdgpu_userq_create(struct drm_file *filp, union 
drm_amdgpu_userq *args)
 
        queue->doorbell_index = index;
        xa_init_flags(&queue->fence_drv_xa, XA_FLAGS_ALLOC);
-       r = amdgpu_userq_fence_driver_alloc(adev, queue);
+       r = amdgpu_userq_fence_driver_alloc(adev, fpriv->eventfd_mgr, queue);
        if (r) {
                drm_file_err(uq_mgr->file, "Failed to alloc fence driver\n");
                goto unlock;
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
index 3c30512a6266..a69b95f74fbe 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.c
@@ -31,6 +31,7 @@
 
 #include "amdgpu.h"
 #include "amdgpu_userq_fence.h"
+#include "amdgpu_eventfd.h"
 
 static const struct dma_fence_ops amdgpu_userq_fence_ops;
 static struct kmem_cache *amdgpu_userq_fence_slab;
@@ -78,6 +79,7 @@ amdgpu_userq_fence_write(struct amdgpu_userq_fence_driver 
*fence_drv,
 }
 
 int amdgpu_userq_fence_driver_alloc(struct amdgpu_device *adev,
+                                   struct amdgpu_eventfd_mgr *eventfd_mgr,
                                    struct amdgpu_usermode_queue *userq)
 {
        struct amdgpu_userq_fence_driver *fence_drv;
@@ -104,18 +106,26 @@ int amdgpu_userq_fence_driver_alloc(struct amdgpu_device 
*adev,
        fence_drv->context = dma_fence_context_alloc(1);
        get_task_comm(fence_drv->timeline_name, current);
 
+       fence_drv->eventfd_mgr = eventfd_mgr;
+       if (fence_drv->eventfd_mgr)
+               amdgpu_eventfd_mgr_get(fence_drv->eventfd_mgr);
+
        xa_lock_irqsave(&adev->userq_xa, flags);
        r = xa_err(__xa_store(&adev->userq_xa, userq->doorbell_index,
                              fence_drv, GFP_KERNEL));
        xa_unlock_irqrestore(&adev->userq_xa, flags);
        if (r)
-               goto free_seq64;
+               goto free_mgr_ref;
 
        userq->fence_drv = fence_drv;
 
        return 0;
 
-free_seq64:
+free_mgr_ref:
+       if (fence_drv->eventfd_mgr) {
+               amdgpu_eventfd_mgr_put(fence_drv->eventfd_mgr);
+               fence_drv->eventfd_mgr = NULL;
+       }
        amdgpu_seq64_free(adev, fence_drv->va);
 free_fence_drv:
        kfree(fence_drv);
@@ -214,6 +224,16 @@ void amdgpu_userq_fence_driver_destroy(struct kref *ref)
                        __xa_erase(xa, index);
        xa_unlock_irqrestore(xa, flags);
 
+       /*
+        * Drop the eventfd manager reference held by this fence driver.
+        * Do this after fences are canceled (so any fence completion paths
+        * that might signal still have a valid mgr while we unwind).
+        */
+       if (fence_drv->eventfd_mgr) {
+               amdgpu_eventfd_mgr_put(fence_drv->eventfd_mgr);
+               fence_drv->eventfd_mgr = NULL;
+       }
+
        /* Free seq64 memory */
        amdgpu_seq64_free(adev, fence_drv->va);
        kfree(fence_drv);
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.h
index d76add2afc77..857b43bb64f7 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq_fence.h
@@ -29,6 +29,8 @@
 
 #include "amdgpu_userq.h"
 
+struct amdgpu_eventfd_mgr;
+
 struct amdgpu_userq_fence {
        struct dma_fence base;
        /*
@@ -56,6 +58,7 @@ struct amdgpu_userq_fence_driver {
        struct list_head fences;
        struct amdgpu_device *adev;
        char timeline_name[TASK_COMM_LEN];
+       struct amdgpu_eventfd_mgr *eventfd_mgr; /* kref'd */
 };
 
 int amdgpu_userq_fence_slab_init(void);
@@ -64,6 +67,7 @@ void amdgpu_userq_fence_slab_fini(void);
 void amdgpu_userq_fence_driver_get(struct amdgpu_userq_fence_driver 
*fence_drv);
 void amdgpu_userq_fence_driver_put(struct amdgpu_userq_fence_driver 
*fence_drv);
 int amdgpu_userq_fence_driver_alloc(struct amdgpu_device *adev,
+                                   struct amdgpu_eventfd_mgr *eventfd_mgr,
                                    struct amdgpu_usermode_queue *userq);
 void amdgpu_userq_fence_driver_free(struct amdgpu_usermode_queue *userq);
 void amdgpu_userq_fence_driver_process(struct amdgpu_userq_fence_driver 
*fence_drv);
-- 
2.34.1

Reply via email to