aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/drm_fops.c
diff options
context:
space:
mode:
authorArnd Bergmann <arnd@arndb.de>2010-07-10 17:51:39 -0400
committerDave Airlie <airlied@redhat.com>2010-08-04 21:54:40 -0400
commit58374713c9dfb4d231f8c56cac089f6fbdedc2ec (patch)
tree9ba01c3990b5a8625437d13722595f5063f2d915 /drivers/gpu/drm/drm_fops.c
parenta1e09b62592eb57e25f8d076ffa5b7bef18be812 (diff)
drm: kill BKL from common code
This restricts the use of the big kernel lock to the i830 and i810 device drivers. The three remaining users in common code (open, ioctl and release) get converted to a new mutex, the drm_global_mutex, making the locking stricter than the big kernel lock. This may have a performance impact, but only in those cases that currently don't use DRM_UNLOCKED flag in the ioctl list and would benefit from that anyway. The reason why i810 and i830 cannot use drm_global_mutex in their mmap functions is a lock-order inversion problem between the current use of the BKL and mmap_sem in these drivers. Since the BKL has release-on-sleep semantics, it's harmless but it would cause trouble if we replace the BKL with a mutex. Instead, these drivers get their own ioctl wrappers that take the BKL around every ioctl call and then set their own handlers as DRM_UNLOCKED. Signed-off-by: Arnd Bergmann <arnd@arndb.de> Cc: David Airlie <airlied@linux.ie> Cc: dri-devel@lists.freedesktop.org Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/drm_fops.c')
-rw-r--r--drivers/gpu/drm/drm_fops.c23
1 files changed, 11 insertions, 12 deletions
diff --git a/drivers/gpu/drm/drm_fops.c b/drivers/gpu/drm/drm_fops.c
index e7aace20981f..2ca8df8b6102 100644
--- a/drivers/gpu/drm/drm_fops.c
+++ b/drivers/gpu/drm/drm_fops.c
@@ -39,6 +39,9 @@
39#include <linux/slab.h> 39#include <linux/slab.h>
40#include <linux/smp_lock.h> 40#include <linux/smp_lock.h>
41 41
42/* from BKL pushdown: note that nothing else serializes idr_find() */
43DEFINE_MUTEX(drm_global_mutex);
44
42static int drm_open_helper(struct inode *inode, struct file *filp, 45static int drm_open_helper(struct inode *inode, struct file *filp,
43 struct drm_device * dev); 46 struct drm_device * dev);
44 47
@@ -175,8 +178,7 @@ int drm_stub_open(struct inode *inode, struct file *filp)
175 178
176 DRM_DEBUG("\n"); 179 DRM_DEBUG("\n");
177 180
178 /* BKL pushdown: note that nothing else serializes idr_find() */ 181 mutex_lock(&drm_global_mutex);
179 lock_kernel();
180 minor = idr_find(&drm_minors_idr, minor_id); 182 minor = idr_find(&drm_minors_idr, minor_id);
181 if (!minor) 183 if (!minor)
182 goto out; 184 goto out;
@@ -197,7 +199,7 @@ int drm_stub_open(struct inode *inode, struct file *filp)
197 fops_put(old_fops); 199 fops_put(old_fops);
198 200
199out: 201out:
200 unlock_kernel(); 202 mutex_unlock(&drm_global_mutex);
201 return err; 203 return err;
202} 204}
203 205
@@ -472,7 +474,7 @@ int drm_release(struct inode *inode, struct file *filp)
472 struct drm_device *dev = file_priv->minor->dev; 474 struct drm_device *dev = file_priv->minor->dev;
473 int retcode = 0; 475 int retcode = 0;
474 476
475 lock_kernel(); 477 mutex_lock(&drm_global_mutex);
476 478
477 DRM_DEBUG("open_count = %d\n", dev->open_count); 479 DRM_DEBUG("open_count = %d\n", dev->open_count);
478 480
@@ -573,17 +575,14 @@ int drm_release(struct inode *inode, struct file *filp)
573 if (atomic_read(&dev->ioctl_count)) { 575 if (atomic_read(&dev->ioctl_count)) {
574 DRM_ERROR("Device busy: %d\n", 576 DRM_ERROR("Device busy: %d\n",
575 atomic_read(&dev->ioctl_count)); 577 atomic_read(&dev->ioctl_count));
576 spin_unlock(&dev->count_lock); 578 retcode = -EBUSY;
577 unlock_kernel(); 579 goto out;
578 return -EBUSY;
579 } 580 }
580 spin_unlock(&dev->count_lock); 581 retcode = drm_lastclose(dev);
581 unlock_kernel();
582 return drm_lastclose(dev);
583 } 582 }
583out:
584 spin_unlock(&dev->count_lock); 584 spin_unlock(&dev->count_lock);
585 585 mutex_unlock(&drm_global_mutex);
586 unlock_kernel();
587 586
588 return retcode; 587 return retcode;
589} 588}