aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/gpu/drm/vmwgfx/vmwgfx_drv.c94
1 files changed, 89 insertions, 5 deletions
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
index 54cfeb6fc3b1..8fdbe26a98d2 100644
--- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
+++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
@@ -982,12 +982,70 @@ out_no_tfile:
982 return ret; 982 return ret;
983} 983}
984 984
985static long vmw_unlocked_ioctl(struct file *filp, unsigned int cmd, 985static struct vmw_master *vmw_master_check(struct drm_device *dev,
986 unsigned long arg) 986 struct drm_file *file_priv,
987 unsigned int flags)
988{
989 int ret;
990 struct vmw_fpriv *vmw_fp = vmw_fpriv(file_priv);
991 struct vmw_master *vmaster;
992
993 if (file_priv->minor->type != DRM_MINOR_LEGACY ||
994 !(flags & DRM_AUTH))
995 return NULL;
996
997 ret = mutex_lock_interruptible(&dev->master_mutex);
998 if (unlikely(ret != 0))
999 return ERR_PTR(-ERESTARTSYS);
1000
1001 if (file_priv->is_master) {
1002 mutex_unlock(&dev->master_mutex);
1003 return NULL;
1004 }
1005
1006 /*
1007 * Check if we were previously master, but now dropped.
1008 */
1009 if (vmw_fp->locked_master) {
1010 mutex_unlock(&dev->master_mutex);
1011 DRM_ERROR("Dropped master trying to access ioctl that "
1012 "requires authentication.\n");
1013 return ERR_PTR(-EACCES);
1014 }
1015 mutex_unlock(&dev->master_mutex);
1016
1017 /*
1018 * Taking the drm_global_mutex after the TTM lock might deadlock
1019 */
1020 if (!(flags & DRM_UNLOCKED)) {
1021 DRM_ERROR("Refusing locked ioctl access.\n");
1022 return ERR_PTR(-EDEADLK);
1023 }
1024
1025 /*
1026 * Take the TTM lock. Possibly sleep waiting for the authenticating
1027 * master to become master again, or for a SIGTERM if the
1028 * authenticating master exits.
1029 */
1030 vmaster = vmw_master(file_priv->master);
1031 ret = ttm_read_lock(&vmaster->lock, true);
1032 if (unlikely(ret != 0))
1033 vmaster = ERR_PTR(ret);
1034
1035 return vmaster;
1036}
1037
1038static long vmw_generic_ioctl(struct file *filp, unsigned int cmd,
1039 unsigned long arg,
1040 long (*ioctl_func)(struct file *, unsigned int,
1041 unsigned long))
987{ 1042{
988 struct drm_file *file_priv = filp->private_data; 1043 struct drm_file *file_priv = filp->private_data;
989 struct drm_device *dev = file_priv->minor->dev; 1044 struct drm_device *dev = file_priv->minor->dev;
990 unsigned int nr = DRM_IOCTL_NR(cmd); 1045 unsigned int nr = DRM_IOCTL_NR(cmd);
1046 struct vmw_master *vmaster;
1047 unsigned int flags;
1048 long ret;
991 1049
992 /* 1050 /*
993 * Do extra checking on driver private ioctls. 1051 * Do extra checking on driver private ioctls.
@@ -996,18 +1054,44 @@ static long vmw_unlocked_ioctl(struct file *filp, unsigned int cmd,
996 if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END) 1054 if ((nr >= DRM_COMMAND_BASE) && (nr < DRM_COMMAND_END)
997 && (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) { 1055 && (nr < DRM_COMMAND_BASE + dev->driver->num_ioctls)) {
998 const struct drm_ioctl_desc *ioctl = 1056 const struct drm_ioctl_desc *ioctl =
999 &vmw_ioctls[nr - DRM_COMMAND_BASE]; 1057 &vmw_ioctls[nr - DRM_COMMAND_BASE];
1000 1058
1001 if (unlikely(ioctl->cmd_drv != cmd)) { 1059 if (unlikely(ioctl->cmd_drv != cmd)) {
1002 DRM_ERROR("Invalid command format, ioctl %d\n", 1060 DRM_ERROR("Invalid command format, ioctl %d\n",
1003 nr - DRM_COMMAND_BASE); 1061 nr - DRM_COMMAND_BASE);
1004 return -EINVAL; 1062 return -EINVAL;
1005 } 1063 }
1064 flags = ioctl->flags;
1065 } else if (!drm_ioctl_flags(nr, &flags))
1066 return -EINVAL;
1067
1068 vmaster = vmw_master_check(dev, file_priv, flags);
1069 if (unlikely(IS_ERR(vmaster))) {
1070 DRM_INFO("IOCTL ERROR %d\n", nr);
1071 return PTR_ERR(vmaster);
1006 } 1072 }
1007 1073
1008 return drm_ioctl(filp, cmd, arg); 1074 ret = ioctl_func(filp, cmd, arg);
1075 if (vmaster)
1076 ttm_read_unlock(&vmaster->lock);
1077
1078 return ret;
1079}
1080
1081static long vmw_unlocked_ioctl(struct file *filp, unsigned int cmd,
1082 unsigned long arg)
1083{
1084 return vmw_generic_ioctl(filp, cmd, arg, &drm_ioctl);
1009} 1085}
1010 1086
1087#ifdef CONFIG_COMPAT
1088static long vmw_compat_ioctl(struct file *filp, unsigned int cmd,
1089 unsigned long arg)
1090{
1091 return vmw_generic_ioctl(filp, cmd, arg, &drm_compat_ioctl);
1092}
1093#endif
1094
1011static void vmw_lastclose(struct drm_device *dev) 1095static void vmw_lastclose(struct drm_device *dev)
1012{ 1096{
1013 struct drm_crtc *crtc; 1097 struct drm_crtc *crtc;
@@ -1315,7 +1399,7 @@ static const struct file_operations vmwgfx_driver_fops = {
1315 .poll = vmw_fops_poll, 1399 .poll = vmw_fops_poll,
1316 .read = vmw_fops_read, 1400 .read = vmw_fops_read,
1317#if defined(CONFIG_COMPAT) 1401#if defined(CONFIG_COMPAT)
1318 .compat_ioctl = drm_compat_ioctl, 1402 .compat_ioctl = vmw_compat_ioctl,
1319#endif 1403#endif
1320 .llseek = noop_llseek, 1404 .llseek = noop_llseek,
1321}; 1405};