drm/i915: Track purged state.
authorChris Wilson <chris@chris-wilson.co.uk>
Tue, 22 Sep 2009 13:24:13 +0000 (14:24 +0100)
committerChris Wilson <chris@chris-wilson.co.uk>
Wed, 23 Sep 2009 00:10:38 +0000 (01:10 +0100)
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>
drivers/gpu/drm/i915/i915_gem.c
include/drm/i915_drm.h

index 8beec97..f4f714e 100644 (file)
@@ -1470,6 +1470,7 @@ i915_gem_object_put_pages(struct drm_gem_object *obj)
        int i;
 
        BUG_ON(obj_priv->pages_refcount == 0);
        int i;
 
        BUG_ON(obj_priv->pages_refcount == 0);
+       BUG_ON(obj_priv->madv == __I915_MADV_PURGED);
 
        if (--obj_priv->pages_refcount != 0)
                return;
 
        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)
 {
 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
 }
 
 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 (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;
        }
                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;
 
        }
        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;
                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;
        }
 
                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);
 
 
        /* 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);
 
        drm_gem_object_unreference(obj);
        mutex_unlock(&dev->struct_mutex);
 
index 607c9da..7e0cb1d 100644 (file)
@@ -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_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 */
 
 struct drm_i915_gem_madvise {
        /** Handle of the buffer to change the backing store advice */