aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2011-01-12 18:49:13 -0500
committerChris Wilson <chris@chris-wilson.co.uk>2011-01-13 11:06:05 -0500
commitdd6864a4edb9b2d0055a7f30e17cbc521098b1be (patch)
tree5c3b41913378fe69c506f54f9ac3ee45a1809f6c /drivers/gpu/drm
parentc37d9a5de94a6fe60a756af350cd21aa9bbbc8a1 (diff)
drm/i915/execbuffer: Reorder relocations to match new object order
On the fault path, commit 6fe4f140 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>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/i915/i915_gem_execbuffer.c15
1 files changed, 9 insertions, 6 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index e69834341ef0..6b34e98a1270 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -636,6 +636,7 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
636{ 636{
637 struct drm_i915_gem_relocation_entry *reloc; 637 struct drm_i915_gem_relocation_entry *reloc;
638 struct drm_i915_gem_object *obj; 638 struct drm_i915_gem_object *obj;
639 int *reloc_offset;
639 int i, total, ret; 640 int i, total, ret;
640 641
641 /* We may process another execbuffer during the unlock... */ 642 /* We may process another execbuffer during the unlock... */
@@ -653,8 +654,11 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
653 for (i = 0; i < count; i++) 654 for (i = 0; i < count; i++)
654 total += exec[i].relocation_count; 655 total += exec[i].relocation_count;
655 656
657 reloc_offset = drm_malloc_ab(count, sizeof(*reloc_offset));
656 reloc = drm_malloc_ab(total, sizeof(*reloc)); 658 reloc = drm_malloc_ab(total, sizeof(*reloc));
657 if (reloc == NULL) { 659 if (reloc == NULL || reloc_offset == NULL) {
660 drm_free_large(reloc);
661 drm_free_large(reloc_offset);
658 mutex_lock(&dev->struct_mutex); 662 mutex_lock(&dev->struct_mutex);
659 return -ENOMEM; 663 return -ENOMEM;
660 } 664 }
@@ -672,6 +676,7 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
672 goto err; 676 goto err;
673 } 677 }
674 678
679 reloc_offset[i] = total;
675 total += exec[i].relocation_count; 680 total += exec[i].relocation_count;
676 } 681 }
677 682
@@ -705,17 +710,14 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
705 if (ret) 710 if (ret)
706 goto err; 711 goto err;
707 712
708 total = 0;
709 list_for_each_entry(obj, objects, exec_list) { 713 list_for_each_entry(obj, objects, exec_list) {
714 int offset = obj->exec_entry - exec;
710 obj->base.pending_read_domains = 0; 715 obj->base.pending_read_domains = 0;
711 obj->base.pending_write_domain = 0; 716 obj->base.pending_write_domain = 0;
712 ret = i915_gem_execbuffer_relocate_object_slow(obj, eb, 717 ret = i915_gem_execbuffer_relocate_object_slow(obj, eb,
713 reloc + total); 718 reloc + reloc_offset[offset]);
714 if (ret) 719 if (ret)
715 goto err; 720 goto err;
716
717 total += exec->relocation_count;
718 exec++;
719 } 721 }
720 722
721 /* Leave the user relocations as are, this is the painfully slow path, 723 /* Leave the user relocations as are, this is the painfully slow path,
@@ -726,6 +728,7 @@ i915_gem_execbuffer_relocate_slow(struct drm_device *dev,
726 728
727err: 729err:
728 drm_free_large(reloc); 730 drm_free_large(reloc);
731 drm_free_large(reloc_offset);
729 return ret; 732 return ret;
730} 733}
731 734