On 2/16/26 16:49, Srinivasan Shanmugam wrote:
> Add a per-drm_file eventfd registry to amdgpu and wire up the new
> render-node IOCTLs:
> 
>   DRM_IOCTL_AMDGPU_EVENTFD_BIND
>   DRM_IOCTL_AMDGPU_EVENTFD_UNBIND
> 
> This allows userspace to bind an eventfd to an event_id on a per-file
> basis. The mapping is stored in an xarray protected by a mutex inside
> amdgpu_fpriv.
> 
> Each event_id maps to a struct amdgpu_eventfd_entry containing the
> associated eventfd_ctx. Bind replaces any existing binding for the same
> event_id. Unbind removes the mapping and drops the eventfd reference.
> 
> The registry is initialized during driver open and fully cleaned up
> during DRM release to ensure proper lifetime handling and to avoid
> leaking eventfd references. Entries are freed via RCU so future IRQ-side
> users can do lockless lookups.


You should probably encapsulate all this in an eventfd_mgr object and not put 
so much code into amdgpu_kms.c

I suggest to just put the full eventfd handling into amdgpu_eventfd.[ch] and 
then have both event_mgr as well as event_id object in there.

RCU sounds good, but is probably not necessary at all. Just use the IRQ safe 
xarray lock variants.

Regards,
Christian. 

