aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-11-07 20:12:29 -0500
committerChris Wilson <chris@chris-wilson.co.uk>2010-11-08 04:19:11 -0500
commitb47b30ccdaad5f2fc39a1a65921bffd150574a91 (patch)
tree9eaef1721b05daa71010de638e02b2e6b4850598 /drivers/gpu/drm/i915
parent16a02cf08a2de0863daf7ebb91718d7c6bbe7f9c (diff)
drm/i915: Avoid might_fault during pwrite whilst holding our mutex
... and so prevent a potential circular reference: [ INFO: possible circular locking dependency detected ] 2.6.37-rc1-uwe1+ #4 ------------------------------------------------------- Xorg/1401 is trying to acquire lock: (&mm->mmap_sem){++++++}, at: [<c01e4ddb>] might_fault+0x4b/0xa0 but task is already holding lock: (&dev->struct_mutex){+.+.+.}, at: [<f869c3ac>] i915_mutex_lock_interruptible+0x3c/0x60 [i915] which lock already depends on the new lock. When the locking around the pwrite ioctl was simplified, I did not spot that the phys path never took any locks and so we introduced this potential circular reference. Reported-by: Uwe Helm <uwe.helm@googlemail.com> Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'drivers/gpu/drm/i915')
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c25
1 files changed, 16 insertions, 9 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 984eb6e9db03..eba9b1615228 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -4878,17 +4878,24 @@ i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
4878 struct drm_file *file_priv) 4878 struct drm_file *file_priv)
4879{ 4879{
4880 struct drm_i915_gem_object *obj_priv = to_intel_bo(obj); 4880 struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
4881 void *obj_addr; 4881 void *vaddr = obj_priv->phys_obj->handle->vaddr + args->offset;
4882 int ret; 4882 char __user *user_data = (char __user *) (uintptr_t) args->data_ptr;
4883 char __user *user_data;
4884 4883
4885 user_data = (char __user *) (uintptr_t) args->data_ptr; 4884 DRM_DEBUG_DRIVER("vaddr %p, %lld\n", vaddr, args->size);
4886 obj_addr = obj_priv->phys_obj->handle->vaddr + args->offset;
4887 4885
4888 DRM_DEBUG_DRIVER("obj_addr %p, %lld\n", obj_addr, args->size); 4886 if (__copy_from_user_inatomic_nocache(vaddr, user_data, args->size)) {
4889 ret = copy_from_user(obj_addr, user_data, args->size); 4887 unsigned long unwritten;
4890 if (ret) 4888
4891 return -EFAULT; 4889 /* The physical object once assigned is fixed for the lifetime
4890 * of the obj, so we can safely drop the lock and continue
4891 * to access vaddr.
4892 */
4893 mutex_unlock(&dev->struct_mutex);
4894 unwritten = copy_from_user(vaddr, user_data, args->size);
4895 mutex_lock(&dev->struct_mutex);
4896 if (unwritten)
4897 return -EFAULT;
4898 }
4892 4899
4893 drm_agp_chipset_flush(dev); 4900 drm_agp_chipset_flush(dev);
4894 return 0; 4901 return 0;