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