drm/i915: Refactor put_fence() to use the common fence writing routine
authorChris Wilson <chris@chris-wilson.co.uk>
Tue, 17 Apr 2012 14:31:31 +0000 (15:31 +0100)
committerDaniel Vetter <daniel.vetter@ffwll.ch>
Wed, 18 Apr 2012 11:34:30 +0000 (13:34 +0200)
One clarification that we make is to the existing semantics of
obj->tiling_changed to only mean that we need to update an associated
fence register (including the NO_FENCE when executing an untiled but
fenced GPU command). If we do not have a fence register or pending
fenced GPU access for the object (after put_fence() for example), then
we can clear the tiling_changed flag as any fence will necessarily be
rewritten upon acquisition.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
drivers/gpu/drm/i915/i915_gem.c

index 199306d..3601b8b 100644 (file)
@@ -50,10 +50,28 @@ static int i915_gem_phys_pwrite(struct drm_device *dev,
                                struct drm_file *file);
 static void i915_gem_free_object_tail(struct drm_i915_gem_object *obj);
 
+static void i915_gem_write_fence(struct drm_device *dev, int reg,
+                                struct drm_i915_gem_object *obj);
+static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj,
+                                        struct drm_i915_fence_reg *fence,
+                                        bool enable);
+
 static int i915_gem_inactive_shrink(struct shrinker *shrinker,
                                    struct shrink_control *sc);
 static void i915_gem_object_truncate(struct drm_i915_gem_object *obj);
 
+static inline void i915_gem_object_fence_lost(struct drm_i915_gem_object *obj)
+{
+       if (obj->tiling_mode)
+               i915_gem_release_mmap(obj);
+
+       /* As we do not have an associated fence register, we will force
+        * a tiling change if we ever need to acquire one.
+        */
+       obj->tiling_changed = false;
+       obj->fence_reg = I915_FENCE_REG_NONE;
+}
+
 /* some bookkeeping */
 static void i915_gem_info_add_obj(struct drm_i915_private *dev_priv,
                                  size_t size)
@@ -2301,6 +2319,32 @@ static void i915_gem_write_fence(struct drm_device *dev, int reg,
        }
 }
 
+static inline int fence_number(struct drm_i915_private *dev_priv,
+                              struct drm_i915_fence_reg *fence)
+{
+       return fence - dev_priv->fence_regs;
+}
+
+static void i915_gem_object_update_fence(struct drm_i915_gem_object *obj,
+                                        struct drm_i915_fence_reg *fence,
+                                        bool enable)
+{
+       struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
+       int reg = fence_number(dev_priv, fence);
+
+       i915_gem_write_fence(obj->base.dev, reg, enable ? obj : NULL);
+
+       if (enable) {
+               obj->fence_reg = reg;
+               fence->obj = obj;
+               list_move_tail(&fence->lru_list, &dev_priv->mm.fence_list);
+       } else {
+               obj->fence_reg = I915_FENCE_REG_NONE;
+               fence->obj = NULL;
+               list_del_init(&fence->lru_list);
+       }
+}
+
 static int
 i915_gem_object_flush_fence(struct drm_i915_gem_object *obj)
 {
@@ -2339,24 +2383,20 @@ i915_gem_object_flush_fence(struct drm_i915_gem_object *obj)
 int
 i915_gem_object_put_fence(struct drm_i915_gem_object *obj)
 {
+       struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
        int ret;
 
-       if (obj->tiling_mode)
-               i915_gem_release_mmap(obj);
-
        ret = i915_gem_object_flush_fence(obj);
        if (ret)
                return ret;
 
-       if (obj->fence_reg != I915_FENCE_REG_NONE) {
-               struct drm_i915_private *dev_priv = obj->base.dev->dev_private;
-
-               WARN_ON(dev_priv->fence_regs[obj->fence_reg].pin_count);
-               i915_gem_clear_fence_reg(obj->base.dev,
-                                        &dev_priv->fence_regs[obj->fence_reg]);
+       if (obj->fence_reg == I915_FENCE_REG_NONE)
+               return 0;
 
-               obj->fence_reg = I915_FENCE_REG_NONE;
-       }
+       i915_gem_object_update_fence(obj,
+                                    &dev_priv->fence_regs[obj->fence_reg],
+                                    false);
+       i915_gem_object_fence_lost(obj);
 
        return 0;
 }