Skip to contentSkip to conversation

BDW Semaphores

PATCH In review Ben Widawsky 5 participants 25 messages Apr 29, 2014 – May 7, 2014

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover BDW Semaphores

Okay, trying this again after the somewhat painful VCS2 rebase. I think I got to all of Ville's comments, but I could have missed a few. I apologize if so.

Daniel, even if you don't merge the whole series, the first few would really help rebase pain - though now that VCS2 is merged, there's probably not much other than execlists to be painful

The series is completely untested since the last rebase. I also didn't look really closely to make sure the rebase was correct - I'm just totally short on time atm. It was tested before that.

Ben Widawsky (13):
drm/i915: Move semaphore specific ring members to struct drm/i915: Virtualize the ringbuffer signal func drm/i915: Move ring_begin to signal()
drm/i915: Make semaphore updates more precise drm/i915: gen specific ring init
drm/i915/bdw: implement semaphore signal drm/i915/bdw: implement semaphore wait drm/i915: Implement MI decode for gen8 drm/i915/bdw: poll semaphores
drm/i915: Extract semaphore error collection drm/i915/bdw: collect semaphore error state drm/i915: semaphore debugfs
DONT_MERGE drm/i915: FORCE_RESTORE for gen8 semaphores

 drivers/gpu/drm/i915/i915_debugfs.c     |  70 ++++++
 drivers/gpu/drm/i915/i915_drv.h         |   2 +
 drivers/gpu/drm/i915/i915_gem.c         |  10 +-
 drivers/gpu/drm/i915/i915_gem_context.c |   7 +
 drivers/gpu/drm/i915/i915_gpu_error.c   |  79 +++++--
 drivers/gpu/drm/i915/i915_irq.c         |  14 +-
 drivers/gpu/drm/i915/i915_reg.h         |   8 +-
 drivers/gpu/drm/i915/intel_ringbuffer.c | 405 ++++++++++++++++++++++----------
 drivers/gpu/drm/i915/intel_ringbuffer.h |  90 ++++++-
 9 files changed, 528 insertions(+), 157 deletions(-)
Signature · 1 line
1.9.2
#1 lore raw

PATCH 1/13 drm/i915: Move semaphore specific ring members to struct

This will be helpful in abstracting some of the code in preparation for gen8 semaphores.

v2: Move mbox stuff to a separate struct

v3: Rebased over VCS2 work

---
 drivers/gpu/drm/i915/i915_gem.c         |  10 +--
 drivers/gpu/drm/i915/i915_gpu_error.c   |   6 +-
 drivers/gpu/drm/i915/i915_irq.c         |   3 +-
 drivers/gpu/drm/i915/intel_ringbuffer.c | 124 ++++++++++++++++----------------
 drivers/gpu/drm/i915/intel_ringbuffer.h |  19 +++--
 5 files changed, 82 insertions(+), 80 deletions(-)
drivers/gpu/drm/i915/i915_gem.c +5 -5
index b00a77e..dae51c3 100644
@@ -2119,8 +2119,8 @@ i915_gem_init_seqno(struct drm_device *dev, u32 seqno)
 	for_each_ring(ring, dev_priv, i) {
 		intel_ring_init_seqno(ring, seqno);
 
-		for (j = 0; j < ARRAY_SIZE(ring->sync_seqno); j++)
-			ring->sync_seqno[j] = 0;
+		for (j = 0; j < ARRAY_SIZE(ring->semaphore.sync_seqno); j++)
+			ring->semaphore.sync_seqno[j] = 0;
 	}
 
 	return 0;
@@ -2692,7 +2692,7 @@ i915_gem_object_sync(struct drm_i915_gem_object *obj,
 	idx = intel_ring_sync_index(from, to);
 
 	seqno = obj->last_read_seqno;
-	if (seqno <= from->sync_seqno[idx])
+	if (seqno <= from->semaphore.sync_seqno[idx])
 		return 0;
 
 	ret = i915_gem_check_olr(obj->ring, seqno);
@@ -2700,13 +2700,13 @@ i915_gem_object_sync(struct drm_i915_gem_object *obj,
 		return ret;
 
 	trace_i915_gem_ring_sync_to(from, to, seqno);
-	ret = to->sync_to(to, from, seqno);
+	ret = to->semaphore.sync_to(to, from, seqno);
 	if (!ret)
 		/* We use last_read_seqno because sync_to()
 		 * might have just caused seqno wrap under
 		 * the radar.
 		 */
-		from->sync_seqno[idx] = obj->last_read_seqno;
+		from->semaphore.sync_seqno[idx] = obj->last_read_seqno;
 
 	return ret;
 }
drivers/gpu/drm/i915/i915_gpu_error.c +3 -3
index 51e9978..2d81985 100644
@@ -757,14 +757,14 @@ static void i915_record_ring_state(struct drm_device *dev,
 			= I915_READ(RING_SYNC_0(ring->mmio_base));
 		ering->semaphore_mboxes[1]
 			= I915_READ(RING_SYNC_1(ring->mmio_base));
-		ering->semaphore_seqno[0] = ring->sync_seqno[0];
-		ering->semaphore_seqno[1] = ring->sync_seqno[1];
+		ering->semaphore_seqno[0] = ring->semaphore.sync_seqno[0];
+		ering->semaphore_seqno[1] = ring->semaphore.sync_seqno[1];
 	}
 
 	if (HAS_VEBOX(dev)) {
 		ering->semaphore_mboxes[2] =
 			I915_READ(RING_SYNC_2(ring->mmio_base));
-		ering->semaphore_seqno[2] = ring->sync_seqno[2];
+		ering->semaphore_seqno[2] = ring->semaphore.sync_seqno[2];
 	}
 
 	if (INTEL_INFO(dev)->gen >= 4) {
drivers/gpu/drm/i915/i915_irq.c +1 -2
index 7e0d577..2d76183 100644
@@ -2595,8 +2595,7 @@ semaphore_wait_to_signaller_ring(struct intel_ring_buffer *ring, u32 ipehr)
 			if(ring == signaller)
 				continue;
 
-			if (sync_bits ==
-			    signaller->semaphore_register[ring->id])
+			if (sync_bits == signaller->semaphore.mbox.wait[ring->id])
 				return signaller;
 		}
 	}
drivers/gpu/drm/i915/intel_ringbuffer.c +61 -63

211 lines not on this page · raw message

