diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/gpu/drm/drm_drv.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/gpu/drm/drm_drv.c')
-rw-r--r-- | drivers/gpu/drm/drm_drv.c | 96 |
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); | |||
366 | module_exit(drm_core_exit); | 369 | module_exit(drm_core_exit); |
367 | 370 | ||
368 | /** | 371 | /** |
372 | * Copy and IOCTL return string to user space | ||
373 | */ | ||
374 | static 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 | */ |
407 | int drm_ioctl(struct inode *inode, struct file *filp, | 438 | long 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, |