> 
> 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]>
> Change-Id: I78635bba4772843138a51a6152a3fa621cb07353
> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu.h     |  20 ++++
>  drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c |   3 +
>  drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 116 ++++++++++++++++++++++++
>  3 files changed, 139 insertions(+)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> index 0f6e9cdbe7d8..2baeb0b20df1 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> @@ -44,6 +44,8 @@
>  #include <linux/hashtable.h>
>  #include <linux/dma-fence.h>
>  #include <linux/pci.h>
> +#include <linux/xarray.h>
> +#include <linux/rcupdate.h>
>  
>  #include <drm/ttm/ttm_bo.h>
>  #include <drm/ttm/ttm_placement.h>
> @@ -452,8 +454,26 @@ struct amdgpu_fpriv {
>  
>       /** GPU partition selection */
>       uint32_t                xcp_id;
> +
> +     /* eventfd registry for KFD-event unification (per drm_file) */
> +     struct mutex eventfd_lock;
> +     struct xarray eventfd_xa; /* key: event_id (u32) -> struct 
> amdgpu_eventfd_entry* */
> +};
> +
> +struct amdgpu_eventfd_entry {
> +     struct rcu_head rcu;
> +     struct eventfd_ctx *ctx;
>  };
>  
> +struct drm_device;
> +struct drm_file;
> +
> +int amdgpu_eventfd_bind_ioctl(struct drm_device *dev, void *data,
> +                           struct drm_file *file_priv);
> +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);
> +
>  int amdgpu_file_to_fpriv(struct file *filp, struct amdgpu_fpriv **fpriv);
>  
>  /*
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> index 03814a23eb54..98e2fa78c787 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> @@ -2955,6 +2955,7 @@ static int amdgpu_drm_release(struct inode *inode, 
> struct file *filp)
>               fpriv->evf_mgr.fd_closing = true;
>               amdgpu_eviction_fence_destroy(&fpriv->evf_mgr);
>               amdgpu_userq_mgr_fini(&fpriv->userq_mgr);
> +             amdgpu_eventfd_registry_fini(fpriv);
>               drm_dev_exit(idx);
>       }
>  
> @@ -3062,6 +3063,8 @@ const struct drm_ioctl_desc amdgpu_ioctls_kms[] = {
>       DRM_IOCTL_DEF_DRV(AMDGPU_USERQ_SIGNAL, amdgpu_userq_signal_ioctl, 
> DRM_AUTH|DRM_RENDER_ALLOW),
>       DRM_IOCTL_DEF_DRV(AMDGPU_USERQ_WAIT, amdgpu_userq_wait_ioctl, 
> DRM_AUTH|DRM_RENDER_ALLOW),
>       DRM_IOCTL_DEF_DRV(AMDGPU_GEM_LIST_HANDLES, 
> amdgpu_gem_list_handles_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
> +     DRM_IOCTL_DEF_DRV(AMDGPU_EVENTFD_BIND, amdgpu_eventfd_bind_ioctl, 
> DRM_RENDER_ALLOW),
> +     DRM_IOCTL_DEF_DRV(AMDGPU_EVENTFD_UNBIND, amdgpu_eventfd_unbind_ioctl, 
> DRM_RENDER_ALLOW),
>  };
>  
>  static const struct drm_driver amdgpu_kms_driver = {
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> index f69332eed051..43da5bc36b7c 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> @@ -39,6 +39,10 @@
>  #include <linux/uaccess.h>
>  #include <linux/pci.h>
>  #include <linux/pm_runtime.h>
> +#include <linux/eventfd.h>
> +#include <linux/rcupdate.h>
> +#include <linux/eventfd.h>
> +#include <linux/slab.h>
>  #include "amdgpu_amdkfd.h"
>  #include "amdgpu_gem.h"
>  #include "amdgpu_display.h"
> @@ -634,6 +638,113 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev,
>       return 0;
>  }
>  
> +static void amdgpu_eventfd_entry_free_rcu(struct rcu_head *rcu)
> +{
> +     struct amdgpu_eventfd_entry *e =
> +             container_of(rcu, struct amdgpu_eventfd_entry, rcu);
> +
> +     if (e->ctx)
> +             eventfd_ctx_put(e->ctx);
> +     kfree(e);
> +}
> +
> +void amdgpu_eventfd_registry_fini(struct amdgpu_fpriv *fpriv)
> +{
> +     unsigned long index;
> +     struct amdgpu_eventfd_entry *e;
> +
> +     if (!fpriv)
> +             return;
> +
> +     /*
> +      * Serialize with bind/unbind via eventfd_lock,
> +      * and use xa_lock to safely erase while iterating.
> +      */
> +     mutex_lock(&fpriv->eventfd_lock);
> +
> +     xa_lock(&fpriv->eventfd_xa);
> +     xa_for_each(&fpriv->eventfd_xa, index, e) {
> +             __xa_erase(&fpriv->eventfd_xa, index);
> +             call_rcu(&e->rcu, amdgpu_eventfd_entry_free_rcu);
> +     }
> +     xa_unlock(&fpriv->eventfd_xa);
> +
> +     mutex_unlock(&fpriv->eventfd_lock);
> +
> +     /* Wait for any RCU readers before destroying the xarray. */
> +     synchronize_rcu();
> +     xa_destroy(&fpriv->eventfd_xa);
> +}
> +
> +int amdgpu_eventfd_bind_ioctl(struct drm_device *dev, void *data,
> +                           struct drm_file *file_priv)
> +{
> +     struct amdgpu_device *adev = drm_to_adev(dev);
> +     struct amdgpu_fpriv *fpriv = file_priv->driver_priv;
> +     struct drm_amdgpu_eventfd_bind *args = data;
> +     struct amdgpu_eventfd_entry *e, *old;
> +     struct eventfd_ctx *ctx;
> +
> +     if (!fpriv || !adev)
> +             return -ENODEV;
> +     if (args->flags)
> +             return -EINVAL;
> +     if (args->eventfd < 0)
> +             return -EINVAL;
> +
> +     ctx = eventfd_ctx_fdget(args->eventfd);
> +     if (IS_ERR(ctx))
> +             return PTR_ERR(ctx);
> +
> +     e = kzalloc(sizeof(*e), GFP_KERNEL);
> +     if (!e) {
> +             eventfd_ctx_put(ctx);
> +             return -ENOMEM;
> +     }
> +     e->ctx = ctx;
> +
> +     mutex_lock(&fpriv->eventfd_lock);
> +     old = xa_store(&fpriv->eventfd_xa, args->event_id, e, GFP_KERNEL);
> +     mutex_unlock(&fpriv->eventfd_lock);
> +
> +     if (xa_is_err(old)) {
> +             int ret = xa_err(old);
> +
> +             eventfd_ctx_put(ctx);
> +             kfree(e);
> +             return ret;
> +     }
> +
> +     /* Replace existing binding for same event_id. */
> +     if (old)
> +             call_rcu(&old->rcu, amdgpu_eventfd_entry_free_rcu);
> +
> +     return 0;
> +}
> +
> +int amdgpu_eventfd_unbind_ioctl(struct drm_device *dev, void *data,
> +                             struct drm_file *file_priv)
> +{
> +     struct amdgpu_fpriv *fpriv = file_priv->driver_priv;
> +     struct drm_amdgpu_eventfd_unbind *args = data;
> +     struct amdgpu_eventfd_entry *e;
> +
> +     if (!fpriv)
> +             return -ENODEV;
> +     if (args->flags)
> +             return -EINVAL;
> +
> +     mutex_lock(&fpriv->eventfd_lock);
> +     e = xa_erase(&fpriv->eventfd_xa, args->event_id);
> +     mutex_unlock(&fpriv->eventfd_lock);
> +
> +     if (!e)
> +             return -ENOENT;
> +
> +     call_rcu(&e->rcu, amdgpu_eventfd_entry_free_rcu);
> +     return 0;
> +}
> +
>  /*
>   * Userspace get information ioctl
>   */
> @@ -1469,6 +1580,8 @@ int amdgpu_driver_open_kms(struct drm_device *dev, 
> struct drm_file *file_priv)
>               goto out_suspend;
>       }
>  
> +     mutex_init(&fpriv->eventfd_lock);
> +     xa_init(&fpriv->eventfd_xa);
>       pasid = amdgpu_pasid_alloc(16);
>       if (pasid < 0) {
>               dev_warn(adev->dev, "No more PASIDs available!");
> @@ -1538,6 +1651,7 @@ int amdgpu_driver_open_kms(struct drm_device *dev, 
> struct drm_file *file_priv)
>       if (pasid)
>               amdgpu_pasid_free(pasid);
>  
> +     xa_destroy(&fpriv->eventfd_xa);
>       kfree(fpriv);
>  
>  out_suspend:
> @@ -1568,6 +1682,8 @@ void amdgpu_driver_postclose_kms(struct drm_device *dev,
>       if (!fpriv)
>               return;
>  
> +     amdgpu_eventfd_registry_fini(fpriv);
> +
>       pm_runtime_get_sync(dev->dev);
>  
>       if (amdgpu_device_ip_get_ip_block(adev, AMD_IP_BLOCK_TYPE_UVD) != NULL)

Reply via email to