diff options
-rw-r--r-- | drivers/gpu/drm/i915/i915_gem.c | 25 |
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; |