|
@@ -2668,7 +2668,6 @@ static void i965_write_fence_reg(struct drm_device *dev, int reg,
|
|
|
drm_i915_private_t *dev_priv = dev->dev_private;
|
|
|
int fence_reg;
|
|
|
int fence_pitch_shift;
|
|
|
- uint64_t val;
|
|
|
|
|
|
if (INTEL_INFO(dev)->gen >= 6) {
|
|
|
fence_reg = FENCE_REG_SANDYBRIDGE_0;
|
|
@@ -2678,8 +2677,23 @@ static void i965_write_fence_reg(struct drm_device *dev, int reg,
|
|
|
fence_pitch_shift = I965_FENCE_PITCH_SHIFT;
|
|
|
}
|
|
|
|
|
|
+ fence_reg += reg * 8;
|
|
|
+
|
|
|
+ /* To w/a incoherency with non-atomic 64-bit register updates,
|
|
|
+ * we split the 64-bit update into two 32-bit writes. In order
|
|
|
+ * for a partial fence not to be evaluated between writes, we
|
|
|
+ * precede the update with write to turn off the fence register,
|
|
|
+ * and only enable the fence as the last step.
|
|
|
+ *
|
|
|
+ * For extra levels of paranoia, we make sure each step lands
|
|
|
+ * before applying the next step.
|
|
|
+ */
|
|
|
+ I915_WRITE(fence_reg, 0);
|
|
|
+ POSTING_READ(fence_reg);
|
|
|
+
|
|
|
if (obj) {
|
|
|
u32 size = obj->gtt_space->size;
|
|
|
+ uint64_t val;
|
|
|
|
|
|
val = (uint64_t)((obj->gtt_offset + size - 4096) &
|
|
|
0xfffff000) << 32;
|
|
@@ -2688,12 +2702,16 @@ static void i965_write_fence_reg(struct drm_device *dev, int reg,
|
|
|
if (obj->tiling_mode == I915_TILING_Y)
|
|
|
val |= 1 << I965_FENCE_TILING_Y_SHIFT;
|
|
|
val |= I965_FENCE_REG_VALID;
|
|
|
- } else
|
|
|
- val = 0;
|
|
|
|
|
|
- fence_reg += reg * 8;
|
|
|
- I915_WRITE64(fence_reg, val);
|
|
|
- POSTING_READ(fence_reg);
|
|
|
+ I915_WRITE(fence_reg + 4, val >> 32);
|
|
|
+ POSTING_READ(fence_reg + 4);
|
|
|
+
|
|
|
+ I915_WRITE(fence_reg + 0, val);
|
|
|
+ POSTING_READ(fence_reg);
|
|
|
+ } else {
|
|
|
+ I915_WRITE(fence_reg + 4, 0);
|
|
|
+ POSTING_READ(fence_reg + 4);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
static void i915_write_fence_reg(struct drm_device *dev, int reg,
|