@@ -2339,7 +2339,7 @@ i915_gem_object_get_pages(struct drm_gem_object *obj)
return 0;
}
-static void i965_write_fence_reg(struct drm_i915_fence_reg *reg)
+static void i965_write_fence_reg(struct drm_i915_fence_reg *reg, int pipelined)
{
struct drm_gem_object *obj = reg->obj;
struct drm_device *dev = obj->dev;
@@ -2347,6 +2347,7 @@ static void i965_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;
uint64_t val;
+ RING_LOCALS;
val = (uint64_t)((obj_priv->gtt_offset + obj->size - 4096) &
0xfffff000) << 32;
@@ -2356,10 +2357,20 @@ static void i965_write_fence_reg(struct drm_i915_fence_reg *reg)
val |= 1 << I965_FENCE_TILING_Y_SHIFT;
val |= I965_FENCE_REG_VALID;
- I915_WRITE64(FENCE_REG_965_0 + (regnum * 8), val);
+ if (pipelined) {
+ BEGIN_LP_RING(6);
+ OUT_RING(MI_LOAD_REGISTER_IMM);
+ OUT_RING(FENCE_REG_965_0 + (regnum * 8));
+ OUT_RING((uint32_t) val);
+ OUT_RING(MI_LOAD_REGISTER_IMM);
+ OUT_RING(FENCE_REG_965_0 + (regnum * 8) + 4);
+ OUT_RING((uint32_t) (val >> 32));
+ ADVANCE_LP_RING();
+ } else
+ I915_WRITE64(FENCE_REG_965_0 + (regnum * 8), val);
}
-static void i915_write_fence_reg(struct drm_i915_fence_reg *reg)
+static void i915_write_fence_reg(struct drm_i915_fence_reg *reg, int pipelined)
{
struct drm_gem_object *obj = reg->obj;
struct drm_device *dev = obj->dev;
@@ -2369,6 +2380,7 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *reg)
int tile_width;
uint32_t fence_reg, val;
uint32_t pitch_val;
+ RING_LOCALS;
if ((obj_priv->gtt_offset & ~I915_FENCE_START_MASK) ||
(obj_priv->gtt_offset & (obj->size - 1))) {
@@ -2398,10 +2410,18 @@ static void i915_write_fence_reg(struct drm_i915_fence_reg *reg)
fence_reg = FENCE_REG_830_0 + (regnum * 4);
else
fence_reg = FENCE_REG_945_8 + ((regnum - 8) * 4);
- I915_WRITE(fence_reg, val);
+
+ if (pipelined) {
+ BEGIN_LP_RING(3);
+ OUT_RING(MI_LOAD_REGISTER_IMM);
+ OUT_RING(fence_reg);
+ OUT_RING(val);
+ ADVANCE_LP_RING();
+ } else
+ I915_WRITE(fence_reg, val);
}
-static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
+static void i830_write_fence_reg(struct drm_i915_fence_reg *reg, int pipelined)
{
struct drm_gem_object *obj = reg->obj;
struct drm_device *dev = obj->dev;
@@ -2411,6 +2431,7 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
uint32_t val;
uint32_t pitch_val;
uint32_t fence_size_bits;
+ RING_LOCALS;
if ((obj_priv->gtt_offset & ~I830_FENCE_START_MASK) ||
(obj_priv->gtt_offset & (obj->size - 1))) {
@@ -2432,7 +2453,14 @@ static void i830_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 (pipelined) {
+ BEGIN_LP_RING(3);
+ OUT_RING(MI_LOAD_REGISTER_IMM);
+ OUT_RING(FENCE_REG_830_0 + (regnum * 4));
+ OUT_RING(val);
+ ADVANCE_LP_RING();
+ } else
+ I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val);
}
static int i915_find_fence_reg(struct drm_device *dev, int pipelined)
@@ -2517,6 +2545,14 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj, int pipelined)
/* Wait for the gpu to setup the fence it it was pipelined. */
if (!pipelined && reg->setup_seqno != 0) {
+ /* With certain error conditions, the request might not
+ * yet have been emitted. */
+ if (reg->setup_seqno == dev_priv->mm.next_gem_seqno) {
+ uint32_t seqno = i915_add_request(dev, NULL);
+ if (seqno == 0)
+ return -ENOMEM;
+ }
+
ret = i915_wait_request(dev, reg->setup_seqno);
if (ret != 0)
return ret;
@@ -2562,18 +2598,12 @@ i915_gem_object_get_fence_reg(struct drm_gem_object *obj, int pipelined)
else
reg->setup_seqno = 0;
- if (pipelined && reg->last_rendering_seqno != 0) {
- ret = i915_wait_request(dev, reg->last_rendering_seqno);
- if (ret != 0)
- return ret;
- }
-
if (IS_I965G(dev))
- i965_write_fence_reg(reg);
+ i965_write_fence_reg(reg, pipelined);
else if (IS_I9XX(dev))
- i915_write_fence_reg(reg);
+ i915_write_fence_reg(reg, pipelined);
else
- i830_write_fence_reg(reg);
+ i830_write_fence_reg(reg, pipelined);
trace_i915_gem_object_get_fence(obj, obj_priv->fence_reg,
obj_priv->tiling_mode);