Skip to content

Commit

Permalink
drm/i915/execbuffer: Reorder relocations to match new object order
Browse files Browse the repository at this point in the history
On the fault path, commit 6fe4f14 introduction a regression whereby it
changed the sequence of the objects but continued to use the original
ordering of relocation entries. The result was that incorrect GTT offsets
were being fed into the execbuffer causing lots of misrendering and
potential hangs.

Reported-by: Linus Torvalds <torvalds@linux-foundation.org>
Tested-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
  • Loading branch information
Chris Wilson committed Jan 13, 2011
1 parent c37d9a5 commit dd6864a
Showing 1 changed file with 9 additions and 6 deletions.
15 changes: 9 additions & 6 deletions drivers/gpu/drm/i915/i915_gem_execbuffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -636,6 +636,7 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
{
struct drm_i915_gem_relocation_entry *reloc;
struct drm_i915_gem_object *obj;
int *reloc_offset;
int i, total, ret;

/* We may process another execbuffer during the unlock... */
Expand All @@ -653,8 +654,11 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
for (i = 0; i < count; i++)
total += exec[i].relocation_count;

reloc_offset = drm_malloc_ab(count, sizeof(*reloc_offset));
reloc = drm_malloc_ab(total, sizeof(*reloc));
if (reloc == NULL) {
if (reloc == NULL || reloc_offset == NULL) {
drm_free_large(reloc);
drm_free_large(reloc_offset);
mutex_lock(&dev->struct_mutex);
return -ENOMEM;
}
Expand All @@ -672,6 +676,7 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
goto err;
}

reloc_offset[i] = total;
total += exec[i].relocation_count;
}

Expand Down Expand Up @@ -705,17 +710,14 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
if (ret)
goto err;

total = 0;
list_for_each_entry(obj, objects, exec_list) {
int offset = obj->exec_entry - exec;
obj->base.pending_read_domains = 0;
obj->base.pending_write_domain = 0;
ret = i915_gem_execbuffer_relocate_object_slow(obj, eb,
reloc + total);
reloc + reloc_offset[offset]);
if (ret)
goto err;

total += exec->relocation_count;
exec++;
}

/* Leave the user relocations as are, this is the painfully slow path,
Expand All @@ -726,6 +728,7 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,

err:
drm_free_large(reloc);
drm_free_large(reloc_offset);
return ret;
}

Expand Down

0 comments on commit dd6864a

Please sign in to comment.