Skip to content

Commit

Permalink
drm/i915: Batch copy_from_user for relocation processing
Browse files Browse the repository at this point in the history
Originally the code tried to allocate a large enough array to perform
the copy using vmalloc, performance wasn't great and throughput was
improved by processing each individual relocation entry separately.
This too is not as efficient as one would desire. A compromise would be
to allocate a single page, or to allocate a few entries on the stack,
and process the copy in batches. The latter gives simpler code and more
consistent performance due to a lack of heuristic.

x11perf -copywinwin10:	n450/pnv	i3-330m		i5-2520m (cpu)
               before: 	  249000	 785000		 1280000 (80%)
                 page:	  264000	 896000		 1280000 (65%)
             on-stack:	  264000	 902000		 1280000 (67%)

v2: Use 512-bytes of stack for batching rather than allocate a page.
v3: Tidy the code slightly with more descriptive variable names

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Reviewed-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
  • Loading branch information
Chris Wilson authored and Daniel Vetter committed Mar 26, 2012
1 parent 0fb3f96 commit 1d83f44
Showing 1 changed file with 29 additions and 13 deletions.
42 changes: 29 additions & 13 deletions drivers/gpu/drm/i915/i915_gem_execbuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -405,30 +405,46 @@ static int
i915_gem_execbuffer_relocate_object(struct drm_i915_gem_object *obj,
struct eb_objects *eb)
{
#define N_RELOC(x) ((x) / sizeof(struct drm_i915_gem_relocation_entry))
struct drm_i915_gem_relocation_entry stack_reloc[N_RELOC(512)];
struct drm_i915_gem_relocation_entry __user *user_relocs;
struct drm_i915_gem_exec_object2 *entry = obj->exec_entry;
int i, ret;
int remain, ret;

user_relocs = (void __user *)(uintptr_t)entry->relocs_ptr;
for (i = 0; i < entry->relocation_count; i++) {
struct drm_i915_gem_relocation_entry reloc;

if (__copy_from_user_inatomic(&reloc,
user_relocs+i,
sizeof(reloc)))
remain = entry->relocation_count;
while (remain) {
struct drm_i915_gem_relocation_entry *r = stack_reloc;
int count = remain;
if (count > ARRAY_SIZE(stack_reloc))
count = ARRAY_SIZE(stack_reloc);
remain -= count;

if (__copy_from_user_inatomic(r, user_relocs, count*sizeof(r[0])))
return -EFAULT;

ret = i915_gem_execbuffer_relocate_entry(obj, eb, &reloc);
if (ret)
return ret;
do {
u64 offset = r->presumed_offset;

if (__copy_to_user_inatomic(&user_relocs[i].presumed_offset,
&reloc.presumed_offset,
sizeof(reloc.presumed_offset)))
return -EFAULT;
ret = i915_gem_execbuffer_relocate_entry(obj, eb, r);
if (ret)
return ret;

if (r->presumed_offset != offset &&
__copy_to_user_inatomic(&user_relocs->presumed_offset,
&r->presumed_offset,
sizeof(r->presumed_offset))) {
return -EFAULT;
}

user_relocs++;
r++;
} while (--count);
}

return 0;
#undef N_RELOC
}

static int
Expand Down

0 comments on commit 1d83f44

Please sign in to comment.