[Intel-gfx] [PATCH] drm/i915: blitter ring workaround for gen6

Ben Widawsky ben at bwidawsk.net
Mon Oct 3 03:27:12 CEST 2011


Found this through doc inspection. I don't have a failing test case that this
fixes, but the docs specify we need to do it in addition to the A0 workaround.

Signed-off-by: Ben Widawsky <ben at bwidawsk.net>
---
 drivers/gpu/drm/i915/intel_ringbuffer.c |   58 +++++++++++++++++++++++++++++--
 1 files changed, 55 insertions(+), 3 deletions(-)

diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index 0e99589..163f734 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -1233,13 +1233,18 @@ blt_ring_put_irq(struct intel_ring_buffer *ring)
 }
 
 
+/* SNB C0 and D0 need ever more workarounds */
+#define NEED_MORE_BLT_WORKAROUND(dev) \
+	(dev->pdev->revision == 9 || dev->pdev->revision == 10)
+
 /* Workaround for some stepping of SNB,
  * each time when BLT engine ring tail moved,
  * the first command in the ring to be parsed
  * should be MI_BATCH_BUFFER_START
  */
 #define NEED_BLT_WORKAROUND(dev) \
-	(IS_GEN6(dev) && (dev->pdev->revision < 8))
+	((IS_GEN6(dev) && (dev->pdev->revision < 8)) || \
+	(IS_GEN6(dev) && NEED_MORE_BLT_WORKAROUND(dev)))
 
 static inline struct drm_i915_gem_object *
 to_blt_workaround(struct intel_ring_buffer *ring)
@@ -1286,10 +1291,20 @@ static int blt_ring_begin(struct intel_ring_buffer *ring,
 			  int num_dwords)
 {
 	if (ring->private) {
-		int ret = intel_ring_begin(ring, num_dwords+2);
+		int ret;
+		if (NEED_MORE_BLT_WORKAROUND(ring->dev))
+			num_dwords += 46;
+		else
+			num_dwords += 2;
+		ret = intel_ring_begin(ring, num_dwords);
 		if (ret)
 			return ret;
 
+		if (NEED_MORE_BLT_WORKAROUND(ring->dev)) {
+			int i = 0;
+			for (i = 0; i < 32; i++)
+				intel_ring_emit(ring, MI_NOOP);
+		}
 		intel_ring_emit(ring, MI_BATCH_BUFFER_START);
 		intel_ring_emit(ring, to_blt_workaround(ring)->gtt_offset);
 
@@ -1298,6 +1313,25 @@ static int blt_ring_begin(struct intel_ring_buffer *ring,
 		return intel_ring_begin(ring, 4);
 }
 
+static void blt_ring_begin2(struct intel_ring_buffer *ring)
+{
+	if (!ring->private)
+		return;
+
+	intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
+	intel_ring_emit(ring, 0x2209c);
+	intel_ring_emit(ring, 0x20002);
+	intel_ring_emit(ring, MI_FLUSH_DW);
+	intel_ring_emit(ring, 0x2209c);
+	intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
+	intel_ring_emit(ring, 0x2209c);
+	intel_ring_emit(ring, 0x20000);
+	intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
+	intel_ring_emit(ring, 0x2209c);
+	intel_ring_emit(ring, 0x20000);
+	intel_ring_emit(ring, MI_NOOP);
+}
+
 static int blt_ring_flush(struct intel_ring_buffer *ring,
 			  u32 invalidate, u32 flush)
 {
@@ -1315,10 +1349,28 @@ static int blt_ring_flush(struct intel_ring_buffer *ring,
 	intel_ring_emit(ring, 0);
 	intel_ring_emit(ring, 0);
 	intel_ring_emit(ring, MI_NOOP);
+	blt_ring_begin2(ring);
 	intel_ring_advance(ring);
 	return 0;
 }
 
+static int
+blt_ring_dispatch_execbuffer(struct intel_ring_buffer *ring,
+			      u32 offset, u32 len)
+{
+	int ret;
+
+	ret = blt_ring_begin(ring, 4);
+	if (ret)
+		return ret;
+	intel_ring_emit(ring, MI_BATCH_BUFFER_START | MI_BATCH_NON_SECURE_I965);
+	/* bit0-7 is the length on GEN6+ */
+	intel_ring_emit(ring, offset);
+	blt_ring_begin2(ring);
+	intel_ring_advance(ring);
+
+	return 0;
+}
 static void blt_ring_cleanup(struct intel_ring_buffer *ring)
 {
 	if (!ring->private)
@@ -1341,7 +1393,7 @@ static const struct intel_ring_buffer gen6_blt_ring = {
 	.get_seqno		= ring_get_seqno,
 	.irq_get		= blt_ring_get_irq,
 	.irq_put		= blt_ring_put_irq,
-	.dispatch_execbuffer	= gen6_ring_dispatch_execbuffer,
+	.dispatch_execbuffer	= blt_ring_dispatch_execbuffer,
 	.cleanup		= blt_ring_cleanup,
 	.sync_to		= gen6_blt_ring_sync_to,
 	.semaphore_register	= {MI_SEMAPHORE_SYNC_BR,
-- 
1.7.6.4




More information about the Intel-gfx mailing list