[PATCH 03/25] hack to get better backtraces for freed objects

Maarten Lankhorst maarten.lankhorst at linux.intel.com
Fri Apr 17 11:06:05 UTC 2020


Signed-off-by: Maarten Lankhorst <maarten.lankhorst at linux.intel.com>
---
 drivers/gpu/drm/i915/gem/i915_gem_object.c | 123 ++++++++++++---------
 drivers/gpu/drm/i915/i915_vma.c            |   4 +-
 2 files changed, 73 insertions(+), 54 deletions(-)

diff --git a/drivers/gpu/drm/i915/gem/i915_gem_object.c b/drivers/gpu/drm/i915/gem/i915_gem_object.c
index 3f01cdd1a39b..c0eb32a7ff59 100644
--- a/drivers/gpu/drm/i915/gem/i915_gem_object.c
+++ b/drivers/gpu/drm/i915/gem/i915_gem_object.c
@@ -41,12 +41,12 @@ static struct i915_global_object {
 
 struct drm_i915_gem_object *i915_gem_object_alloc(void)
 {
-	return kmem_cache_zalloc(global.slab_objects, GFP_KERNEL);
+	return kzalloc(sizeof(struct drm_i915_gem_object), GFP_KERNEL);
 }
 
 void i915_gem_object_free(struct drm_i915_gem_object *obj)
 {
-	return kmem_cache_free(global.slab_objects, obj);
+	return kfree(obj);
 }
 
 void i915_gem_object_init(struct drm_i915_gem_object *obj,
@@ -160,70 +160,85 @@ static void __i915_gem_free_object_rcu(struct rcu_head *head)
 	atomic_dec(&i915->mm.free_count);
 }
 
-static void __i915_gem_free_objects(struct drm_i915_private *i915,
-				    struct llist_node *freed)
+static void __i915_gem_object_free(struct drm_i915_gem_object *obj)
 {
-	struct drm_i915_gem_object *obj, *on;
-	intel_wakeref_t wakeref;
+	struct i915_mmap_offset *mmo, *mn;
 
-	wakeref = intel_runtime_pm_get(&i915->runtime_pm);
-	llist_for_each_entry_safe(obj, on, freed, freed) {
-		struct i915_mmap_offset *mmo, *mn;
+	trace_i915_gem_object_destroy(obj);
+
+	if (!list_empty(&obj->vma.list)) {
+		struct i915_vma *vma;
 
-		trace_i915_gem_object_destroy(obj);
+		/*
+		  * Note that the vma keeps an object reference while
+		  * it is active, so it *should* not sleep while we
+		  * destroy it. Our debug code errs insits it *might*.
+		  * For the moment, play along.
+		  */
+		spin_lock(&obj->vma.lock);
+		while ((vma = list_first_entry_or_null(&obj->vma.list,
+							struct i915_vma,
+							obj_link))) {
+			GEM_BUG_ON(vma->obj != obj);
+			spin_unlock(&obj->vma.lock);
 
-		if (!list_empty(&obj->vma.list)) {
-			struct i915_vma *vma;
+			__i915_vma_put(vma);
 
-			/*
-			 * Note that the vma keeps an object reference while
-			 * it is active, so it *should* not sleep while we
-			 * destroy it. Our debug code errs insits it *might*.
-			 * For the moment, play along.
-			 */
 			spin_lock(&obj->vma.lock);
-			while ((vma = list_first_entry_or_null(&obj->vma.list,
-							       struct i915_vma,
-							       obj_link))) {
-				GEM_BUG_ON(vma->obj != obj);
-				spin_unlock(&obj->vma.lock);
+		}
+		spin_unlock(&obj->vma.lock);
+	}
 
-				__i915_vma_put(vma);
+	i915_gem_object_release_mmap(obj);
 
-				spin_lock(&obj->vma.lock);
-			}
-			spin_unlock(&obj->vma.lock);
-		}
+	rbtree_postorder_for_each_entry_safe(mmo, mn,
+					      &obj->mmo.offsets,
+					      offset) {
+		drm_vma_offset_remove(obj->base.dev->vma_offset_manager,
+				      &mmo->vma_node);
+		kfree(mmo);
+	}
+	obj->mmo.offsets = RB_ROOT;
 
-		i915_gem_object_release_mmap(obj);
+	GEM_BUG_ON(obj->userfault_count);
+	GEM_BUG_ON(!list_empty(&obj->lut_list));
 
-		rbtree_postorder_for_each_entry_safe(mmo, mn,
-						     &obj->mmo.offsets,
-						     offset) {
-			drm_vma_offset_remove(obj->base.dev->vma_offset_manager,
-					      &mmo->vma_node);
-			kfree(mmo);
-		}
-		obj->mmo.offsets = RB_ROOT;
+	atomic_set(&obj->mm.pages_pin_count, 0);
+	__i915_gem_object_put_pages(obj);
+	GEM_BUG_ON(i915_gem_object_has_pages(obj));
+	bitmap_free(obj->bit_17);
 
-		GEM_BUG_ON(obj->userfault_count);
-		GEM_BUG_ON(!list_empty(&obj->lut_list));
+	if (obj->base.import_attach)
+		drm_prime_gem_destroy(&obj->base, NULL);
 
-		atomic_set(&obj->mm.pages_pin_count, 0);
-		__i915_gem_object_put_pages(obj);
-		GEM_BUG_ON(i915_gem_object_has_pages(obj));
-		bitmap_free(obj->bit_17);
+	drm_gem_free_mmap_offset(&obj->base);
 
-		if (obj->base.import_attach)
-			drm_prime_gem_destroy(&obj->base, NULL);
+	if (obj->ops->release)
+		obj->ops->release(obj);
 
-		drm_gem_free_mmap_offset(&obj->base);
+	/* But keep the pointer alive for RCU-protected lookups */
+	synchronize_rcu();
+	__i915_gem_free_object_rcu(&obj->rcu);
+}
 
-		if (obj->ops->release)
-			obj->ops->release(obj);
+static void __i915_gem_free_object(struct drm_i915_gem_object *obj)
+{
+	struct drm_i915_private *i915 = to_i915(READ_ONCE(obj->base.dev));
+	intel_wakeref_t wakeref;
+
+	with_intel_runtime_pm(&i915->runtime_pm, wakeref)
+		__i915_gem_object_free(obj);
+}
 
-		/* But keep the pointer alive for RCU-protected lookups */
-		call_rcu(&obj->rcu, __i915_gem_free_object_rcu);
+static void __i915_gem_free_objects(struct drm_i915_private *i915,
+				    struct llist_node *freed)
+{
+	struct drm_i915_gem_object *obj, *on;
+	intel_wakeref_t wakeref;
+
+	wakeref = intel_runtime_pm_get(&i915->runtime_pm);
+	llist_for_each_entry_safe(obj, on, freed, freed) {
+		__i915_gem_object_free(obj);
 		cond_resched();
 	}
 	intel_runtime_pm_put(&i915->runtime_pm, wakeref);
@@ -279,8 +294,12 @@ void i915_gem_free_object(struct drm_gem_object *gem_obj)
 	 * worker and performing frees directly from subsequent allocations for
 	 * crude but effective memory throttling.
 	 */
-	if (llist_add(&obj->freed, &i915->mm.free_list))
-		queue_work(i915->wq, &i915->mm.free_work);
+	if (in_atomic() || irqs_disabled()) {
+		if (llist_add(&obj->freed, &i915->mm.free_list))
+			queue_work(i915->wq, &i915->mm.free_work);
+	} else {
+		__i915_gem_free_object(obj);
+	}
 }
 
 static bool gpu_write_needs_clflush(struct drm_i915_gem_object *obj)
diff --git a/drivers/gpu/drm/i915/i915_vma.c b/drivers/gpu/drm/i915/i915_vma.c
index f0383a68c981..23a9128c909a 100644
--- a/drivers/gpu/drm/i915/i915_vma.c
+++ b/drivers/gpu/drm/i915/i915_vma.c
@@ -45,12 +45,12 @@ static struct i915_global_vma {
 
 struct i915_vma *i915_vma_alloc(void)
 {
-	return kmem_cache_zalloc(global.slab_vmas, GFP_KERNEL);
+	return kzalloc(sizeof(struct i915_vma), GFP_KERNEL);
 }
 
 void i915_vma_free(struct i915_vma *vma)
 {
-	return kmem_cache_free(global.slab_vmas, vma);
+	return kfree(vma);
 }
 
 #if IS_ENABLED(CONFIG_DRM_I915_ERRLOG_GEM) && IS_ENABLED(CONFIG_DRM_DEBUG_MM)
-- 
2.25.1



More information about the Intel-gfx-trybot mailing list