drivers/gpu/drm/i915/intel_ringbuffer.h +12 -7
index 13e398f..6a44a64 100644
@@ -90,7 +90,6 @@ struct  intel_ring_buffer {
 	unsigned irq_refcount; /* protected by dev_priv->irq_lock */
 	u32		irq_enable_mask;	/* bitmask to enable ring interrupt */
 	u32		trace_irq_seqno;
-	u32		sync_seqno[I915_NUM_RINGS-1];
 	bool __must_check (*irq_get)(struct intel_ring_buffer *ring);
 	void		(*irq_put)(struct intel_ring_buffer *ring);
 
@@ -118,14 +117,20 @@ struct  intel_ring_buffer {
 #define I915_DISPATCH_SECURE 0x1
 #define I915_DISPATCH_PINNED 0x2
 	void		(*cleanup)(struct intel_ring_buffer *ring);
-	int		(*sync_to)(struct intel_ring_buffer *ring,
+
+	struct {
+		u32	sync_seqno[I915_NUM_RINGS-1];
+		/* AKA wait() */
+		int	(*sync_to)(struct intel_ring_buffer *ring,
 				   struct intel_ring_buffer *to,
 				   u32 seqno);
-
-	/* our mbox written by others */
-	u32		semaphore_register[I915_NUM_RINGS];
-	/* mboxes this ring signals to */
-	u32		signal_mbox[I915_NUM_RINGS];
+		struct {
+			/* our mbox written by others */
+			u32		wait[I915_NUM_RINGS];
+			/* mboxes this ring signals to */
+			u32		signal[I915_NUM_RINGS];
+		} mbox;
+	} semaphore;
 
 	/**
 	 * List of objects currently involved in rendering from the
Signature · 6 lines
1.9.2

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
#2 lore raw

PATCH 2/13 drm/i915: Virtualize the ringbuffer signal func

In reply to Ben Widawsky

This abstraction again is in preparation for gen8. Gen8 will bring new semantics for doing this operation.

While here, make the writes of MI_NOOPs explicit for non-existent rings. This should have been implicit before.

NOTE: This is going to be removed in a few patches.

---
 drivers/gpu/drm/i915/intel_ringbuffer.c | 42 ++++++++++++++++++++-------------
 drivers/gpu/drm/i915/intel_ringbuffer.h | 11 +++++----
 2 files changed, 32 insertions(+), 21 deletions(-)
drivers/gpu/drm/i915/intel_ringbuffer.c +25 -17
index 3076a99..ea81b54 100644
@@ -663,20 +663,32 @@ static void render_ring_cleanup(struct intel_ring_buffer *ring)
 	ring->scratch.obj = NULL;
 }
 
-static void
-update_mboxes(struct intel_ring_buffer *ring,
-	      u32 mmio_offset)
+static void gen6_signal(struct intel_ring_buffer *signaller)
 {
+	struct drm_i915_private *dev_priv = signaller->dev->dev_private;
+	struct intel_ring_buffer *useless;
+	int i;
+
 /* NB: In order to be able to do semaphore MBOX updates for varying number
  * of rings, it's easiest if we round up each individual update to a
  * multiple of 2 (since ring updates must always be a multiple of 2)
  * even though the actual update only requires 3 dwords.
  */
 #define MBOX_UPDATE_DWORDS 4
-	intel_ring_emit(ring, MI_LOAD_REGISTER_IMM(1));
-	intel_ring_emit(ring, mmio_offset);
-	intel_ring_emit(ring, ring->outstanding_lazy_seqno);
-	intel_ring_emit(ring, MI_NOOP);
+	for_each_ring(useless, dev_priv, i) {
+		u32 mbox_reg = signaller->semaphore.mbox.signal[i];
+		if (mbox_reg != GEN6_NOSYNC) {
+			intel_ring_emit(signaller, MI_LOAD_REGISTER_IMM(1));
+			intel_ring_emit(signaller, mbox_reg);
+			intel_ring_emit(signaller, signaller->outstanding_lazy_seqno);
+			intel_ring_emit(signaller, MI_NOOP);
+		} else {
+			intel_ring_emit(signaller, MI_NOOP);
+			intel_ring_emit(signaller, MI_NOOP);
+			intel_ring_emit(signaller, MI_NOOP);
+			intel_ring_emit(signaller, MI_NOOP);
+		}
+	}
 }
 
 /**
@@ -692,9 +704,7 @@ static int
 gen6_add_request(struct intel_ring_buffer *ring)
 {
 	struct drm_device *dev = ring->dev;
-	struct drm_i915_private *dev_priv = dev->dev_private;
-	struct intel_ring_buffer *useless;
-	int i, ret, num_dwords = 4;
+	int ret, num_dwords = 4;
 
 	if (i915_semaphore_is_enabled(dev))
 		num_dwords += ((I915_NUM_RINGS-1) * MBOX_UPDATE_DWORDS);
@@ -704,13 +714,7 @@ gen6_add_request(struct intel_ring_buffer *ring)
 	if (ret)
 		return ret;
 
-	if (i915_semaphore_is_enabled(dev)) {
-		for_each_ring(useless, dev_priv, i) {
-			u32 mbox_reg = ring->semaphore.mbox.signal[i];
-			if (mbox_reg != GEN6_NOSYNC)
-				update_mboxes(ring, mbox_reg);
-		}
-	}
+	ring->semaphore.signal(ring);
 
 	intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
 	intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
@@ -1920,6 +1924,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
 		ring->get_seqno = gen6_ring_get_seqno;
 		ring->set_seqno = ring_set_seqno;
 		ring->semaphore.sync_to = gen6_ring_sync;
+		ring->semaphore.signal = gen6_signal;
 		/*
 		 * The current semaphore is only applied on pre-gen8 platform.
 		 * And there is no VCS2 ring on the pre-gen8 platform. So the
@@ -2104,6 +2109,7 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev)
 				gen6_ring_dispatch_execbuffer;
 		}
 		ring->semaphore.sync_to = gen6_ring_sync;
+		ring->semaphore.signal = gen6_signal;
 		/*
 		 * The current semaphore is only applied on pre-gen8 platform.
 		 * And there is no VCS2 ring on the pre-gen8 platform. So the
@@ -2221,6 +2227,7 @@ int intel_init_blt_ring_buffer(struct drm_device *dev)
 		ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
 	}
 	ring->semaphore.sync_to = gen6_ring_sync;
+	ring->semaphore.signal = gen6_signal;
 	/*
 	 * The current semaphore is only applied on pre-gen8 platform. And
 	 * there is no VCS2 ring on the pre-gen8 platform. So the semaphore
@@ -2270,6 +2277,7 @@ int intel_init_vebox_ring_buffer(struct drm_device *dev)
 		ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
 	}
 	ring->semaphore.sync_to = gen6_ring_sync;
+	ring->semaphore.signal = gen6_signal;
 	ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VER;
 	ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_VEV;
 	ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VEB;
drivers/gpu/drm/i915/intel_ringbuffer.h +7 -4
index 6a44a64..830ff26 100644
@@ -120,16 +120,19 @@ struct  intel_ring_buffer {
 
 	struct {
 		u32	sync_seqno[I915_NUM_RINGS-1];
-		/* AKA wait() */
-		int	(*sync_to)(struct intel_ring_buffer *ring,
-				   struct intel_ring_buffer *to,
-				   u32 seqno);
+
 		struct {
 			/* our mbox written by others */
 			u32		wait[I915_NUM_RINGS];
 			/* mboxes this ring signals to */
 			u32		signal[I915_NUM_RINGS];
 		} mbox;
+
+		/* AKA wait() */
+		int	(*sync_to)(struct intel_ring_buffer *ring,
+				   struct intel_ring_buffer *to,
+				   u32 seqno);
+		void	(*signal)(struct intel_ring_buffer *signaller);
 	} semaphore;
 
 	/**
Signature · 6 lines
1.9.2

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
#3 lore raw

PATCH 3/13 drm/i915: Move ring_begin to signal()

In reply to Ben Widawsky

Add_request has always contained both the semaphore mailbox updates as well as the breadcrumb writes. Since the semaphore signal is the one which actually knows about the number of dwords it needs to emit to the ring, we move the ring_begin to that function. This allows us to remove the hideously shared #define

On a related not, gen8 will use a different number of dwords for semaphores, but not for add request.

v2: Make number of dwords an explicit part of signalling (via function argument). (Chris)

v3: very slight comment change

---
 drivers/gpu/drm/i915/intel_ringbuffer.c | 39 +++++++++++++++++++--------------
 drivers/gpu/drm/i915/intel_ringbuffer.h |  4 +++-
 2 files changed, 25 insertions(+), 18 deletions(-)
drivers/gpu/drm/i915/intel_ringbuffer.c +22 -17
index ea81b54..e0c7bf2 100644
@@ -663,18 +663,28 @@ static void render_ring_cleanup(struct intel_ring_buffer *ring)
 	ring->scratch.obj = NULL;
 }
 
-static void gen6_signal(struct intel_ring_buffer *signaller)
+static int gen6_signal(struct intel_ring_buffer *signaller,
+		       unsigned int num_dwords)
 {
-	struct drm_i915_private *dev_priv = signaller->dev->dev_private;
+	struct drm_device *dev = signaller->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_ring_buffer *useless;
-	int i;
+	int i, ret;
 
-/* NB: In order to be able to do semaphore MBOX updates for varying number
- * of rings, it's easiest if we round up each individual update to a
- * multiple of 2 (since ring updates must always be a multiple of 2)
- * even though the actual update only requires 3 dwords.
- */
+	/* NB: In order to be able to do semaphore MBOX updates for varying
+	 * number of rings, it's easiest if we round up each individual update
+	 * to a multiple of 2 (since ring updates must always be a multiple of
+	 * 2) even though the actual update only requires 3 dwords.
+	 */
 #define MBOX_UPDATE_DWORDS 4
+	if (i915_semaphore_is_enabled(dev))
+		num_dwords += ((I915_NUM_RINGS-1) * MBOX_UPDATE_DWORDS);
+
+	ret = intel_ring_begin(signaller, num_dwords);
+	if (ret)
+		return ret;
+#undef MBOX_UPDATE_DWORDS
+
 	for_each_ring(useless, dev_priv, i) {
 		u32 mbox_reg = signaller->semaphore.mbox.signal[i];
 		if (mbox_reg != GEN6_NOSYNC) {
@@ -689,6 +699,8 @@ static void gen6_signal(struct intel_ring_buffer *signaller)
 			intel_ring_emit(signaller, MI_NOOP);
 		}
 	}
+
+	return 0;
 }
 
 /**
@@ -703,19 +715,12 @@ static void gen6_signal(struct intel_ring_buffer *signaller)
 static int
 gen6_add_request(struct intel_ring_buffer *ring)
 {
-	struct drm_device *dev = ring->dev;
-	int ret, num_dwords = 4;
-
-	if (i915_semaphore_is_enabled(dev))
-		num_dwords += ((I915_NUM_RINGS-1) * MBOX_UPDATE_DWORDS);
-#undef MBOX_UPDATE_DWORDS
+	int ret;
 
-	ret = intel_ring_begin(ring, num_dwords);
+	ret = ring->semaphore.signal(ring, 4);
 	if (ret)
 		return ret;
 
-	ring->semaphore.signal(ring);
-
 	intel_ring_emit(ring, MI_STORE_DWORD_INDEX);
 	intel_ring_emit(ring, I915_GEM_HWS_INDEX << MI_STORE_DWORD_INDEX_SHIFT);
 	intel_ring_emit(ring, ring->outstanding_lazy_seqno);
drivers/gpu/drm/i915/intel_ringbuffer.h +3 -1
index 830ff26..0fdf030 100644
@@ -132,7 +132,9 @@ struct  intel_ring_buffer {
 		int	(*sync_to)(struct intel_ring_buffer *ring,
 				   struct intel_ring_buffer *to,
 				   u32 seqno);
-		void	(*signal)(struct intel_ring_buffer *signaller);
+		int	(*signal)(struct intel_ring_buffer *signaller,
+				  /* num_dwords needed by caller */
+				  unsigned int num_dwords);
 	} semaphore;
 
 	/**
Signature · 6 lines
1.9.2

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
#4 lore raw

PATCH 4/13 drm/i915: Make semaphore updates more precise

In reply to Ben Widawsky

With the ring mask we now have an easy way to know the number of rings in the system, and therefore can accurately predict the number of dwords to emit for semaphore signalling. This was not possible (easily) previously.

There should be no functional impact, simply fewer instructions emitted.

While we're here, simply do the round up to 2 instead of the fancier rounding we did before, which rounding up per mbox, ie 4. This also allows us to drop the unnecessary MI_NOOP, so not really 4, 3.

v2: Use 3 dwords instead of 4 (Ville)
Do the proper calculation to get the number of dwords to emit (Ville) Conditionally set .sync_to when semaphores are enabled (Ville)

v3: Rebased on VCS2
Replace hweight_long with hweight32 (Ville)

---
 drivers/gpu/drm/i915/intel_ringbuffer.c | 173 +++++++++++++++++---------------
 1 file changed, 90 insertions(+), 83 deletions(-)
drivers/gpu/drm/i915/intel_ringbuffer.c +90 -83
index e0c7bf2..7aedc0c 100644
@@ -666,24 +666,19 @@ static void render_ring_cleanup(struct intel_ring_buffer *ring)
 static int gen6_signal(struct intel_ring_buffer *signaller,
 		       unsigned int num_dwords)
 {
+#define MBOX_UPDATE_DWORDS 3
 	struct drm_device *dev = signaller->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_ring_buffer *useless;
-	int i, ret;
+	int i, ret, num_rings;
 
-	/* NB: In order to be able to do semaphore MBOX updates for varying
-	 * number of rings, it's easiest if we round up each individual update
-	 * to a multiple of 2 (since ring updates must always be a multiple of
-	 * 2) even though the actual update only requires 3 dwords.
-	 */
-#define MBOX_UPDATE_DWORDS 4
-	if (i915_semaphore_is_enabled(dev))
-		num_dwords += ((I915_NUM_RINGS-1) * MBOX_UPDATE_DWORDS);
+	num_rings = hweight32(INTEL_INFO(dev)->ring_mask);
+	num_dwords += round_up((num_rings-1) * MBOX_UPDATE_DWORDS, 2);
+#undef MBOX_UPDATE_DWORDS
 
 	ret = intel_ring_begin(signaller, num_dwords);
 	if (ret)
 		return ret;
-#undef MBOX_UPDATE_DWORDS
 
 	for_each_ring(useless, dev_priv, i) {
 		u32 mbox_reg = signaller->semaphore.mbox.signal[i];
@@ -691,15 +686,13 @@ static int gen6_signal(struct intel_ring_buffer *signaller,
 			intel_ring_emit(signaller, MI_LOAD_REGISTER_IMM(1));
 			intel_ring_emit(signaller, mbox_reg);
 			intel_ring_emit(signaller, signaller->outstanding_lazy_seqno);
-			intel_ring_emit(signaller, MI_NOOP);
-		} else {
-			intel_ring_emit(signaller, MI_NOOP);
-			intel_ring_emit(signaller, MI_NOOP);
-			intel_ring_emit(signaller, MI_NOOP);
-			intel_ring_emit(signaller, MI_NOOP);
 		}
 	}
 
+	/* If num_dwords was rounded, make sure the tail pointer is correct */
+	if (num_rings % 2 == 0)
+		intel_ring_emit(signaller, MI_NOOP);
+
 	return 0;
 }
 
@@ -717,7 +710,11 @@ gen6_add_request(struct intel_ring_buffer *ring)
 {
 	int ret;
 
-	ret = ring->semaphore.signal(ring, 4);
+	if (ring->semaphore.signal)
+		ret = ring->semaphore.signal(ring, 4);
+	else
+		ret = intel_ring_begin(ring, 4);
+
 	if (ret)
 		return ret;
 
@@ -1928,24 +1925,27 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
 		ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT;
 		ring->get_seqno = gen6_ring_get_seqno;
 		ring->set_seqno = ring_set_seqno;
-		ring->semaphore.sync_to = gen6_ring_sync;
-		ring->semaphore.signal = gen6_signal;
-		/*
-		 * The current semaphore is only applied on pre-gen8 platform.
-		 * And there is no VCS2 ring on the pre-gen8 platform. So the
-		 * semaphore between RCS and VCS2 is initialized as INVALID.
-		 * Gen8 will initialize the sema between VCS2 and RCS later.
-		 */
-		ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_INVALID;
-		ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_RV;
-		ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_RB;
-		ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_RVE;
-		ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
-		ring->semaphore.mbox.signal[RCS] = GEN6_NOSYNC;
-		ring->semaphore.mbox.signal[VCS] = GEN6_VRSYNC;
-		ring->semaphore.mbox.signal[BCS] = GEN6_BRSYNC;
-		ring->semaphore.mbox.signal[VECS] = GEN6_VERSYNC;
-		ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+		if (i915_semaphore_is_enabled(dev)) {
+			ring->semaphore.sync_to = gen6_ring_sync;
+			ring->semaphore.signal = gen6_signal;
+			/*
+			 * The current semaphore is only applied on pre-gen8
+			 * platform.  And there is no VCS2 ring on the pre-gen8
+			 * platform. So the semaphore between RCS and VCS2 is
+			 * initialized as INVALID.  Gen8 will initialize the
+			 * sema between VCS2 and RCS later.
+			 */
+			ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_RV;
+			ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_RB;
+			ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_RVE;
+			ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.signal[RCS] = GEN6_NOSYNC;
+			ring->semaphore.mbox.signal[VCS] = GEN6_VRSYNC;
+			ring->semaphore.mbox.signal[BCS] = GEN6_BRSYNC;
+			ring->semaphore.mbox.signal[VECS] = GEN6_VERSYNC;
+			ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+		}
 	} else if (IS_GEN5(dev)) {
 		ring->add_request = pc_render_add_request;
 		ring->flush = gen4_render_ring_flush;
@@ -2113,24 +2113,27 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev)
 			ring->dispatch_execbuffer =
 				gen6_ring_dispatch_execbuffer;
 		}
-		ring->semaphore.sync_to = gen6_ring_sync;
-		ring->semaphore.signal = gen6_signal;
-		/*
-		 * The current semaphore is only applied on pre-gen8 platform.
-		 * And there is no VCS2 ring on the pre-gen8 platform. So the
-		 * semaphore between VCS and VCS2 is initialized as INVALID.
-		 * Gen8 will initialize the sema between VCS2 and VCS later.
-		 */
-		ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VR;
-		ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID;
-		ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VB;
-		ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_VVE;
-		ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
-		ring->semaphore.mbox.signal[RCS] = GEN6_RVSYNC;
-		ring->semaphore.mbox.signal[VCS] = GEN6_NOSYNC;
-		ring->semaphore.mbox.signal[BCS] = GEN6_BVSYNC;
-		ring->semaphore.mbox.signal[VECS] = GEN6_VEVSYNC;
-		ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+		if (i915_semaphore_is_enabled(dev)) {
+			ring->semaphore.sync_to = gen6_ring_sync;
+			ring->semaphore.signal = gen6_signal;
+			/*
+			 * The current semaphore is only applied on pre-gen8
+			 * platform.  And there is no VCS2 ring on the pre-gen8
+			 * platform. So the semaphore between VCS and VCS2 is
+			 * initialized as INVALID.  Gen8 will initialize the
+			 * sema between VCS2 and VCS later.
+			 */
+			ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VR;
+			ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VB;
+			ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_VVE;
+			ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.signal[RCS] = GEN6_RVSYNC;
+			ring->semaphore.mbox.signal[VCS] = GEN6_NOSYNC;
+			ring->semaphore.mbox.signal[BCS] = GEN6_BVSYNC;
+			ring->semaphore.mbox.signal[VECS] = GEN6_VEVSYNC;
+			ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+		}
 	} else {
 		ring->mmio_base = BSD_RING_BASE;
 		ring->flush = bsd_ring_flush;
@@ -2231,24 +2234,26 @@ int intel_init_blt_ring_buffer(struct drm_device *dev)
 		ring->irq_put = gen6_ring_put_irq;
 		ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
 	}
