xf86-video-intel: src/i965_reg.h src/intel.h src/intel_batchbuffer.c src/intel_driver.c

Daniel Vetter danvet at kemper.freedesktop.org
Tue Oct 11 01:55:43 PDT 2011


 src/i965_reg.h          |    2 +
 src/intel.h             |    1 
 src/intel_batchbuffer.c |   50 ++++++++++++++++++++++++++++++++++++++++--------
 src/intel_driver.c      |    7 ++++++
 4 files changed, 52 insertions(+), 8 deletions(-)

New commits:
commit d0184b59095d5b8fab1a65ceba075d29189130d4
Author: Daniel Vetter <daniel.vetter at ffwll.ch>
Date:   Sun Oct 9 18:43:14 2011 +0200

    snb: implement PIPE_CONTROL workaround
    
    Sandybdrige requires an elaborate dance to flush caches without
    hanging the gpu. See public docs Vol2Part1 1.7.4.1 PIPE_CONTROL
    or the corrensponding code in mesa/kernel.
    
    This (together with the corresponding patch for the kernel) seems to
    fix the hangs in cairo-perf-traces I'm seeing on my snb machine.
    
    v2: Incorporate review from Chris Wilson. For paranoia keep all three
    PIPE_CONTROL cmds in the same batchbuffer to avoid upsetting the gpu.
    
    Signed-off-by: Daniel Vetter <daniel.vetter at ffwll.ch>

diff --git a/src/i965_reg.h b/src/i965_reg.h
index 904e506..e7b0d15 100644
--- a/src/i965_reg.h
+++ b/src/i965_reg.h
@@ -294,6 +294,7 @@
 #define BRW_CLIP_ENABLE		       1
 
 /* for BRW_PIPE_CONTROL */
+#define BRW_PIPE_CONTROL_CS_STALL      (1 << 20)
 #define BRW_PIPE_CONTROL_NOWRITE       (0 << 14)
 #define BRW_PIPE_CONTROL_WRITE_QWORD   (1 << 14)
 #define BRW_PIPE_CONTROL_WRITE_DEPTH   (2 << 14)
@@ -305,6 +306,7 @@
 #define BRW_PIPE_CONTROL_NOTIFY_ENABLE (1 << 8)
 #define BRW_PIPE_CONTROL_GLOBAL_GTT    (1 << 2)
 #define BRW_PIPE_CONTROL_LOCAL_PGTT    (0 << 2)
+#define BRW_PIPE_CONTROL_STALL_AT_SCOREBOARD    (1 << 1)
 #define BRW_PIPE_CONTROL_DEPTH_CACHE_FLUSH	(1 << 0)
 
 /* VERTEX_BUFFER_STATE Structure */
diff --git a/src/intel.h b/src/intel.h
index 899d250..2f72830 100644
--- a/src/intel.h
+++ b/src/intel.h
@@ -283,6 +283,7 @@ typedef struct intel_screen_private {
 	struct list batch_pixmaps;
 	struct list flush_pixmaps;
 	struct list in_flight;
+	drm_intel_bo *wa_scratch_bo;
 
 	/* For Xvideo */
 	Bool use_overlay;
diff --git a/src/intel_batchbuffer.c b/src/intel_batchbuffer.c
index d0a41aa..89a9969 100644
--- a/src/intel_batchbuffer.c
+++ b/src/intel_batchbuffer.c
@@ -137,6 +137,35 @@ void intel_batch_do_flush(ScrnInfoPtr scrn)
 		list_del(intel->flush_pixmaps.next);
 }
 
