drm/i915: fix 945 fence register writes for fence 8 and above.
authorEric Anholt <eric@anholt.net>
Wed, 11 Mar 2009 05:34:49 +0000 (22:34 -0700)
committerEric Anholt <eric@anholt.net>
Wed, 11 Mar 2009 18:02:06 +0000 (11:02 -0700)
The last 8 fence registers sit at a different offset, so when we went to set
fence number 8 in the lower offset, we instead set PGETBL_CTL, and the GPU
got all sorts of angry at us.

fd.o bug #20567.  Easily reproducible by running glxgears and killing it about
6 times.

Signed-off-by: Eric Anholt <eric@anholt.net>
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_reg.h

index b0ff5c4..37427e4 100644 (file)
@@ -1476,7 +1476,7 @@ static void i915_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;
        int tile_width;
-       uint32_t val;
+       uint32_t fence_reg, val;
        uint32_t pitch_val;
 
        if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) ||
@@ -1503,7 +1503,11 @@ static void i915_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 (regnum < 8)
+               fence_reg = FENCE_REG_830_0 + (regnum * 4);
+       else
+               fence_reg = FENCE_REG_945_8 + ((regnum - 8) * 4);
+       I915_WRITE(fence_reg, val);
 }
 
 static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
@@ -1687,8 +1691,17 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj)
 
        if (IS_I965G(dev))
                I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0);
-       else
-               I915_WRITE(FENCE_REG_830_0 + (obj_priv->fence_reg * 4), 0);
+       else {
+               uint32_t fence_reg;
+
+               if (obj_priv->fence_reg < 8)
+                       fence_reg = FENCE_REG_830_0 + obj_priv->fence_reg * 4;
+               else
+                       fence_reg = FENCE_REG_945_8 + (obj_priv->fence_reg -
+                                                      8) * 4;
+
+               I915_WRITE(fence_reg, 0);
+       }
 
        dev_priv->fence_regs[obj_priv->fence_reg].obj = NULL;
        obj_priv->fence_reg = I915_FENCE_REG_NONE;
index 9d6539a..90600d8 100644 (file)
  * Fence registers
  */
 #define FENCE_REG_830_0                        0x2000
+#define FENCE_REG_945_8                        0x3000
 #define   I830_FENCE_START_MASK                0x07f80000
 #define   I830_FENCE_TILING_Y_SHIFT    12
 #define   I830_FENCE_SIZE_BITS(size)   ((ffs((size) >> 19) - 1) << 8)