-	ring->semaphore.sync_to = gen6_ring_sync;
-	ring->semaphore.signal = gen6_signal;
-	/*
-	 * The current semaphore is only applied on pre-gen8 platform. And
-	 * there is no VCS2 ring on the pre-gen8 platform. So the semaphore
-	 * between BCS and VCS2 is initialized as INVALID.
-	 * Gen8 will initialize the sema between BCS and VCS2 later.
-	 */
-	ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_BR;
-	ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_BV;
-	ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID;
-	ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_BVE;
-	ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
-	ring->semaphore.mbox.signal[RCS] = GEN6_RBSYNC;
-	ring->semaphore.mbox.signal[VCS] = GEN6_VBSYNC;
-	ring->semaphore.mbox.signal[BCS] = GEN6_NOSYNC;
-	ring->semaphore.mbox.signal[VECS] = GEN6_VEBSYNC;
-	ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+	if (i915_semaphore_is_enabled(dev)) {
+		ring->semaphore.signal = gen6_signal;
+		ring->semaphore.sync_to = gen6_ring_sync;
+		/*
+		 * The current semaphore is only applied on pre-gen8 platform.
+		 * And there is no VCS2 ring on the pre-gen8 platform. So the
+		 * semaphore between BCS and VCS2 is initialized as INVALID.
+		 * Gen8 will initialize the sema between BCS and VCS2 later.
+		 */
+		ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_BR;
+		ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_BV;
+		ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID;
+		ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_BVE;
+		ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
+		ring->semaphore.mbox.signal[RCS] = GEN6_RBSYNC;
+		ring->semaphore.mbox.signal[VCS] = GEN6_VBSYNC;
+		ring->semaphore.mbox.signal[BCS] = GEN6_NOSYNC;
+		ring->semaphore.mbox.signal[VECS] = GEN6_VEBSYNC;
+		ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+	}
 	ring->init = init_ring_common;
 
 	return intel_init_ring_buffer(dev, ring);
@@ -2281,18 +2286,20 @@ int intel_init_vebox_ring_buffer(struct drm_device *dev)
 		ring->irq_put = hsw_vebox_put_irq;
 		ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
 	}
-	ring->semaphore.sync_to = gen6_ring_sync;
-	ring->semaphore.signal = gen6_signal;
-	ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VER;
-	ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_VEV;
-	ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VEB;
-	ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID;
-	ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
-	ring->semaphore.mbox.signal[RCS] = GEN6_RVESYNC;
-	ring->semaphore.mbox.signal[VCS] = GEN6_VVESYNC;
-	ring->semaphore.mbox.signal[BCS] = GEN6_BVESYNC;
-	ring->semaphore.mbox.signal[VECS] = GEN6_NOSYNC;
-	ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+	if (i915_semaphore_is_enabled(dev)) {
+		ring->semaphore.sync_to = gen6_ring_sync;
+		ring->semaphore.signal = gen6_signal;
+		ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VER;
+		ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_VEV;
+		ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VEB;
+		ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID;
+		ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
+		ring->semaphore.mbox.signal[RCS] = GEN6_RVESYNC;
+		ring->semaphore.mbox.signal[VCS] = GEN6_VVESYNC;
+		ring->semaphore.mbox.signal[BCS] = GEN6_BVESYNC;
+		ring->semaphore.mbox.signal[VECS] = GEN6_NOSYNC;
+		ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+	}
 	ring->init = init_ring_common;
 
 	return intel_init_ring_buffer(dev, ring);
Signature · 6 lines
1.9.2

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
#5 lore raw

Re: [PATCH 04/13] drm/i915: Make semaphore updates more precise

Quoted 81 lines · Ben Widawsky

With the ring mask we now have an easy way to know the number of rings in the system, and therefore can accurately predict the number of dwords to emit for semaphore signalling. This was not possible (easily) previously.

There should be no functional impact, simply fewer instructions emitted.

While we're here, simply do the round up to 2 instead of the fancier rounding we did before, which rounding up per mbox, ie 4. This also allows us to drop the unnecessary MI_NOOP, so not really 4, 3.

v2: Use 3 dwords instead of 4 (Ville)
Do the proper calculation to get the number of dwords to emit (Ville) Conditionally set .sync_to when semaphores are enabled (Ville)

v3: Rebased on VCS2
Replace hweight_long with hweight32 (Ville)

---
 drivers/gpu/drm/i915/intel_ringbuffer.c | 173 +++++++++++++++++---------------
 1 file changed, 90 insertions(+), 83 deletions(-)
drivers/gpu/drm/i915/intel_ringbuffer.c +9 -16
index e0c7bf2..7aedc0c 100644
@@ -666,24 +666,19 @@ static void render_ring_cleanup(struct intel_ring_buffer *ring)
 static int gen6_signal(struct intel_ring_buffer *signaller,
 		       unsigned int num_dwords)
 {
+#define MBOX_UPDATE_DWORDS 3
 	struct drm_device *dev = signaller->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct intel_ring_buffer *useless;
-	int i, ret;
+	int i, ret, num_rings;
 
-	/* NB: In order to be able to do semaphore MBOX updates for varying
-	 * number of rings, it's easiest if we round up each individual update
-	 * to a multiple of 2 (since ring updates must always be a multiple of
-	 * 2) even though the actual update only requires 3 dwords.
-	 */
-#define MBOX_UPDATE_DWORDS 4
-	if (i915_semaphore_is_enabled(dev))
-		num_dwords += ((I915_NUM_RINGS-1) * MBOX_UPDATE_DWORDS);
+	num_rings = hweight32(INTEL_INFO(dev)->ring_mask);
+	num_dwords += round_up((num_rings-1) * MBOX_UPDATE_DWORDS, 2);
+#undef MBOX_UPDATE_DWORDS
 
 	ret = intel_ring_begin(signaller, num_dwords);
 	if (ret)
 		return ret;
-#undef MBOX_UPDATE_DWORDS
 
 	for_each_ring(useless, dev_priv, i) {
 		u32 mbox_reg = signaller->semaphore.mbox.signal[i];
@@ -691,15 +686,13 @@ static int gen6_signal(struct intel_ring_buffer *signaller,
 			intel_ring_emit(signaller, MI_LOAD_REGISTER_IMM(1));
 			intel_ring_emit(signaller, mbox_reg);
 			intel_ring_emit(signaller, signaller->outstanding_lazy_seqno);
-			intel_ring_emit(signaller, MI_NOOP);
-		} else {
-			intel_ring_emit(signaller, MI_NOOP);
-			intel_ring_emit(signaller, MI_NOOP);
-			intel_ring_emit(signaller, MI_NOOP);
-			intel_ring_emit(signaller, MI_NOOP);
 		}
 	}
 
+	/* If num_dwords was rounded, make sure the tail pointer is correct */
+	if (num_rings % 2 == 0)
+		intel_ring_emit(signaller, MI_NOOP);
+
 	return 0;
 }
 
@@ -717,7 +710,11 @@ gen6_add_request(struct intel_ring_buffer *ring)
 {
 	int ret;

drivers/gpu/drm/i915/intel_ringbuffer.c gen6_add_request(struct intel_ring_buffer *ring) · line 720

Quoted 10 lines
drivers/gpu/drm/i915/intel_ringbuffer.c +5 -1
 
-	ret = ring->semaphore.signal(ring, 4);
+	if (ring->semaphore.signal)
+		ret = ring->semaphore.signal(ring, 4);
+	else
+		ret = intel_ring_begin(ring, 4);
+
 	if (ret)
 		return ret;
 

The hunks below look like a different patch. Accidental squash while rebasing?

I've merged patches 1-3 of this series already.
-Daniel

Quoted 177 lines
drivers/gpu/drm/i915/intel_ringbuffer.c +76 -66
@@ -1928,24 +1925,27 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
 		ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT;
 		ring->get_seqno = gen6_ring_get_seqno;
 		ring->set_seqno = ring_set_seqno;
-		ring->semaphore.sync_to = gen6_ring_sync;
-		ring->semaphore.signal = gen6_signal;
-		/*
-		 * The current semaphore is only applied on pre-gen8 platform.
-		 * And there is no VCS2 ring on the pre-gen8 platform. So the
-		 * semaphore between RCS and VCS2 is initialized as INVALID.
-		 * Gen8 will initialize the sema between VCS2 and RCS later.
-		 */
-		ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_INVALID;
-		ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_RV;
-		ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_RB;
-		ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_RVE;
-		ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
-		ring->semaphore.mbox.signal[RCS] = GEN6_NOSYNC;
-		ring->semaphore.mbox.signal[VCS] = GEN6_VRSYNC;
-		ring->semaphore.mbox.signal[BCS] = GEN6_BRSYNC;
-		ring->semaphore.mbox.signal[VECS] = GEN6_VERSYNC;
-		ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+		if (i915_semaphore_is_enabled(dev)) {
+			ring->semaphore.sync_to = gen6_ring_sync;
+			ring->semaphore.signal = gen6_signal;
+			/*
+			 * The current semaphore is only applied on pre-gen8
+			 * platform.  And there is no VCS2 ring on the pre-gen8
+			 * platform. So the semaphore between RCS and VCS2 is
+			 * initialized as INVALID.  Gen8 will initialize the
+			 * sema between VCS2 and RCS later.
+			 */
+			ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_RV;
+			ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_RB;
+			ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_RVE;
+			ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.signal[RCS] = GEN6_NOSYNC;
+			ring->semaphore.mbox.signal[VCS] = GEN6_VRSYNC;
+			ring->semaphore.mbox.signal[BCS] = GEN6_BRSYNC;
+			ring->semaphore.mbox.signal[VECS] = GEN6_VERSYNC;
+			ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+		}
 	} else if (IS_GEN5(dev)) {
 		ring->add_request = pc_render_add_request;
 		ring->flush = gen4_render_ring_flush;
@@ -2113,24 +2113,27 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev)
 			ring->dispatch_execbuffer =
 				gen6_ring_dispatch_execbuffer;
 		}
-		ring->semaphore.sync_to = gen6_ring_sync;
-		ring->semaphore.signal = gen6_signal;
-		/*
-		 * The current semaphore is only applied on pre-gen8 platform.
-		 * And there is no VCS2 ring on the pre-gen8 platform. So the
-		 * semaphore between VCS and VCS2 is initialized as INVALID.
-		 * Gen8 will initialize the sema between VCS2 and VCS later.
-		 */
-		ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VR;
-		ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID;
-		ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VB;
-		ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_VVE;
-		ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
-		ring->semaphore.mbox.signal[RCS] = GEN6_RVSYNC;
-		ring->semaphore.mbox.signal[VCS] = GEN6_NOSYNC;
-		ring->semaphore.mbox.signal[BCS] = GEN6_BVSYNC;
-		ring->semaphore.mbox.signal[VECS] = GEN6_VEVSYNC;
-		ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+		if (i915_semaphore_is_enabled(dev)) {
+			ring->semaphore.sync_to = gen6_ring_sync;
+			ring->semaphore.signal = gen6_signal;
+			/*
+			 * The current semaphore is only applied on pre-gen8
+			 * platform.  And there is no VCS2 ring on the pre-gen8
+			 * platform. So the semaphore between VCS and VCS2 is
+			 * initialized as INVALID.  Gen8 will initialize the
+			 * sema between VCS2 and VCS later.
+			 */
+			ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VR;
+			ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VB;
+			ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_VVE;
+			ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.signal[RCS] = GEN6_RVSYNC;
+			ring->semaphore.mbox.signal[VCS] = GEN6_NOSYNC;
+			ring->semaphore.mbox.signal[BCS] = GEN6_BVSYNC;
+			ring->semaphore.mbox.signal[VECS] = GEN6_VEVSYNC;
+			ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+		}
 	} else {
 		ring->mmio_base = BSD_RING_BASE;
 		ring->flush = bsd_ring_flush;
@@ -2231,24 +2234,26 @@ int intel_init_blt_ring_buffer(struct drm_device *dev)
 		ring->irq_put = gen6_ring_put_irq;
 		ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
 	}
-	ring->semaphore.sync_to = gen6_ring_sync;
-	ring->semaphore.signal = gen6_signal;
-	/*
-	 * The current semaphore is only applied on pre-gen8 platform. And
-	 * there is no VCS2 ring on the pre-gen8 platform. So the semaphore
-	 * between BCS and VCS2 is initialized as INVALID.
-	 * Gen8 will initialize the sema between BCS and VCS2 later.
-	 */
-	ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_BR;
-	ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_BV;
-	ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID;
-	ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_BVE;
-	ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
-	ring->semaphore.mbox.signal[RCS] = GEN6_RBSYNC;
-	ring->semaphore.mbox.signal[VCS] = GEN6_VBSYNC;
-	ring->semaphore.mbox.signal[BCS] = GEN6_NOSYNC;
-	ring->semaphore.mbox.signal[VECS] = GEN6_VEBSYNC;
-	ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+	if (i915_semaphore_is_enabled(dev)) {
+		ring->semaphore.signal = gen6_signal;
+		ring->semaphore.sync_to = gen6_ring_sync;
+		/*
+		 * The current semaphore is only applied on pre-gen8 platform.
+		 * And there is no VCS2 ring on the pre-gen8 platform. So the
+		 * semaphore between BCS and VCS2 is initialized as INVALID.
+		 * Gen8 will initialize the sema between BCS and VCS2 later.
+		 */
+		ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_BR;
+		ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_BV;
+		ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID;
+		ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_BVE;
+		ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
+		ring->semaphore.mbox.signal[RCS] = GEN6_RBSYNC;
+		ring->semaphore.mbox.signal[VCS] = GEN6_VBSYNC;
+		ring->semaphore.mbox.signal[BCS] = GEN6_NOSYNC;
+		ring->semaphore.mbox.signal[VECS] = GEN6_VEBSYNC;
+		ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+	}
 	ring->init = init_ring_common;
 
 	return intel_init_ring_buffer(dev, ring);
