[RFC 3/3] drm/i915: Add the truncation logic for Stolen objects.

sourab.gupta
2014-03-05T11:35:31Z

From: Sourab Gupta <sourab.gupta@intel.com>

Adding the truncation logic for buffer objects with backing storage
from stolen memory. The objects will be truncated when user marks them
as purgeable and they are part of the inactive list.

Testcase: igt/gem_stolen_mem

Signed-off-by: Sourab Gupta <sourab.gupta@intel.com>

Signed-off-by: Akash Goel <akash.goel@intel.com>
Signed-off-by: Sourab Gupta <sourab.gupta@intel.com>
---
drivers/gpu/drm/i915/i915_drv.h | 1 +
drivers/gpu/drm/i915/i915_gem.c | 11 ++++++++++-
drivers/gpu/drm/i915/i915_gem_stolen.c | 32 ++++++++++++++++++++++++++++++++
3 files changed, 43 insertions(+), 1 deletion(-)

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index b5f603f..02142c0 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -2443,6 +2443,7 @@ i915_gem_object_create_stolen_for_preallocated(struct drm_device *dev,
u32 size);
void i915_gem_object_move_to_stolen(struct drm_i915_gem_object *obj);
void i915_gem_object_release_stolen(struct drm_i915_gem_object *obj);
+void i915_gem_object_truncate_stolen(struct drm_i915_gem_object *obj);

/* i915_gem_tiling.c */
static inline bool i915_gem_object_needs_bit17_swizzle(struct drm_i915_gem_object *obj)
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index f57ca31..d106806 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -2071,6 +2071,11 @@ i915_gem_object_move_to_inactive(struct drm_i915_gem_object *obj)
obj->fenced_gpu_access = false;

obj->active = 0;
+
+ /* Truncate the stolen obj immediately if it is marked as purgeable */
+ if(obj->stolen && (i915_gem_object_is_purgeable(obj) ) )
+ i915_gem_object_truncate_stolen(obj);
+
drm_gem_object_unreference(&obj->base);

WARN_ON(i915_verify_lists(dev));
@@ -4069,6 +4074,10 @@ i915_gem_madvise_ioctl(struct drm_device *dev, void *data,
if (i915_gem_object_is_purgeable(obj) && obj->pages == NULL)
i915_gem_object_truncate(obj);

+ /* if the stolen mem object is no longer active, discard its backing storage */
+ if (obj->stolen && i915_gem_object_is_purgeable(obj) && i915_gem_object_is_inactive(obj))
+ i915_gem_object_truncate_stolen(obj);
+
args->retained = obj->madv != __I915_MADV_PURGED;

out:
@@ -4187,7 +4196,7 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)

/* Stolen objects don't hold a ref, but do hold pin count. Fix that up
* before progressing. */
- if (obj->stolen)
+ if ((obj->stolen) && (obj->madv != __I915_MADV_PURGED))
i915_gem_object_unpin_pages(obj);

if (WARN_ON(obj->pages_pin_count))
diff --git a/drivers/gpu/drm/i915/i915_gem_stolen.c b/drivers/gpu/drm/i915/i915_gem_stolen.c
index 6758ba4..1ecc447 100644
--- a/drivers/gpu/drm/i915/i915_gem_stolen.c
+++ b/drivers/gpu/drm/i915/i915_gem_stolen.c
@@ -471,6 +471,11 @@ i915_gem_object_move_to_stolen(struct drm_i915_gem_object *obj)
if (size == 0)
return;

+ if (obj->madv != I915_MADV_WILLNEED) {
+ DRM_ERROR("Attempting to allocate a purgeable object\n");
+ return;
+ }
+
/* Check if already shmem space has been allocated for the object
* or not. We cannot rely upon on the value of 'pages' field for this.
* As even though if the 'pages' field is NULL, it does not actually
@@ -549,3 +554,30 @@ i915_gem_object_release_stolen(struct drm_i915_gem_object *obj)
obj->stolen = NULL;
}
}
+
+/*
+ * This function truncates stolen objects to reclaim their backing storage
+ * from stolen mem area. Currently objects are truncated when they are
+ * marked as purgeable and are in inactive list.
+ * Stolen objects are not considered for truncation by shrinker, as their
+ * physical pages are kept as pinned throughout their existance.
+ */
+void
+i915_gem_object_truncate_stolen(struct drm_i915_gem_object *obj)
+{
+ struct i915_vma *vma_temp,*next;
+
+ BUG_ON(!obj->stolen);
+
+ list_for_each_entry_safe(vma_temp, next, &obj->vma_list, vma_link)
+ WARN_ON(i915_vma_unbind(vma_temp));
+
+ i915_gem_object_unpin_pages(obj);
+ i915_gem_object_put_pages(obj);
+
+ /* Release the stolen space */
+ i915_gem_object_release_stolen(obj);
+
+ obj->madv = __I915_MADV_PURGED;
+
+}
--
1.7.9.5