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

Reply via email to