aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2010-12-22 09:04:47 -0500
committerChris Wilson <chris@chris-wilson.co.uk>2011-01-11 15:35:41 -0500
commit55249baaa5cd188ebd9acdb047eeaed8092e4a93 (patch)
treeec52e1bdb516ce0bd259614b3c068960450b9236 /drivers/gpu/drm
parent35c3047ad15849335242b847c94f180ef45db490 (diff)
drm/i915: Workaround erratum on i830 for TAIL pointer within last 2 cachelines
On i830 if the tail pointer is set to within 2 cachelines of the end of the buffer, the chip may hang. So instead if the tail were to land in that location, we pad the end of the buffer with NOPs, and start again at the beginning. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.c13
-rw-r--r--drivers/gpu/drm/i915/intel_ringbuffer.h1
2 files changed, 11 insertions, 3 deletions
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 56bc95c056dd..2de0e45464c5 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -785,6 +785,14 @@ int intel_init_ring_buffer(struct drm_device *dev,
785 if (ret) 785 if (ret)
786 goto err_unmap; 786 goto err_unmap;
787 787
788 /* Workaround an erratum on the i830 which causes a hang if
789 * the TAIL pointer points to within the last 2 cachelines
790 * of the buffer.
791 */
792 ring->effective_size = ring->size;
793 if (IS_I830(ring->dev))
794 ring->effective_size -= 128;
795
788 return 0; 796 return 0;
789 797
790err_unmap: 798err_unmap:
@@ -827,8 +835,7 @@ void intel_cleanup_ring_buffer(struct intel_ring_buffer *ring)
827static int intel_wrap_ring_buffer(struct intel_ring_buffer *ring) 835static int intel_wrap_ring_buffer(struct intel_ring_buffer *ring)
828{ 836{
829 unsigned int *virt; 837 unsigned int *virt;
830 int rem; 838 int rem = ring->size - ring->tail;
831 rem = ring->size - ring->tail;
832 839
833 if (ring->space < rem) { 840 if (ring->space < rem) {
834 int ret = intel_wait_ring_buffer(ring, rem); 841 int ret = intel_wait_ring_buffer(ring, rem);
@@ -895,7 +902,7 @@ int intel_ring_begin(struct intel_ring_buffer *ring,
895 int n = 4*num_dwords; 902 int n = 4*num_dwords;
896 int ret; 903 int ret;
897 904
898 if (unlikely(ring->tail + n > ring->size)) { 905 if (unlikely(ring->tail + n > ring->effective_size)) {
899 ret = intel_wrap_ring_buffer(ring); 906 ret = intel_wrap_ring_buffer(ring);
900 if (unlikely(ret)) 907 if (unlikely(ret))
901 return ret; 908 return ret;
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.h b/drivers/gpu/drm/i915/intel_ringbuffer.h
index 8e2e357ad6ee..bbbf505c8b56 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.h
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.h
@@ -49,6 +49,7 @@ struct intel_ring_buffer {
49 u32 tail; 49 u32 tail;
50 int space; 50 int space;
51 int size; 51 int size;
52 int effective_size;
52 struct intel_hw_status_page status_page; 53 struct intel_hw_status_page status_page;
53 54
54 u32 irq_seqno; /* last seq seem at irq time */ 55 u32 irq_seqno; /* last seq seem at irq time */