]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - drivers/gpu/drm/drm_ioctl.c
Merge remote-tracking branch 'drm-misc/topic/drm-misc'
[karo-tx-linux.git] / drivers / gpu / drm / drm_ioctl.c
index d93e7378c0779dd54be72447421aa49cc12c3f4f..8ce2a0c591165018c49392e7ad2b828a1fb3b94b 100644 (file)
@@ -40,7 +40,7 @@
 static int drm_version(struct drm_device *dev, void *data,
                       struct drm_file *file_priv);
 
-/**
+/*
  * Get the bus id.
  *
  * \param inode device inode.
@@ -75,7 +75,7 @@ drm_unset_busid(struct drm_device *dev,
        master->unique_len = 0;
 }
 
-/**
+/*
  * Set the bus id.
  *
  * \param inode device inode.
@@ -149,7 +149,7 @@ static int drm_set_busid(struct drm_device *dev, struct drm_file *file_priv)
        return 0;
 }
 
-/**
+/*
  * Get a mapping information.
  *
  * \param inode device inode.
@@ -201,7 +201,7 @@ static int drm_getmap(struct drm_device *dev, void *data,
        return 0;
 }
 
-/**
+/*
  * Get client information.
  *
  * \param inode device inode.
@@ -244,7 +244,7 @@ static int drm_getclient(struct drm_device *dev, void *data,
        }
 }
 
-/**
+/*
  * Get statistics information.
  *
  * \param inode device inode.
@@ -265,7 +265,7 @@ static int drm_getstats(struct drm_device *dev, void *data,
        return 0;
 }
 
-/**
+/*
  * Get device/driver capabilities
  */
 static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
@@ -318,7 +318,7 @@ static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_
        return 0;
 }
 
-/**
+/*
  * Set device/driver capabilities
  */
 static int
@@ -352,7 +352,7 @@ drm_setclientcap(struct drm_device *dev, void *data, struct drm_file *file_priv)
        return 0;
 }
 
