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@xxxxxxxxxxxx> --- 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 _______________________________________________ dri-devel mailing list dri-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/dri-devel