[Intel-gfx] [PATCH 11/13] drm/i915: pipelined fencing, part 1: fence stealing

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


This is mostly just infrastructure to thread the pipelined
argument through all relevant functions. Nothing is really
pipelined, yet, because i915_gem_object_get_fence_reg waits
for the fenced gpu access when pipelined == 1.

Pipelined fence clearing is a no-op because we'll overwrite
the fence reg anyway in i915_gem_object_get_fence_reg. The only
other caller of i915_gem_clear_fence_reg is the unbind code,
which is always synchronous.

Only mark execbuffer fences as pipelined for now and but a FIXME
comment for the pageflip stuff. Doing pipelined fencing for pageflip
needs some more usage tracking and I'm not sure this is worth it
for the fence will be pinned for an indetermined long time.

Signed-off-by: Daniel Vetter <daniel.vetter at ffwll.ch>
---
 drivers/gpu/drm/i915/i915_drv.h        |    4 +-
 drivers/gpu/drm/i915/i915_gem.c        |   35 +++++++++++++++++++++-----------
 drivers/gpu/drm/i915/i915_gem_tiling.c |    2 +-
 drivers/gpu/drm/i915/intel_display.c   |    4 ++-
 4 files changed, 29 insertions(+), 16 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index f26a037..c684d0e 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -871,8 +871,8 @@ void i915_gem_release_mmap(struct drm_gem_object *obj);
 void i915_gem_lastclose(struct drm_device *dev);
 uint32_t i915_get_gem_seqno(struct drm_device *dev);
 bool i915_seqno_passed(uint32_t seq1, uint32_t seq2);
-int i915_gem_object_get_fence_reg(struct drm_gem_object *obj);
-int i915_gem_object_put_fence_reg(struct drm_gem_object *obj);
+int i915_gem_object_get_fence_reg(struct drm_gem_object *obj, int pipelined);
+int i915_gem_object_put_fence_reg(struct drm_gem_object *obj, int pipelined);
 void i915_gem_retire_requests(struct drm_device *dev);
 void i915_gem_retire_work_handler(struct work_struct *work);
 void i915_gem_clflush_object(struct drm_gem_object *obj);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 83c7d58..1fd7a65 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -49,7 +49,8 @@ static void i915_gem_object_set_to_full_cpu_read_domain(struct drm_gem_object *o
 static int i915_gem_object_wait_rendering(struct drm_gem_object *obj);
 static int i915_gem_object_bind_to_gtt(struct drm_gem_object *obj,
 					   unsigned alignment);
-static void i915_gem_clear_fence_reg(struct drm_gem_object *obj);
+static void i915_gem_clear_fence_reg(struct drm_gem_object *obj,
+				     int pipelined);
 static int i915_gem_evict_something(struct drm_device *dev, int min_size);
 static int i915_gem_evict_from_inactive_list(struct drm_device *dev);
 static int i915_gem_phys_pwrite(struct drm_device *dev, struct drm_gem_object *obj,
@@ -1215,7 +1216,7 @@ int i915_gem_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
 
 	/* Need a new fence register? */
 	if (obj_priv->tiling_mode != I915_TILING_NONE) {
-		ret = i915_gem_object_get_fence_reg(obj);
+		ret = i915_gem_object_get_fence_reg(obj, 0);
 		if (ret)
 			goto unlock;
 	}
@@ -2075,7 +2076,7 @@ i915_gem_object_unbind(struct drm_gem_object *obj)
 
 	/* release the fence reg _after_ flushing */
 	if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
-		i915_gem_clear_fence_reg(obj);
+		i915_gem_clear_fence_reg(obj, 0);
 
 	if (obj_priv->agp_mem != NULL) {
 		drm_unbind_agp(obj_priv->agp_mem);
@@ -2426,7 +2427,7 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
 	I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val);
 }
 
-static int i915_find_fence_reg(struct drm_device *dev)
+static int i915_find_fence_reg(struct drm_device *dev, int pipelined)
 {
 	struct drm_i915_fence_reg *reg = NULL;
 	struct drm_i915_gem_object *obj_priv = NULL;
@@ -2471,7 +2472,7 @@ static int i915_find_fence_reg(struct drm_device *dev)
 	 * under us.
 	 */
 	drm_gem_object_reference(obj);
-	ret = i915_gem_object_put_fence_reg(obj);
+	ret = i915_gem_object_put_fence_reg(obj, pipelined);
 	drm_gem_object_unreference(obj);
 	if (ret != 0)
 		return ret;
@@ -2493,7 +2494,7 @@ static int i915_find_fence_reg(struct drm_device *dev)
  * and tiling format.
  */
 int
-i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
+i915_gem_object_get_fence_reg(struct drm_gem_object *obj, int pipelined)
 {
 	struct drm_device *dev = obj->dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -2528,7 +2529,7 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
 		break;
 	}
 
-	ret = i915_find_fence_reg(dev);
+	ret = i915_find_fence_reg(dev, pipelined);
 	if (ret < 0)
 		return ret;
 
@@ -2538,6 +2539,12 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
 
 	reg->obj = obj;
 
+	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);
 	else if (IS_I9XX(dev))
@@ -2559,7 +2566,7 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
  * data structures in dev_priv and obj_priv.
  */
 static void
-i915_gem_clear_fence_reg(struct drm_gem_object *obj)
+i915_gem_clear_fence_reg(struct drm_gem_object *obj, int pipelined)
 {
 	struct drm_device *dev = obj->dev;
 	drm_i915_private_t *dev_priv = dev->dev_private;
@@ -2567,6 +2574,8 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj)
 	struct drm_i915_fence_reg *reg =
 		&dev_priv->fence_regs[obj_priv->fence_reg];
 
+	if (pipelined)
+		goto end;
 	if (IS_I965G(dev))
 		I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0);
 	else {
@@ -2581,6 +2590,7 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj)
 		I915_WRITE(fence_reg, 0);
 	}
 
