diff mbox

[11/15] drm/i915: pipelined fencing, part 1: fence stealing

Message ID 1268323140-12006-12-git-send-email-daniel.vetter@ffwll.ch (mailing list archive)
State Deferred, archived
Headers show

Commit Message

Daniel Vetter March 11, 2010, 3:58 p.m. UTC
None
diff mbox

Patch

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index c32b60c..41718be 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -916,8 +916,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 5183fdd..4bf8bf7 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,
@@ -1195,7 +1196,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;
 	}
@@ -2079,8 +2080,11 @@  i915_gem_object_unbind(struct drm_gem_object *obj)
 	BUG_ON(obj_priv->active);
 
 	/* release the fence reg _after_ flushing */
-	if (obj_priv->fence_reg != I915_FENCE_REG_NONE)
-		i915_gem_clear_fence_reg(obj);
+	if (obj_priv->fence_reg != I915_FENCE_REG_NONE) {
+		ret = i915_gem_object_put_fence_reg(obj, 0);
+		if (ret != 0)
+			return ret;
+	}
 
 	if (obj_priv->agp_mem != NULL) {
 		drm_unbind_agp(obj_priv->agp_mem);
@@ -2451,7 +2455,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;
@@ -2496,7 +2500,7 @@  static int i915_find_fence_reg(struct drm_device *dev)
 	 * private reference to obj like the other callers of put_fence_reg
 	 * (set_tiling ioctl) do. */
 	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;
@@ -2518,7 +2522,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;
@@ -2553,7 +2557,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;
 
@@ -2563,6 +2567,13 @@  i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
 
 	reg->obj = obj;
 
+	/* WIP: Synchronize again for the not-yet-pipeplined stuff */
+	if (pipelined && reg->last_rendering_seqno != 0) {
+		ret = i915_wait_request(dev, reg->last_rendering_seqno);
+		if (ret != 0)
+			return ret;
+	}
+
 	if (IS_GEN6(dev))
 		sandybridge_write_fence_reg(reg);
 	else if (IS_I965G(dev))
@@ -2586,7 +2597,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;
@@ -2594,6 +2605,9 @@  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_GEN6(dev)) {
 		I915_WRITE64(FENCE_REG_SANDYBRIDGE_0 +
 			     (obj_priv->fence_reg * 8), 0);
@@ -2611,6 +2625,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);
@@ -2625,7 +2640,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_device *dev = obj->dev;
 	struct drm_i915_gem_object *obj_priv = obj->driver_private;
@@ -2646,13 +2662,13 @@  i915_gem_object_put_fence_reg(struct drm_gem_object *obj)
 	if (!IS_I965G(dev)) {
 		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;
 }
@@ -3340,7 +3356,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 b5c55d8..6bea767 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -327,7 +327,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 9cd6de5..c01dadb 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1273,7 +1273,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;