[RFC PATCH] drm: split up drm_ioctl to allow drivers to hook into "core" functions

Ilia Mirkin imirkin at alum.mit.edu
Sun Dec 31 18:15:09 UTC 2017


Currently there's no way to allow a driver to reimplement any ioctls
from the drm core. This can be desirable to, e.g., override fixed format
selection logic, without turning to a midlayer-like solution.

Signed-off-by: Ilia Mirkin <imirkin at alum.mit.edu>
---

I want drm_mode_addfb to pick a different format for depth=30 than the
one it currently selects. Flipping it for all drivers would break a
bunch of existing ones, so this enables a driver to take control.

Alternatively I can stash something into drm_device which specifies the
preferred depth=30 fb format. However from my cursory observations of
dri-devel discussions, midlayering is seen as a problem and not a
solution.

 drivers/gpu/drm/drm_ioctl.c | 36 ++++++++++++++++++++++++------------
 include/drm/drm_ioctl.h     |  2 ++
 2 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index 4aafe4802099..698d69c6db0a 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -767,12 +767,7 @@ long drm_ioctl(struct file *filp,
 	struct drm_file *file_priv = filp->private_data;
 	struct drm_device *dev;
 	const struct drm_ioctl_desc *ioctl = NULL;
-	drm_ioctl_t *func;
 	unsigned int nr = DRM_IOCTL_NR(cmd);
-	int retcode = -EINVAL;
-	char stack_kdata[128];
-	char *kdata = NULL;
-	unsigned int in_size, out_size, drv_size, ksize;
 	bool is_driver_ioctl;
 
 	dev = file_priv->minor->dev;
@@ -784,16 +779,33 @@ long drm_ioctl(struct file *filp,
 
 	if (is_driver_ioctl) {
 		/* driver ioctl */
-		if (nr - DRM_COMMAND_BASE >= dev->driver->num_ioctls)
-			goto err_i1;
-		ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
+		if (nr - DRM_COMMAND_BASE < dev->driver->num_ioctls)
+			ioctl = &dev->driver->ioctls[nr - DRM_COMMAND_BASE];
 	} else {
 		/* core ioctl */
-		if (nr >= DRM_CORE_IOCTL_COUNT)
-			goto err_i1;
-		ioctl = &drm_ioctls[nr];
+		if (nr < DRM_CORE_IOCTL_COUNT)
+			ioctl = &drm_ioctls[nr];
 	}
 
+	return __drm_ioctl(filp, cmd, arg, ioctl);
+}
+EXPORT_SYMBOL(drm_ioctl);
+
+long __drm_ioctl(struct file *filp,
+		 unsigned int cmd, unsigned long arg,
+		 const struct drm_ioctl_desc *ioctl)
+{
+	struct drm_file *file_priv = filp->private_data;
+	drm_ioctl_t *func;
+	unsigned int nr = DRM_IOCTL_NR(cmd);
+	int retcode = -EINVAL;
+	char stack_kdata[128];
+	char *kdata = NULL;
+	unsigned int in_size, out_size, drv_size, ksize;
+
+	if (!ioctl)
+		goto err_i1;
+
 	drv_size = _IOC_SIZE(ioctl->cmd);
 	out_size = in_size = _IOC_SIZE(cmd);
 	if ((cmd & ioctl->cmd & IOC_IN) == 0)
@@ -851,7 +863,7 @@ long drm_ioctl(struct file *filp,
 		DRM_DEBUG("ret = %d\n", retcode);
 	return retcode;
 }
-EXPORT_SYMBOL(drm_ioctl);
+EXPORT_SYMBOL(__drm_ioctl);
 
 /**
  * drm_ioctl_flags - Check for core ioctl and return ioctl permission flags
diff --git a/include/drm/drm_ioctl.h b/include/drm/drm_ioctl.h
index add42809642a..e08f8ea66f2a 100644
--- a/include/drm/drm_ioctl.h
+++ b/include/drm/drm_ioctl.h
@@ -172,6 +172,8 @@ struct drm_ioctl_desc {
 
 int drm_ioctl_permit(u32 flags, struct drm_file *file_priv);
 long drm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
+long __drm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg,
+		 const struct drm_ioctl_desc *ioctl);
 long drm_ioctl_kernel(struct file *, drm_ioctl_t, void *, u32);
 #ifdef CONFIG_COMPAT
 long drm_compat_ioctl(struct file *filp, unsigned int cmd, unsigned long arg);
-- 
2.13.6



More information about the dri-devel mailing list