Browse Source

drm/i915: Move the hw semaphore initialisation from GEM to the engine

Since we are setting engine local values that are tied to the hardware,
move it out of i915_gem_init_seqno() into the intel_ring_init_seqno()
backend, next to where the other hw semaphore registers are written.

v2: Make the explanatory comment about always resetting the semaphores to
0 irrespective of the value of the reset seqno.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Cc: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Reviewed-by: Mika Kuoppala <mika.kuoppala@linux.intel.com>
Reviewed-by: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Link: http://patchwork.freedesktop.org/patch/msgid/1460010558-10705-4-git-send-email-chris@chris-wilson.co.uk
Chris Wilson 9 years ago
parent
commit
29dcb57026
2 changed files with 13 additions and 6 deletions
  1. 2 6
      drivers/gpu/drm/i915/i915_gem.c
  2. 11 0
      drivers/gpu/drm/i915/intel_ringbuffer.c

+ 2 - 6
drivers/gpu/drm/i915/i915_gem.c

@@ -2468,7 +2468,7 @@ i915_gem_init_seqno(struct drm_device *dev, u32 seqno)
 {
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_engine_cs *engine;
 	struct intel_engine_cs *engine;
-	int ret, j;
+	int ret;
 
 
 	/* Carefully retire all requests without writing to the rings */
 	/* Carefully retire all requests without writing to the rings */
 	for_each_engine(engine, dev_priv) {
 	for_each_engine(engine, dev_priv) {
@@ -2479,13 +2479,9 @@ i915_gem_init_seqno(struct drm_device *dev, u32 seqno)
 	i915_gem_retire_requests(dev);
 	i915_gem_retire_requests(dev);
 
 
 	/* Finally reset hw state */
 	/* Finally reset hw state */
-	for_each_engine(engine, dev_priv) {
+	for_each_engine(engine, dev_priv)
 		intel_ring_init_seqno(engine, seqno);
 		intel_ring_init_seqno(engine, seqno);
 
 
-		for (j = 0; j < ARRAY_SIZE(engine->semaphore.sync_seqno); j++)
-			engine->semaphore.sync_seqno[j] = 0;
-	}
-
 	return 0;
 	return 0;
 }
 }
 
 

+ 11 - 0
drivers/gpu/drm/i915/intel_ringbuffer.c

@@ -2552,14 +2552,25 @@ void intel_ring_init_seqno(struct intel_engine_cs *engine, u32 seqno)
 {
 {
 	struct drm_i915_private *dev_priv = to_i915(engine->dev);
 	struct drm_i915_private *dev_priv = to_i915(engine->dev);
 
 
+	/* Our semaphore implementation is strictly monotonic (i.e. we proceed
+	 * so long as the semaphore value in the register/page is greater
+	 * than the sync value), so whenever we reset the seqno,
+	 * so long as we reset the tracking semaphore value to 0, it will
+	 * always be before the next request's seqno. If we don't reset
+	 * the semaphore value, then when the seqno moves backwards all
+	 * future waits will complete instantly (causing rendering corruption).
+	 */
 	if (INTEL_INFO(dev_priv)->gen == 6 || INTEL_INFO(dev_priv)->gen == 7) {
 	if (INTEL_INFO(dev_priv)->gen == 6 || INTEL_INFO(dev_priv)->gen == 7) {
 		I915_WRITE(RING_SYNC_0(engine->mmio_base), 0);
 		I915_WRITE(RING_SYNC_0(engine->mmio_base), 0);
 		I915_WRITE(RING_SYNC_1(engine->mmio_base), 0);
 		I915_WRITE(RING_SYNC_1(engine->mmio_base), 0);
 		if (HAS_VEBOX(dev_priv))
 		if (HAS_VEBOX(dev_priv))
 			I915_WRITE(RING_SYNC_2(engine->mmio_base), 0);
 			I915_WRITE(RING_SYNC_2(engine->mmio_base), 0);
 	}
 	}
+	memset(engine->semaphore.sync_seqno, 0,
+	       sizeof(engine->semaphore.sync_seqno));
 
 
 	engine->set_seqno(engine, seqno);
 	engine->set_seqno(engine, seqno);
+
 	engine->hangcheck.seqno = seqno;
 	engine->hangcheck.seqno = seqno;
 }
 }