Skip to content

Commit

Permalink
drm/i915: Add ioctl to set 'purgeability' of objects
Browse files Browse the repository at this point in the history
Similar to the madvise() concept, the application may wish to mark some
data as volatile. That is in the event of memory pressure the kernel is
free to discard such buffers safe in the knowledge that the application
can recreate them on demand, and is simply using these as a cache.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
  • Loading branch information
Chris Wilson authored and Jesse Barnes committed Sep 17, 2009
1 parent 3116971 commit 3ef94da
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 8 deletions.
1 change: 1 addition & 0 deletions drivers/gpu/drm/i915/i915_dma.c
Original file line number Diff line number Diff line change
Expand Up @@ -1616,6 +1616,7 @@ struct drm_ioctl_desc i915_ioctls[] = {
DRM_IOCTL_DEF(DRM_I915_GEM_GET_TILING, i915_gem_get_tiling, 0),
DRM_IOCTL_DEF(DRM_I915_GEM_GET_APERTURE, i915_gem_get_aperture_ioctl, 0),
DRM_IOCTL_DEF(DRM_I915_GET_PIPE_FROM_CRTC_ID, intel_get_pipe_from_crtc_id, 0),
DRM_IOCTL_DEF(DRM_I915_GEM_MADVISE, i915_gem_madvise_ioctl, 0),
};

int i915_max_ioctl = DRM_ARRAY_SIZE(i915_ioctls);
Expand Down
7 changes: 7 additions & 0 deletions drivers/gpu/drm/i915/i915_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,11 @@ struct drm_i915_gem_object {
* in an execbuffer object list.
*/
int in_execbuffer;

/**
* Advice: are the backing pages purgeable?
*/
int madv;
};

