Add amdgpu_eventfd_signal(), a helper to signal an eventfd previously
bound to an event_id for the given drm_file (amdgpu_fpriv).

The helper is IRQ-safe: it uses RCU read-side protection and lockless
xa_load() to find the mapping. Bind/unbind and final teardown already
use call_rcu() + synchronize_rcu(), ensuring safe lifetime of entries.

Cc: Harish Kasiviswanathan <[email protected]>
Cc: Felix Kuehling <[email protected]>
Cc: Alex Deucher <[email protected]>
Cc: Christian König <[email protected]>
Signed-off-by: Srinivasan Shanmugam <[email protected]>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu.h     |  1 +
 drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 21 +++++++++++++++++++++
 2 files changed, 22 insertions(+)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h 
b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
index 2baeb0b20df1..b0e9b7ff2f80 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -473,6 +473,7 @@ int amdgpu_eventfd_bind_ioctl(struct drm_device *dev, void 
*data,
 int amdgpu_eventfd_unbind_ioctl(struct drm_device *dev, void *data,
                                struct drm_file *file_priv);
 void amdgpu_eventfd_registry_fini(struct amdgpu_fpriv *fpriv);
+void amdgpu_eventfd_signal(struct amdgpu_fpriv *fpriv, u32 event_id, u64 
count);
 
 int amdgpu_file_to_fpriv(struct file *filp, struct amdgpu_fpriv **fpriv);
 
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
index 43da5bc36b7c..66e2ae8b7c8a 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -745,6 +745,27 @@ int amdgpu_eventfd_unbind_ioctl(struct drm_device *dev, 
void *data,
        return 0;
 }
 
+void amdgpu_eventfd_signal(struct amdgpu_fpriv *fpriv, u32 event_id, u64 count)
+{
+       struct amdgpu_eventfd_entry *e;
+       struct eventfd_ctx *ctx;
+
+       if (!fpriv || !count)
+               return;
+
+       /*
+        * IRQ-side: lockless lookup. Lifetime is protected by:
+        *  - bind/unbind freeing entries via call_rcu()
+        *  - registry_fini() calling synchronize_rcu() before xa_destroy()
+        */
+       rcu_read_lock();
+       e = xa_load(&fpriv->eventfd_xa, event_id);
+       ctx = e ? READ_ONCE(e->ctx) : NULL;
+       if (ctx)
+               eventfd_signal(ctx);
+       rcu_read_unlock();
+}
+
 /*
  * Userspace get information ioctl
  */
-- 
2.34.1

Reply via email to