Pipelining tiling changes will complicate all places that need
a correct fence register to be set up. So hide this complexity
behind a small helper function.

i915_gem_object_get_fence loses all it's external callers by these
changes, so convert it into a static function

Signed-off-by: Daniel Vetter <daniel.vet...@ffwll.ch>
---
 drivers/gpu/drm/i915/i915_drv.h      |    2 +-
 drivers/gpu/drm/i915/i915_gem.c      |   52 ++++++++++++++++++++++++++++-----
 drivers/gpu/drm/i915/intel_display.c |   16 ++--------
 3 files changed, 49 insertions(+), 21 deletions(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 242993b..7aec3ec 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -918,7 +918,7 @@ 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_adjust_fencing(struct drm_gem_object *obj);
 int i915_gem_object_put_fence_reg(struct drm_gem_object *obj);
 void i915_gem_retire_requests(struct drm_device *dev);
 void i915_gem_retire_work_handler(struct work_struct *work);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 47c46ed..8e73a12 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -974,6 +974,10 @@ i915_gem_pwrite_ioctl(struct drm_device *dev, void *data,
                ret = i915_gem_phys_pwrite(dev, obj, args, file_priv);
        else if (obj_priv->tiling_mode == I915_TILING_NONE &&
                 dev->gtt_total != 0) {
+               ret = i915_gem_object_adjust_fencing(obj);
+               if (ret != 0)
+                       return ret;
+
                ret = i915_gem_gtt_pwrite_fast(dev, obj, args, file_priv);
                if (ret == -EFAULT) {
                        ret = i915_gem_gtt_pwrite_slow(dev, obj, args,
@@ -1191,12 +1195,9 @@ int i915_gem_fault(struct vm_area_struct *vma, struct 
vm_fault *vmf)
                        goto unlock;
        }
 
-       /* Need a new fence register? */
-       if (obj_priv->tiling_mode != I915_TILING_NONE) {
-               ret = i915_gem_object_get_fence_reg(obj);
-               if (ret)
-                       goto unlock;
-       }
+       ret = i915_gem_object_adjust_fencing(obj);
+       if (ret)
+               goto unlock;
 
        pfn = ((dev->agp->base + obj_priv->gtt_offset) >> PAGE_SHIFT) +
                page_offset;
@@ -2475,7 +2476,7 @@ static int i915_find_fence_reg(struct drm_device *dev)
  * It then sets up the reg based on the object's properties: address, pitch
  * and tiling format.
  */
-int
+static int
 i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
 {
        struct drm_device *dev = obj->dev;
@@ -2536,6 +2537,41 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj)
 }
 
 /**
+ * i915_gem_object_adjust_fencing - ensure correct fencing for an object
+ * @obj: object to map through a fence reg
+ *
+ * Tiling changes may be delayed untill fenced access is actually needed.
+ * Batchbuffer submitted via execbuf2 may not need a fence, so delaying
+ * gtt remapping and fence register changes (which all stall the gpu) as
+ * long as possible is beneficial.
+ *
+ * This function ensures that all delayed operations have been carried out and
+ * the object can be correctly accessed via fences.
+ */
+int
+i915_gem_object_adjust_fencing(struct drm_gem_object *obj)
+{
+       struct drm_i915_gem_object *obj_priv = to_intel_bo(obj);
+       int ret;
+
+       if (!i915_gem_object_fence_offset_ok(obj, obj_priv->tiling_mode)) {
+               ret = i915_gem_object_unbind(obj);
+               if (ret != 0)
+                       return ret;
+               ret = i915_gem_object_bind_to_gtt(obj, 0);
+               if (ret != 0)
+                       return ret;
+       }
+
+       if (obj_priv->tiling_mode != I915_TILING_NONE) {
+               ret = i915_gem_object_get_fence_reg(obj);
+               if (ret != 0)
+                       return ret;
+       }
+       return 0;
+}
+
+/**
  * i915_gem_clear_fence_reg - clear out fence register info
  * @obj: object to clear
  *
@@ -3309,7 +3345,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_adjust_fencing(obj);
                if (ret != 0) {
                        if (ret != -EBUSY && ret != -ERESTARTSYS)
                                DRM_ERROR("Failure to install fence: %d\n",
diff --git a/drivers/gpu/drm/i915/intel_display.c 
b/drivers/gpu/drm/i915/intel_display.c
index 3836f56..56b673d 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -1249,18 +1249,10 @@ intel_pin_and_fence_fb_obj(struct drm_device *dev, 
struct drm_gem_object *obj)
        if (ret != 0)
                return ret;
 
-       /* Install a fence for tiled scan-out. Pre-i965 always needs a
-        * fence, whereas 965+ only requires a fence if using
-        * framebuffer compression.  For simplicity, we always install
-        * a fence as the cost is not that onerous.
-        */
-       if (obj_priv->fence_reg == I915_FENCE_REG_NONE &&
-           obj_priv->tiling_mode != I915_TILING_NONE) {
-               ret = i915_gem_object_get_fence_reg(obj);
-               if (ret != 0) {
-                       i915_gem_object_unpin(obj);
-                       return ret;
-               }
+       ret = i915_gem_object_adjust_fencing(obj);
+       if (ret != 0) {
+               i915_gem_object_unpin(obj);
+               return ret;
        }
 
        return 0;
-- 
1.6.6.1

_______________________________________________
Intel-gfx mailing list
Intel-gfx@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/intel-gfx

Reply via email to