[Intel-gfx] [PATCH] drm/i915: Clear fence register on tiling stride change.
Chris Wilson
chris at chris-wilson.co.uk
Wed Feb 11 15:26:48 CET 2009
The fence register value also depends upon the stride of the object, so we
need to clear the fence if that is changed as well.
Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
drivers/gpu/drm/i915/i915_drv.h | 1 +
drivers/gpu/drm/i915/i915_gem.c | 45 +++++++++++++++++++++++++------
drivers/gpu/drm/i915/i915_gem_tiling.c | 34 ++++++++++++------------
3 files changed, 54 insertions(+), 26 deletions(-)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 3151da4..1084b03 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -618,6 +618,7 @@ void i915_gem_object_unpin(struct drm_gem_object *obj);
int i915_gem_object_unbind(struct drm_gem_object *obj);
void i915_gem_lastclose(struct drm_device *dev);
uint32_t i915_get_gem_seqno(struct drm_device *dev);
+int i915_gem_object_put_fence_reg(struct drm_gem_object *obj);
void i915_gem_retire_requests(struct drm_device *dev);
void i915_gem_retire_work_handler(struct work_struct *work);
void i915_gem_clflush_object(struct drm_gem_object *obj);
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index ade6c18..29d5405 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1520,7 +1520,6 @@ static void i830_write_fence_reg(struct drm_i915_fence_reg *reg)
val |= I830_FENCE_REG_VALID;
I915_WRITE(FENCE_REG_830_0 + (regnum * 4), val);
-
}
/**
@@ -1673,13 +1672,6 @@ try_again:
return 0;
}
-/**
- * i915_gem_clear_fence_reg - clear out fence register info
- * @obj: object to clear
- *
- * Zeroes out the fence register itself and clears out the associated
- * data structures in dev_priv and obj_priv.
- */
static void
i915_gem_clear_fence_reg(struct drm_gem_object *obj)
{
@@ -1693,7 +1685,6 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj)
obj_priv->fence_reg, obj,
obj_priv->gtt_offset, obj->size);
#endif
-
if (IS_I965G(dev))
I915_WRITE64(FENCE_REG_965_0 + (obj_priv->fence_reg * 8), 0);
else
@@ -1704,6 +1695,42 @@ i915_gem_clear_fence_reg(struct drm_gem_object *obj)
}
/**
+ * i915_gem_object_put_fence_reg - waits on outstanding fenced access
+ * to the buffer to finish, and then resets the fence register.
+ * @obj: tiled object holding a fence register.
+ *
+ * Zeroes out the fence register itself and clears out the associated
+ * data structures in dev_priv and obj_priv.
+ */
+int
+i915_gem_object_put_fence_reg(struct drm_gem_object *obj)
+{
+ struct drm_device *dev = obj->dev;
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+
+ if (obj_priv->fence_reg == I915_FENCE_REG_NONE)
+ return 0;
+
+ /* On the i915, GPU access to tiled buffers is via a fence,
+ * therefore we must wait for any outstanding access to complete
+ * before clearing the fence.
+ */
+ if (!IS_I965G(dev)) {
+ int ret;
+
+ i915_gem_object_flush_gpu_write_domain(obj);
+ i915_gem_object_flush_gtt_write_domain(obj);
+ ret = i915_gem_object_wait_rendering(obj);
+ if (ret != 0)
+ return ret;
+ }
+
+ i915_gem_clear_fence_reg (obj);
+
+ return 0;
+}
+
+/**
* Finds free space in the GTT aperture and binds the object there.
*/
static int
diff --git a/drivers/gpu/drm/i915/i915_gem_tiling.c b/drivers/gpu/drm/i915/i915_gem_tiling.c
index 7fb4191..1beaddc 100644
--- a/drivers/gpu/drm/i915/i915_gem_tiling.c
+++ b/drivers/gpu/drm/i915/i915_gem_tiling.c
@@ -252,6 +252,7 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
drm_i915_private_t *dev_priv = dev->dev_private;
struct drm_gem_object *obj;
struct drm_i915_gem_object *obj_priv;
+ int ret = 0;
obj = drm_gem_object_lookup(dev, file_priv, args->handle);
if (obj == NULL)
@@ -259,15 +260,15 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
obj_priv = obj->driver_private;
if (!i915_tiling_ok(dev, args->stride, obj->size, args->tiling_mode)) {
+ mutex_lock(&dev->struct_mutex);
drm_gem_object_unreference(obj);
+ mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}
- mutex_lock(&dev->struct_mutex);
-
if (args->tiling_mode == I915_TILING_NONE) {
- obj_priv->tiling_mode = I915_TILING_NONE;
args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
+ args->stride = 0;
} else {
if (args->tiling_mode == I915_TILING_X)
args->swizzle_mode = dev_priv->mm.bit_6_swizzle_x;
@@ -277,32 +278,31 @@ i915_gem_set_tiling(struct drm_device *dev, void *data,
if (args->swizzle_mode == I915_BIT_6_SWIZZLE_UNKNOWN) {
args->tiling_mode = I915_TILING_NONE;
args->swizzle_mode = I915_BIT_6_SWIZZLE_NONE;
+ args->stride = 0;
}
}
- if (args->tiling_mode != obj_priv->tiling_mode) {
- int ret;
- /* Unbind the object, as switching tiling means we're
- * switching the cache organization due to fencing, probably.
- */
- ret = i915_gem_object_unbind(obj);
+ mutex_lock(&dev->struct_mutex);
+ if (args->tiling_mode != obj_priv->tiling_mode ||
+ args->stride != obj_priv->stride) {
+ ret = i915_gem_object_put_fence_reg(obj);
if (ret != 0) {
WARN(ret != -ERESTARTSYS,
- "failed to unbind object for tiling switch");
+ "failed to clear fence register for"
+ "tiling switch");
args->tiling_mode = obj_priv->tiling_mode;
- mutex_unlock(&dev->struct_mutex);
- drm_gem_object_unreference(obj);
-
- return ret;
+ args->stride = obj_priv->stride;
+ goto err;
}
+
obj_priv->tiling_mode = args->tiling_mode;
+ obj_priv->stride = args->stride;
}
- obj_priv->stride = args->stride;
-
+err:
drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);
- return 0;
+ return ret;
}
/**
--
1.6.0.4
More information about the Intel-gfx
mailing list