[Intel-gfx] [PATCH 1/2] drm/i915: Fix PIPE_CONTROL command on Sandybridge

Zhenyu Wang zhenyuw at linux.intel.com
Thu May 27 04:26:42 CEST 2010


Sandybridge(Gen6) has new format for PIPE_CONTROL command,
the flush and post-op control are in dword 1 now. This
changes command length field for difference between Ironlake
and Sandybridge.

I tried to test this with noop request and issue PIPE_CONTROL
command for each sequence and track notify interrupts, which
seems work fine. Hopefully we don't need workaround like on
Ironlake for Sandybridge.

Signed-off-by: Zhenyu Wang <zhenyuw at linux.intel.com>
---
 drivers/gpu/drm/i915/i915_gem.c |   77 +++++++++++++++++++++++----------------
 drivers/gpu/drm/i915/i915_reg.h |   11 +++++-
 2 files changed, 55 insertions(+), 33 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 112699f..aad41b7 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1595,7 +1595,7 @@ i915_gem_process_flushing_list(struct drm_device *dev,
 
 #define PIPE_CONTROL_FLUSH(addr)					\
 	OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |		\
-		 PIPE_CONTROL_DEPTH_STALL);				\
+		 PIPE_CONTROL_DEPTH_STALL | 2);				\
 	OUT_RING(addr | PIPE_CONTROL_GLOBAL_GTT);			\
 	OUT_RING(0);							\
 	OUT_RING(0);							\
@@ -1635,37 +1635,50 @@ i915_add_request(struct drm_device *dev, struct drm_file *file_priv,
 		dev_priv->mm.next_gem_seqno++;
 
 	if (HAS_PIPE_CONTROL(dev)) {
-		u32 scratch_addr = dev_priv->seqno_gfx_addr + 128;
+		if (IS_GEN6(dev)) {
+			BEGIN_LP_RING(6);
+			OUT_RING(GFX_OP_PIPE_CONTROL | 3);
+			OUT_RING(PIPE_CONTROL_QW_WRITE |
+				 PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_IS_FLUSH |
+				 PIPE_CONTROL_NOTIFY);
+			OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
+			OUT_RING(seqno);
+			OUT_RING(0);
+			OUT_RING(0);
+			ADVANCE_LP_RING();
+		} else {
+			u32 scratch_addr = dev_priv->seqno_gfx_addr + 128;
 
-		/*
-		 * Workaround qword write incoherence by flushing the
-		 * PIPE_NOTIFY buffers out to memory before requesting
-		 * an interrupt.
-		 */
-		BEGIN_LP_RING(32);
-		OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
-			 PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH);
-		OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
-		OUT_RING(seqno);
-		OUT_RING(0);
-		PIPE_CONTROL_FLUSH(scratch_addr);
-		scratch_addr += 128; /* write to separate cachelines */
-		PIPE_CONTROL_FLUSH(scratch_addr);
-		scratch_addr += 128;
-		PIPE_CONTROL_FLUSH(scratch_addr);
-		scratch_addr += 128;
-		PIPE_CONTROL_FLUSH(scratch_addr);
-		scratch_addr += 128;
-		PIPE_CONTROL_FLUSH(scratch_addr);
-		scratch_addr += 128;
-		PIPE_CONTROL_FLUSH(scratch_addr);
-		OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
-			 PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH |
-			 PIPE_CONTROL_NOTIFY);
-		OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
-		OUT_RING(seqno);
-		OUT_RING(0);
-		ADVANCE_LP_RING();
+			/*
+			 * Workaround qword write incoherence by flushing the
+			 * PIPE_NOTIFY buffers out to memory before requesting
+			 * an interrupt.
+			 */
+			BEGIN_LP_RING(32);
+			OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
+				 PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH | 2);
+			OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
+			OUT_RING(seqno);
+			OUT_RING(0);
+			PIPE_CONTROL_FLUSH(scratch_addr);
+			scratch_addr += 128; /* write to separate cachelines */
+			PIPE_CONTROL_FLUSH(scratch_addr);
+			scratch_addr += 128;
+			PIPE_CONTROL_FLUSH(scratch_addr);
+			scratch_addr += 128;
+			PIPE_CONTROL_FLUSH(scratch_addr);
+			scratch_addr += 128;
+			PIPE_CONTROL_FLUSH(scratch_addr);
+			scratch_addr += 128;
+			PIPE_CONTROL_FLUSH(scratch_addr);
+			OUT_RING(GFX_OP_PIPE_CONTROL | PIPE_CONTROL_QW_WRITE |
+				 PIPE_CONTROL_WC_FLUSH | PIPE_CONTROL_TC_FLUSH |
+				 PIPE_CONTROL_NOTIFY);
+			OUT_RING(dev_priv->seqno_gfx_addr | PIPE_CONTROL_GLOBAL_GTT);
+			OUT_RING(seqno);
+			OUT_RING(0);
+			ADVANCE_LP_RING();
+		}
 	} else {
 		BEGIN_LP_RING(4);
 		OUT_RING(MI_STORE_DWORD_INDEX);
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index f3e39cc..2740f09 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -230,7 +230,12 @@
 #define   ASYNC_FLIP                (1<<22)
 #define   DISPLAY_PLANE_A           (0<<20)
 #define   DISPLAY_PLANE_B           (1<<20)
-#define GFX_OP_PIPE_CONTROL	((0x3<<29)|(0x3<<27)|(0x2<<24)|2)
+#define GFX_OP_PIPE_CONTROL	((0x3<<29)|(0x3<<27)|(0x2<<24))
+#define   PIPE_CONTROL_CS_STALL	(1<<20)
+#define   PIPE_CONTROL_GLOBAL_SNAPSHOT_COUNT_RESET	(1<<19)
+#define   PIPE_CONTROL_TLB_INVALIDATE	(1<<18)
+#define   PIPE_CONTROL_SYNC_GFDT	(1<<17)
+#define   PIPE_CONTROL_MEDIA_STATE_CLEAR	(1<<16)
 #define   PIPE_CONTROL_QW_WRITE	(1<<14)
 #define   PIPE_CONTROL_DEPTH_STALL (1<<13)
 #define   PIPE_CONTROL_WC_FLUSH	(1<<12)
@@ -238,6 +243,10 @@
 #define   PIPE_CONTROL_TC_FLUSH (1<<10) /* GM45+ only */
 #define   PIPE_CONTROL_ISP_DIS	(1<<9)
 #define   PIPE_CONTROL_NOTIFY	(1<<8)
+#define   PIPE_CONTROL_VF_CACHE_INVALIDATE	(1<<4)
+#define   PIPE_CONTROL_CONST_CACHE_INVALIDATE	(1<<3)
+#define   PIPE_CONTROL_STATE_CACHE_INVALIDATE	(1<<2)
+#define   PIPE_CONTROL_DEPTH_CACHE_FLUSH	(1<<0)
 #define   PIPE_CONTROL_GLOBAL_GTT (1<<2) /* in addr dword */
 #define   PIPE_CONTROL_STALL_EN	(1<<1) /* in addr word, Ironlake+ only */
 
-- 
1.7.0.4




More information about the Intel-gfx mailing list