+end:
 	reg->obj = NULL;
 	obj_priv->fence_reg = I915_FENCE_REG_NONE;
 	list_del_init(&reg->lru_list);
@@ -2595,7 +2605,8 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj)
  * data structures in dev_priv and obj_priv.
  */
 int
-i915_gem_object_put_fence_reg(struct drm_gem_object *obj)
+i915_gem_object_put_fence_reg(struct drm_gem_object *obj,
+			      int pipelined)
 {
 	struct drm_i915_gem_object *obj_priv = obj->driver_private;
 
@@ -2611,13 +2622,13 @@ i915_gem_object_put_fence_reg(struct drm_gem_object *obj)
 	if (obj_priv->fenced_gpu_access) {
 		int ret;
 
-		ret = i915_gem_object_flush_gpu_write_domain(obj, 0);
+		ret = i915_gem_object_flush_gpu_write_domain(obj, pipelined);
 		if (ret != 0)
 			return ret;
 	}
 
 	i915_gem_object_flush_gtt_write_domain(obj);
-	i915_gem_clear_fence_reg (obj);
+	i915_gem_clear_fence_reg(obj, pipelined);
 
 	return 0;
 }
@@ -3317,7 +3328,7 @@ i915_gem_object_pin_and_relocate(struct drm_gem_object *obj,
 	 * properly handle blits to/from tiled surfaces.
 	 */
 	if (need_fence) {
-		ret = i915_gem_object_get_fence_reg(obj);
+		ret = i915_gem_object_get_fence_reg(obj, 1);
 		if (ret != 0) {
 			if (ret != -EBUSY && ret != -ERESTARTSYS)
 				DRM_ERROR("Failure to install fence: %d\n",
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
index b0cbe3a..6879f04 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -362,7 +362,7 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
 		if (!i915_gem_object_fence_offset_ok(obj, args->tiling_mode))
 		    ret = i915_gem_object_unbind(obj);
 		else
-		    ret = i915_gem_object_put_fence_reg(obj);
+		    ret = i915_gem_object_put_fence_reg(obj, 0);
 		if (ret != 0) {
 			WARN(ret != -ERESTARTSYS,
 			     "failed to reset object for tiling switch");
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 9dc2eed..fd870d0 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1149,7 +1149,9 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev, struct drm_gem_object *obj)
 	 */
 	if (obj_priv->fence_reg == I915_FENCE_REG_NONE &&
 	    obj_priv->tiling_mode != I915_TILING_NONE) {
-		ret = i915_gem_object_get_fence_reg(obj);
+		/* FIXME: Check whether pipelined fencing makes
+		 * sense for the pageflip. */
+		ret = i915_gem_object_get_fence_reg(obj, 0);
 		if (ret != 0) {
 			i915_gem_object_unpin(obj);
 			return ret;
-- 
1.6.6.1




More information about the Intel-gfx mailing list