From c14287944497ee3b7ec6401db8413811eba744f0 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Fran=C3=A7ois=20Tigeot?= Date: Sun, 31 May 2015 19:02:10 +0200 Subject: [PATCH] drm: Partially sync drm_ioctl() with Linux 3.14 It now uses the drm_global_mutex lockmgr lock --- sys/dev/drm/drm_drv.c | 54 +++++++++++++++------------------- sys/dev/drm/drm_fops.c | 5 ++++ sys/dev/drm/include/drm/drmP.h | 10 +++++++ 3 files changed, 38 insertions(+), 31 deletions(-) diff --git a/sys/dev/drm/drm_drv.c b/sys/dev/drm/drm_drv.c index 7d18bad9fb..6eb1cd2f90 100644 --- a/sys/dev/drm/drm_drv.c +++ b/sys/dev/drm/drm_drv.c @@ -722,17 +722,19 @@ void drm_cdevpriv_dtor(void *cd) int drm_ioctl(struct dev_ioctl_args *ap) { struct cdev *kdev = ap->a_head.a_dev; + struct drm_device *dev; + struct drm_ioctl_desc *ioctl = NULL; u_long cmd = ap->a_cmd; + unsigned int nr = DRM_IOCTL_NR(cmd); + int retcode = 0; caddr_t data = ap->a_data; struct thread *p = curthread; - struct drm_device *dev = drm_get_device_from_kdev(kdev); - int retcode = 0; - struct drm_ioctl_desc *ioctl; int (*func)(struct drm_device *dev, void *data, struct drm_file *file_priv); - int nr = DRM_IOCTL_NR(cmd); int is_driver_ioctl = 0; struct drm_file *file_priv; + dev = drm_get_device_from_kdev(kdev); + retcode = devfs_get_cdevpriv(ap->a_fp, (void **)&file_priv); if (retcode !=0) { DRM_ERROR("can't find authenticator\n"); @@ -741,22 +743,8 @@ int drm_ioctl(struct dev_ioctl_args *ap) atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]); - DRM_DEBUG_VERBOSE("pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n", - DRM_CURRENTPID, cmd, nr, (long)dev->dev, - file_priv->authenticated); - - switch (cmd) { - case FIONBIO: - case FIOASYNC: - return 0; - - case FIOSETOWN: - return fsetown(*(int *)data, &dev->buf_sigio); - - case FIOGETOWN: - *(int *) data = fgetown(&dev->buf_sigio); - return 0; - } + if (drm_device_is_unplugged(dev)) + return -ENODEV; if (IOCGROUP(cmd) != DRM_IOCTL_BASE) { DRM_DEBUG("Bad ioctl group 0x%x\n", (int)IOCGROUP(cmd)); @@ -774,6 +762,12 @@ int drm_ioctl(struct dev_ioctl_args *ap) ioctl = &dev->driver->ioctls[nr]; is_driver_ioctl = 1; } + + DRM_DEBUG_VERBOSE("pid=%d, cmd=0x%02lx, nr=0x%02x, dev 0x%lx, auth=%d\n", + DRM_CURRENTPID, cmd, nr, (long)dev->dev, + file_priv->authenticated); + + /* Do not trust userspace, use our own definition */ func = ioctl->func; if (func == NULL) { @@ -788,25 +782,23 @@ int drm_ioctl(struct dev_ioctl_args *ap) if (is_driver_ioctl) { if ((ioctl->flags & DRM_UNLOCKED) == 0) - DRM_LOCK(dev); + mutex_lock(&drm_global_mutex); /* shared code returns -errno */ retcode = -func(dev, data, file_priv); if ((ioctl->flags & DRM_UNLOCKED) == 0) - DRM_UNLOCK(dev); + mutex_unlock(&drm_global_mutex); } else { retcode = func(dev, data, file_priv); } - if (retcode != 0) - DRM_DEBUG(" returning %d\n", retcode); - if (retcode != 0 && - (drm_debug & DRM_DEBUGBITS_FAILED_IOCTL) != 0) { - kprintf( -"pid %d, cmd 0x%02lx, nr 0x%02x/%1d, dev 0x%lx, auth %d, res %d\n", - DRM_CURRENTPID, cmd, nr, is_driver_ioctl, (long)dev->dev, - file_priv->authenticated, retcode); - } + if (!ioctl) + DRM_DEBUG("invalid ioctl: pid=%d, dev=0x%lx, auth=%d, cmd=0x%02lx, nr=0x%02x\n", + DRM_CURRENTPID, + (long)dev->dev, + file_priv->authenticated, cmd, nr); + if (retcode) + DRM_DEBUG("ret = %d\n", retcode); return retcode; } diff --git a/sys/dev/drm/drm_fops.c b/sys/dev/drm/drm_fops.c index af67bc8846..0255d90c17 100644 --- a/sys/dev/drm/drm_fops.c +++ b/sys/dev/drm/drm_fops.c @@ -39,6 +39,11 @@ #include #include +#include + +/* from BKL pushdown: note that nothing else serializes idr_find() */ +DEFINE_MUTEX(drm_global_mutex); +EXPORT_SYMBOL(drm_global_mutex); extern drm_pci_id_list_t *drm_find_description(int vendor, int device, drm_pci_id_list_t *idlist); diff --git a/sys/dev/drm/include/drm/drmP.h b/sys/dev/drm/include/drm/drmP.h index 430f722994..d6335da329 100644 --- a/sys/dev/drm/include/drm/drmP.h +++ b/sys/dev/drm/include/drm/drmP.h @@ -1133,6 +1133,8 @@ struct drm_device { int modesetting; int switch_power_state; + + atomic_t unplugged; /* device has been unplugged or gone away */ }; #define DRM_SWITCH_POWER_ON 0 @@ -1145,6 +1147,13 @@ static __inline__ int drm_core_check_feature(struct drm_device *dev, return ((dev->driver->driver_features & feature) ? 1 : 0); } +static inline int drm_device_is_unplugged(struct drm_device *dev) +{ + int ret = atomic_read(&dev->unplugged); + smp_rmb(); + return ret; +} + #if __OS_HAS_AGP static inline int drm_core_has_AGP(struct drm_device *dev) { @@ -1206,6 +1215,7 @@ d_ioctl_t drm_ioctl; extern int drm_lastclose(struct drm_device *dev); /* Device support (drm_fops.h) */ +extern struct lock drm_global_mutex; d_open_t drm_open; d_close_t drm_close; d_read_t drm_read; -- 2.41.0