WAIT_EVENT currently provides the per-file queue, matching, and lifetime infrastructure, but no producer creates records when a user queue fence completes.
Add an IRQ-safe helper which appends a WAIT_EVENT record using the queue pointer as the internal routing key. The record takes a queue reference before it is published and releases it through the existing record cleanup paths. The producer does not translate the queue pointer back to a queue ID. Instead, the WAIT_EVENT ioctl adds the queue ID supplied by the waiter to the matched record immediately before returning it to userspace. This keeps queue IDs at the UAPI boundary while retaining queue-pointer-based matching internally. Call the helper from amdgpu_userq_process_fence_irq(), next to the existing EVENTFD notification. This reuses the established doorbell-to-queue lookup and does not add another queue lookup or change the GFX interrupt handling. Signed-off-by: Srinivasan Shanmugam <[email protected]> Reviewed-by: Alex Deucher <[email protected]> --- drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c | 6 +++ .../gpu/drm/amd/amdgpu/amdgpu_wait_event.c | 53 +++++++++++++++++++ .../gpu/drm/amd/amdgpu/amdgpu_wait_event.h | 4 ++ 3 files changed, 63 insertions(+) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c index aa17e55d52e8..28f9d3fe0e80 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_userq.c @@ -264,6 +264,7 @@ void amdgpu_userq_process_fence_irq(struct amdgpu_device *adev, u32 doorbell) struct xarray *xa = &adev->userq_doorbell_xa; struct amdgpu_usermode_queue *queue; struct amdgpu_eventfd_mgr *eventfd_mgr; + struct amdgpu_wait_event_mgr *wait_event_mgr; unsigned long flags; int r; @@ -286,6 +287,11 @@ void amdgpu_userq_process_fence_irq(struct amdgpu_device *adev, u32 doorbell) amdgpu_eventfd_signal(eventfd_mgr, DRM_AMDGPU_EVENT_TYPE_USERQ_EOP, queue); + + wait_event_mgr = amdgpu_userq_wait_event_mgr(queue->userq_mgr); + amdgpu_wait_event_add(wait_event_mgr, + DRM_AMDGPU_EVENT_TYPE_USERQ_EOP, + queue); } xa_unlock_irqrestore(xa, flags); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_wait_event.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_wait_event.c index f98de1d94b56..ddbd03059916 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_wait_event.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_wait_event.c @@ -63,6 +63,27 @@ static bool amdgpu_wait_event_valid_type(u32 event_type) } } +static void +amdgpu_wait_event_set_queue_id(struct amdgpu_wait_event_record *rec, + u32 queue_id) +{ + rec->data.queue_id = queue_id; + + switch (rec->data.event_type) { + case DRM_AMDGPU_EVENT_TYPE_USERQ_EOP: + rec->data.u.queue.queue_id = queue_id; + break; + case DRM_AMDGPU_EVENT_TYPE_QUEUE_RESET: + rec->data.u.reset.queue_id = queue_id; + break; + case DRM_AMDGPU_EVENT_TYPE_SCRATCH: + rec->data.u.scratch.queue_id = queue_id; + break; + default: + break; + } +} + static void amdgpu_wait_event_record_free(struct amdgpu_wait_event_record *rec) { @@ -167,6 +188,35 @@ void amdgpu_wait_event_mgr_init(struct amdgpu_wait_event_mgr *mgr) mgr->dead = false; } +void amdgpu_wait_event_add(struct amdgpu_wait_event_mgr *mgr, + u32 event_type, + struct amdgpu_usermode_queue *queue) +{ + struct amdgpu_wait_event_record *rec; + unsigned long flags; + + rec = kzalloc(sizeof(*rec), GFP_ATOMIC); + if (!rec) + return; + + kref_get(&queue->refcount); + rec->queue = queue; + rec->data.event_type = event_type; + rec->data.seqno = atomic64_inc_return(&mgr->seqno); + + spin_lock_irqsave(&mgr->lock, flags); + if (mgr->dead) { + spin_unlock_irqrestore(&mgr->lock, flags); + amdgpu_wait_event_record_free(rec); + return; + } + + list_add_tail(&rec->node, &mgr->pending); + spin_unlock_irqrestore(&mgr->lock, flags); + + wake_up_interruptible(&mgr->wq); +} + void amdgpu_wait_event_mgr_fini(struct amdgpu_wait_event_mgr *mgr) { struct amdgpu_wait_event_record *rec, *tmp; @@ -270,6 +320,9 @@ int amdgpu_wait_event_drm_ioctl(struct drm_device *dev, void *data, } } + if (queue) + amdgpu_wait_event_set_queue_id(rec, args->queue_id); + if (copy_to_user(u64_to_user_ptr(args->out_ptr), &rec->data, sizeof(rec->data))) ret = -EFAULT; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_wait_event.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_wait_event.h index e887fffdc4ac..07e043dcc2e7 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_wait_event.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_wait_event.h @@ -56,6 +56,10 @@ void amdgpu_wait_event_mgr_fini(struct amdgpu_wait_event_mgr *mgr); void amdgpu_wait_event_remove_queue(struct amdgpu_wait_event_mgr *mgr, struct amdgpu_usermode_queue *queue); +void amdgpu_wait_event_add(struct amdgpu_wait_event_mgr *mgr, + u32 event_type, + struct amdgpu_usermode_queue *queue); + int amdgpu_wait_event_drm_ioctl(struct drm_device *dev, void *data, struct drm_file *file_priv); -- 2.34.1
