[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