/**
Expand Down Expand Up @@ -705,6 +710,8 @@ int i915_gem_busy_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
int i915_gem_throttle_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
int i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
int i915_gem_entervt_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv);
int i915_gem_leavevt_ioctl(struct drm_device *dev, void *data,
Expand Down
81 changes: 73 additions & 8 deletions drivers/gpu/drm/i915/i915_gem.c
Original file line number Diff line number Diff line change
Expand Up @@ -1436,13 +1436,21 @@ i915_gem_object_put_pages(struct drm_gem_object *obj)
if (obj_priv->tiling_mode != I915_TILING_NONE)
i915_gem_object_save_bit_17_swizzle(obj);

for (i = 0; i < page_count; i++)
if (obj_priv->pages[i] != NULL) {
if (obj_priv->dirty)
set_page_dirty(obj_priv->pages[i]);
mark_page_accessed(obj_priv->pages[i]);
page_cache_release(obj_priv->pages[i]);
}
if (obj_priv->madv == I915_MADV_DONTNEED)
obj_priv->dirty = 0;

for (i = 0; i < page_count; i++) {
if (obj_priv->pages[i] == NULL)
break;

if (obj_priv->dirty)
set_page_dirty(obj_priv->pages[i]);

if (obj_priv->madv == I915_MADV_WILLNEED)
mark_page_accessed(obj_priv->pages[i]);

page_cache_release(obj_priv->pages[i]);
}
obj_priv->dirty = 0;

drm_free_large(obj_priv->pages);
Expand Down Expand Up @@ -2412,6 +2420,12 @@ 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) {
DRM_ERROR("Attempting to bind a purgeable object\n");
return -EINVAL;
}

if (alignment == 0)
alignment = i915_gem_get_gtt_alignment(obj);
if (alignment & (i915_gem_get_gtt_alignment(obj) - 1)) {
Expand Down Expand Up @@ -3679,6 +3693,13 @@ 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");
drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);
return -EINVAL;
}

if (obj_priv->pin_filp != NULL && obj_priv->pin_filp != file_priv) {
DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n",
args->handle);
Expand Down Expand Up @@ -3791,6 +3812,49 @@ i915_gem_throttle_ioctl(struct drm_device *dev, void *data,
return i915_gem_ring_throttle(dev, file_priv);
}

int
i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
struct drm_file *file_priv)
{
struct drm_i915_gem_madvise *args = data;
struct drm_gem_object *obj;
struct drm_i915_gem_object *obj_priv;

switch (args->madv) {
case I915_MADV_DONTNEED:
case I915_MADV_WILLNEED:
break;
default:
return -EINVAL;
}

obj = drm_gem_object_lookup(dev, file_priv, args->handle);
if (obj == NULL) {
DRM_ERROR("Bad handle in i915_gem_madvise_ioctl(): %d\n",
args->handle);
return -EBADF;
}

mutex_lock(&dev->struct_mutex);
obj_priv = obj->driver_private;

if (obj_priv->pin_count) {
drm_gem_object_unreference(obj);
mutex_unlock(&dev->struct_mutex);

DRM_ERROR("Attempted i915_gem_madvise_ioctl() on a pinned object\n");
return -EINVAL;
}

obj_priv->madv = args->madv;
args->retained = obj_priv->gtt_space != NULL;

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

return 0;
}

int i915_gem_init_object(struct drm_gem_object *obj)
{
struct drm_i915_gem_object *obj_priv;
Expand All @@ -3815,6 +3879,7 @@ int i915_gem_init_object(struct drm_gem_object *obj)
obj_priv->fence_reg = I915_FENCE_REG_NONE;
INIT_LIST_HEAD(&obj_priv->list);
INIT_LIST_HEAD(&obj_priv->fence_list);
obj_priv->madv = I915_MADV_WILLNEED;

return 0;
}
Expand Down Expand Up @@ -4506,7 +4571,7 @@ i915_gem_object_truncate(struct drm_gem_object *obj)
static inline int
i915_gem_object_is_purgeable(struct drm_i915_gem_object *obj_priv)
{
return !obj_priv->dirty;
return !obj_priv->dirty || obj_priv->madv == I915_MADV_DONTNEED;
}

static int
Expand Down
18 changes: 18 additions & 0 deletions include/drm/i915_drm.h
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,7 @@ typedef struct _drm_i915_sarea {
#define DRM_I915_GEM_GET_APERTURE 0x23
#define DRM_I915_GEM_MMAP_GTT 0x24
#define DRM_I915_GET_PIPE_FROM_CRTC_ID 0x25
#define DRM_I915_GEM_MADVISE 0x26

#define DRM_IOCTL_I915_INIT DRM_IOW( DRM_COMMAND_BASE + DRM_I915_INIT, drm_i915_init_t)
#define DRM_IOCTL_I915_FLUSH DRM_IO ( DRM_COMMAND_BASE + DRM_I915_FLUSH)
Expand Down Expand Up @@ -221,6 +222,7 @@ typedef struct _drm_i915_sarea {
#define DRM_IOCTL_I915_GEM_GET_TILING DRM_IOWR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_TILING, struct drm_i915_gem_get_tiling)
#define DRM_IOCTL_I915_GEM_GET_APERTURE DRM_IOR (DRM_COMMAND_BASE + DRM_I915_GEM_GET_APERTURE, struct drm_i915_gem_get_aperture)
#define DRM_IOCTL_I915_GET_PIPE_FROM_CRTC_ID DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GET_PIPE_FROM_CRTC_ID, struct drm_intel_get_pipe_from_crtc_id)
#define DRM_IOCTL_I915_GEM_MADVISE DRM_IOWR(DRM_COMMAND_BASE + DRM_I915_GEM_MADVISE, struct drm_i915_gem_madvise)

/* Allow drivers to submit batchbuffers directly to hardware, relying
* on the security mechanisms provided by hardware.
Expand Down Expand Up @@ -667,4 +669,20 @@ struct drm_i915_get_pipe_from_crtc_id {
__u32 pipe;
};

#define I915_MADV_WILLNEED 0
#define I915_MADV_DONTNEED 1

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

/* Advice: either the buffer will be needed again in the near future,
* or wont be and could be discarded under memory pressure.
*/
__u32 madv;

/** Whether the backing store still exists. */
__u32 retained;
};

#endif /* _I915_DRM_H_ */

0 comments on commit 3ef94da

Please sign in to comment.