aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_drv.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/drm_drv.c')
-rw-r--r--drivers/gpu/drm/drm_drv.c96
1 files changed, 67 insertions, 29 deletions
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index a75ca63deea6..4a66201edaec 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -47,6 +47,7 @@
47 */ 47 */
48 48
49#include <linux/debugfs.h> 49#include <linux/debugfs.h>
50#include <linux/slab.h>
50#include "drmP.h" 51#include "drmP.h"
51#include "drm_core.h" 52#include "drm_core.h"
52 53
@@ -125,26 +126,28 @@ static struct drm_ioctl_desc drm_ioctls[] = {
125 126
126 DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), 127 DRM_IOCTL_DEF(DRM_IOCTL_UPDATE_DRAW, drm_update_drawable_info, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY),
127 128
128 DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, 0), 129 DRM_IOCTL_DEF(DRM_IOCTL_GEM_CLOSE, drm_gem_close_ioctl, DRM_UNLOCKED),
129 DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH), 130 DRM_IOCTL_DEF(DRM_IOCTL_GEM_FLINK, drm_gem_flink_ioctl, DRM_AUTH|DRM_UNLOCKED),
130 DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH), 131 DRM_IOCTL_DEF(DRM_IOCTL_GEM_OPEN, drm_gem_open_ioctl, DRM_AUTH|DRM_UNLOCKED),
131 132
132 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_MASTER|DRM_CONTROL_ALLOW), 133 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETRESOURCES, drm_mode_getresources, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
133 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_MASTER|DRM_CONTROL_ALLOW), 134 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCRTC, drm_mode_getcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
134 DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW), 135 DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETCRTC, drm_mode_setcrtc, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
135 DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW), 136 DRM_IOCTL_DEF(DRM_IOCTL_MODE_CURSOR, drm_mode_cursor_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
136 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_MASTER), 137 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETGAMMA, drm_mode_gamma_get_ioctl, DRM_MASTER|DRM_UNLOCKED),
137 DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER), 138 DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETGAMMA, drm_mode_gamma_set_ioctl, DRM_MASTER|DRM_UNLOCKED),
138 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_MASTER|DRM_CONTROL_ALLOW), 139 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETENCODER, drm_mode_getencoder, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
139 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_MASTER|DRM_CONTROL_ALLOW), 140 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETCONNECTOR, drm_mode_getconnector, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
140 DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_mode_attachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW), 141 DRM_IOCTL_DEF(DRM_IOCTL_MODE_ATTACHMODE, drm_mode_attachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
141 DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_mode_detachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW), 142 DRM_IOCTL_DEF(DRM_IOCTL_MODE_DETACHMODE, drm_mode_detachmode_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
142 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_MASTER | DRM_CONTROL_ALLOW), 143 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPERTY, drm_mode_getproperty_ioctl, DRM_MASTER | DRM_CONTROL_ALLOW|DRM_UNLOCKED),
143 DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW), 144 DRM_IOCTL_DEF(DRM_IOCTL_MODE_SETPROPERTY, drm_mode_connector_property_set_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
144 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW), 145 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETPROPBLOB, drm_mode_getblob_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
145 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW), 146 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
146 DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW), 147 DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
147 DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW), 148 DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
149 DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED),
150 DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW|DRM_UNLOCKED)
148}; 151};
149 152
150#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) 153#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
@@ -366,6 +369,29 @@ module_init(drm_core_init);
366module_exit(drm_core_exit); 369module_exit(drm_core_exit);
367 370
368/** 371/**
372 * Copy and IOCTL return string to user space
373 */
374static int drm_copy_field(char *buf, size_t *buf_len, const char *value)
375{
376 int len;
377
378 /* don't overflow userbuf */
379 len = strlen(value);
380 if (len > *buf_len)
381 len = *buf_len;
382
383 /* let userspace know exact length of driver value (which could be
384 * larger than the userspace-supplied buffer) */
385 *buf_len = strlen(value);
386
387 /* finally, try filling in the userbuf */
388 if (len && buf)
389 if (copy_to_user(buf, value, len))
390 return -EFAULT;
391 return 0;
392}
393
394/**
369 * Get version information 395 * Get version information
370 * 396 *
371 * \param inode device inode. 397 * \param inode device inode.
@@ -380,16 +406,21 @@ static int drm_version(struct drm_device *dev, void *data,
380 struct drm_file *file_priv) 406 struct drm_file *file_priv)
381{ 407{
382 struct drm_version *version = data; 408 struct drm_version *version = data;
383 int len; 409 int err;
384 410
385 version->version_major = dev->driver->major; 411 version->version_major = dev->driver->major;
386 version->version_minor = dev->driver->minor; 412 version->version_minor = dev->driver->minor;
387 version->version_patchlevel = dev->driver->patchlevel; 413 version->version_patchlevel = dev->driver->patchlevel;
388 DRM_COPY(version->name, dev->driver->name); 414 err = drm_copy_field(version->name, &version->name_len,
389 DRM_COPY(version->date, dev->driver->date); 415 dev->driver->name);
390 DRM_COPY(version->desc, dev->driver->desc); 416 if (!err)
391 417 err = drm_copy_field(version->date, &version->date_len,
392 return 0; 418 dev->driver->date);
419 if (!err)
420 err = drm_copy_field(version->desc, &version->desc_len,
421 dev->driver->desc);
422
423 return err;
393} 424}
394 425
395/** 426/**
@@ -404,11 +435,11 @@ static int drm_version(struct drm_device *dev, void *data,
404 * Looks up the ioctl function in the ::ioctls table, checking for root 435 * Looks up the ioctl function in the ::ioctls table, checking for root
405 * previleges if so required, and dispatches to the respective function. 436 * previleges if so required, and dispatches to the respective function.
406 */ 437 */
407int drm_ioctl(struct inode *inode, struct file *filp, 438long drm_ioctl(struct file *filp,
408 unsigned int cmd, unsigned long arg) 439 unsigned int cmd, unsigned long arg)
409{ 440{
410 struct drm_file *file_priv = filp->private_data; 441 struct drm_file *file_priv = filp->private_data;
411 struct drm_device *dev = file_priv->minor->dev; 442 struct drm_device *dev;
412 struct drm_ioctl_desc *ioctl; 443 struct drm_ioctl_desc *ioctl;
413 drm_ioctl_t *func; 444 drm_ioctl_t *func;
414 unsigned int nr = DRM_IOCTL_NR(cmd); 445 unsigned int nr = DRM_IOCTL_NR(cmd);
@@ -416,6 +447,7 @@ int drm_ioctl(struct inode *inode, struct file *filp,
416 char stack_kdata[128]; 447 char stack_kdata[128];
417 char *kdata = NULL; 448 char *kdata = NULL;
418 449
450 dev = file_priv->minor->dev;
419 atomic_inc(&dev->ioctl_count); 451 atomic_inc(&dev->ioctl_count);
420 atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]); 452 atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]);
421 ++file_priv->ioctl_count; 453 ++file_priv->ioctl_count;
@@ -471,7 +503,13 @@ int drm_ioctl(struct inode *inode, struct file *filp,
471 goto err_i1; 503 goto err_i1;
472 } 504 }
473 } 505 }
474 retcode = func(dev, kdata, file_priv); 506 if (ioctl->flags & DRM_UNLOCKED)
507 retcode = func(dev, kdata, file_priv);
508 else {
509 lock_kernel();
510 retcode = func(dev, kdata, file_priv);
511 unlock_kernel();
512 }
475 513
476 if (cmd & IOC_OUT) { 514 if (cmd & IOC_OUT) {
477 if (copy_to_user((void __user *)arg, kdata, 515 if (copy_to_user((void __user *)arg, kdata,