[PATCH 10/10] drm/i915: Add blocking dead object freeing to i915_gem_evict_vm

Maarten Lankhorst maarten.lankhorst at linux.intel.com
Tue Jan 11 16:07:27 UTC 2022


Signed-off-by: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_object.c | 28 +++++++++++++++++++---
 drivers/gpu/drm/i915/gem/i915_gem_object.h |  3 +++
 drivers/gpu/drm/i915/i915_gem_evict.c      | 22 +++++++++++++----
 drivers/gpu/drm/i915/i915_gem_ww.c         | 19 ++++++++++++++-
 4 files changed, 64 insertions(+), 8 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
index fd34b1a115c4..101d4f60157b 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
@@ -89,6 +89,7 @@ void i915_gem_object_init(struct drm_i915_gem_object *obj,
 	mutex_init(&obj->mm.get_page.lock);
 	INIT_RADIX_TREE(&obj->mm.get_dma_page.radix, GFP_KERNEL | __GFP_NOWARN);
 	mutex_init(&obj->mm.get_dma_page.lock);
+	kref_init(&i915_gem_to_ttm(obj)->kref);
 }
 
 /**
@@ -319,6 +320,29 @@ void __i915_gem_free_object(struct drm_i915_gem_object *obj)
 	__i915_gem_object_fini(obj);
 }
 
+static void __i915_gem_free_object_free_destroy(struct kref *kref)
+{
+	struct drm_i915_gem_object *obj = container_of(kref, struct drm_i915_gem_object, __do_not_access.kref);
+
+	__i915_gem_free_object(obj);
+
+	/* But keep the pointer alive for RCU-protected lookups */
+	call_rcu(&obj->rcu, __i915_gem_free_object_rcu);
+}
+
+void i915_gem_object_free_get(struct drm_i915_gem_object *obj)
+{
+	kref_get(&i915_gem_to_ttm(obj)->kref);
+}
+
+void i915_gem_object_free_put(struct drm_i915_gem_object *obj)
+{
+	if (obj->ops->delayed_free)
+		ttm_bo_put(i915_gem_to_ttm(obj));
+	else
+		kref_put(&i915_gem_to_ttm(obj)->kref, __i915_gem_free_object_free_destroy);
+}
+
 static void __i915_gem_free_objects(struct drm_i915_private *i915,
 				    struct llist_node *freed)
 {
@@ -340,10 +364,8 @@ static void __i915_gem_free_objects(struct drm_i915_private *i915,
 
 		__i915_gem_object_pages_fini(obj);
 		i915_gem_object_unlock(obj);
-		__i915_gem_free_object(obj);
 
-		/* But keep the pointer alive for RCU-protected lookups */
-		call_rcu(&obj->rcu, __i915_gem_free_object_rcu);
+		i915_gem_object_free_put(obj);
 		cond_resched();
 	}
 }
diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.h b/drivers/gpu/drm/i915/gem/i915_gem_object.h
index 08db9af75a62..1b7ee6cd65bf 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.h
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.h
@@ -123,6 +123,9 @@ i915_gem_object_get_rcu(struct drm_i915_gem_object *obj)
 	return obj;
 }
 
+void i915_gem_object_free_get(struct drm_i915_gem_object *obj);
+void i915_gem_object_free_put(struct drm_i915_gem_object *obj);
+
 static inline struct drm_i915_gem_object *
 i915_gem_object_lookup(struct drm_file *file, u32 handle)
 {
diff --git a/drivers/gpu/drm/i915/i915_gem_evict.c b/drivers/gpu/drm/i915/i915_gem_evict.c
index ec1423e60516..d66f60493522 100644
--- a/drivers/gpu/drm/i915/i915_gem_evict.c
+++ b/drivers/gpu/drm/i915/i915_gem_evict.c
@@ -422,18 +422,32 @@ int i915_gem_evict_vm(struct i915_address_space *vm, struct i915_gem_ww_ctx *ww)
 		if (dma_resv_locking_ctx(vma->obj->base.resv) != &ww->ctx &&
 		    !i915_gem_object_trylock_to_evict(vma->obj, ww)) {
 			struct drm_i915_gem_object *obj;
+			bool dead = false;
 
 			if (i915_vma_is_pinned(vma))
 				continue;
 
 			obj = i915_gem_object_get_rcu(vma->obj);
-			if (!obj)
-				/* Object's dead, can't drop vm->mutex safely */
-				continue;
+			if (!obj) {
+				obj = vma->obj;
+				i915_gem_object_free_get(obj);
+				dead = true;
+			}
 
 			mutex_unlock(&vm->mutex);
 			ret = i915_gem_object_lock_to_evict(obj, ww);
-			i915_gem_object_put(obj);
+
+
+			if (dead) {
+				if (!ret) {
+					__i915_gem_object_pages_fini(obj);
+					list_del(&obj->obj_link);
+					i915_gem_object_unlock(obj);
+				}
+				i915_gem_object_free_put(obj);
+			} else {
+				i915_gem_object_put(obj);
+			}
 
 			if (ret) {
 				i915_gem_ww_ctx_unlock_evictions(ww);
diff --git a/drivers/gpu/drm/i915/i915_gem_ww.c b/drivers/gpu/drm/i915/i915_gem_ww.c
index 5e7c14cb43d0..b4eef420807d 100644
--- a/drivers/gpu/drm/i915/i915_gem_ww.c
+++ b/drivers/gpu/drm/i915/i915_gem_ww.c
@@ -5,6 +5,7 @@
 #include <linux/dma-resv.h>
 #include "i915_gem_ww.h"
 #include "gem/i915_gem_object.h"
+#include "gem/i915_gem_ttm.h"
 
 void i915_gem_ww_ctx_init(struct i915_gem_ww_ctx *ww, bool intr)
 {
@@ -72,6 +73,19 @@ int __must_check i915_gem_ww_ctx_backoff(struct i915_gem_ww_ctx *ww)
 	else
 		dma_resv_lock_slow(ww->contended->base.resv, &ww->ctx);
 
+	if (ww->contended_evict && !kref_read(&i915_gem_to_ttm(ww->contended)->kref)) {
+		/* dead object, reap it */
+		if (!ret) {
+			__i915_gem_object_pages_fini(ww->contended);
+			i915_gem_object_unlock(ww->contended);
+		}
+
+		i915_gem_object_free_put(ww->contended);
+		ww->contended_evict = false;
+		ww->contended = NULL;
+		return ret;
+	}
+
 	if (!ret) {
 		list_add_tail(&ww->contended->obj_link,
 			      !ww->contended_evict ? &ww->obj_list : &ww->eviction_list);
@@ -112,7 +126,10 @@ static inline int __i915_gem_object_lock(struct drm_i915_gem_object *obj,
 		ret = 0;
 
 	if (ret == -EDEADLK) {
-		i915_gem_object_get(obj);
+		if (!evict)
+			i915_gem_object_get(obj);
+		else if (!i915_gem_object_get_rcu(obj))
+			i915_gem_object_free_get(obj);
 		ww->contended = obj;
 		ww->contended_evict = evict;
 	}
-- 
2.34.1



More information about the Intel-gfx-trybot mailing list