From fb01c2a39a73f5c9305fe768ad6b383307cc9704 Mon Sep 17 00:00:00 2001 From: Niranjana Vishwanathapura Date: Fri, 1 Jul 2022 15:50:55 -0700 Subject: drm/i915/vm_bind: Fix vm->vm_bind_mutex and vm->mutex nesting VM_BIND functionality maintain that vm->vm_bind_mutex will never be taken while holding vm->mutex. However, while closing 'vm', vma is destroyed while holding vm->mutex. But vma releasing needs to take vm->vm_bind_mutex in order to delete vma from the vm_bind_list. To avoid this, destroy the vma outside vm->mutex while closing the 'vm'. Signed-off-by: Niranjana Vishwanathapura --- drivers/gpu/drm/i915/gt/intel_gtt.c | 23 ++++++++++++++++++----- 1 file changed, 18 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/i915/gt/intel_gtt.c b/drivers/gpu/drm/i915/gt/intel_gtt.c index 4ab3bda644ff..4f707d0eb3ef 100644 --- a/drivers/gpu/drm/i915/gt/intel_gtt.c +++ b/drivers/gpu/drm/i915/gt/intel_gtt.c @@ -109,7 +109,8 @@ int map_pt_dma_locked(struct i915_address_space *vm, struct drm_i915_gem_object return 0; } -static void clear_vm_list(struct list_head *list) +static void clear_vm_list(struct list_head *list, + struct list_head *destroy_list) { struct i915_vma *vma, *vn; @@ -138,8 +139,7 @@ static void clear_vm_list(struct list_head *list) i915_vm_resv_get(vma->vm); vma->vm_ddestroy = true; } else { - i915_vma_destroy_locked(vma); - i915_gem_object_put(obj); + list_move_tail(&vma->vm_link, destroy_list); } } @@ -147,16 +147,29 @@ static void clear_vm_list(struct list_head *list) static void __i915_vm_close(struct i915_address_space *vm) { + struct i915_vma *vma, *vn; + struct list_head list; + + INIT_LIST_HEAD(&list); + mutex_lock(&vm->mutex); - clear_vm_list(&vm->bound_list); - clear_vm_list(&vm->unbound_list); + clear_vm_list(&vm->bound_list, &list); + clear_vm_list(&vm->unbound_list, &list); /* Check for must-fix unanticipated side-effects */ GEM_BUG_ON(!list_empty(&vm->bound_list)); GEM_BUG_ON(!list_empty(&vm->unbound_list)); mutex_unlock(&vm->mutex); + + /* Destroy vmas outside vm->mutex */ + list_for_each_entry_safe(vma, vn, &list, vm_link) { + struct drm_i915_gem_object *obj = vma->obj; + + i915_vma_destroy(vma); + i915_gem_object_put(obj); + } } /* lock the vm into the current ww, if we lock one, we lock all */ -- cgit v1.2.3