[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:40:46 UTC 2017
On Sun, Dec 31, 2017 at 1:15 PM, Ilia Mirkin <imirkin at alum.mit.edu> wrote:
> 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.
Ugh, of course this is turning into a disaster as well.
drm_mode_addfb2 isn't exported, so I have to copy all the
functionality into nouveau, or move it to drm_kms_helper or whatever.
The flag in drm_device approach is sounding a lot more palatable. Let
me know what the best way to proceed is.
This is all to fix a regression, btw, since previous to nouveau
becoming atomic this all worked fine -- it just looked at the
30bpp'ness of the fb and assumed. Now it actually cares about specific
formats, and we run into all these problems.
>
> 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