drm/i915: fix 945 fence register writes for fence 8 and above.

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>

+18 -4
+17 -4
drivers/gpu/drm/i915/i915_gem.c
··· 1476 struct drm_i915_gem_object *obj_priv = obj->driver_private; 1477 int regnum = obj_priv->fence_reg; 1478 int tile_width; 1479 - uint32_t val; 1480 uint32_t pitch_val; 1481 1482 if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) || ··· 1503 val |= pitch_val << I830_FENCE_PITCH_SHIFT; 1504 val |= I830_FENCE_REG_VALID; 1505 1506 - I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val); 1507 } 1508 1509 static void i830_write_fence_reg(struct drm_i915_fence_reg *reg) ··· 1691 1692 if (IS_I965G(dev)) 1693 I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0); 1694 - else 1695 - I915_WRITE(FENCE_REG_830_0 + (obj_priv->fence_reg * 4), 0); 1696 1697 dev_priv->fence_regs[obj_priv->fence_reg].obj = NULL; 1698 obj_priv->fence_reg = I915_FENCE_REG_NONE;
··· 1476 struct drm_i915_gem_object *obj_priv = obj->driver_private; 1477 int regnum = obj_priv->fence_reg; 1478 int tile_width; 1479 + uint32_t fence_reg, val; 1480 uint32_t pitch_val; 1481 1482 if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) || ··· 1503 val |= pitch_val << I830_FENCE_PITCH_SHIFT; 1504 val |= I830_FENCE_REG_VALID; 1505 1506 + if (regnum < 8) 1507 + fence_reg = FENCE_REG_830_0 + (regnum * 4); 1508 + else 1509 + fence_reg = FENCE_REG_945_8 + ((regnum - 8) * 4); 1510 + I915_WRITE(fence_reg, val); 1511 } 1512 1513 static void i830_write_fence_reg(struct drm_i915_fence_reg *reg) ··· 1687 1688 if (IS_I965G(dev)) 1689 I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0); 1690 + else { 1691 + uint32_t fence_reg; 1692 + 1693 + if (obj_priv->fence_reg < 8) 1694 + fence_reg = FENCE_REG_830_0 + obj_priv->fence_reg * 4; 1695 + else 1696 + fence_reg = FENCE_REG_945_8 + (obj_priv->fence_reg - 1697 + 8) * 4; 1698 + 1699 + I915_WRITE(fence_reg, 0); 1700 + } 1701 1702 dev_priv->fence_regs[obj_priv->fence_reg].obj = NULL; 1703 obj_priv->fence_reg = I915_FENCE_REG_NONE;
+1
drivers/gpu/drm/i915/i915_reg.h
··· 184 * Fence registers 185 */ 186 #define FENCE_REG_830_0 0x2000 187 #define I830_FENCE_START_MASK 0x07f80000 188 #define I830_FENCE_TILING_Y_SHIFT 12 189 #define I830_FENCE_SIZE_BITS(size) ((ffs((size) >> 19) - 1) << 8)
··· 184 * Fence registers 185 */ 186 #define FENCE_REG_830_0 0x2000 187 + #define FENCE_REG_945_8 0x3000 188 #define I830_FENCE_START_MASK 0x07f80000 189 #define I830_FENCE_TILING_Y_SHIFT 12 190 #define I830_FENCE_SIZE_BITS(size) ((ffs((size) >> 19) - 1) << 8)