Commit bb6baf76 authored by Chris Wilson's avatar Chris Wilson
Browse files

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: default avatarChris Wilson <chris@chris-wilson.co.uk>
parent 9731129c
Loading
Loading
Loading
Loading
+15 −9
Original line number Original line Diff line number Diff line
@@ -1470,6 +1470,7 @@ i915_gem_object_put_pages(struct drm_gem_object *obj)
	int i;
	int i;


	BUG_ON(obj_priv->pages_refcount == 0);
	BUG_ON(obj_priv->pages_refcount == 0);
	BUG_ON(obj_priv->madv == __I915_MADV_PURGED);


	if (--obj_priv->pages_refcount != 0)
	if (--obj_priv->pages_refcount != 0)
		return;
		return;
@@ -1534,11 +1535,14 @@ i915_gem_object_move_to_flushing(struct drm_gem_object *obj)
static void
static void
i915_gem_object_truncate(struct drm_gem_object *obj)
i915_gem_object_truncate(struct drm_gem_object *obj)
{
{
	struct drm_i915_gem_object *obj_priv = obj->driver_private;
	struct inode *inode;
	struct inode *inode;


	inode = obj->filp->f_path.dentry->d_inode;
	inode = obj->filp->f_path.dentry->d_inode;
	if (inode->i_op->truncate)
	if (inode->i_op->truncate)
		inode->i_op->truncate (inode);
		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)
	if (dev_priv->mm.suspended)
		return -EBUSY;
		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");
		DRM_ERROR("Attempting to bind a purgeable object\n");
		return -EINVAL;
		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) {
	if (obj_priv->madv != I915_MADV_WILLNEED) {
		DRM_ERROR("Attempting to pin a I915_MADV_DONTNEED buffer\n");
		DRM_ERROR("Attempting to pin a purgeable buffer\n");
		drm_gem_object_unreference(obj);
		drm_gem_object_unreference(obj);
		mutex_unlock(&dev->struct_mutex);
		mutex_unlock(&dev->struct_mutex);
		return -EINVAL;
		return -EINVAL;
@@ -4081,14 +4085,16 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
		return -EINVAL;
		return -EINVAL;
	}
	}


	if (obj_priv->madv != __I915_MADV_PURGED)
		obj_priv->madv = args->madv;
		obj_priv->madv = args->madv;
	args->retained = obj_priv->gtt_space != NULL;


	/* if the object is no longer bound, discard its backing storage */
	/* if the object is no longer bound, discard its backing storage */
	if (i915_gem_object_is_purgeable(obj_priv) &&
	if (i915_gem_object_is_purgeable(obj_priv) &&
	    obj_priv->gtt_space == NULL)
	    obj_priv->gtt_space == NULL)
		i915_gem_object_truncate(obj);
		i915_gem_object_truncate(obj);


	args->retained = obj_priv->madv != __I915_MADV_PURGED;

	drm_gem_object_unreference(obj);
	drm_gem_object_unreference(obj);
	mutex_unlock(&dev->struct_mutex);
	mutex_unlock(&dev->struct_mutex);


+1 −0
Original line number Original line Diff line number Diff line
@@ -671,6 +671,7 @@ struct drm_i915_get_pipe_from_crtc_id {


#define I915_MADV_WILLNEED 0
#define I915_MADV_WILLNEED 0
#define I915_MADV_DONTNEED 1
#define I915_MADV_DONTNEED 1
#define __I915_MADV_PURGED 2 /* internal state */


struct drm_i915_gem_madvise {
struct drm_i915_gem_madvise {
	/** Handle of the buffer to change the backing store advice */
	/** Handle of the buffer to change the backing store advice */