@@ -2281,18 +2286,20 @@ int intel_init_vebox_ring_buffer(struct drm_device *dev)
 		ring->irq_put = hsw_vebox_put_irq;
 		ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
 	}
-	ring->semaphore.sync_to = gen6_ring_sync;
-	ring->semaphore.signal = gen6_signal;
-	ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VER;
-	ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_VEV;
-	ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VEB;
-	ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID;
-	ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
-	ring->semaphore.mbox.signal[RCS] = GEN6_RVESYNC;
-	ring->semaphore.mbox.signal[VCS] = GEN6_VVESYNC;
-	ring->semaphore.mbox.signal[BCS] = GEN6_BVESYNC;
-	ring->semaphore.mbox.signal[VECS] = GEN6_NOSYNC;
-	ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+	if (i915_semaphore_is_enabled(dev)) {
+		ring->semaphore.sync_to = gen6_ring_sync;
+		ring->semaphore.signal = gen6_signal;
+		ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VER;
+		ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_VEV;
+		ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VEB;
+		ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID;
+		ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
+		ring->semaphore.mbox.signal[RCS] = GEN6_RVESYNC;
+		ring->semaphore.mbox.signal[VCS] = GEN6_VVESYNC;
+		ring->semaphore.mbox.signal[BCS] = GEN6_BVESYNC;
+		ring->semaphore.mbox.signal[VECS] = GEN6_NOSYNC;
+		ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+	}
 	ring->init = init_ring_common;
 
 	return intel_init_ring_buffer(dev, ring);
Signature · 6 lines
1.9.2

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 3 lines
Daniel Vetter
Software Engineer, Intel Corporation
+41 (0) 79 365 57 48 - http://blog.ffwll.ch
#6 lore raw

PATCH 5/13 drm/i915: gen specific ring init

In reply to Ben Widawsky

Gen8 has already had some differentiation with how it handles rings. Semaphores bring yet more differences, and now is as good a time as any to do the split.

Also, since gen8 doesn't actually use semaphores up until this point, put the proper "NULL" values in for the mbox info.

v2: v1 had a stale commit message

v3: Move everything in the is_semaphore_enabled() check

v4: VCS2 rebase
Remove double assignment of signal in render ring (Ville)

---
 drivers/gpu/drm/i915/intel_ringbuffer.c | 187 +++++++++++++++++++++-----------
 1 file changed, 123 insertions(+), 64 deletions(-)
drivers/gpu/drm/i915/intel_ringbuffer.c +123 -64
index 7aedc0c..f2bae6f 100644
@@ -1909,19 +1909,33 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
 	ring->id = RCS;
 	ring->mmio_base = RENDER_RING_BASE;
 
-	if (INTEL_INFO(dev)->gen >= 6) {
+	if (INTEL_INFO(dev)->gen >= 8) {
+		ring->add_request = gen6_add_request;
+		ring->flush = gen8_render_ring_flush;
+		ring->irq_get = gen8_ring_get_irq;
+		ring->irq_put = gen8_ring_put_irq;
+		ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT;
+		ring->get_seqno = gen6_ring_get_seqno;
+		ring->set_seqno = ring_set_seqno;
+		if (i915_semaphore_is_enabled(dev)) {
+			ring->semaphore.sync_to = gen6_ring_sync;
+			ring->semaphore.signal = gen6_signal;
+			ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.signal[RCS] = GEN6_NOSYNC;
+			ring->semaphore.mbox.signal[VCS] = GEN6_NOSYNC;
+			ring->semaphore.mbox.signal[BCS] = GEN6_NOSYNC;
+			ring->semaphore.mbox.signal[VECS] = GEN6_NOSYNC;
+		}
+	} else if (INTEL_INFO(dev)->gen >= 6) {
 		ring->add_request = gen6_add_request;
 		ring->flush = gen7_render_ring_flush;
 		if (INTEL_INFO(dev)->gen == 6)
 			ring->flush = gen6_render_ring_flush;
-		if (INTEL_INFO(dev)->gen >= 8) {
-			ring->flush = gen8_render_ring_flush;
-			ring->irq_get = gen8_ring_get_irq;
-			ring->irq_put = gen8_ring_put_irq;
-		} else {
-			ring->irq_get = gen6_ring_get_irq;
-			ring->irq_put = gen6_ring_put_irq;
-		}
+		ring->irq_get = gen6_ring_get_irq;
+		ring->irq_put = gen6_ring_put_irq;
 		ring->irq_enable_mask = GT_RENDER_USER_INTERRUPT;
 		ring->get_seqno = gen6_ring_get_seqno;
 		ring->set_seqno = ring_set_seqno;
@@ -1973,6 +1987,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
 		ring->irq_enable_mask = I915_USER_INTERRUPT;
 	}
 	ring->write_tail = ring_write_tail;
+
 	if (IS_HASWELL(dev))
 		ring->dispatch_execbuffer = hsw_ring_dispatch_execbuffer;
 	else if (IS_GEN8(dev))
@@ -2106,33 +2121,48 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev)
 			ring->irq_put = gen8_ring_put_irq;
 			ring->dispatch_execbuffer =
 				gen8_ring_dispatch_execbuffer;
+			if (i915_semaphore_is_enabled(dev)) {
+				ring->semaphore.sync_to = gen6_ring_sync;
+				ring->semaphore.signal = gen6_signal;
+				/*
+				 * The current semaphore is only applied on
+				 * pre-gen8 platform.  And there is no VCS2 ring
+				 * on the pre-gen8 platform. So the semaphore
+				 * between VCS and VCS2 is initialized as
+				 * INVALID.  Gen8 will initialize the sema
+				 * between VCS2 and VCS later.
+				 */
+				ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_INVALID;
+				ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID;
+				ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID;
+				ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID;
+				ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
+				ring->semaphore.mbox.signal[RCS] = GEN6_NOSYNC;
+				ring->semaphore.mbox.signal[VCS] = GEN6_NOSYNC;
+				ring->semaphore.mbox.signal[BCS] = GEN6_NOSYNC;
+				ring->semaphore.mbox.signal[VECS] = GEN6_NOSYNC;
+				ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+			}
 		} else {
 			ring->irq_enable_mask = GT_BSD_USER_INTERRUPT;
 			ring->irq_get = gen6_ring_get_irq;
 			ring->irq_put = gen6_ring_put_irq;
 			ring->dispatch_execbuffer =
 				gen6_ring_dispatch_execbuffer;
-		}
-		if (i915_semaphore_is_enabled(dev)) {
-			ring->semaphore.sync_to = gen6_ring_sync;
-			ring->semaphore.signal = gen6_signal;
-			/*
-			 * The current semaphore is only applied on pre-gen8
-			 * platform.  And there is no VCS2 ring on the pre-gen8
-			 * platform. So the semaphore between VCS and VCS2 is
-			 * initialized as INVALID.  Gen8 will initialize the
-			 * sema between VCS2 and VCS later.
-			 */
-			ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VR;
-			ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID;
-			ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VB;
-			ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_VVE;
-			ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
-			ring->semaphore.mbox.signal[RCS] = GEN6_RVSYNC;
-			ring->semaphore.mbox.signal[VCS] = GEN6_NOSYNC;
-			ring->semaphore.mbox.signal[BCS] = GEN6_BVSYNC;
-			ring->semaphore.mbox.signal[VECS] = GEN6_VEVSYNC;
-			ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+			if (i915_semaphore_is_enabled(dev)) {
+				ring->semaphore.sync_to = gen6_ring_sync;
+				ring->semaphore.signal = gen6_signal;
+				ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VR;
+				ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID;
+				ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VB;
+				ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_VVE;
+				ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
+				ring->semaphore.mbox.signal[RCS] = GEN6_RVSYNC;
+				ring->semaphore.mbox.signal[VCS] = GEN6_NOSYNC;
+				ring->semaphore.mbox.signal[BCS] = GEN6_BVSYNC;
+				ring->semaphore.mbox.signal[VECS] = GEN6_VEVSYNC;
+				ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+			}
 		}
 	} else {
 		ring->mmio_base = BSD_RING_BASE;
@@ -2228,31 +2258,46 @@ int intel_init_blt_ring_buffer(struct drm_device *dev)
 		ring->irq_get = gen8_ring_get_irq;
 		ring->irq_put = gen8_ring_put_irq;
 		ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer;
+		if (i915_semaphore_is_enabled(dev)) {
+			ring->semaphore.sync_to = gen6_ring_sync;
+			ring->semaphore.signal = gen6_signal;
+			ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.signal[RCS] = GEN6_NOSYNC;
+			ring->semaphore.mbox.signal[VCS] = GEN6_NOSYNC;
+			ring->semaphore.mbox.signal[BCS] = GEN6_NOSYNC;
+			ring->semaphore.mbox.signal[VECS] = GEN6_NOSYNC;
+			ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+		}
 	} else {
 		ring->irq_enable_mask = GT_BLT_USER_INTERRUPT;
 		ring->irq_get = gen6_ring_get_irq;
 		ring->irq_put = gen6_ring_put_irq;
 		ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
-	}
-	if (i915_semaphore_is_enabled(dev)) {
-		ring->semaphore.signal = gen6_signal;
-		ring->semaphore.sync_to = gen6_ring_sync;
-		/*
-		 * The current semaphore is only applied on pre-gen8 platform.
-		 * And there is no VCS2 ring on the pre-gen8 platform. So the
-		 * semaphore between BCS and VCS2 is initialized as INVALID.
-		 * Gen8 will initialize the sema between BCS and VCS2 later.
-		 */
-		ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_BR;
-		ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_BV;
-		ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID;
-		ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_BVE;
-		ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
-		ring->semaphore.mbox.signal[RCS] = GEN6_RBSYNC;
-		ring->semaphore.mbox.signal[VCS] = GEN6_VBSYNC;
-		ring->semaphore.mbox.signal[BCS] = GEN6_NOSYNC;
-		ring->semaphore.mbox.signal[VECS] = GEN6_VEBSYNC;
-		ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+		if (i915_semaphore_is_enabled(dev)) {
+			ring->semaphore.signal = gen6_signal;
+			ring->semaphore.sync_to = gen6_ring_sync;
+			/*
+			 * The current semaphore is only applied on pre-gen8
+			 * platform.  And there is no VCS2 ring on the pre-gen8
+			 * platform. So the semaphore between BCS and VCS2 is
+			 * initialized as INVALID.  Gen8 will initialize the
+			 * sema between BCS and VCS2 later.
+			 */
+			ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_BR;
+			ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_BV;
+			ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_BVE;
+			ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.signal[RCS] = GEN6_RBSYNC;
+			ring->semaphore.mbox.signal[VCS] = GEN6_VBSYNC;
+			ring->semaphore.mbox.signal[BCS] = GEN6_NOSYNC;
+			ring->semaphore.mbox.signal[VECS] = GEN6_VEBSYNC;
+			ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+		}
 	}
 	ring->init = init_ring_common;
 
@@ -2280,25 +2325,39 @@ int intel_init_vebox_ring_buffer(struct drm_device *dev)
 		ring->irq_get = gen8_ring_get_irq;
 		ring->irq_put = gen8_ring_put_irq;
 		ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer;
+		if (i915_semaphore_is_enabled(dev)) {
+			ring->semaphore.sync_to = gen6_ring_sync;
+			ring->semaphore.signal = gen6_signal;
+			ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.signal[RCS] = GEN6_NOSYNC;
+			ring->semaphore.mbox.signal[VCS] = GEN6_NOSYNC;
+			ring->semaphore.mbox.signal[BCS] = GEN6_NOSYNC;
+			ring->semaphore.mbox.signal[VECS] = GEN6_NOSYNC;
+			ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+		}
 	} else {
 		ring->irq_enable_mask = PM_VEBOX_USER_INTERRUPT;
 		ring->irq_get = hsw_vebox_get_irq;
 		ring->irq_put = hsw_vebox_put_irq;
 		ring->dispatch_execbuffer = gen6_ring_dispatch_execbuffer;
-	}
-	if (i915_semaphore_is_enabled(dev)) {
-		ring->semaphore.sync_to = gen6_ring_sync;
-		ring->semaphore.signal = gen6_signal;
-		ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VER;
-		ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_VEV;
-		ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VEB;
-		ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID;
-		ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
-		ring->semaphore.mbox.signal[RCS] = GEN6_RVESYNC;
-		ring->semaphore.mbox.signal[VCS] = GEN6_VVESYNC;
-		ring->semaphore.mbox.signal[BCS] = GEN6_BVESYNC;
-		ring->semaphore.mbox.signal[VECS] = GEN6_NOSYNC;
-		ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+		if (i915_semaphore_is_enabled(dev)) {
+			ring->semaphore.sync_to = gen6_ring_sync;
+			ring->semaphore.signal = gen6_signal;
+			ring->semaphore.mbox.wait[RCS] = MI_SEMAPHORE_SYNC_VER;
+			ring->semaphore.mbox.wait[VCS] = MI_SEMAPHORE_SYNC_VEV;
+			ring->semaphore.mbox.wait[BCS] = MI_SEMAPHORE_SYNC_VEB;
+			ring->semaphore.mbox.wait[VECS] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.wait[VCS2] = MI_SEMAPHORE_SYNC_INVALID;
+			ring->semaphore.mbox.signal[RCS] = GEN6_RVESYNC;
+			ring->semaphore.mbox.signal[VCS] = GEN6_VVESYNC;
+			ring->semaphore.mbox.signal[BCS] = GEN6_BVESYNC;
+			ring->semaphore.mbox.signal[VECS] = GEN6_NOSYNC;
+			ring->semaphore.mbox.signal[VCS2] = GEN6_NOSYNC;
+		}
 	}
 	ring->init = init_ring_common;
 
