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.

UAPI is placed last in the series since it enables the userspace-facing
feature.

Cc: Alex Deucher <[email protected]>
Cc: Christian König <[email protected]>
Signed-off-by: Srinivasan Shanmugam <[email protected]>
Change-Id: Ibe6a3be80f6435c1fe2a3243b63e6ed2fc6391ee
---
 drivers/gpu/drm/amd/amdgpu/amdgpu.h     |  6 +++++
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c |  2 ++
 drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 28 +++++++++++++++++++++
 include/uapi/drm/amdgpu_drm.h           | 33 +++++++++++++++++++++++++
 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..0955290f180b 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h
@@ -458,6 +458,12 @@ struct amdgpu_fpriv {
        struct amdgpu_eventfd_mgr       eventfd_mgr;
 };
 
+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);
+
 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..0393026534f9 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -3062,6 +3062,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 ad27274a9e92..e06bb19bcb12 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c
@@ -634,6 +634,34 @@ static int amdgpu_hw_ip_info(struct amdgpu_device *adev,
        return 0;
 }
 
+int amdgpu_eventfd_bind_ioctl(struct drm_device *dev, void *data,
+                             struct drm_file *file_priv)
+{
+       struct amdgpu_fpriv *fpriv = file_priv->driver_priv;
+       struct drm_amdgpu_eventfd_bind *args = data;
+
+       if (!fpriv)
+               return -EINVAL;
+       if (args->flags || !args->event_id || args->eventfd < 0)
+               return -EINVAL;
+
+       return amdgpu_eventfd_bind(&fpriv->eventfd_mgr, args->event_id, 
args->eventfd);
+}
+
+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;
+
+       if (!fpriv)
+               return -ENODEV;
+       if (args->flags || !args->event_id || args->eventfd < 0)
+               return -EINVAL;
+
+       return amdgpu_eventfd_unbind(&fpriv->eventfd_mgr, args->event_id, 
args->eventfd);
+}
+
 /*
  * Userspace get information ioctl
  */
diff --git a/include/uapi/drm/amdgpu_drm.h b/include/uapi/drm/amdgpu_drm.h
index 22fcf2a69134..5fdaa141cf82 100644
--- a/include/uapi/drm/amdgpu_drm.h
+++ b/include/uapi/drm/amdgpu_drm.h
@@ -39,6 +39,8 @@ extern "C" {
 #endif
 
 #define DRM_AMDGPU_GEM_CREATE          0x00
+#define DRM_AMDGPU_EVENTFD_BIND                0x1A
+#define DRM_AMDGPU_EVENTFD_UNBIND      0x1B
 #define DRM_AMDGPU_GEM_MMAP            0x01
 #define DRM_AMDGPU_CTX                 0x02
 #define DRM_AMDGPU_BO_LIST             0x03
@@ -79,6 +81,10 @@ 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_BIND \
+       DRM_IOW(DRM_COMMAND_BASE + DRM_AMDGPU_EVENTFD_BIND, struct 
drm_amdgpu_eventfd_bind)
+#define DRM_IOCTL_AMDGPU_EVENTFD_UNBIND \
+       DRM_IOW(DRM_COMMAND_BASE + DRM_AMDGPU_EVENTFD_UNBIND, struct 
drm_amdgpu_eventfd_unbind)
 
 /**
  * DOC: memory domains
@@ -204,6 +210,33 @@ union drm_amdgpu_gem_create {
        struct drm_amdgpu_gem_create_out        out;
 };
 
+/**
+ * struct drm_amdgpu_eventfd_bind - Bind an eventfd to an event_id.
+ * @event_id: Userspace-defined event identifier.
+ * @eventfd:  eventfd file descriptor.
+ * @flags:    Must be 0.
+ *
+ * Duplicate binds of the same eventfd to the same event_id are idempotent
+ * and return success without creating an additional binding.
+ */
+struct drm_amdgpu_eventfd_bind {
+       __u32 event_id;
+       __s32 eventfd;
+       __u32 flags;
+};
+
+/**
+ * struct drm_amdgpu_eventfd_unbind - Unbind an eventfd from an event_id.
+ * @event_id: Userspace-defined event identifier.
+ * @eventfd:  eventfd file descriptor.
+ * @flags:    Must be 0.
+ */
+struct drm_amdgpu_eventfd_unbind {
+       __u32 event_id;
+       __s32 eventfd;
+       __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

Reply via email to