Commit 2bc43b5c authored by Florian Mickler's avatar Florian Mickler Committed by Eric Anholt

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: default avatarFlorian Mickler <florian@mickler.org>
[anholt: cleanups of unnecessary changes, consistency in APIs]
Signed-off-by: default avatarEric Anholt <eric@anholt.net>
parent 5b40f871
...@@ -141,15 +141,18 @@ fast_shmem_read(struct page **pages, ...@@ -141,15 +141,18 @@ fast_shmem_read(struct page **pages,
int length) int length)
{ {
char __iomem *vaddr; char __iomem *vaddr;
int ret; int unwritten;
vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT], KM_USER0); vaddr = kmap_atomic(pages[page_base >> PAGE_SHIFT], KM_USER0);
if (vaddr == NULL) if (vaddr == NULL)
return -ENOMEM; return -ENOMEM;
ret = __copy_to_user_inatomic(data, vaddr + page_offset, length); unwritten = __copy_to_user_inatomic(data, vaddr + page_offset, length);
kunmap_atomic(vaddr, KM_USER0); kunmap_atomic(vaddr, KM_USER0);
return ret; if (unwritten)
return -EFAULT;
return 0;
} }
static inline int static inline int
...@@ -3000,13 +3003,13 @@ i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object *exec_list, ...@@ -3000,13 +3003,13 @@ i915_gem_get_relocs_from_user(struct drm_i915_gem_exec_object *exec_list,
drm_free(*relocs, reloc_count * sizeof(**relocs), drm_free(*relocs, reloc_count * sizeof(**relocs),
DRM_MEM_DRIVER); DRM_MEM_DRIVER);
*relocs = NULL; *relocs = NULL;
return ret; return -EFAULT;
} }
reloc_index += exec_list[i].relocation_count; reloc_index += exec_list[i].relocation_count;
} }
return ret; return 0;
} }
static int static int
...@@ -3015,23 +3018,28 @@ i915_gem_put_relocs_to_user(struct drm_i915_gem_exec_object *exec_list, ...@@ -3015,23 +3018,28 @@ i915_gem_put_relocs_to_user(struct drm_i915_gem_exec_object *exec_list,
struct drm_i915_gem_relocation_entry *relocs) struct drm_i915_gem_relocation_entry *relocs)
{ {
uint32_t reloc_count = 0, i; uint32_t reloc_count = 0, i;
int ret; int ret = 0;
for (i = 0; i < buffer_count; i++) { for (i = 0; i < buffer_count; i++) {
struct drm_i915_gem_relocation_entry __user *user_relocs; struct drm_i915_gem_relocation_entry __user *user_relocs;
int unwritten;
user_relocs = (void __user *)(uintptr_t)exec_list[i].relocs_ptr; user_relocs = (void __user *)(uintptr_t)exec_list[i].relocs_ptr;
if (ret == 0) { unwritten = copy_to_user(user_relocs,
ret = copy_to_user(user_relocs, &relocs[reloc_count],
&relocs[reloc_count], exec_list[i].relocation_count *
exec_list[i].relocation_count * sizeof(*relocs));
sizeof(*relocs));
if (unwritten) {
ret = -EFAULT;
goto err;
} }
reloc_count += exec_list[i].relocation_count; reloc_count += exec_list[i].relocation_count;
} }
err:
drm_free(relocs, reloc_count * sizeof(*relocs), DRM_MEM_DRIVER); drm_free(relocs, reloc_count * sizeof(*relocs), DRM_MEM_DRIVER);
return ret; return ret;
...@@ -3306,10 +3314,12 @@ err: ...@@ -3306,10 +3314,12 @@ err:
(uintptr_t) args->buffers_ptr, (uintptr_t) args->buffers_ptr,
exec_list, exec_list,
sizeof(*exec_list) * args->buffer_count); sizeof(*exec_list) * args->buffer_count);
if (ret) if (ret) {
ret = -EFAULT;
DRM_ERROR("failed to copy %d exec entries " DRM_ERROR("failed to copy %d exec entries "
"back to user (%d)\n", "back to user (%d)\n",
args->buffer_count, ret); args->buffer_count, ret);
}
} }
/* Copy the updated relocations out regardless of current error /* Copy the updated relocations out regardless of current error
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment