aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_ioctl.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_ioctl.c')
-rw-r--r--drivers/gpu/drm/drm_ioctl.c96
1 files changed, 71 insertions, 25 deletions
diff --git a/drivers/gpu/drm/drm_ioctl.c b/drivers/gpu/drm/drm_ioctl.c
index 9a860ca1e9d7..8ce2a0c59116 100644
--- a/drivers/gpu/drm/drm_ioctl.c
+++ b/drivers/gpu/drm/drm_ioctl.c
@@ -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,9 +551,10 @@ 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_IOCTL_DEF(DRM_IOCTL_VERSION, drm_version,
+ DRM_UNLOCKED|DRM_RENDER_ALLOW|DRM_CONTROL_ALLOW),
DRM_IOCTL_DEF(DRM_IOCTL_GET_UNIQUE, drm_getunique, 0),
DRM_IOCTL_DEF(DRM_IOCTL_GET_MAGIC, drm_getmagic, 0),
DRM_IOCTL_DEF(DRM_IOCTL_IRQ_BUSID, drm_irq_by_busid, DRM_MASTER|DRM_ROOT_ONLY),
@@ -570,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),
@@ -634,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)
@@ -657,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;
@@ -722,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);
@@ -753,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)
{