drm/i915: Fix use of uninitialized var in 40a5f0de

i915_gem_put_relocs_to_user returned an uninitialized value which
got returned to userspace. This caused libdrm in my setup to never
get out of a do{}while() loop retrying i915_gem_execbuffer.

result was hanging X, overheating of cpu and 2-3gb of logfile-spam.

This patch adresses the issue by
1. initializing vars in this file where necessary
2. correcting wrongly interpreted return values of copy_[from/to]_user

Signed-off-by: Florian Mickler <florian@mickler.org>
[anholt: cleanups of unnecessary changes, consistency in APIs]
Signed-off-by: Eric Anholt <eric@anholt.net>

authored by Florian Mickler and committed by Eric Anholt 2bc43b5c 5b40f871

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