aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c34
1 files changed, 22 insertions, 12 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 33ab07b0d712..6f7d0e27036f 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -141,15 +141,18 @@ fast_shmem_read(struct page **pages,
141 int length) 141 int length)
142{ 142{
143 char __iomem *vaddr; 143 char __iomem *vaddr;
144 int ret; 144 int unwritten;
145 145
146 vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT], KM_USER0); 146 vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT], KM_USER0);
147 if (vaddr == NULL) 147 if (vaddr == NULL)
148 return -ENOMEM; 148 return -ENOMEM;
149 ret = __copy_to_user_inatomic(data, vaddr + page_offset, length); 149 unwritten = __copy_to_user_inatomic(data, vaddr + page_offset, length);
150 kunmap_atomic(vaddr, KM_USER0); 150 kunmap_atomic(vaddr, KM_USER0);
151 151
152 return ret; 152 if (unwritten)
153 return -EFAULT;
154
155 return 0;
153} 156}
154 157
155static inline int 158static inline int
@@ -3000,13 +3003,13 @@ i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object *exec_list,
3000 drm_free(*relocs, reloc_count * sizeof(**relocs), 3003 drm_free(*relocs, reloc_count * sizeof(**relocs),
3001 DRM_MEM_DRIVER); 3004 DRM_MEM_DRIVER);
3002 *relocs = NULL; 3005 *relocs = NULL;
3003 return ret; 3006 return -EFAULT;
3004 } 3007 }
3005 3008
3006 reloc_index += exec_list[i].relocation_count; 3009 reloc_index += exec_list[i].relocation_count;
3007 } 3010 }
3008 3011
3009 return ret; 3012 return 0;
3010} 3013}
3011 3014
3012static int 3015static int
@@ -3015,23 +3018,28 @@ i915_gem_put_relocs_to_user(struct drm_i915_gem_exec_object *exec_list,
3015 struct drm_i915_gem_relocation_entry *relocs) 3018 struct drm_i915_gem_relocation_entry *relocs)
3016{ 3019{
3017 uint32_t reloc_count = 0, i; 3020 uint32_t reloc_count = 0, i;
3018 int ret; 3021 int ret = 0;
3019 3022
3020 for (i = 0; i < buffer_count; i++) { 3023 for (i = 0; i < buffer_count; i++) {
3021 struct drm_i915_gem_relocation_entry __user *user_relocs; 3024 struct drm_i915_gem_relocation_entry __user *user_relocs;
3025 int unwritten;
3022 3026
3023 user_relocs = (void __user *)(uintptr_t)exec_list[i].relocs_ptr; 3027 user_relocs = (void __user *)(uintptr_t)exec_list[i].relocs_ptr;
3024 3028
3025 if (ret == 0) { 3029 unwritten = copy_to_user(user_relocs,
3026 ret = copy_to_user(user_relocs, 3030 &relocs[reloc_count],
3027 &relocs[reloc_count], 3031 exec_list[i].relocation_count *
3028 exec_list[i].relocation_count * 3032 sizeof(*relocs));
3029 sizeof(*relocs)); 3033
3034 if (unwritten) {
3035 ret = -EFAULT;
3036 goto err;
3030 } 3037 }
3031 3038
3032 reloc_count += exec_list[i].relocation_count; 3039 reloc_count += exec_list[i].relocation_count;
3033 } 3040 }
3034 3041
3042err:
3035 drm_free(relocs, reloc_count * sizeof(*relocs), DRM_MEM_DRIVER); 3043 drm_free(relocs, reloc_count * sizeof(*relocs), DRM_MEM_DRIVER);
3036 3044
3037 return ret; 3045 return ret;
@@ -3306,10 +3314,12 @@ err:
3306 (uintptr_t) args->buffers_ptr, 3314 (uintptr_t) args->buffers_ptr,
3307 exec_list, 3315 exec_list,
3308 sizeof(*exec_list) * args->buffer_count); 3316 sizeof(*exec_list) * args->buffer_count);
3309 if (ret) 3317 if (ret) {
3318 ret = -EFAULT;
3310 DRM_ERROR("failed to copy %d exec entries " 3319 DRM_ERROR("failed to copy %d exec entries "
3311 "back to user (%d)\n", 3320 "back to user (%d)\n",
3312 args->buffer_count, ret); 3321 args->buffer_count, ret);
3322 }
3313 } 3323 }
3314 3324
3315 /* Copy the updated relocations out regardless of current error 3325 /* Copy the updated relocations out regardless of current error