aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/i915_gem.c
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2009-09-14 11:50:29 -0400
committerJesse Barnes <jbarnes@virtuousgeek.org>2009-09-17 17:43:31 -0400
commit3ef94daae7530b4ebcd2e5f48f1028cd2d2470ba (patch)
tree130f7e46f4d34b3016775c9e1980d971c475dc55 /drivers/gpu/drm/i915/i915_gem.c
parent31169714fc928aed4e945b959dca2bedd259b9c9 (diff)
drm/i915: Add ioctl to set 'purgeability' of objects
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>
Diffstat (limited to 'drivers/gpu/drm/i915/i915_gem.c')
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c81
1 files changed, 73 insertions, 8 deletions
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 2fff2e0a976e..2ab30f251943 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1436,13 +1436,21 @@ i915_gem_object_put_pages(struct drm_gem_object *obj)
1436 if (obj_priv->tiling_mode != I915_TILING_NONE) 1436 if (obj_priv->tiling_mode != I915_TILING_NONE)
1437 i915_gem_object_save_bit_17_swizzle(obj); 1437 i915_gem_object_save_bit_17_swizzle(obj);
1438 1438
1439 for (i = 0; i < page_count; i++) 1439 if (obj_priv->madv == I915_MADV_DONTNEED)
1440 if (obj_priv->pages[i] != NULL) { 1440 obj_priv->dirty = 0;
1441 if (obj_priv->dirty) 1441
1442 set_page_dirty(obj_priv->pages[i]); 1442 for (i = 0; i < page_count; i++) {
1443 mark_page_accessed(obj_priv->pages[i]); 1443 if (obj_priv->pages[i] == NULL)
1444 page_cache_release(obj_priv->pages[i]); 1444 break;
1445 } 1445
1446 if (obj_priv->dirty)
1447 set_page_dirty(obj_priv->pages[i]);
1448
1449 if (obj_priv->madv == I915_MADV_WILLNEED)
1450 mark_page_accessed(obj_priv->pages[i]);
1451
1452 page_cache_release(obj_priv->pages[i]);
1453 }
1446 obj_priv->dirty = 0; 1454 obj_priv->dirty = 0;
1447 1455
1448 drm_free_large(obj_priv->pages); 1456 drm_free_large(obj_priv->pages);
@@ -2412,6 +2420,12 @@ i915_gem_object_bind_to_gtt(struct drm_gem_object *obj, unsigned alignment)
2412 2420
2413 if (dev_priv->mm.suspended) 2421 if (dev_priv->mm.suspended)
2414 return -EBUSY; 2422 return -EBUSY;
2423
2424 if (obj_priv->madv == I915_MADV_DONTNEED) {
2425 DRM_ERROR("Attempting to bind a purgeable object\n");
2426 return -EINVAL;
2427 }
2428
2415 if (alignment == 0) 2429 if (alignment == 0)
2416 alignment = i915_gem_get_gtt_alignment(obj); 2430 alignment = i915_gem_get_gtt_alignment(obj);
2417 if (alignment & (i915_gem_get_gtt_alignment(obj) - 1)) { 2431 if (alignment & (i915_gem_get_gtt_alignment(obj) - 1)) {
@@ -3679,6 +3693,13 @@ i915_gem_pin_ioctl(struct drm_device *dev, void *data,
3679 } 3693 }
3680 obj_priv = obj->driver_private; 3694 obj_priv = obj->driver_private;
3681 3695
3696 if (obj_priv->madv == I915_MADV_DONTNEED) {
3697 DRM_ERROR("Attempting to pin a I915_MADV_DONTNEED buffer\n");
3698 drm_gem_object_unreference(obj);
3699 mutex_unlock(&dev->struct_mutex);
3700 return -EINVAL;
3701 }
3702
3682 if (obj_priv->pin_filp != NULL && obj_priv->pin_filp != file_priv) { 3703 if (obj_priv->pin_filp != NULL && obj_priv->pin_filp != file_priv) {
3683 DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n", 3704 DRM_ERROR("Already pinned in i915_gem_pin_ioctl(): %d\n",
3684 args->handle); 3705 args->handle);
@@ -3791,6 +3812,49 @@ i915_gem_throttle_ioctl(struct drm_device *dev, void *data,
3791 return i915_gem_ring_throttle(dev, file_priv); 3812 return i915_gem_ring_throttle(dev, file_priv);
3792} 3813}
3793 3814
3815int
3816i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
3817 struct drm_file *file_priv)
3818{
3819 struct drm_i915_gem_madvise *args = data;
3820 struct drm_gem_object *obj;
3821 struct drm_i915_gem_object *obj_priv;
3822
3823 switch (args->madv) {
3824 case I915_MADV_DONTNEED:
3825 case I915_MADV_WILLNEED:
3826 break;
3827 default:
3828 return -EINVAL;
3829 }
3830
3831 obj = drm_gem_object_lookup(dev, file_priv, args->handle);
3832 if (obj == NULL) {
3833 DRM_ERROR("Bad handle in i915_gem_madvise_ioctl(): %d\n",
3834 args->handle);
3835 return -EBADF;
3836 }
3837
3838 mutex_lock(&dev->struct_mutex);
3839 obj_priv = obj->driver_private;
3840
3841 if (obj_priv->pin_count) {
3842 drm_gem_object_unreference(obj);
3843 mutex_unlock(&dev->struct_mutex);
3844
3845 DRM_ERROR("Attempted i915_gem_madvise_ioctl() on a pinned object\n");
3846 return -EINVAL;
3847 }
3848
3849 obj_priv->madv = args->madv;
3850 args->retained = obj_priv->gtt_space != NULL;
3851
3852 drm_gem_object_unreference(obj);
3853 mutex_unlock(&dev->struct_mutex);
3854
3855 return 0;
3856}
3857
3794int i915_gem_init_object(struct drm_gem_object *obj) 3858int i915_gem_init_object(struct drm_gem_object *obj)
3795{ 3859{
3796 struct drm_i915_gem_object *obj_priv; 3860 struct drm_i915_gem_object *obj_priv;
@@ -3815,6 +3879,7 @@ int i915_gem_init_object(struct drm_gem_object *obj)
3815 obj_priv->fence_reg = I915_FENCE_REG_NONE; 3879 obj_priv->fence_reg = I915_FENCE_REG_NONE;
3816 INIT_LIST_HEAD(&obj_priv->list); 3880 INIT_LIST_HEAD(&obj_priv->list);
3817 INIT_LIST_HEAD(&obj_priv->fence_list); 3881 INIT_LIST_HEAD(&obj_priv->fence_list);
3882 obj_priv->madv = I915_MADV_WILLNEED;
3818 3883
3819 return 0; 3884 return 0;
3820} 3885}
@@ -4506,7 +4571,7 @@ i915_gem_object_truncate(struct drm_gem_object *obj)
4506static inline int 4571static inline int
4507i915_gem_object_is_purgeable(struct drm_i915_gem_object *obj_priv) 4572i915_gem_object_is_purgeable(struct drm_i915_gem_object *obj_priv)
4508{ 4573{
4509 return !obj_priv->dirty; 4574 return !obj_priv->dirty || obj_priv->madv == I915_MADV_DONTNEED;
4510} 4575}
4511 4576
4512static int 4577static int