Signature · 1 line
1.9.2
#7 lore raw

PATCH 6/13 drm/i915/bdw: implement semaphore signal

In reply to Ben Widawsky

Semaphore signalling works similarly to previous GENs with the exception that the per ring mailboxes no longer exist. Instead you must define your own space, somewhere in the GTT.

The comments in the code define the layout I've opted for, which should be fairly future proof. Ie. I tried to define offsets in abstract terms (NUM_RINGS, seqno size, etc).

NOTE: If one wanted to move this to the HWSP they could. I've decided one 4k object would be easier to deal with, and provide potential wins with cache locality, but that's all speculative.

v2: Update the macro to not need the other ring's ring->id (Chris) Update the comment to use the correct formula (Chris)

v3: Move the macros the ringbuffer.h to prevent churn in next patch (Ville)

v4: Fixed compilation rebase conflict
commit 1ec9e26ddab06459e89a890431b2de064c5d1056

Author: Daniel Vetter <[email protected]>
Date:   Fri Feb 14 14:01:11 2014 +0100

drm/i915: Consolidate binding parameters into flags

v5: VCS2 rebase
Replace hweight_long with hweight32

---
 drivers/gpu/drm/i915/i915_drv.h         |   1 +
 drivers/gpu/drm/i915/i915_reg.h         |   5 +-
 drivers/gpu/drm/i915/intel_ringbuffer.c | 166 ++++++++++++++++++++++----------
 drivers/gpu/drm/i915/intel_ringbuffer.h |  78 +++++++++++++--
 4 files changed, 190 insertions(+), 60 deletions(-)