-/**
+/*
  * Setversion ioctl.
  *
  * \param inode device inode.
@@ -406,7 +406,18 @@ done:
        return retcode;
 }
 
-/** No-op ioctl. */
+/**
+ * drm_noop - DRM no-op ioctl implemntation
+ * @dev: DRM device for the ioctl
+ * @data: data pointer for the ioctl
+ * @file_priv: DRM file for the ioctl call
+ *
+ * This no-op implementation for drm ioctls is useful for deprecated
+ * functionality where we can't return a failure code because existing userspace
+ * checks the result of the ioctl, but doesn't care about the action.
+ *
+ * Always returns successfully with 0.
+ */
 int drm_noop(struct drm_device *dev, void *data,
             struct drm_file *file_priv)
 {
@@ -416,6 +427,28 @@ int drm_noop(struct drm_device *dev, void *data,
 EXPORT_SYMBOL(drm_noop);
 
 /**
+ * drm_invalid_op - DRM invalid ioctl implemntation
+ * @dev: DRM device for the ioctl
+ * @data: data pointer for the ioctl
+ * @file_priv: DRM file for the ioctl call
+ *
+ * This no-op implementation for drm ioctls is useful for deprecated
+ * functionality where we really don't want to allow userspace to call the ioctl
+ * any more. This is the case for old ums interfaces for drivers that
+ * transitioned to kms gradually and so kept the old legacy tables around. This
+ * only applies to radeon and i915 kms drivers, other drivers shouldn't need to
+ * use this function.
+ *
+ * Always fails with a return value of -EINVAL.
+ */
+int drm_invalid_op(struct drm_device *dev, void *data,
+                  struct drm_file *file_priv)
+{
+       return -EINVAL;
+}
+EXPORT_SYMBOL(drm_invalid_op);
+
+/*
  * Copy and IOCTL return string to user space
  */
 static int drm_copy_field(char __user *buf, size_t *buf_len, const char *value)
@@ -438,7 +471,7 @@ static int drm_copy_field(char __user *buf, size_t *buf_len, const char *value)
        return 0;
 }
 
-/**
+/*
  * Get version information
  *
  * \param inode device inode.
@@ -470,7 +503,7 @@ static int drm_version(struct drm_device *dev, void *data,
        return err;
 }
 
-/**
+/*
  * drm_ioctl_permit - Check ioctl permissions against caller
  *
  * @flags: ioctl permission flags.
@@ -518,7 +551,7 @@ EXPORT_SYMBOL(drm_ioctl_permit);
                .name = #ioctl                  \
        }
 
-/** Ioctl table */
+/* Ioctl table */
 static const struct drm_ioctl_desc drm_ioctls[] = {
        DRM_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version,
                      DRM_UNLOCKED|DRM_RENDER_ALLOW|DRM_CONTROL_ALLOW),
@@ -571,7 +604,7 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
 
        DRM_IOCTL_DEF(DRM_IOCTL_CONTROL, drm_control, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
 
-#if __OS_HAS_AGP
+#if IS_ENABLED(CONFIG_AGP)
        DRM_IOCTL_DEF(DRM_IOCTL_AGP_ACQUIRE, drm_agp_acquire_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF(DRM_IOCTL_AGP_RELEASE, drm_agp_release_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
        DRM_IOCTL_DEF(DRM_IOCTL_AGP_ENABLE, drm_agp_enable_ioctl, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
@@ -635,16 +668,16 @@ static const struct drm_ioctl_desc drm_ioctls[] = {
 #define DRM_CORE_IOCTL_COUNT   ARRAY_SIZE( drm_ioctls )
 
 /**
- * Called whenever a process performs an ioctl on /dev/drm.
- *
- * \param inode device inode.
- * \param file_priv DRM file private.
- * \param cmd command.
- * \param arg user argument.
- * \return zero on success or negative number on failure.
+ * drm_ioctl - ioctl callback implementation for DRM drivers
+ * @filp: file this ioctl is called on
+ * @cmd: ioctl cmd number
+ * @arg: user argument
  *
  * Looks up the ioctl function in the ::ioctls table, checking for root
  * previleges if so required, and dispatches to the respective function.
+ *
+ * Returns:
+ * Zero on success, negative error code on failure.
  */
 long drm_ioctl(struct file *filp,
              unsigned int cmd, unsigned long arg)
@@ -658,13 +691,16 @@ long drm_ioctl(struct file *filp,
        char stack_kdata[128];
        char *kdata = NULL;
        unsigned int usize, asize, drv_size;
+       bool is_driver_ioctl;
 
        dev = file_priv->minor->dev;
 
        if (drm_device_is_unplugged(dev))
                return -ENODEV;
 
-       if (nr >= DRM_COMMAND_BASE && nr < DRM_COMMAND_END) {
+       is_driver_ioctl = nr >= DRM_COMMAND_BASE && nr < DRM_COMMAND_END;
+
+       if (is_driver_ioctl) {
                /* driver ioctl */
                if (nr - DRM_COMMAND_BASE >= dev->driver->num_ioctls)
                        goto err_i1;
@@ -723,7 +759,10 @@ long drm_ioctl(struct file *filp,
                memset(kdata, 0, usize);
        }
 
-       if (ioctl->flags & DRM_UNLOCKED)
+       /* Enforce sane locking for kms driver ioctls. Core ioctls are
+        * too messy still. */
+       if ((drm_core_check_feature(dev, DRIVER_MODESET) && is_driver_ioctl) ||
+           (ioctl->flags & DRM_UNLOCKED))
                retcode = func(dev, kdata, file_priv);
        else {
                mutex_lock(&drm_global_mutex);
@@ -754,9 +793,15 @@ EXPORT_SYMBOL(drm_ioctl);
 
 /**
  * drm_ioctl_flags - Check for core ioctl and return ioctl permission flags
+ * @nr: ioctl number
+ * @flags: where to return the ioctl permission flags
+ *
+ * This ioctl is only used by the vmwgfx driver to augment the access checks
+ * done by the drm core and insofar a pretty decent layering violation. This
+ * shouldn't be used by any drivers.
  *
- * @nr: Ioctl number.
- * @flags: Where to return the ioctl permission flags
+ * Returns:
+ * True if the @nr corresponds to a DRM core ioctl numer, false otherwise.
  */
 bool drm_ioctl_flags(unsigned int nr, unsigned int *flags)
 {