Commit bb6baf76 authored by Chris Wilson's avatar Chris Wilson

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
...@@ -1470,6 +1470,7 @@ i915_gem_object_put_pages(struct drm_gem_object *obj) ...@@ -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) ...@@ -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 inode *inode; struct drm_i915_gem_object *obj_priv = obj->driver_private;
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) ...@@ -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, ...@@ -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, ...@@ -4081,14 +4085,16 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
return -EINVAL; return -EINVAL;
} }
obj_priv->madv = args->madv; if (obj_priv->madv != __I915_MADV_PURGED)
args->retained = obj_priv->gtt_space != NULL; obj_priv->madv = args->madv;
/* 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);
......
...@@ -671,6 +671,7 @@ struct drm_i915_get_pipe_from_crtc_id { ...@@ -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 */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment