[RFC PATCH 2/3] drm: define new accel major and register it

From: Oded Gabbay
Date: Sat Oct 22 2022 - 17:47:02 EST


The accelerator devices will be exposed to the user space with a new,
dedicated major number - 261.

The drm core registers the new major number as a char device and create
corresponding sysfs and debugfs root entries, same as for the drm major.

In case CONFIG_ACCEL is not selected, this code is not compiled in.

Signed-off-by: Oded Gabbay <ogabbay@xxxxxxxxxx>
---
Documentation/admin-guide/devices.txt | 5 +++
drivers/gpu/drm/drm_drv.c | 45 +++++++++++++++++++++++
drivers/gpu/drm/drm_internal.h | 3 ++
drivers/gpu/drm/drm_sysfs.c | 52 +++++++++++++++++++++++++++
include/drm/drm_ioctl.h | 1 +
5 files changed, 106 insertions(+)

diff --git a/Documentation/admin-guide/devices.txt b/Documentation/admin-guide/devices.txt
index 9764d6edb189..06c525e01ea5 100644
--- a/Documentation/admin-guide/devices.txt
+++ b/Documentation/admin-guide/devices.txt
@@ -3080,6 +3080,11 @@
...
255 = /dev/osd255 256th OSD Device

+ 261 char Compute Acceleration Devices
+ 0 = /dev/accel/accel0 First acceleration device
+ 1 = /dev/accel/accel1 Second acceleration device
+ ...
+
384-511 char RESERVED FOR DYNAMIC ASSIGNMENT
Character devices that request a dynamic allocation of major
number will take numbers starting from 511 and downward,
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index 8214a0b1ab7f..b58ffb1433d6 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -67,6 +67,10 @@ static bool drm_core_init_complete;

static struct dentry *drm_debugfs_root;

+#ifdef CONFIG_ACCEL
+static struct dentry *accel_debugfs_root;
+#endif
+
DEFINE_STATIC_SRCU(drm_unplug_srcu);

/*
@@ -1031,9 +1035,19 @@ static const struct file_operations drm_stub_fops = {
.llseek = noop_llseek,
};

+static void accel_core_exit(void)
+{
+#ifdef CONFIG_ACCEL
+ unregister_chrdev(ACCEL_MAJOR, "accel");
+ debugfs_remove(accel_debugfs_root);
+ accel_sysfs_destroy();
+#endif
+}
+
static void drm_core_exit(void)
{
drm_privacy_screen_lookup_exit();
+ accel_core_exit();
unregister_chrdev(DRM_MAJOR, "drm");
debugfs_remove(drm_debugfs_root);
drm_sysfs_destroy();
@@ -1041,6 +1055,33 @@ static void drm_core_exit(void)
drm_connector_ida_destroy();
}

+static int __init accel_core_init(void)
+{
+#ifdef CONFIG_ACCEL
+ int ret;
+
+ ret = accel_sysfs_init();
+ if (ret < 0) {
+ DRM_ERROR("Cannot create ACCEL class: %d\n", ret);
+ goto error;
+ }
+
+ accel_debugfs_root = debugfs_create_dir("accel", NULL);
+
+ ret = register_chrdev(ACCEL_MAJOR, "accel", &drm_stub_fops);
+ if (ret < 0)
+ goto error;
+
+error:
+ /* Any cleanup will be done in drm_core_exit() that will call
+ * to accel_core_exit()
+ */
+ return ret;
+#else
+ return 0;
+#endif
+}
+
static int __init drm_core_init(void)
{
int ret;
@@ -1061,6 +1102,10 @@ static int __init drm_core_init(void)
if (ret < 0)
goto error;

+ ret = accel_core_init();
+ if (ret < 0)
+ goto error;
+
drm_privacy_screen_lookup_init();

drm_core_init_complete = true;
diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h
index 7bb98e6a446d..cbeb9bd3c312 100644
--- a/drivers/gpu/drm/drm_internal.h
+++ b/drivers/gpu/drm/drm_internal.h
@@ -147,9 +147,12 @@ void drm_master_internal_release(struct drm_device *dev);

/* drm_sysfs.c */
extern struct class *drm_class;
+extern struct class *accel_class;

int drm_sysfs_init(void);
void drm_sysfs_destroy(void);
+int accel_sysfs_init(void);
+void accel_sysfs_destroy(void);
struct device *drm_sysfs_minor_alloc(struct drm_minor *minor);
int drm_sysfs_connector_add(struct drm_connector *connector);
void drm_sysfs_connector_remove(struct drm_connector *connector);
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index 430e00b16eec..70b2a28f55c4 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -56,6 +56,7 @@ static struct device_type drm_sysfs_device_connector = {
};

struct class *drm_class;
+struct class *accel_class;

#ifdef CONFIG_ACPI
static bool drm_connector_acpi_bus_match(struct device *dev)
@@ -148,6 +149,57 @@ static void drm_sysfs_release(struct device *dev)
kfree(dev);
}

+static char *accel_devnode(struct device *dev, umode_t *mode)
+{
+ return kasprintf(GFP_KERNEL, "accel/%s", dev_name(dev));
+}
+
+static CLASS_ATTR_STRING(accel_version, 0444, "accel 1.0.0 20221018");
+
+/**
+ * accel_sysfs_init - initialize sysfs helpers
+ *
+ * This is used to create the ACCEL class, which is the implicit parent of any
+ * other top-level ACCEL sysfs objects.
+ *
+ * You must call accel_sysfs_destroy() to release the allocated resources.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int accel_sysfs_init(void)
+{
+ int err;
+
+ accel_class = class_create(THIS_MODULE, "accel");
+ if (IS_ERR(accel_class))
+ return PTR_ERR(accel_class);
+
+ err = class_create_file(accel_class, &class_attr_accel_version.attr);
+ if (err) {
+ class_destroy(accel_class);
+ accel_class = NULL;
+ return err;
+ }
+
+ accel_class->devnode = accel_devnode;
+
+ return 0;
+}
+
+/**
+ * accel_sysfs_destroy - destroys ACCEL class
+ *
+ * Destroy the ACCEL device class.
+ */
+void accel_sysfs_destroy(void)
+{
+ if (IS_ERR_OR_NULL(accel_class))
+ return;
+ class_remove_file(accel_class, &class_attr_accel_version.attr);
+ class_destroy(accel_class);
+ accel_class = NULL;
+}
+
/*
* Connector properties
*/
diff --git a/include/drm/drm_ioctl.h b/include/drm/drm_ioctl.h
index 6ed61c371f6c..88e4926208e7 100644
--- a/include/drm/drm_ioctl.h
+++ b/include/drm/drm_ioctl.h
@@ -70,6 +70,7 @@ typedef int drm_ioctl_compat_t(struct file *filp, unsigned int cmd,
#define DRM_IOCTL_NR(n) _IOC_NR(n)
#define DRM_IOCTL_TYPE(n) _IOC_TYPE(n)
#define DRM_MAJOR 226
+#define ACCEL_MAJOR 261

/**
* enum drm_ioctl_flags - DRM ioctl flags
--
2.34.1