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.c55
1 files changed, 46 insertions, 9 deletions
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index a75ca63deea6..766c46875a20 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -145,6 +145,8 @@ static struct drm_ioctl_desc drm_ioctls[] = {
145 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW), 145 DRM_IOCTL_DEF(DRM_IOCTL_MODE_GETFB, drm_mode_getfb, DRM_MASTER|DRM_CONTROL_ALLOW),
146 DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW), 146 DRM_IOCTL_DEF(DRM_IOCTL_MODE_ADDFB, drm_mode_addfb, DRM_MASTER|DRM_CONTROL_ALLOW),
147 DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW), 147 DRM_IOCTL_DEF(DRM_IOCTL_MODE_RMFB, drm_mode_rmfb, DRM_MASTER|DRM_CONTROL_ALLOW),
148 DRM_IOCTL_DEF(DRM_IOCTL_MODE_PAGE_FLIP, drm_mode_page_flip_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW),
149 DRM_IOCTL_DEF(DRM_IOCTL_MODE_DIRTYFB, drm_mode_dirtyfb_ioctl, DRM_MASTER|DRM_CONTROL_ALLOW)
148}; 150};
149 151
150#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls ) 152#define DRM_CORE_IOCTL_COUNT ARRAY_SIZE( drm_ioctls )
@@ -366,6 +368,29 @@ module_init(drm_core_init);
366module_exit(drm_core_exit); 368module_exit(drm_core_exit);
367 369
368/** 370/**
371 * Copy and IOCTL return string to user space
372 */
373static int drm_copy_field(char *buf, size_t *buf_len, const char *value)
374{
375 int len;
376
377 /* don't overflow userbuf */
378 len = strlen(value);
379 if (len > *buf_len)
380 len = *buf_len;
381
382 /* let userspace know exact length of driver value (which could be
383 * larger than the userspace-supplied buffer) */
384 *buf_len = strlen(value);
385
386 /* finally, try filling in the userbuf */
387 if (len && buf)
388 if (copy_to_user(buf, value, len))
389 return -EFAULT;
390 return 0;
391}
392
393/**
369 * Get version information 394 * Get version information
370 * 395 *
371 * \param inode device inode. 396 * \param inode device inode.
@@ -380,16 +405,21 @@ static int drm_version(struct drm_device *dev, void *data,
380 struct drm_file *file_priv) 405 struct drm_file *file_priv)
381{ 406{
382 struct drm_version *version = data; 407 struct drm_version *version = data;
383 int len; 408 int err;
384 409
385 version->version_major = dev->driver->major; 410 version->version_major = dev->driver->major;
386 version->version_minor = dev->driver->minor; 411 version->version_minor = dev->driver->minor;
387 version->version_patchlevel = dev->driver->patchlevel; 412 version->version_patchlevel = dev->driver->patchlevel;
388 DRM_COPY(version->name, dev->driver->name); 413 err = drm_copy_field(version->name, &version->name_len,
389 DRM_COPY(version->date, dev->driver->date); 414 dev->driver->name);
390 DRM_COPY(version->desc, dev->driver->desc); 415 if (!err)
391 416 err = drm_copy_field(version->date, &version->date_len,
392 return 0; 417 dev->driver->date);
418 if (!err)
419 err = drm_copy_field(version->desc, &version->desc_len,
420 dev->driver->desc);
421
422 return err;
393} 423}
394 424
395/** 425/**
@@ -404,11 +434,11 @@ static int drm_version(struct drm_device *dev, void *data,
404 * Looks up the ioctl function in the ::ioctls table, checking for root 434 * Looks up the ioctl function in the ::ioctls table, checking for root
405 * previleges if so required, and dispatches to the respective function. 435 * previleges if so required, and dispatches to the respective function.
406 */ 436 */
407int drm_ioctl(struct inode *inode, struct file *filp, 437long drm_ioctl(struct file *filp,
408 unsigned int cmd, unsigned long arg) 438 unsigned int cmd, unsigned long arg)
409{ 439{
410 struct drm_file *file_priv = filp->private_data; 440 struct drm_file *file_priv = filp->private_data;
411 struct drm_device *dev = file_priv->minor->dev; 441 struct drm_device *dev;
412 struct drm_ioctl_desc *ioctl; 442 struct drm_ioctl_desc *ioctl;
413 drm_ioctl_t *func; 443 drm_ioctl_t *func;
414 unsigned int nr = DRM_IOCTL_NR(cmd); 444 unsigned int nr = DRM_IOCTL_NR(cmd);
@@ -416,6 +446,7 @@ int drm_ioctl(struct inode *inode, struct file *filp,
416 char stack_kdata[128]; 446 char stack_kdata[128];
417 char *kdata = NULL; 447 char *kdata = NULL;
418 448
449 dev = file_priv->minor->dev;
419 atomic_inc(&dev->ioctl_count); 450 atomic_inc(&dev->ioctl_count);
420 atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]); 451 atomic_inc(&dev->counts[_DRM_STAT_IOCTLS]);
421 ++file_priv->ioctl_count; 452 ++file_priv->ioctl_count;
@@ -471,7 +502,13 @@ int drm_ioctl(struct inode *inode, struct file *filp,
471 goto err_i1; 502 goto err_i1;
472 } 503 }
473 } 504 }
474 retcode = func(dev, kdata, file_priv); 505 if (ioctl->flags & DRM_UNLOCKED)
506 retcode = func(dev, kdata, file_priv);
507 else {
508 lock_kernel();
509 retcode = func(dev, kdata, file_priv);
510 unlock_kernel();
511 }
475 512
476 if (cmd & IOC_OUT) { 513 if (cmd & IOC_OUT) {
477 if (copy_to_user((void __user *)arg, kdata, 514 if (copy_to_user((void __user *)arg, kdata,