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
