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 6d652e8ac978..1b7c0b0d05b6 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -458,6 +458,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 03814a23eb54..c73147e71566 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -3062,6 +3062,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 ad27274a9e92..12f00620cac7 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; + + 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 22fcf2a69134..d37854d37916 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 */ -- 2.34.1
