On 6/11/26 09:26, Srinivasan Shanmugam wrote:
> The current EVENTFD UAPI uses a userspace-defined event identifier.
> 
> For render-node event notifications, userspace should subscribe to
> kernel-defined event types instead, allowing the kernel to define event
> semantics and signaling sources.
> 
> Add a shared AMDGPU EVENTFD event type enum and update the EVENTFD UAPI
> to use event_type instead of event_id.
> 
> Value 0 is reserved and rejected by the existing event_type validation.
> 
> queue_id remains part of the UAPI and is used to distinguish
> queue-scoped subscriptions from GPU/device-scoped subscriptions.
> 
> Eventfd signaling remains notification-only.
> 
> v10: (per Christian)
> - Add a comment clarifying that the flags field is currently unused,
>   reserved for future UAPI extensions, and must be zero.
> - Introduce event_type directly in the EVENTFD UAPI.
> - Remove the INVALID event type; value 0 remains rejected by validation.
> - Squash the event_id to event_type rename into the original UAPI patch.
> 
> v11: (per Christian)
> - Keep the event_id to event_type rename in this patch so that later
>   patches focus only on queue reference handling.
> - Move queue reference conversion and queue-scoped EVENTFD handling
>   into the subsequent patch to reduce noise in this change.
> 
> Cc: Alex Deucher <[email protected]>
> Cc: Christian König <[email protected]>
> Signed-off-by: Srinivasan Shanmugam <[email protected]>

Reviewed-by: Christian König <[email protected]>

