[PATCH] drm/i915: Flush the queue of freed objects on shrinking

Chris Wilson chris at chris-wilson.co.uk
Wed Jun 26 19:53:07 UTC 2019


While we can't flush all the objects that are already added to the delay
free queue as they may have been grabbed already by the free thread, we
can try our best to free anything still in the queue before shrinking.

Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
---
 drivers/gpu/drm/i915/gem/i915_gem_object.c   | 24 +++++++++++++-------
 drivers/gpu/drm/i915/gem/i915_gem_object.h   |  5 +++-
 drivers/gpu/drm/i915/gem/i915_gem_shrinker.c |  3 +++
 drivers/gpu/drm/i915/i915_gem.c              |  2 +-
 4 files changed, 24 insertions(+), 10 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
index 43194fbcbc2e..75de10e46ff7 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
@@ -147,7 +147,8 @@ void i915_gem_close_object(struct drm_gem_object *gem, struct drm_file *file)
 }
 
 static void __i915_gem_free_objects(struct drm_i915_private *i915,
-				    struct llist_node *freed)
+				    struct llist_node *freed,
+				    unsigned int flags)
 {
 	struct drm_i915_gem_object *obj, *on;
 	intel_wakeref_t wakeref;
@@ -158,7 +159,8 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915,
 
 		trace_i915_gem_object_destroy(obj);
 
-		mutex_lock(&i915->drm.struct_mutex);
+		if (!(flags & FREE_OBJECTS_LOCKED))
+			mutex_lock(&i915->drm.struct_mutex);
 
 		list_for_each_entry_safe(vma, vn, &obj->vma.list, obj_link) {
 			GEM_BUG_ON(i915_vma_is_active(vma));
@@ -184,7 +186,8 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915,
 			spin_unlock_irqrestore(&i915->mm.obj_lock, flags);
 		}
 
-		mutex_unlock(&i915->drm.struct_mutex);
+		if (!(flags & FREE_OBJECTS_LOCKED))
+			mutex_unlock(&i915->drm.struct_mutex);
 
 		GEM_BUG_ON(atomic_read(&obj->bind_count));
 		GEM_BUG_ON(obj->userfault_count);
@@ -209,12 +212,14 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915,
 		GEM_BUG_ON(!atomic_read(&i915->mm.free_count));
 		atomic_dec(&i915->mm.free_count);
 
-		cond_resched();
+		if (!(flags & FREE_OBJECTS_LOCKED))
+			cond_resched();
 	}
 	intel_runtime_pm_put(&i915->runtime_pm, wakeref);
 }
 
-void i915_gem_flush_free_objects(struct drm_i915_private *i915)
+void i915_gem_flush_free_objects(struct drm_i915_private *i915,
+				 unsigned long flags)
 {
 	struct llist_node *freed;
 
@@ -223,12 +228,15 @@ void i915_gem_flush_free_objects(struct drm_i915_private *i915)
 	if (!llist_empty(&i915->mm.free_list)) { /* quick test for hotpath */
 		/* Only one consumer of llist_del_first() allowed */
 		spin_lock(&i915->mm.free_lock);
-		freed = llist_del_first(&i915->mm.free_list);
+		if (flags & FREE_OBJECTS_ALL)
+			freed = llist_del_all(&i915->mm.free_list);
+		else
+			freed = llist_del_first(&i915->mm.free_list);
 		spin_unlock(&i915->mm.free_lock);
 	}
 	if (unlikely(freed)) {
 		freed->next = NULL;
-		__i915_gem_free_objects(i915, freed);
+		__i915_gem_free_objects(i915, freed, flags);
 	}
 }
 
@@ -251,7 +259,7 @@ static void __i915_gem_free_work(struct work_struct *work)
 	while ((freed = llist_del_all(&i915->mm.free_list))) {
 		spin_unlock(&i915->mm.free_lock);
 
-		__i915_gem_free_objects(i915, freed);
+		__i915_gem_free_objects(i915, freed, 0);
 		if (need_resched())
 			return;
 
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
index 20754c15412a..e2f2eaade8a5 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
@@ -40,7 +40,10 @@ int i915_gem_object_attach_phys(struct drm_i915_gem_object *obj, int align);
 void i915_gem_close_object(struct drm_gem_object *gem, struct drm_file *file);
 void i915_gem_free_object(struct drm_gem_object *obj);
 
-void i915_gem_flush_free_objects(struct drm_i915_private *i915);
+void i915_gem_flush_free_objects(struct drm_i915_private *i915,
+				 unsigned long flags);
+#define FREE_OBJECTS_ALL BIT(0)
+#define FREE_OBJECTS_LOCKED BIT(1)
 
 struct sg_table *
 __i915_gem_object_unset_pages(struct drm_i915_gem_object *obj);
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c b/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c
index d99f1a600b96..763c84551a80 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_shrinker.c
@@ -170,6 +170,9 @@ i915_gem_shrink(struct drm_i915_private *i915,
 
 	trace_i915_gem_shrink(i915, target, shrink);
 
+	i915_gem_flush_free_objects(i915,
+				    FREE_OBJECTS_ALL | FREE_OBJECTS_LOCKED);
+
 	/*
 	 * Unbinding of objects will require HW access; Let us not wake the
 	 * device just to recover a little memory. If absolutely necessary,
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index b7f290b77f8f..323cc2b52b6b 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -227,7 +227,7 @@ i915_gem_create_ioctl(struct drm_device *dev, void *data,
 	struct drm_i915_private *dev_priv = to_i915(dev);
 	struct drm_i915_gem_create *args = data;
 
-	i915_gem_flush_free_objects(dev_priv);
+	i915_gem_flush_free_objects(dev_priv, 0);
 
 	return i915_gem_create(file, dev_priv,
 			       &args->size, &args->handle);
-- 
2.20.1



More information about the Intel-gfx-trybot mailing list