+static void intel_emit_post_sync_nonzero_flush(ScrnInfoPtr scrn)
+{
+	intel_screen_private *intel = intel_get_screen_private(scrn);
+
+	/* keep this entire sequence of 3 PIPE_CONTROL cmds in one batch to
+	 * avoid upsetting the gpu. */
+	BEGIN_BATCH(3*4);
+	OUT_BATCH(BRW_PIPE_CONTROL | (4 - 2));
+	OUT_BATCH(BRW_PIPE_CONTROL_CS_STALL |
+		  BRW_PIPE_CONTROL_STALL_AT_SCOREBOARD);
+	OUT_BATCH(0); /* address */
+	OUT_BATCH(0); /* write data */
+
+	OUT_BATCH(BRW_PIPE_CONTROL | (4 - 2));
+	OUT_BATCH(BRW_PIPE_CONTROL_WRITE_QWORD);
+	OUT_RELOC(intel->wa_scratch_bo,
+		  I915_GEM_DOMAIN_INSTRUCTION, I915_GEM_DOMAIN_INSTRUCTION, 0);
+	OUT_BATCH(0); /* write data */
+
+	/* now finally the _real flush */
+	OUT_BATCH(BRW_PIPE_CONTROL | (4 - 2));
+	OUT_BATCH(BRW_PIPE_CONTROL_WC_FLUSH |
+		  BRW_PIPE_CONTROL_TC_FLUSH |
+		  BRW_PIPE_CONTROL_NOWRITE);
+	OUT_BATCH(0); /* write address */
+	OUT_BATCH(0); /* write data */
+	ADVANCE_BATCH();
+}
+
 void intel_batch_emit_flush(ScrnInfoPtr scrn)
 {
 	intel_screen_private *intel = intel_get_screen_private(scrn);
@@ -154,14 +183,19 @@ void intel_batch_emit_flush(ScrnInfoPtr scrn)
 			OUT_BATCH(0);
 			ADVANCE_BATCH();
 		} else  {
-			BEGIN_BATCH(4);
-			OUT_BATCH(BRW_PIPE_CONTROL | (4 - 2));
-			OUT_BATCH(BRW_PIPE_CONTROL_WC_FLUSH |
-				  BRW_PIPE_CONTROL_TC_FLUSH |
-				  BRW_PIPE_CONTROL_NOWRITE);
-			OUT_BATCH(0); /* write address */
-			OUT_BATCH(0); /* write data */
-			ADVANCE_BATCH();
+			if ((INTEL_INFO(intel)->gen == 60)) {
+				/* HW-Workaround for Sandybdrige */
+				intel_emit_post_sync_nonzero_flush(scrn);
+			} else {
+				BEGIN_BATCH(4);
+				OUT_BATCH(BRW_PIPE_CONTROL | (4 - 2));
+				OUT_BATCH(BRW_PIPE_CONTROL_WC_FLUSH |
+					  BRW_PIPE_CONTROL_TC_FLUSH |
+					  BRW_PIPE_CONTROL_NOWRITE);
+				OUT_BATCH(0); /* write address */
+				OUT_BATCH(0); /* write data */
+				ADVANCE_BATCH();
+			}
 		}
 	} else {
 		flags = MI_WRITE_DIRTY_STATE | MI_INVALIDATE_MAP_CACHE;
diff --git a/src/intel_driver.c b/src/intel_driver.c
index 7fc1c1a..24696da 100644
--- a/src/intel_driver.c
+++ b/src/intel_driver.c
@@ -416,11 +416,18 @@ static int intel_init_bufmgr(intel_screen_private *intel)
 	list_init(&intel->flush_pixmaps);
 	list_init(&intel->in_flight);
 
+	if ((INTEL_INFO(intel)->gen == 60)) {
+		intel->wa_scratch_bo =
+			drm_intel_bo_alloc(intel->bufmgr, "wa scratch",
+					   4096, 4096);
+	}
+
 	return TRUE;
 }
 
 static void intel_bufmgr_fini(intel_screen_private *intel)
 {
+	drm_intel_bo_unreference(intel->wa_scratch_bo);
 	drm_intel_bufmgr_destroy(intel->bufmgr);
 }
 


More information about the xorg-commit mailing list