summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2009-09-22 17:24:13 +0400
committerChris Wilson <chris@chris-wilson.co.uk>2009-09-23 04:10:38 +0400
commitbb6baf76f45708dbba651ed76a7ad94462f30c0b (patch)
treea58c54d10d9f35f32799d59189467607a84c1b4c
parent9731129c5e3077d0c2da13479f91c3a07e341f70 (diff)
downloadlinux-bb6baf76f45708dbba651ed76a7ad94462f30c0b.tar.xz
drm/i915: Track purged state.
In order to correctly prevent the invalid reuse of a purged buffer, we need to track such events and warn the user before something bad happens. Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c24
-rw-r--r--include/drm/i915_drm.h1
2 files changed, 16 insertions, 9 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 8beec97fa348..f4f714e39b7b 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1470,6 +1470,7 @@ i915_gem_object_put_pages(struct drm_gem_object *obj)
int i;
BUG_ON(obj_priv->pages_refcount == 0);
+ BUG_ON(obj_priv->madv == __I915_MADV_PURGED);
if (--obj_priv->pages_refcount != 0)
return;
@@ -1534,11 +1535,14 @@ i915_gem_object_move_to_flushing(struct drm_gem_object *obj)
static void
i915_gem_object_truncate(struct drm_gem_object *obj)
{
- struct inode *inode;
+ struct drm_i915_gem_object *obj_priv = obj->driver_private;
+ struct inode *inode;
- inode = obj->filp->f_path.dentry->d_inode;
- if (inode->i_op->truncate)
- inode->i_op->truncate (inode);
+ inode = obj->filp->f_path.dentry->d_inode;
+ if (inode->i_op->truncate)
+ inode->i_op->truncate (inode);
+
+ obj_priv->madv = __I915_MADV_PURGED;
}
static inline int
@@ -2559,7 +2563,7 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
if (dev_priv->mm.suspended)
return -EBUSY;
- if (obj_priv->madv == I915_MADV_DONTNEED) {
+ if (obj_priv->madv != I915_MADV_WILLNEED) {
DRM_ERROR("Attempting to bind a purgeable object\n");
return -EINVAL;
}
@@ -3928,8 +3932,8 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data,
}
obj_priv = obj->driver_private;
- if (obj_priv->madv == I915_MADV_DONTNEED) {
- DRM_ERROR("Attempting to pin a I915_MADV_DONTNEED buffer\n");
+ if (obj_priv->madv != I915_MADV_WILLNEED) {
+ DRM_ERROR("Attempting to pin a purgeable buffer\n");
drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);
return -EINVAL;
@@ -4081,14 +4085,16 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
return -EINVAL;
}
- obj_priv->madv = args->madv;
- args->retained = obj_priv->gtt_space != NULL;
+ if (obj_priv->madv != __I915_MADV_PURGED)
+ obj_priv->madv = args->madv;
/* if the object is no longer bound, discard its backing storage */
if (i915_gem_object_is_purgeable(obj_priv) &&
obj_priv->gtt_space == NULL)
i915_gem_object_truncate(obj);
+ args->retained = obj_priv->madv != __I915_MADV_PURGED;
+
drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);
diff --git a/include/drm/i915_drm.h b/include/drm/i915_drm.h
index 607c9da061e8..7e0cb1da92e6 100644
--- a/include/drm/i915_drm.h
+++ b/include/drm/i915_drm.h
@@ -671,6 +671,7 @@ struct drm_i915_get_pipe_from_crtc_id {
#define I915_MADV_WILLNEED 0
#define I915_MADV_DONTNEED 1
+#define __I915_MADV_PURGED 2 /* internal state */
struct drm_i915_gem_madvise {
/** Handle of the buffer to change the backing store advice */