drivers/gpu/drm/i915/i915_drv.h +1 -0
index 50dfc3a..44cb744 100644
@@ -1293,6 +1293,7 @@ struct drm_i915_private {
 
 	struct pci_dev *bridge_dev;
 	struct intel_ring_buffer ring[I915_NUM_RINGS];
+	struct drm_i915_gem_object *semaphore_obj;
 	uint32_t last_seqno, next_seqno;
 
 	drm_dma_handle_t *status_page_dmah;
drivers/gpu/drm/i915/i915_reg.h +4 -1
index 0eff337..8e6ec03 100644
@@ -229,7 +229,7 @@
 #define   MI_DISPLAY_FLIP_IVB_SPRITE_B (3 << 19)
 #define   MI_DISPLAY_FLIP_IVB_PLANE_C  (4 << 19)
 #define   MI_DISPLAY_FLIP_IVB_SPRITE_C (5 << 19)
-#define MI_SEMAPHORE_MBOX	MI_INSTR(0x16, 1) /* gen6+ */
+#define MI_SEMAPHORE_MBOX	MI_INSTR(0x16, 1) /* gen6, gen7 */
 #define   MI_SEMAPHORE_GLOBAL_GTT    (1<<22)
 #define   MI_SEMAPHORE_UPDATE	    (1<<21)
 #define   MI_SEMAPHORE_COMPARE	    (1<<20)
@@ -255,6 +255,8 @@
 #define   MI_RESTORE_EXT_STATE_EN	(1<<2)
 #define   MI_FORCE_RESTORE		(1<<1)
 #define   MI_RESTORE_INHIBIT		(1<<0)
+#define MI_SEMAPHORE_SIGNAL	MI_INSTR(0x1b, 0) /* GEN8+ */
+#define   MI_SEMAPHORE_TARGET(engine)	((engine)<<15)
 #define MI_STORE_DWORD_IMM	MI_INSTR(0x20, 1)
 #define   MI_MEM_VIRTUAL	(1 << 22) /* 965+ only */
 #define MI_STORE_DWORD_INDEX	MI_INSTR(0x21, 1)
@@ -349,6 +351,7 @@
 #define   PIPE_CONTROL_TEXTURE_CACHE_INVALIDATE		(1<<10) /* GM45+ only */
 #define   PIPE_CONTROL_INDIRECT_STATE_DISABLE		(1<<9)
 #define   PIPE_CONTROL_NOTIFY				(1<<8)
+#define   PIPE_CONTROL_FLUSH_ENABLE			(1<<7) /* gen7+ */
 #define   PIPE_CONTROL_VF_CACHE_INVALIDATE		(1<<4)
 #define   PIPE_CONTROL_CONST_CACHE_INVALIDATE		(1<<3)
 #define   PIPE_CONTROL_STATE_CACHE_INVALIDATE		(1<<2)
drivers/gpu/drm/i915/intel_ringbuffer.c +113 -53

221 lines not on this page · raw message

drivers/gpu/drm/i915/intel_ringbuffer.h +72 -6

93 lines not on this page · raw message

Signature · 1 line
1.9.2
#8 lore raw

PATCH 7/13 drm/i915/bdw: implement semaphore wait

In reply to Ben Widawsky

Semaphore waits use a new instruction, MI_SEMAPHORE_WAIT. The seqno to wait on is all well defined by the table in the previous patch. There is nothing else different from previous GEN's semaphore synchronization code.

v2: Update macros to not require the other ring's ring->id (Chris)

---
 drivers/gpu/drm/i915/i915_reg.h         |  3 +++
 drivers/gpu/drm/i915/intel_ringbuffer.c | 33 +++++++++++++++++++++++++++++----
 drivers/gpu/drm/i915/intel_ringbuffer.h |  4 ++--
 3 files changed, 34 insertions(+), 6 deletions(-)
drivers/gpu/drm/i915/i915_reg.h +3 -0
index 8e6ec03..712ae05 100644
@@ -257,6 +257,9 @@
 #define   MI_RESTORE_INHIBIT		(1<<0)
 #define MI_SEMAPHORE_SIGNAL	MI_INSTR(0x1b, 0) /* GEN8+ */
 #define   MI_SEMAPHORE_TARGET(engine)	((engine)<<15)
+#define MI_SEMAPHORE_WAIT	MI_INSTR(0x1c, 2) /* GEN8+ */
+#define   MI_SEMAPHORE_POLL		(1<<15)
+#define   MI_SEMAPHORE_SAD_GTE_SDD	(1<<12)
 #define MI_STORE_DWORD_IMM	MI_INSTR(0x20, 1)
 #define   MI_MEM_VIRTUAL	(1 << 22) /* 965+ only */
 #define MI_STORE_DWORD_INDEX	MI_INSTR(0x21, 1)
drivers/gpu/drm/i915/intel_ringbuffer.c +29 -4
index 03324b2..31b1f3c 100644
@@ -827,6 +827,31 @@ static inline bool i915_gem_has_seqno_wrapped(struct drm_device *dev,
  * @signaller - ring which has, or will signal
  * @seqno - seqno which the waiter will block on
  */
+
+static int
+gen8_ring_sync(struct intel_ring_buffer *waiter,
+	       struct intel_ring_buffer *signaller,
+	       u32 seqno)
+{
+	struct drm_i915_private *dev_priv = waiter->dev->dev_private;
+	int ret;
+
+	ret = intel_ring_begin(waiter, 4);
+	if (ret)
+		return ret;
+
+	intel_ring_emit(waiter, MI_SEMAPHORE_WAIT |
+				MI_SEMAPHORE_GLOBAL_GTT |
+				MI_SEMAPHORE_SAD_GTE_SDD);
+	intel_ring_emit(waiter, seqno);
+	intel_ring_emit(waiter,
+			lower_32_bits(GEN8_WAIT_OFFSET(waiter, signaller->id)));
+	intel_ring_emit(waiter,
+			upper_32_bits(GEN8_WAIT_OFFSET(waiter, signaller->id)));
+	intel_ring_advance(waiter);
+	return 0;
+}
+
 static int
 gen6_ring_sync(struct intel_ring_buffer *waiter,
 	       struct intel_ring_buffer *signaller,
@@ -2023,7 +2048,7 @@ int intel_init_render_ring_buffer(struct drm_device *dev)
 		ring->set_seqno = ring_set_seqno;
 		if (i915_semaphore_is_enabled(dev)) {
 			BUG_ON(!dev_priv->semaphore_obj);
-			ring->semaphore.sync_to = gen6_ring_sync;
+			ring->semaphore.sync_to = gen8_ring_sync;
 			ring->semaphore.signal = gen8_rcs_signal;
 			GEN8_RING_SEMAPHORE_INIT;
 		}
@@ -2217,7 +2242,7 @@ int intel_init_bsd_ring_buffer(struct drm_device *dev)
 			ring->dispatch_execbuffer =
 				gen8_ring_dispatch_execbuffer;
 			if (i915_semaphore_is_enabled(dev)) {
-				ring->semaphore.sync_to = gen6_ring_sync;
+				ring->semaphore.sync_to = gen8_ring_sync;
 				ring->semaphore.signal = gen8_xcs_signal;
 				GEN8_RING_SEMAPHORE_INIT;
 			}
@@ -2337,7 +2362,7 @@ int intel_init_blt_ring_buffer(struct drm_device *dev)
 		ring->irq_put = gen8_ring_put_irq;
 		ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer;
 		if (i915_semaphore_is_enabled(dev)) {
-			ring->semaphore.sync_to = gen6_ring_sync;
+			ring->semaphore.sync_to = gen8_ring_sync;
 			ring->semaphore.signal = gen8_xcs_signal;
 			GEN8_RING_SEMAPHORE_INIT;
 		}
@@ -2395,7 +2420,7 @@ int intel_init_vebox_ring_buffer(struct drm_device *dev)
 		ring->irq_put = gen8_ring_put_irq;
 		ring->dispatch_execbuffer = gen8_ring_dispatch_execbuffer;
 		if (i915_semaphore_is_enabled(dev)) {
-			ring->semaphore.sync_to = gen6_ring_sync;
+			ring->semaphore.sync_to = gen8_ring_sync;
 			ring->semaphore.signal = gen8_xcs_signal;
 			GEN8_RING_SEMAPHORE_INIT;
 		}
drivers/gpu/drm/i915/intel_ringbuffer.h +2 -2
index d7de09b..a7ff166 100644
@@ -45,10 +45,10 @@ struct  intel_hw_status_page {
 	(ring->id * I915_NUM_RINGS * i915_semaphore_seqno_size) + \
 	(i915_semaphore_seqno_size * (to)))
 
-#define GEN8_WAIT_OFFSET(from) \
+#define GEN8_WAIT_OFFSET(__ring, from) \
 	(i915_gem_obj_ggtt_offset(dev_priv->semaphore_obj) + \
 	((from) * I915_NUM_RINGS * i915_semaphore_seqno_size) + \
-	(i915_semaphore_seqno_size * ring->id))
+	(i915_semaphore_seqno_size * (__ring)->id))
 
 #define GEN8_RING_SEMAPHORE_INIT do { \
 	if (!dev_priv->semaphore_obj) { \
Signature · 1 line
1.9.2
#9 lore raw

PATCH 8/13 drm/i915: Implement MI decode for gen8

In reply to Ben Widawsky

From: Ben Widawsky <[email protected]>

This is needed to implement ipehr_is_semaphore_wait

---
 drivers/gpu/drm/i915/i915_irq.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)
drivers/gpu/drm/i915/i915_irq.c +5 -6
index 2d76183..bfd21c7 100644
@@ -2561,12 +2561,9 @@ static bool
 ipehr_is_semaphore_wait(struct drm_device *dev, u32 ipehr)
 {
 	if (INTEL_INFO(dev)->gen >= 8) {
-		/*
-		 * FIXME: gen8 semaphore support - currently we don't emit
-		 * semaphores on bdw anyway, but this needs to be addressed when
-		 * we merge that code.
-		 */
-		return false;
+		/* Broadwell's semaphore wait is 3 dwords. We hope IPEHR is the
+		 * first dword. */
+		return (ipehr >> 23) == 0x1c;
 	} else {
 		ipehr &= ~MI_SEMAPHORE_SYNC_MASK;
 		return ipehr == (MI_SEMAPHORE_MBOX | MI_SEMAPHORE_COMPARE |
@@ -2586,6 +2583,8 @@ semaphore_wait_to_signaller_ring(struct intel_ring_buffer *ring, u32 ipehr)
 		 * FIXME: gen8 semaphore support - currently we don't emit
 		 * semaphores on bdw anyway, but this needs to be addressed when
 		 * we merge that code.
+		 *
+		 * XXX: Gen8 needs more than just IPEHR.
 		 */
 		return NULL;
 	} else {
Signature · 1 line
1.9.2
#10 lore raw

Re: [PATCH 08/13] drm/i915: Implement MI decode for gen8

Quoted 30 lines · Ben Widawsky

From: Ben Widawsky <[email protected]>

This is needed to implement ipehr_is_semaphore_wait

---
 drivers/gpu/drm/i915/i915_irq.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)
drivers/gpu/drm/i915/i915_irq.c +3 -6
index 2d76183..bfd21c7 100644
@@ -2561,12 +2561,9 @@ static bool
 ipehr_is_semaphore_wait(struct drm_device *dev, u32 ipehr)
 {
 	if (INTEL_INFO(dev)->gen >= 8) {
-		/*
-		 * FIXME: gen8 semaphore support - currently we don't emit
-		 * semaphores on bdw anyway, but this needs to be addressed when
-		 * we merge that code.
-		 */
-		return false;
+		/* Broadwell's semaphore wait is 3 dwords. We hope IPEHR is the
+		 * first dword. */
+		return (ipehr >> 23) == 0x1c;
 	} else {
 		ipehr &= ~MI_SEMAPHORE_SYNC_MASK;
 		return ipehr == (MI_SEMAPHORE_MBOX | MI_SEMAPHORE_COMPARE |

drivers/gpu/drm/i915/i915_irq.c semaphore_wait_to_signaller_ring(struct intel_ring_buffer *ring, u32 ipehr) · line 2588

Quoted 6 lines
drivers/gpu/drm/i915/i915_irq.c +2 -0
@@ -2586,6 +2583,8 @@ semaphore_wait_to_signaller_ring(struct intel_ring_buffer *ring, u32 ipehr)
 		 * FIXME: gen8 semaphore support - currently we don't emit
 		 * semaphores on bdw anyway, but this needs to be addressed when
 		 * we merge that code.
+		 *
+		 * XXX: Gen8 needs more than just IPEHR.
 		 */

I believe something like this should take care of the remaining gap.

drivers/gpu/drm/i915/i915_irq.c +16 -8
index 2446e61..cd1069e 100644
@@ -2590,19 +2590,21 @@ ipehr_is_semaphore_wait(struct drm_device *dev, u32 ipehr)
 }
 
 static struct intel_ring_buffer *
-semaphore_wait_to_signaller_ring(struct intel_ring_buffer *ring, u32 ipehr)
+semaphore_wait_to_signaller_ring(struct intel_ring_buffer *ring,
+				 u32 ipehr, u64 offset)
 {
 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
 	struct intel_ring_buffer *signaller;
 	int i;
 
 	if (INTEL_INFO(dev_priv->dev)->gen >= 8) {
-		/*
-		 * FIXME: gen8 semaphore support - currently we don't emit
-		 * semaphores on bdw anyway, but this needs to be addressed when
-		 * we merge that code.
-		 */
-		return NULL;
+		for_each_ring(signaller, dev_priv, i) {
+			if (ring == signaller)
+				continue;
+
+			if (offset == signaller->semaphore.signal_gtt[ring->id])
+				return signaller;
+		}
 	} else {
 		u32 sync_bits = ipehr & MI_SEMAPHORE_SYNC_MASK;
 
@@ -2627,6 +2629,7 @@ semaphore_waits_for(struct intel_ring_buffer *ring, u32 *seqno)
 {
 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
 	u32 cmd, ipehr, head;
+	u64 offset = 0;
 	int i;
 
 	ipehr = I915_READ(RING_IPEHR(ring->mmio_base));
@@ -2662,7 +2665,12 @@ semaphore_waits_for(struct intel_ring_buffer *ring, u32 *seqno)
 		return NULL;
 
 	*seqno = ioread32(ring->virtual_start + head + 4) + 1;
-	return semaphore_wait_to_signaller_ring(ring, ipehr);
+	if (INTEL_INFO(dev_priv->dev)->gen >= 8) {
+		offset = ioread32(ring->virtual_start + head + 12);
+		offset <<= 32;
+		offset |= ioread32(ring->virtual_start + head + 8);
+	}
+	return semaphore_wait_to_signaller_ring(ring, ipehr, offset);
 }
 
 static int semaphore_passed(struct intel_ring_buffer *ring)
Signature · 1 line
1.8.3.2
Quoted 9 lines
drivers/gpu/drm/i915/i915_irq.c +0 -0
 		return NULL;
 	} else {
Signature · 6 lines
1.9.2

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 2 lines
Ville Syrjälä
Intel OTC
#11 lore raw

Re: [PATCH 08/13] drm/i915: Implement MI decode for gen8

Quoted 31 lines · Ville Syrjälä
Quoted 30 lines · Ben Widawsky

From: Ben Widawsky <[email protected]>

This is needed to implement ipehr_is_semaphore_wait

---
 drivers/gpu/drm/i915/i915_irq.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)
drivers/gpu/drm/i915/i915_irq.c +3 -6
index 2d76183..bfd21c7 100644
@@ -2561,12 +2561,9 @@ static bool
 ipehr_is_semaphore_wait(struct drm_device *dev, u32 ipehr)
 {
 	if (INTEL_INFO(dev)->gen >= 8) {
-		/*
-		 * FIXME: gen8 semaphore support - currently we don't emit
-		 * semaphores on bdw anyway, but this needs to be addressed when
-		 * we merge that code.
-		 */
-		return false;
+		/* Broadwell's semaphore wait is 3 dwords. We hope IPEHR is the
+		 * first dword. */
+		return (ipehr >> 23) == 0x1c;
 	} else {
 		ipehr &= ~MI_SEMAPHORE_SYNC_MASK;
 		return ipehr == (MI_SEMAPHORE_MBOX | MI_SEMAPHORE_COMPARE |
@@ -2586,6 +2583,8 @@ semaphore_wait_to_signaller_ring(struct intel_ring_buffer *ring, u32 ipehr)
Quoted 9 lines

drivers/gpu/drm/i915/i915_irq.c semaphore_wait_to_signaller_ring(struct intel_ring_buffer *ring, u32 ipehr) · line 2588

Quoted 6 lines
drivers/gpu/drm/i915/i915_irq.c +2 -0
 		 * FIXME: gen8 semaphore support - currently we don't emit
 		 * semaphores on bdw anyway, but this needs to be addressed when
 		 * we merge that code.
+		 *
+		 * XXX: Gen8 needs more than just IPEHR.
 		 */

I believe something like this should take care of the remaining gap.

Thanks for the help. At this point I just want to get the damn thing merged, and want to avoid any extra risk. Would you mind resending this as a distinct patch (authored by you), after we get the rest merged?

Quoted 76 lines
drivers/gpu/drm/i915/i915_irq.c +16 -8
index 2446e61..cd1069e 100644
@@ -2590,19 +2590,21 @@ ipehr_is_semaphore_wait(struct drm_device *dev, u32 ipehr)
 }
 
 static struct intel_ring_buffer *
-semaphore_wait_to_signaller_ring(struct intel_ring_buffer *ring, u32 ipehr)
+semaphore_wait_to_signaller_ring(struct intel_ring_buffer *ring,
+				 u32 ipehr, u64 offset)
 {
 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
 	struct intel_ring_buffer *signaller;
 	int i;
 
 	if (INTEL_INFO(dev_priv->dev)->gen >= 8) {
-		/*
-		 * FIXME: gen8 semaphore support - currently we don't emit
-		 * semaphores on bdw anyway, but this needs to be addressed when
-		 * we merge that code.
-		 */
-		return NULL;
+		for_each_ring(signaller, dev_priv, i) {
+			if (ring == signaller)
+				continue;
+
+			if (offset == signaller->semaphore.signal_gtt[ring->id])
+				return signaller;
+		}
 	} else {
 		u32 sync_bits = ipehr & MI_SEMAPHORE_SYNC_MASK;
 
@@ -2627,6 +2629,7 @@ semaphore_waits_for(struct intel_ring_buffer *ring, u32 *seqno)
 {
 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
 	u32 cmd, ipehr, head;
+	u64 offset = 0;
 	int i;
 
 	ipehr = I915_READ(RING_IPEHR(ring->mmio_base));
@@ -2662,7 +2665,12 @@ semaphore_waits_for(struct intel_ring_buffer *ring, u32 *seqno)
 		return NULL;
 
 	*seqno = ioread32(ring->virtual_start + head + 4) + 1;
-	return semaphore_wait_to_signaller_ring(ring, ipehr);
+	if (INTEL_INFO(dev_priv->dev)->gen >= 8) {
+		offset = ioread32(ring->virtual_start + head + 12);
+		offset <<= 32;
+		offset |= ioread32(ring->virtual_start + head + 8);
+	}
+	return semaphore_wait_to_signaller_ring(ring, ipehr, offset);
 }
 
 static int semaphore_passed(struct intel_ring_buffer *ring)
Signature · 1 line
1.8.3.2
Quoted 9 lines
drivers/gpu/drm/i915/i915_irq.c +0 -0
 		return NULL;
 	} else {
Signature · 6 lines
1.9.2

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 6 lines
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 5 lines
Ben Widawsky, Intel Open Source Technology Center
_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
#12 lore raw

Re: [PATCH 08/13] drm/i915: Implement MI decode for gen8

Quoted 42 lines · Ben Widawsky
Quoted 31 lines · Ville Syrjälä
Quoted 30 lines · Ben Widawsky

From: Ben Widawsky <[email protected]>

This is needed to implement ipehr_is_semaphore_wait

---
 drivers/gpu/drm/i915/i915_irq.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)
drivers/gpu/drm/i915/i915_irq.c +3 -6
index 2d76183..bfd21c7 100644
@@ -2561,12 +2561,9 @@ static bool
 ipehr_is_semaphore_wait(struct drm_device *dev, u32 ipehr)
 {
 	if (INTEL_INFO(dev)->gen >= 8) {
-		/*
-		 * FIXME: gen8 semaphore support - currently we don't emit
-		 * semaphores on bdw anyway, but this needs to be addressed when
-		 * we merge that code.
-		 */
-		return false;
+		/* Broadwell's semaphore wait is 3 dwords. We hope IPEHR is the
+		 * first dword. */
+		return (ipehr >> 23) == 0x1c;
 	} else {
 		ipehr &= ~MI_SEMAPHORE_SYNC_MASK;
 		return ipehr == (MI_SEMAPHORE_MBOX | MI_SEMAPHORE_COMPARE |
@@ -2586,6 +2583,8 @@ semaphore_wait_to_signaller_ring(struct intel_ring_buffer *ring, u32 ipehr)
Quoted 9 lines

drivers/gpu/drm/i915/i915_irq.c semaphore_wait_to_signaller_ring(struct intel_ring_buffer *ring, u32 ipehr) · line 2588

Quoted 6 lines
drivers/gpu/drm/i915/i915_irq.c +2 -0
 		 * FIXME: gen8 semaphore support - currently we don't emit
 		 * semaphores on bdw anyway, but this needs to be addressed when
 		 * we merge that code.
+		 *
+		 * XXX: Gen8 needs more than just IPEHR.
 		 */

I believe something like this should take care of the remaining gap.

Quoted 3 lines

Thanks for the help. At this point I just want to get the damn thing merged, and want to avoid any extra risk. Would you mind resending this as a distinct patch (authored by you), after we get the rest merged?

Can do.

Quoted 80 lines
Quoted 77 lines
drivers/gpu/drm/i915/i915_irq.c +16 -8
index 2446e61..cd1069e 100644
@@ -2590,19 +2590,21 @@ ipehr_is_semaphore_wait(struct drm_device *dev, u32 ipehr)
 }
 
 static struct intel_ring_buffer *
-semaphore_wait_to_signaller_ring(struct intel_ring_buffer *ring, u32 ipehr)
+semaphore_wait_to_signaller_ring(struct intel_ring_buffer *ring,
+				 u32 ipehr, u64 offset)
 {
 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
 	struct intel_ring_buffer *signaller;
 	int i;
 
 	if (INTEL_INFO(dev_priv->dev)->gen >= 8) {
-		/*
-		 * FIXME: gen8 semaphore support - currently we don't emit
-		 * semaphores on bdw anyway, but this needs to be addressed when
-		 * we merge that code.
-		 */
-		return NULL;
+		for_each_ring(signaller, dev_priv, i) {
+			if (ring == signaller)
+				continue;
+
+			if (offset == signaller->semaphore.signal_gtt[ring->id])
+				return signaller;
+		}
 	} else {
 		u32 sync_bits = ipehr & MI_SEMAPHORE_SYNC_MASK;
 
@@ -2627,6 +2629,7 @@ semaphore_waits_for(struct intel_ring_buffer *ring, u32 *seqno)
 {
 	struct drm_i915_private *dev_priv = ring->dev->dev_private;
 	u32 cmd, ipehr, head;
+	u64 offset = 0;
 	int i;
 
 	ipehr = I915_READ(RING_IPEHR(ring->mmio_base));
@@ -2662,7 +2665,12 @@ semaphore_waits_for(struct intel_ring_buffer *ring, u32 *seqno)
 		return NULL;
 
 	*seqno = ioread32(ring->virtual_start + head + 4) + 1;
-	return semaphore_wait_to_signaller_ring(ring, ipehr);
+	if (INTEL_INFO(dev_priv->dev)->gen >= 8) {
+		offset = ioread32(ring->virtual_start + head + 12);
+		offset <<= 32;
+		offset |= ioread32(ring->virtual_start + head + 8);
+	}
+	return semaphore_wait_to_signaller_ring(ring, ipehr, offset);
 }
 
 static int semaphore_passed(struct intel_ring_buffer *ring)
Signature · 1 line
1.8.3.2
Quoted 9 lines
drivers/gpu/drm/i915/i915_irq.c +0 -0
 		return NULL;
 	} else {
Signature · 6 lines
1.9.2

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 6 lines
Ville Syrjälä
Intel OTC
_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 1 line
Ben Widawsky, Intel Open Source Technology Center
Signature · 2 lines
Ville Syrjälä
Intel OTC
#13 lore raw

PATCH 9/13 drm/i915/bdw: poll semaphores

In reply to Ben Widawsky

As Ville points out, it's possible/probable we don't actually need this. Potentially, this validates the letter of the spec, and not the spirit.

Ville:

Quoted 6 lines

I discussed this on irc w/ Ben, and I was suggesting we don't need to poll. Polling apparently can be used as a workaround for certain hardware issues, but it looks like those issues shouldn't affect us, for the momemnt at least. So my suggestion was to try w/o polling first (since there could be some power cost to polling) and add the poll bit if problems arise.

---
 drivers/gpu/drm/i915/intel_ringbuffer.c | 1 +
 1 file changed, 1 insertion(+)
drivers/gpu/drm/i915/intel_ringbuffer.c +1 -0
index 31b1f3c..e7748ef 100644
@@ -842,6 +842,7 @@ gen8_ring_sync(struct intel_ring_buffer *waiter,
 
 	intel_ring_emit(waiter, MI_SEMAPHORE_WAIT |
 				MI_SEMAPHORE_GLOBAL_GTT |
+				MI_SEMAPHORE_POLL |
 				MI_SEMAPHORE_SAD_GTE_SDD);
 	intel_ring_emit(waiter, seqno);
 	intel_ring_emit(waiter,
Signature · 1 line
1.9.2
#14 lore raw

Re: [PATCH 09/13] drm/i915/bdw: poll semaphores

Quoted 10 lines · Ben Widawsky

As Ville points out, it's possible/probable we don't actually need this. Potentially, this validates the letter of the spec, and not the spirit.

Ville:

Quoted 6 lines

I discussed this on irc w/ Ben, and I was suggesting we don't need to poll. Polling apparently can be used as a workaround for certain hardware issues, but it looks like those issues shouldn't affect us, for the momemnt at least. So my suggestion was to try w/o polling first (since there could be some power cost to polling) and add the poll bit if problems arise.

I had another look at bspec and there seems to be a bit more text about the signal mode stuff since the last time I looked. But it still looks like signal mode should be OK for production hardware.

One of the workarounds says that !RCS rings can lose the PPGTT page directory information when becoming idle while waiting for a semaphore. The workaround is either reprogamming the PPGTT after semaphore wait or disabling the idle message. We already disable the idle message for RCS for some other reason but not for the other rings. Doing that for all rings seems like the easier option here. This seems to apply to production hardware.

There's another idle message disable w/a (using another bit which maybe disables more rc states?) but that seems to affect only pre-production hardware. Here the other option here is to use polling instead.

Quoted 25 lines
---
 drivers/gpu/drm/i915/intel_ringbuffer.c | 1 +
 1 file changed, 1 insertion(+)
drivers/gpu/drm/i915/intel_ringbuffer.c +1 -0
index 31b1f3c..e7748ef 100644
@@ -842,6 +842,7 @@ gen8_ring_sync(struct intel_ring_buffer *waiter,
 
 	intel_ring_emit(waiter, MI_SEMAPHORE_WAIT |
 				MI_SEMAPHORE_GLOBAL_GTT |
+				MI_SEMAPHORE_POLL |
 				MI_SEMAPHORE_SAD_GTE_SDD);
 	intel_ring_emit(waiter, seqno);
 	intel_ring_emit(waiter,
Signature · 6 lines
1.9.2

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 2 lines
Ville Syrjälä
Intel OTC
#15 lore raw

PATCH 10/13 drm/i915: Extract semaphore error collection

In reply to Ben Widawsky
---
 drivers/gpu/drm/i915/i915_gpu_error.c | 30 ++++++++++++++++++------------
 1 file changed, 18 insertions(+), 12 deletions(-)
drivers/gpu/drm/i915/i915_gpu_error.c +18 -12
index 2d81985..a7eaab2 100644
@@ -744,6 +744,23 @@ static void i915_gem_record_fences(struct drm_device *dev,
 	}
 }
 
+
+static void gen6_record_semaphore_state(struct drm_i915_private *dev_priv,
+					struct intel_ring_buffer *ring,
+					struct drm_i915_error_ring *ering)
+{
+	ering->semaphore_mboxes[0] = I915_READ(RING_SYNC_0(ring->mmio_base));
+	ering->semaphore_mboxes[1] = I915_READ(RING_SYNC_1(ring->mmio_base));
+	ering->semaphore_seqno[0] = ring->semaphore.sync_seqno[0];
+	ering->semaphore_seqno[1] = ring->semaphore.sync_seqno[1];
+
+	if (HAS_VEBOX(dev_priv->dev)) {
+		ering->semaphore_mboxes[2] =
+			I915_READ(RING_SYNC_2(ring->mmio_base));
+		ering->semaphore_seqno[2] = ring->semaphore.sync_seqno[2];
+	}
+}
+
 static void i915_record_ring_state(struct drm_device *dev,
 				   struct intel_ring_buffer *ring,
 				   struct drm_i915_error_ring *ering)
@@ -753,18 +770,7 @@ static void i915_record_ring_state(struct drm_device *dev,
 	if (INTEL_INFO(dev)->gen >= 6) {
 		ering->rc_psmi = I915_READ(ring->mmio_base + 0x50);
 		ering->fault_reg = I915_READ(RING_FAULT_REG(ring));
-		ering->semaphore_mboxes[0]
-			= I915_READ(RING_SYNC_0(ring->mmio_base));
-		ering->semaphore_mboxes[1]
-			= I915_READ(RING_SYNC_1(ring->mmio_base));
-		ering->semaphore_seqno[0] = ring->semaphore.sync_seqno[0];
-		ering->semaphore_seqno[1] = ring->semaphore.sync_seqno[1];
-	}
-
-	if (HAS_VEBOX(dev)) {
-		ering->semaphore_mboxes[2] =
-			I915_READ(RING_SYNC_2(ring->mmio_base));
-		ering->semaphore_seqno[2] = ring->semaphore.sync_seqno[2];
+		gen6_record_semaphore_state(dev_priv, ring, ering);
 	}
 
 	if (INTEL_INFO(dev)->gen >= 4) {
Signature · 1 line
1.9.2
#16 lore raw

PATCH 11/13 drm/i915/bdw: collect semaphore error state

In reply to Ben Widawsky

Since the semaphore information is in an object, just dump it, and let the user parse it later.

NOTE: The page being used for the semaphores are incoherent with the CPU. No matter what I do, I cannot figure out a way to read anything but 0s. Note that the semaphore waits are indeed working.

v2: Don't print signal, and wait (they should be the same). Instead, print sync_seqno (Chris)

v3: Free the semaphore error object (Chris)

v4: Fix semaphore offset calculation during error state collection (Ville)

v5: VCS2 rebase
Make semaphore object error capture coding style consistent (Ville) Do the proper math for the signal offset (Ville)

---
 drivers/gpu/drm/i915/i915_drv.h         |  1 +
 drivers/gpu/drm/i915/i915_gpu_error.c   | 51 ++++++++++++++++++++++++++++++---
 drivers/gpu/drm/i915/intel_ringbuffer.h | 14 ++++-----
 3 files changed, 55 insertions(+), 11 deletions(-)
drivers/gpu/drm/i915/i915_drv.h +1 -0
index 44cb744..237faf3 100644
@@ -328,6 +328,7 @@ struct drm_i915_error_state {
 	u64 fence[I915_MAX_NUM_FENCES];
 	struct intel_overlay_error_state *overlay;
 	struct intel_display_error_state *display;
+	struct drm_i915_error_object *semaphore_obj;
 
 	struct drm_i915_error_ring {
 		bool valid;
drivers/gpu/drm/i915/i915_gpu_error.c +47 -4

99 lines not on this page · raw message

drivers/gpu/drm/i915/intel_ringbuffer.h +7 -7
index a7ff166..20af934 100644
@@ -40,9 +40,9 @@ struct  intel_hw_status_page {
  * do the writes, and that must have qw aligned offsets, simply pretend it's 8b.
  */
 #define i915_semaphore_seqno_size sizeof(uint64_t)
-#define GEN8_SIGNAL_OFFSET(to) \
+#define GEN8_SIGNAL_OFFSET(__ring, to) \
 	(i915_gem_obj_ggtt_offset(dev_priv->semaphore_obj) + \
-	(ring->id * I915_NUM_RINGS * i915_semaphore_seqno_size) + \
+	((__ring)->id * I915_NUM_RINGS * i915_semaphore_seqno_size) + \
 	(i915_semaphore_seqno_size * (to)))
 
 #define GEN8_WAIT_OFFSET(__ring, from) \
@@ -54,11 +54,11 @@ struct  intel_hw_status_page {
 	if (!dev_priv->semaphore_obj) { \
 		break; \
 	} \
-	ring->semaphore.signal_ggtt[RCS] = GEN8_SIGNAL_OFFSET(RCS); \
-	ring->semaphore.signal_ggtt[VCS] = GEN8_SIGNAL_OFFSET(VCS); \
-	ring->semaphore.signal_ggtt[BCS] = GEN8_SIGNAL_OFFSET(BCS); \
-	ring->semaphore.signal_ggtt[VECS] = GEN8_SIGNAL_OFFSET(VECS); \
-	ring->semaphore.signal_ggtt[VCS2] = GEN8_SIGNAL_OFFSET(VCS2); \
+	ring->semaphore.signal_ggtt[RCS] = GEN8_SIGNAL_OFFSET(ring, RCS); \
+	ring->semaphore.signal_ggtt[VCS] = GEN8_SIGNAL_OFFSET(ring, VCS); \
+	ring->semaphore.signal_ggtt[BCS] = GEN8_SIGNAL_OFFSET(ring, BCS); \
+	ring->semaphore.signal_ggtt[VECS] = GEN8_SIGNAL_OFFSET(ring, VECS); \
+	ring->semaphore.signal_ggtt[VCS2] = GEN8_SIGNAL_OFFSET(ring, VCS2); \
 	ring->semaphore.signal_ggtt[ring->id] = MI_SEMAPHORE_SYNC_INVALID; \
 	} while(0)
 
Signature · 1 line
1.9.2
#17 lore raw

PATCH 12/13 drm/i915: semaphore debugfs

In reply to Ben Widawsky

Simple debugfs file to display the current state of semaphores. This is useful if you want to see the state without hanging the GPU.

NOTE: This patch is optional to the series.

NOTE2: Like the GPU error state collection, the reads are currently incoherent.

---
 drivers/gpu/drm/i915/i915_debugfs.c | 70 +++++++++++++++++++++++++++++++++++++
 1 file changed, 70 insertions(+)
drivers/gpu/drm/i915/i915_debugfs.c +70 -0
index cad175c..0e02901 100644
@@ -2332,6 +2332,75 @@ static int i915_display_info(struct seq_file *m, void *unused)
 	return 0;
 }
 
+static int i915_semaphore_status(struct seq_file *m, void *unused)
+{
+	struct drm_info_node *node = (struct drm_info_node *) m->private;
+	struct drm_device *dev = node->minor->dev;
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	struct intel_ring_buffer *ring;
+	int i, j, ret;
+
+	if (!i915_semaphore_is_enabled(dev)) {
+		seq_puts(m, "Semaphores are disabled\n");
+		return 0;
+	}
+
+	ret = mutex_lock_interruptible(&dev->struct_mutex);
+	if (ret)
+		return ret;
+
+	if (IS_BROADWELL(dev)) {
+		struct page *page;
+		uint64_t *seqno;
+
+		page = i915_gem_object_get_page(dev_priv->semaphore_obj, 0);
+
+		seqno = (uint64_t *)kmap_atomic(page);
+		for_each_ring(ring, dev_priv, i) {
+			uint64_t offset;
+
+			seq_printf(m, "%s\n", ring->name);
+
+			seq_puts(m, "  Last signal:");
+			for (j = 0; j < I915_NUM_RINGS; j++) {
+				offset = i * I915_NUM_RINGS + j;
+				seq_printf(m, "0x%08llx (0x%02llx) ",
+					   seqno[offset], offset * 8);
+			}
+			seq_putc(m, '\n');
+
+			seq_puts(m, "  Last wait:  ");
+			for (j = 0; j < I915_NUM_RINGS; j++) {
+				offset = i + (j * I915_NUM_RINGS);
+				seq_printf(m, "0x%08llx (0x%02llx) ",
+					   seqno[offset], offset * 8);
+			}
+			seq_putc(m, '\n');
+
+		}
+		kunmap_atomic(seqno);
+	} else {
+		seq_puts(m, "  Last signal:");
+		for_each_ring(ring, dev_priv, i)
+			for (j = 0; j < I915_NUM_RINGS; j++)
+				seq_printf(m, "0x%08x\n",
+					   I915_READ(ring->semaphore.mbox.signal[j]));
+		seq_putc(m, '\n');
+	}
+
+	seq_puts(m, "\nSync seqno:\n");
+	for_each_ring(ring, dev_priv, i) {
+		for (j = 0; j < I915_NUM_RINGS; j++) {
+			seq_printf(m, "  0x%08x ", ring->semaphore.sync_seqno[j]);
+		}
+		seq_putc(m, '\n');
+	}
+	seq_putc(m, '\n');
+
+	mutex_unlock(&dev->struct_mutex);
+	return 0;
+}
+
 struct pipe_crc_info {
 	const char *name;
 	struct drm_device *dev;
@@ -3778,6 +3847,7 @@ static const struct drm_info_list i915_debugfs_list[] = {
 	{"i915_pc8_status", i915_pc8_status, 0},
 	{"i915_power_domain_info", i915_power_domain_info, 0},
 	{"i915_display_info", i915_display_info, 0},
+	{"i915_semaphore_status", i915_semaphore_status, 0},
 };
 #define I915_DEBUGFS_ENTRIES ARRAY_SIZE(i915_debugfs_list)
 
Signature · 1 line
1.9.2
#18 lore raw

PATCH 1/1 drm/i915: Small semaphore debugfs fixup

Each ring only has ring-1 sync seqnos. It is a bug to try to print extra.

This should be squashed into drm/i915: semaphore debugfs. I don't have an easy way at the moment to do the rebase and resend, but that is what should be done.

---
 drivers/gpu/drm/i915/i915_debugfs.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
drivers/gpu/drm/i915/i915_debugfs.c +1 -1
index 0c4159d..7cd3c7f 100644
@@ -2443,7 +2443,7 @@ static int i915_semaphore_status(struct seq_file *m, void *unused)
 
 	seq_puts(m, "\nSync seqno:\n");
 	for_each_ring(ring, dev_priv, i) {
-		for (j = 0; j < I915_NUM_RINGS; j++) {
+		for (j = 0; j < I915_NUM_RINGS - 1; j++) {
 			seq_printf(m, "  0x%08x ", ring->semaphore.sync_seqno[j]);
 		}
 		seq_putc(m, '\n');
Signature · 1 line
1.9.2
#19 lore raw

PATCH 13/13 DONT_MERGE drm/i915: FORCE_RESTORE for gen8 semaphores

In reply to Ben Widawsky

This appears to not actually be needed on the current code. Just putting it on the ML so we can point bug reports at it later.

As pointed out by Ville, the current code is "broken" since we do FORCE_RESTORE, and RESTORE_INHIBIT on the same dword. Anecdotally, this seems fine.

---
 drivers/gpu/drm/i915/i915_gem_context.c | 7 +++++++
 1 file changed, 7 insertions(+)
drivers/gpu/drm/i915/i915_gem_context.c +7 -0
index f77b4c1..aa82fb4 100644
@@ -661,6 +661,13 @@ static int do_switch(struct intel_ring_buffer *ring,
 	if (!to->is_initialized || i915_gem_context_is_default(to))
 		hw_flags |= MI_RESTORE_INHIBIT;
 
+	/* When SW intends to use semaphore signaling between Command streamers,
+	 * it must avoid lite restores in HW by programming "Force Restore" bit
+	 * to ‘1’ in context descriptor during context submission
+	 */
+	if (IS_GEN8(ring->dev) && i915_semaphore_is_enabled(ring->dev))
+		hw_flags |= MI_FORCE_RESTORE;
+
 	ret = mi_set_context(ring, to, hw_flags);
 	if (ret)
 		goto unpin_out;
Signature · 6 lines
1.9.2

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
#20 lore raw

Re: [PATCH 13/13] DONT_MERGE drm/i915: FORCE_RESTORE for gen8 semaphores

Quoted 17 lines · Ben Widawsky

This appears to not actually be needed on the current code. Just putting it on the ML so we can point bug reports at it later.

As pointed out by Ville, the current code is "broken" since we do FORCE_RESTORE, and RESTORE_INHIBIT on the same dword. Anecdotally, this seems fine.

---
 drivers/gpu/drm/i915/i915_gem_context.c | 7 +++++++
 1 file changed, 7 insertions(+)
drivers/gpu/drm/i915/i915_gem_context.c +0 -0
index f77b4c1..aa82fb4 100644

drivers/gpu/drm/i915/i915_gem_context.c static int do_switch(struct intel_ring_buffer *ring, · line 669

Quoted 9 lines
drivers/gpu/drm/i915/i915_gem_context.c +6 -0
@@ -661,6 +661,13 @@ static int do_switch(struct intel_ring_buffer *ring,
 	if (!to->is_initialized || i915_gem_context_is_default(to))
 		hw_flags |= MI_RESTORE_INHIBIT;
 
+	/* When SW intends to use semaphore signaling between Command streamers,
+	 * it must avoid lite restores in HW by programming "Force Restore" bit
+	 * to ‘1’ in context descriptor during context submission
+	 */
+	if (IS_GEN8(ring->dev) && i915_semaphore_is_enabled(ring->dev))
+		hw_flags |= MI_FORCE_RESTORE;

Is it not an error to set both FORCE and INHIBIT?
-Chris

Signature · 5 lines
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
#21 lore raw

Re: [PATCH 13/13] DONT_MERGE drm/i915: FORCE_RESTORE for gen8 semaphores

Quoted 21 lines · Chris Wilson
Quoted 20 lines · Ben Widawsky

This appears to not actually be needed on the current code. Just putting it on the ML so we can point bug reports at it later.

As pointed out by Ville, the current code is "broken" since we do FORCE_RESTORE, and RESTORE_INHIBIT on the same dword. Anecdotally, this seems fine.

---
 drivers/gpu/drm/i915/i915_gem_context.c | 7 +++++++
 1 file changed, 7 insertions(+)
drivers/gpu/drm/i915/i915_gem_context.c +0 -0
index f77b4c1..aa82fb4 100644
@@ -661,6 +661,13 @@ static int do_switch(struct intel_ring_buffer *ring,
 	if (!to->is_initialized || i915_gem_context_is_default(to))
 		hw_flags |= MI_RESTORE_INHIBIT;
 
Quoted 9 lines

drivers/gpu/drm/i915/i915_gem_context.c static int do_switch(struct intel_ring_buffer *ring, · line 669

Quoted 6 lines
drivers/gpu/drm/i915/i915_gem_context.c +6 -0
+	/* When SW intends to use semaphore signaling between Command streamers,
+	 * it must avoid lite restores in HW by programming "Force Restore" bit
+	 * to ‘1’ in context descriptor during context submission
+	 */
+	if (IS_GEN8(ring->dev) && i915_semaphore_is_enabled(ring->dev))
+		hw_flags |= MI_FORCE_RESTORE;

Is it not an error to set both FORCE and INHIBIT?
-Chris

Read the commit message.

Signature · 5 lines
Ben Widawsky, Intel Open Source Technology Center
_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
#22 lore raw

Re: [PATCH 13/13] DONT_MERGE drm/i915: FORCE_RESTORE for gen8 semaphores

Quoted 32 lines · Ben Widawsky
Quoted 21 lines · Chris Wilson
Quoted 20 lines · Ben Widawsky

This appears to not actually be needed on the current code. Just putting it on the ML so we can point bug reports at it later.

As pointed out by Ville, the current code is "broken" since we do FORCE_RESTORE, and RESTORE_INHIBIT on the same dword. Anecdotally, this seems fine.

---
 drivers/gpu/drm/i915/i915_gem_context.c | 7 +++++++
 1 file changed, 7 insertions(+)
drivers/gpu/drm/i915/i915_gem_context.c +0 -0
index f77b4c1..aa82fb4 100644
@@ -661,6 +661,13 @@ static int do_switch(struct intel_ring_buffer *ring,
 	if (!to->is_initialized || i915_gem_context_is_default(to))
 		hw_flags |= MI_RESTORE_INHIBIT;
 
Quoted 9 lines

drivers/gpu/drm/i915/i915_gem_context.c static int do_switch(struct intel_ring_buffer *ring, · line 669

Quoted 6 lines
drivers/gpu/drm/i915/i915_gem_context.c +6 -0
+	/* When SW intends to use semaphore signaling between Command streamers,
+	 * it must avoid lite restores in HW by programming "Force Restore" bit
+	 * to ‘1’ in context descriptor during context submission
+	 */
+	if (IS_GEN8(ring->dev) && i915_semaphore_is_enabled(ring->dev))
+		hw_flags |= MI_FORCE_RESTORE;

Is it not an error to set both FORCE and INHIBIT?
-Chris

Quoted 1 line

Read the commit message.

And for once I was reading the code. Wouldn't it be worth to clear MI_RESTORE_INHIBIT any way to silence the critics? -Chris

Signature · 5 lines
Chris Wilson, Intel Open Source Technology Centre
_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
#23 lore raw

Re: [PATCH 13/13] DONT_MERGE drm/i915: FORCE_RESTORE for gen8 semaphores

Quoted 33 lines · Chris Wilson
Quoted 32 lines · Ben Widawsky
Quoted 30 lines · Chris Wilson
Quoted 17 lines · Ben Widawsky

This appears to not actually be needed on the current code. Just putting it on the ML so we can point bug reports at it later.

As pointed out by Ville, the current code is "broken" since we do FORCE_RESTORE, and RESTORE_INHIBIT on the same dword. Anecdotally, this seems fine.

---
 drivers/gpu/drm/i915/i915_gem_context.c | 7 +++++++
 1 file changed, 7 insertions(+)
drivers/gpu/drm/i915/i915_gem_context.c +0 -0
index f77b4c1..aa82fb4 100644

drivers/gpu/drm/i915/i915_gem_context.c static int do_switch(struct intel_ring_buffer *ring, · line 669

Quoted 9 lines
drivers/gpu/drm/i915/i915_gem_context.c +6 -0
@@ -661,6 +661,13 @@ static int do_switch(struct intel_ring_buffer *ring,
 	if (!to->is_initialized || i915_gem_context_is_default(to))
 		hw_flags |= MI_RESTORE_INHIBIT;
 
+	/* When SW intends to use semaphore signaling between Command streamers,
+	 * it must avoid lite restores in HW by programming "Force Restore" bit
+	 * to ‘1’ in context descriptor during context submission
+	 */
+	if (IS_GEN8(ring->dev) && i915_semaphore_is_enabled(ring->dev))
+		hw_flags |= MI_FORCE_RESTORE;

Is it not an error to set both FORCE and INHIBIT?
-Chris

Quoted 6 lines
Quoted 1 line

Read the commit message.

And for once I was reading the code. Wouldn't it be worth to clear MI_RESTORE_INHIBIT any way to silence the critics? -Chris

If we had interest in merging the patch, I can certainly fix it.

Signature · 5 lines
Ben Widawsky, Intel Open Source Technology Center
_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Reviewed-by on the v1 series
#24 lore raw
In reply to Ben Widawsky
Quoted 10 lines · Ben Widawsky

Okay, trying this again after the somewhat painful VCS2 rebase. I think I got to all of Ville's comments, but I could have missed a few. I apologize if so.

Daniel, even if you don't merge the whole series, the first few would really help rebase pain - though now that VCS2 is merged, there's probably not much other than execlists to be painful

The series is completely untested since the last rebase. I also didn't look really closely to make sure the rebase was correct - I'm just totally short on time atm. It was tested before that.

I think it looks all right, but I must admit to my eyes glazing over when looking at the ring->semaphore... init parts.

I don't really like the GEN8_RING_SEMAPHORE_INIT macro. Not sure why it's not a simple static function.

But anyway I think you can slap on

for patches 1-7 and 10-11 if they didn't have it already.

I left out the poll patch since it shouldn't be needed for production hw AFAICS (I guess we can merge it if we add a comment there that we should try to remove it once the early hardware is sufficiently phased out). The force restore patch doesn't seem applicable for ring buffer mode, and I didn't really look at the debugfs patch so far.

The missing bits seem to be one or two workarounds and the semaphore_wait_to_signaller_ring() thing for which I tried to cobble together something in my reply.

Quoted 34 lines

Ben Widawsky (13):
drm/i915: Move semaphore specific ring members to struct drm/i915: Virtualize the ringbuffer signal func drm/i915: Move ring_begin to signal()
drm/i915: Make semaphore updates more precise drm/i915: gen specific ring init
drm/i915/bdw: implement semaphore signal drm/i915/bdw: implement semaphore wait drm/i915: Implement MI decode for gen8 drm/i915/bdw: poll semaphores
drm/i915: Extract semaphore error collection drm/i915/bdw: collect semaphore error state drm/i915: semaphore debugfs
DONT_MERGE drm/i915: FORCE_RESTORE for gen8 semaphores

 drivers/gpu/drm/i915/i915_debugfs.c     |  70 ++++++
 drivers/gpu/drm/i915/i915_drv.h         |   2 +
 drivers/gpu/drm/i915/i915_gem.c         |  10 +-
 drivers/gpu/drm/i915/i915_gem_context.c |   7 +
 drivers/gpu/drm/i915/i915_gpu_error.c   |  79 +++++--
 drivers/gpu/drm/i915/i915_irq.c         |  14 +-
 drivers/gpu/drm/i915/i915_reg.h         |   8 +-
 drivers/gpu/drm/i915/intel_ringbuffer.c | 405 ++++++++++++++++++++++----------
 drivers/gpu/drm/i915/intel_ringbuffer.h |  90 ++++++-
 9 files changed, 528 insertions(+), 157 deletions(-)
Signature · 6 lines
1.9.2

_______________________________________________
Intel-gfx mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/intel-gfx
Signature · 2 lines
Ville Syrjälä
Intel OTC