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
