On 6/3/26 18:33, Srinivasan Shanmugam wrote:
> Introduce two new UAPI ioctls to allow userspace to bind and unbind an
> eventfd to a userspace-defined event_id on the render node.
>
> The design supports multiple eventfds bound to the same event_id.
> Therefore, unbind includes the eventfd to remove a specific binding.
>
> v2:
> Replace separate EVENTFD bind/unbind ioctls with a single EVENTFD ioctl
> that carries an operation field.
>
> Also add a queue_id parameter to the UAPI so subscriptions can become
> queue-specific in a later step. For now, queue_id is reserved for future
> use and must be 0.
>
> This keeps ioctl number usage smaller and prepares the API for queue-aware
> event routing.
>
> 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 | 5 ++++
> drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 1 +
> drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 33 +++++++++++++++++++++++++
> include/uapi/drm/amdgpu_drm.h | 30 ++++++++++++++++++++++
> 4 files changed, 69 insertions(+)
>
> 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_kms.c
> b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> index f5719500527f..cd127a271c19 100644
> --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
> @@ -634,6 +634,39 @@ 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;
> +
Maybe a comment that flags are reserved for now.
Apart from that looks good to me,
Christian.
> + if (args->flags || !args->event_id || args->eventfd < 0)
> + return -EINVAL;
> +
> + /*
> + * queue_id is reserved for future queue-specific subscriptions.
> + * Keep it zero for now.
> + */
> + if (args->queue_id)
> + return -EINVAL;
> +
> + switch (args->op) {
> + case DRM_AMDGPU_EVENTFD_OP_BIND:
> + return amdgpu_eventfd_bind(&fpriv->eventfd_mgr,
> + args->event_id,
> + args->eventfd);
> + case DRM_AMDGPU_EVENTFD_OP_UNBIND:
> + return amdgpu_eventfd_unbind(&fpriv->eventfd_mgr,
> + args->event_id,
> + 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..63cde4487c47 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,33 @@ union drm_amdgpu_gem_create {
> struct drm_amdgpu_gem_create_out out;
> };
>
> +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 event_id
> + * @op: operation type, see &enum drm_amdgpu_eventfd_op
> + * @event_id: userspace-defined event identifier
> + * @eventfd: eventfd file descriptor
> + * @queue_id: queue identifier for future queue-specific subscriptions
> + * @flags: must be 0
> + *
> + * This ioctl lets userspace register or unregister eventfd notifications
> + * for a render-node event.
> + *
> + * For now, @queue_id is reserved for future queue-specific subscriptions
> + * and must be 0.
> + */
> +struct drm_amdgpu_eventfd {
> + __u32 op;
> + __u32 event_id;
> + __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 */