> ---
>  drivers/gpu/drm/amd/amdgpu/amdgpu.h         |   5 +
>  drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c     |   1 +
>  drivers/gpu/drm/amd/amdgpu/amdgpu_eventfd.c | 107 +++++++++-----------
>  drivers/gpu/drm/amd/amdgpu/amdgpu_eventfd.h |  17 ++--
>  drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c     |  37 +++++++
>  include/uapi/drm/amdgpu_drm.h               |  43 ++++++++
>  6 files changed, 145 insertions(+), 65 deletions(-)
> 
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> index a75c68195df9..54bc31ee795a 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
> @@ -460,6 +460,11 @@ struct amdgpu_fpriv {
>       struct amdgpu_eventfd_mgr       eventfd_mgr;
>  };
>  
> +struct drm_device;
> +struct drm_file;
> +
> +int amdgpu_eventfd_ioctl(struct drm_device *dev, void *data, struct drm_file 
> *file_priv);
> +
>  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 1781c0c3d010..aaa4dd57099f 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
> @@ -3076,6 +3076,7 @@ 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, amdgpu_eventfd_ioctl, 
> DRM_RENDER_ALLOW),
>  };
>  
>  static const struct drm_driver amdgpu_kms_driver = {
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_eventfd.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_eventfd.c
> index 4955ee942a1c..c777d563f1b5 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_eventfd.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_eventfd.c
> @@ -24,14 +24,10 @@
>  /*
>   * Render-node eventfd subscription infrastructure.
>   *
> - * This module provides a simple event notification mechanism for render-node
> - * clients using Linux eventfd objects.
> + * EVENTFD is notification-only. It wakes userspace when a GPU event happens.
> + * Event metadata/details are expected to be consumed separately through the
> + * corresponding wait/event path.
>   *
> - * Userspace can bind an eventfd to a userspace-defined event_id. When the
> - * driver signals that event_id, all eventfds bound to it are notified.
> - *
> - * This mechanism is intended to support lightweight GPU event notifications
> - * without polling from userspace.
>   */
>  
>  #include <linux/slab.h>
> @@ -42,19 +38,19 @@
>  #define AMDGPU_EVENTFD_MAX_BINDS 4096
>  
>  /**
> - * amdgpu_eventfd_id_alloc - allocate an event id container
> - * @event_id: userspace-defined event identifier
> + * amdgpu_eventfd_id_alloc - allocate an event type container
> + * @event_type: kernel-defined AMDGPU event type
>   *
> - * Each event_id represents a notification category. Multiple eventfds can
> - * be bound to the same event_id.
> + * Each event type represents a notification category. Multiple eventfds
> + * can be bound to the same event type.
>   *
>   * This function allocates the container which stores the list of eventfds
> - * associated with that event_id.
> + * associated with that event type.
>   *
>   * Return:
>   * Pointer to the newly allocated structure or NULL on failure.
>   */
> -static struct amdgpu_eventfd_id *amdgpu_eventfd_id_alloc(u32 event_id)
> +static struct amdgpu_eventfd_id *amdgpu_eventfd_id_alloc(u32 event_type)
>  {
>       struct amdgpu_eventfd_id *id;
>  
> @@ -62,43 +58,41 @@ static struct amdgpu_eventfd_id 
> *amdgpu_eventfd_id_alloc(u32 event_id)
>       if (!id)
>               return NULL;
>  
> -     id->event_id = event_id;
> +     id->event_type = event_type;
>       INIT_HLIST_HEAD(&id->entries);
>       id->n_entries = 0;
> +
>       return id;
>  }
>  
>  /**
> - * amdgpu_eventfd_id_get_or_create - find or create an event_id entry
> + * amdgpu_eventfd_id_get_or_create - lookup or create an event type
>   * @mgr: eventfd manager
> - * @event_id: event identifier
> - *
> - * This helper returns the container associated with the given event_id.
> - * If it does not exist, it will create one.
> + * @event_type: kernel-defined AMDGPU event type
>   *
> - * The function is designed to be callable without holding any locks.
> - * Memory allocation is done outside the xarray lock to avoid blocking
> - * inside critical sections.
> + * Find the container associated with the specified event type. If none
> + * exists, allocate and insert a new one.
>   *
>   * Return:
> - * Pointer to the event_id structure or NULL on failure.
> + * Existing event type container or a newly allocated one.
>   */
>  static struct amdgpu_eventfd_id *
> -amdgpu_eventfd_id_get_or_create(struct amdgpu_eventfd_mgr *mgr, u32 event_id)
> +amdgpu_eventfd_id_get_or_create(struct amdgpu_eventfd_mgr *mgr,
> +                             u32 event_type)
>  {
>       struct amdgpu_eventfd_id *id;
>       struct amdgpu_eventfd_id *new_id;
> -     XA_STATE(xas, &mgr->ids, event_id);
> +     XA_STATE(xas, &mgr->ids, event_type);
>       unsigned long flags;
>       int r;
>  
>       xa_lock_irqsave(&mgr->ids, flags);
> -     id = xa_load(&mgr->ids, event_id);
> +     id = xa_load(&mgr->ids, event_type);
>       xa_unlock_irqrestore(&mgr->ids, flags);
>       if (id)
>               return id;
>  
> -     new_id = amdgpu_eventfd_id_alloc(event_id);
> +     new_id = amdgpu_eventfd_id_alloc(event_type);
>       if (!new_id)
>               return NULL;
>  
> @@ -140,7 +134,7 @@ amdgpu_eventfd_id_get_or_create(struct amdgpu_eventfd_mgr 
> *mgr, u32 event_id)
>   *
>   *   event_id -> list of eventfds
>   *
> - * The xarray provides efficient lookup of event_id containers.
> + * The xarray provides efficient lookup of event type containers.
>   */
>  void amdgpu_eventfd_mgr_init(struct amdgpu_eventfd_mgr *mgr)
>  {
> @@ -186,23 +180,19 @@ void amdgpu_eventfd_mgr_fini(struct amdgpu_eventfd_mgr 
> *mgr)
>  }
>  
>  /**
> - * amdgpu_eventfd_bind - bind eventfd to an event_id
> + * amdgpu_eventfd_bind - bind an eventfd to an event type
>   * @mgr: eventfd manager
> - * @event_id: userspace event identifier
> + * @event_type: kernel-defined AMDGPU event type
>   * @eventfd: eventfd file descriptor
>   *
> - * This function allows userspace to subscribe to notifications for a
> - * specific event_id.
> - *
> - * Multiple eventfds can be bound to the same event_id.
> - *
> - * Duplicate bindings of the same eventfd are treated as success and do
> - * not create additional entries.
> + * Register an eventfd subscription for the specified event type.
> + * Duplicate subscriptions are treated as success.
>   *
>   * Return:
> - * 0 on success, negative error code on failure.
> + * 0 on success or a negative error code.
>   */
> -int amdgpu_eventfd_bind(struct amdgpu_eventfd_mgr *mgr, u32 event_id, int 
> eventfd)
> +int amdgpu_eventfd_bind(struct amdgpu_eventfd_mgr *mgr,
> +                     u32 event_type, int eventfd)
>  {
>       struct amdgpu_eventfd_id *id;
>       struct amdgpu_eventfd_entry *e = NULL, *it;
> @@ -211,7 +201,7 @@ int amdgpu_eventfd_bind(struct amdgpu_eventfd_mgr *mgr, 
> u32 event_id, int eventf
>       bool dup = false;
>       int r = 0; /* duplicate binds are treated as success */
>  
> -     if (!mgr || !event_id || eventfd < 0)
> +     if (!mgr || !event_type || eventfd < 0)
>               return -EINVAL;
>  
>       /*
> @@ -229,7 +219,7 @@ int amdgpu_eventfd_bind(struct amdgpu_eventfd_mgr *mgr, 
> u32 event_id, int eventf
>               return PTR_ERR(ctx);
>       }
>  
> -     id = amdgpu_eventfd_id_get_or_create(mgr, event_id);
> +     id = amdgpu_eventfd_id_get_or_create(mgr, event_type);
>       if (!id) {
>               r = -ENOMEM;
>               goto out_put_ctx;
> @@ -259,7 +249,7 @@ int amdgpu_eventfd_bind(struct amdgpu_eventfd_mgr *mgr, 
> u32 event_id, int eventf
>  
>       /*
>        * Re-check duplicate under lock to close the race with another bind()
> -      * for the same (event_id, ctx).
> +      * for the same event_type and eventfd context.
>        */
>       xa_lock_irqsave(&mgr->ids, flags);
>       hlist_for_each_entry(it, &id->entries, hnode) {
> @@ -291,17 +281,18 @@ int amdgpu_eventfd_bind(struct amdgpu_eventfd_mgr *mgr, 
> u32 event_id, int eventf
>  }
>  
>  /**
> - * amdgpu_eventfd_unbind - remove eventfd binding
> + * amdgpu_eventfd_unbind - remove an eventfd subscription
>   * @mgr: eventfd manager
> - * @event_id: event identifier
> + * @event_type: kernel-defined AMDGPU event type
>   * @eventfd: eventfd file descriptor
>   *
> - * Removes an existing binding between an event_id and an eventfd.
> + * Remove an existing subscription for the specified event type.
>   *
>   * Return:
> - * 0 if removed, -ENOENT if binding does not exist.
> + * 0 on success or a negative error code.
>   */
> -int amdgpu_eventfd_unbind(struct amdgpu_eventfd_mgr *mgr, u32 event_id, int 
> eventfd)
> +int amdgpu_eventfd_unbind(struct amdgpu_eventfd_mgr *mgr,
> +                       u32 event_type, int eventfd)
>  {
>       struct amdgpu_eventfd_id *id;
>       struct amdgpu_eventfd_entry *e;
> @@ -310,7 +301,7 @@ int amdgpu_eventfd_unbind(struct amdgpu_eventfd_mgr *mgr, 
> u32 event_id, int even
>       unsigned long flags;
>       bool removed = false;
>  
> -     if (!mgr || !event_id || eventfd < 0)
> +     if (!mgr || !event_type || eventfd < 0)
>               return -EINVAL;
>  
>       ctx = eventfd_ctx_fdget(eventfd);
> @@ -319,7 +310,7 @@ int amdgpu_eventfd_unbind(struct amdgpu_eventfd_mgr *mgr, 
> u32 event_id, int even
>  
>       xa_lock_irqsave(&mgr->ids, flags);
>  
> -     id = xa_load(&mgr->ids, event_id);
> +     id = xa_load(&mgr->ids, event_type);
>       if (!id)
>               goto out_unlock;
>  
> @@ -337,7 +328,7 @@ int amdgpu_eventfd_unbind(struct amdgpu_eventfd_mgr *mgr, 
> u32 event_id, int even
>               atomic_dec(&mgr->bind_count);
>  
>               if (!id->n_entries) {
> -                     __xa_erase(&mgr->ids, event_id);
> +                     __xa_erase(&mgr->ids, event_type);
>                       kfree(id);
>               }
>  
> @@ -352,22 +343,22 @@ int amdgpu_eventfd_unbind(struct amdgpu_eventfd_mgr 
> *mgr, u32 event_id, int even
>  }
>  
>  /**
> - * amdgpu_eventfd_signal - notify all eventfds bound to event_id
> + * amdgpu_eventfd_signal - signal all eventfds bound to an event type
>   * @mgr: eventfd manager
> - * @event_id: event identifier
> + * @event_type: kernel-defined AMDGPU event type
>   *
> - * This function is typically called from interrupt context.
> + * Notify all subscribers associated with the specified event type.
>   *
> - * All eventfds registered for the given event_id will be signaled.
> - * Userspace processes waiting on those eventfds will wake up.
> + * Signaling is notification-only and does not carry additional payload.
>   */
> -void amdgpu_eventfd_signal(struct amdgpu_eventfd_mgr *mgr, u32 event_id)
> +void amdgpu_eventfd_signal(struct amdgpu_eventfd_mgr *mgr,
> +                        u32 event_type)
>  {
>       struct amdgpu_eventfd_id *id;
>       struct amdgpu_eventfd_entry *e;
>       unsigned long flags;
>  
> -     if (!mgr || !event_id)
> +     if (!mgr || !event_type)
>               return;
>  
>       /*
> @@ -376,7 +367,7 @@ void amdgpu_eventfd_signal(struct amdgpu_eventfd_mgr 
> *mgr, u32 event_id)
>        */
>       xa_lock_irqsave(&mgr->ids, flags);
>  
> -     id = xa_load(&mgr->ids, event_id);
> +     id = xa_load(&mgr->ids, event_type);
>       if (id) {
>               hlist_for_each_entry(e, &id->entries, hnode)
>                       eventfd_signal(e->ctx);
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_eventfd.h 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_eventfd.h
> index 248afb1f2f14..e13b86240afc 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_eventfd.h
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_eventfd.h
> @@ -28,9 +28,9 @@
>  #ifndef __AMDGPU_EVENTFD_H__
>  #define __AMDGPU_EVENTFD_H__
>  
> +#include <linux/atomic.h>
>  #include <linux/eventfd.h>
>  #include <linux/xarray.h>
> -#include <linux/atomic.h>
>  
>  struct amdgpu_eventfd_entry {
>       struct eventfd_ctx *ctx;
> @@ -38,22 +38,25 @@ struct amdgpu_eventfd_entry {
>  };
>  
>  struct amdgpu_eventfd_id {
> -     u32 event_id;
> +     u32 event_type;
>       struct hlist_head entries;
>       u32 n_entries;
>  };
>  
>  struct amdgpu_eventfd_mgr {
> -     struct xarray ids;          /* event_id -> struct amdgpu_eventfd_id* */
> -     atomic_t bind_count;        /* total binds across all event_ids */
> +     struct xarray ids;      /* event_type -> struct amdgpu_eventfd_id* */
> +     atomic_t bind_count;    /* total binds across all event types */
>  };
>  
>  void amdgpu_eventfd_mgr_init(struct amdgpu_eventfd_mgr *mgr);
>  void amdgpu_eventfd_mgr_fini(struct amdgpu_eventfd_mgr *mgr);
>  
> -int amdgpu_eventfd_bind(struct amdgpu_eventfd_mgr *mgr, u32 event_id, int 
> eventfd);
> -int amdgpu_eventfd_unbind(struct amdgpu_eventfd_mgr *mgr, u32 event_id, int 
> eventfd);
> +int amdgpu_eventfd_bind(struct amdgpu_eventfd_mgr *mgr,
> +                     u32 event_type, int eventfd);
> +int amdgpu_eventfd_unbind(struct amdgpu_eventfd_mgr *mgr,
> +                       u32 event_type, int eventfd);
>  
> -void amdgpu_eventfd_signal(struct amdgpu_eventfd_mgr *mgr, u32 event_id);
> +void amdgpu_eventfd_signal(struct amdgpu_eventfd_mgr *mgr,
> +                        u32 event_type);
>  
>  #endif /* __AMDGPU_EVENTFD_H__ */
> diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c 
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> index f5719500527f..7cc54b7e3b81 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> @@ -634,6 +634,43 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev,
>       return 0;
>  }
>  
> +int amdgpu_eventfd_ioctl(struct drm_device *dev, void *data,
> +                      struct drm_file *file_priv)
> +{
> +     struct amdgpu_fpriv *fpriv = file_priv->driver_priv;
> +     struct drm_amdgpu_eventfd *args = data;
> +
> +     if (!fpriv)
> +             return -EINVAL;
> +
> +     /*
> +      * flags are reserved for future UAPI extensions and must be zero.
> +      */
> +     if (args->flags || !args->event_type || args->eventfd < 0)
> +             return -EINVAL;
> +
> +     /*
> +      * Queue-scoped subscriptions are enabled by the later
> +      * queue-reference routing patch. Until then, keep
> +      * queue_id zero.
> +      */
> +     if (args->queue_id)
> +             return -EINVAL;
> +
> +     switch (args->op) {
> +     case DRM_AMDGPU_EVENTFD_OP_BIND:
> +             return amdgpu_eventfd_bind(&fpriv->eventfd_mgr,
> +                                        args->event_type,
> +                                        args->eventfd);
> +     case DRM_AMDGPU_EVENTFD_OP_UNBIND:
> +             return amdgpu_eventfd_unbind(&fpriv->eventfd_mgr,
> +                                          args->event_type,
> +                                          args->eventfd);
> +     default:
> +             return -EINVAL;
> +     }
> +}
> +
>  /*
>   * Userspace get information ioctl
>   */
> diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h
> index 9f3090db2f16..bf4fc61cf0c7 100644
> --- a/include/uapi/drm/amdgpu_drm.h
> +++ b/include/uapi/drm/amdgpu_drm.h
> @@ -39,6 +39,7 @@ extern "C" {
>  #endif
>  
>  #define DRM_AMDGPU_GEM_CREATE                0x00
> +#define DRM_AMDGPU_EVENTFD           0x1A
>  #define DRM_AMDGPU_GEM_MMAP          0x01
>  #define DRM_AMDGPU_CTX                       0x02
>  #define DRM_AMDGPU_BO_LIST           0x03
> @@ -79,6 +80,8 @@ extern "C" {
>  #define DRM_IOCTL_AMDGPU_USERQ_SIGNAL        DRM_IOWR(DRM_COMMAND_BASE + 
> DRM_AMDGPU_USERQ_SIGNAL, struct drm_amdgpu_userq_signal)
>  #define DRM_IOCTL_AMDGPU_USERQ_WAIT  DRM_IOWR(DRM_COMMAND_BASE + 
> DRM_AMDGPU_USERQ_WAIT, struct drm_amdgpu_userq_wait)
>  #define DRM_IOCTL_AMDGPU_GEM_LIST_HANDLES DRM_IOWR(DRM_COMMAND_BASE + 
> DRM_AMDGPU_GEM_LIST_HANDLES, struct drm_amdgpu_gem_list_handles)
> +#define DRM_IOCTL_AMDGPU_EVENTFD \
> +     DRM_IOW(DRM_COMMAND_BASE + DRM_AMDGPU_EVENTFD, struct 
> drm_amdgpu_eventfd)
>  
>  /**
>   * DOC: memory domains
> @@ -204,6 +207,46 @@ union drm_amdgpu_gem_create {
>       struct drm_amdgpu_gem_create_out        out;
>  };
>  
> +enum drm_amdgpu_event_type {
> +     DRM_AMDGPU_EVENT_TYPE_USERQ_EOP = 1,
> +     DRM_AMDGPU_EVENT_TYPE_QUEUE_RESET = 2,
> +     DRM_AMDGPU_EVENT_TYPE_MEMORY_EXCEPTION = 3,
> +     DRM_AMDGPU_EVENT_TYPE_SCRATCH = 4,
> +     DRM_AMDGPU_EVENT_TYPE_GPU_RESET = 5,
> +};
> +
> +enum drm_amdgpu_eventfd_op {
> +     DRM_AMDGPU_EVENTFD_OP_BIND = 0,
> +     DRM_AMDGPU_EVENTFD_OP_UNBIND = 1,
> +};
> +
> +/**
> + * struct drm_amdgpu_eventfd - bind or unbind an eventfd to an AMDGPU event
> + * @op: operation type, see &enum drm_amdgpu_eventfd_op
> + * @event_type: kernel-defined AMDGPU event type
> + * @eventfd: eventfd file descriptor
> + * @queue_id: queue identifier for queue-scoped subscriptions, or 0 for
> + *         device/GPU-scoped subscriptions
> + * @flags: must be 0
> + *
> + * This ioctl lets userspace register or unregister eventfd notifications
> + * for a render-node event.
> + *
> + * Eventfd signaling is notification-only.
> + *
> + * USERQ_EOP, QUEUE_RESET, and SCRATCH are queue-scoped events.
> + * Userspace specifies @queue_id when registering these subscriptions.
> + *
> + * MEMORY_EXCEPTION is currently GPU-scoped and requires @queue_id = 0.
> + */
> +struct drm_amdgpu_eventfd {
> +     __u32 op;
> +     __u32 event_type;
> +     __s32 eventfd;
> +     __u32 queue_id;
> +     __u32 flags;
> +};
> +
>  /** Opcode to create new residency list.  */
>  #define AMDGPU_BO_LIST_OP_CREATE     0
>  /** Opcode to destroy previously created residency list */

Reply via email to