[Intel-gfx] [PATCH 13/13] drm/i915: pipelined fencing, part 2: fence setup

Daniel Vetter daniel.vetter at ffwll.ch
Thu Feb 4 22:05:13 CET 2010


This wires the fence setup part up. I've also implemented pipelined
fence setup for 4th gen chips - this may be useful when the pageflip
code switches to pipelined fencing.

With this change, every batchbuffer can use all available fences (save
pinned and scanout, of course) without ever stalling the gpu!

Signed-off-by: Daniel Vetter <daniel.vetter at ffwll.ch>
---
 drivers/gpu/drm/i915/i915_gem.c |   60 +++++++++++++++++++++++++++++----------
 1 files changed, 45 insertions(+), 15 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 5e90587..483b520 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2339,7 +2339,7 @@ i915_gem_object_get_pages(struct drm_gem_object *obj)
 	return 0;
 }
 
-static void i965_write_fence_reg(struct drm_i915_fence_reg *reg)
+static void i965_write_fence_reg(struct drm_i915_fence_reg *reg, int pipelined)
 {
 	struct drm_gem_object *obj = reg->obj;
 	struct drm_device *dev = obj->dev;
@@ -2347,6 +2347,7 @@ static void i965_write_fence_reg(struct drm_i915_fence_reg *reg)
 	struct drm_i915_gem_object *obj_priv = obj->driver_private;
 	int regnum = obj_priv->fence_reg;
 	uint64_t val;
+	RING_LOCALS;
 
 	val = (uint64_t)((obj_priv->gtt_offset + obj->size - 4096) &
 		    0xfffff000) << 32;
@@ -2356,10 +2357,20 @@ static void i965_write_fence_reg(struct drm_i915_fence_reg *reg)
 		val |= 1 << I965_FENCE_TILING_Y_SHIFT;
 	val |= I965_FENCE_REG_VALID;
 
-	I915_WRITE64(FENCE_REG_965_0 + (regnum * 8), val);
+	if (pipelined) {
+		BEGIN_LP_RING(6);
+		OUT_RING(MI_LOAD_REGISTER_IMM);
+		OUT_RING(FENCE_REG_965_0 + (regnum * 8));
+		OUT_RING((uint32_t) val);
+		OUT_RING(MI_LOAD_REGISTER_IMM);
+		OUT_RING(FENCE_REG_965_0 + (regnum * 8) + 4);
+		OUT_RING((uint32_t) (val >> 32));
+		ADVANCE_LP_RING();
+	} else
+		I915_WRITE64(FENCE_REG_965_0 + (regnum * 8), val);
 }
 
-static void i915_write_fence_reg(struct drm_i915_fence_reg *reg)
+static void i915_write_fence_reg(struct drm_i915_fence_reg *reg, int pipelined)
 {
 	struct drm_gem_object *obj = reg->obj;
 	struct drm_device *dev = obj->dev;
@@ -2369,6 +2380,7 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *reg)
 	int tile_width;
 	uint32_t fence_reg, val;
 	uint32_t pitch_val;
+	RING_LOCALS;
 
 	if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) ||
 	    (obj_priv->gtt_offset & (obj->size - 1))) {
@@ -2398,10 +2410,18 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *reg)
 		fence_reg = FENCE_REG_830_0 + (regnum * 4);
 	else
 		fence_reg = FENCE_REG_945_8 + ((regnum - 8) * 4);
-	I915_WRITE(fence_reg, val);
+
+	if (pipelined) {
+		BEGIN_LP_RING(3);
+		OUT_RING(MI_LOAD_REGISTER_IMM);
+		OUT_RING(fence_reg);
+		OUT_RING(val);
+		ADVANCE_LP_RING();
+	} else
+		I915_WRITE(fence_reg, val);
 }
 
-static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
+static void i830_write_fence_reg(struct drm_i915_fence_reg *reg, int pipelined)
 {
 	struct drm_gem_object *obj = reg->obj;
 	struct drm_device *dev = obj->dev;
@@ -2411,6 +2431,7 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
 	uint32_t val;
 	uint32_t pitch_val;
 	uint32_t fence_size_bits;
+	RING_LOCALS;
 
 	if ((obj_priv->gtt_offset & ~I830_FENCE_START_MASK) ||
 	    (obj_priv->gtt_offset & (obj->size - 1))) {
@@ -2432,7 +2453,14 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
 	val |= pitch_val << I830_FENCE_PITCH_SHIFT;
 	val |= I830_FENCE_REG_VALID;
 
-	I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val);
+	if (pipelined) {
+		BEGIN_LP_RING(3);
+		OUT_RING(MI_LOAD_REGISTER_IMM);
+		OUT_RING(FENCE_REG_830_0 + (regnum * 4));
+		OUT_RING(val);
+		ADVANCE_LP_RING();
+	} else
+		I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val);
 }
 
 static int i915_find_fence_reg(struct drm_device *dev, int pipelined)
@@ -2517,6 +2545,14 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj, int pipelined)
 
 		/* Wait for the gpu to setup the fence it it was pipelined. */
 		if (!pipelined && reg->setup_seqno != 0) {
+			/* With certain error conditions, the request might not
+			 * yet have been emitted. */
+			if (reg->setup_seqno == dev_priv->mm.next_gem_seqno) {
+				uint32_t seqno = i915_add_request(dev, NULL);
+				if (seqno == 0)
+					return -ENOMEM;
+			}
+
 			ret = i915_wait_request(dev, reg->setup_seqno);
 			if (ret != 0)
 				return ret;
@@ -2562,18 +2598,12 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj, int pipelined)
 	else
 		reg->setup_seqno = 0;
 
-	if (pipelined && reg->last_rendering_seqno != 0) {
-		ret = i915_wait_request(dev, reg->last_rendering_seqno);
-		if (ret != 0)
-			return ret;
-	}
-
 	if (IS_I965G(dev))
-		i965_write_fence_reg(reg);
+		i965_write_fence_reg(reg, pipelined);
 	else if (IS_I9XX(dev))
-		i915_write_fence_reg(reg);
+		i915_write_fence_reg(reg, pipelined);
 	else
-		i830_write_fence_reg(reg);
+		i830_write_fence_reg(reg, pipelined);
 
 	trace_i915_gem_object_get_fence(obj, obj_priv->fence_reg,
 			obj_priv->tiling_mode);
-- 
1.6.6.1




More information about the Intel-gfx mailing list