drm/i915/gt: Use i915_vm_put on ppgtt_create error paths
authorChris Wilson <chris.p.wilson@intel.com>
Mon, 26 Sep 2022 15:33:33 +0000 (16:33 +0100)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 8 Dec 2022 10:28:37 +0000 (11:28 +0100)
[ Upstream commit 20e377e7b2e7c327039f10db80ba5bcc1f6c882d ]

Now that the scratch page and page directories have a reference back to
the i915_address_space, we cannot do an immediate free of the ppgtt upon
error as those buffer objects will perform a later i915_vm_put in their
deferred frees.

The downside is that by replacing the onion unwind along the error
paths, the ppgtt cleanup must handle a partially constructed vm. This
includes ensuring that the vm->cleanup is set prior to the error path.

Closes: https://gitlab.freedesktop.org/drm/intel/-/issues/6900
Signed-off-by: Chris Wilson <chris.p.wilson@intel.com>
Fixes: 4d8151ae5329 ("drm/i915: Don't free shared locks while shared")
Cc: Thomas Hellström <thomas.hellstrom@linux.intel.com>
Cc: Matthew Auld <matthew.auld@intel.com>
Cc: <stable@vger.kernel.org> # v5.14+
Reviewed-by: Matthew Auld <matthew.auld@intel.com>
Signed-off-by: Matthew Auld <matthew.auld@intel.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20220926153333.102195-1-matthew.auld@intel.com
(cherry picked from commit c286558f58535cf97b717b946d6c96d774a09d17)
Signed-off-by: Tvrtko Ursulin <tvrtko.ursulin@intel.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/gpu/drm/i915/gt/gen6_ppgtt.c
drivers/gpu/drm/i915/gt/gen8_ppgtt.c
drivers/gpu/drm/i915/gt/intel_gtt.c

index 557ef25be057142e0e03f944605b58bddc9ba642..b257666a26fc2386ce7e1b3ca59017585e571e09 100644 (file)
@@ -244,6 +244,7 @@ err_scratch1:
        i915_gem_object_put(vm->scratch[1]);
 err_scratch0:
        i915_gem_object_put(vm->scratch[0]);
+       vm->scratch[0] = NULL;
        return ret;
 }
 
@@ -265,9 +266,10 @@ static void gen6_ppgtt_cleanup(struct i915_address_space *vm)
        gen6_ppgtt_free_pd(ppgtt);
        free_scratch(vm);
 
-       mutex_destroy(&ppgtt->flush);
+       if (ppgtt->base.pd)
+               free_pd(&ppgtt->base.vm, ppgtt->base.pd);
 
-       free_pd(&ppgtt->base.vm, ppgtt->base.pd);
+       mutex_destroy(&ppgtt->flush);
 }
 
 static int pd_vma_set_pages(struct i915_vma *vma)
@@ -470,19 +472,17 @@ struct i915_ppgtt *gen6_ppgtt_create(struct intel_gt *gt)
 
        err = gen6_ppgtt_init_scratch(ppgtt);
        if (err)
-               goto err_free;
+               goto err_put;
 
        ppgtt->base.pd = gen6_alloc_top_pd(ppgtt);
        if (IS_ERR(ppgtt->base.pd)) {
                err = PTR_ERR(ppgtt->base.pd);
-               goto err_scratch;
+               goto err_put;
        }
 
        return &ppgtt->base;
 
-err_scratch:
-       free_scratch(&ppgtt->base.vm);
-err_free:
-       kfree(ppgtt);
+err_put:
+       i915_vm_put(&ppgtt->base.vm);
        return ERR_PTR(err);
 }
index 6e0e52eeb87a69e922063099695678bd749e91d7..0cf604c5a6c24f663d0940c5c682b29a8195475a 100644 (file)
@@ -196,7 +196,10 @@ static void gen8_ppgtt_cleanup(struct i915_address_space *vm)
        if (intel_vgpu_active(vm->i915))
                gen8_ppgtt_notify_vgt(ppgtt, false);
 
-       __gen8_ppgtt_cleanup(vm, ppgtt->pd, gen8_pd_top_count(vm), vm->top);
+       if (ppgtt->pd)
+               __gen8_ppgtt_cleanup(vm, ppgtt->pd,
+                                    gen8_pd_top_count(vm), vm->top);
+
        free_scratch(vm);
 }
 
@@ -656,8 +659,10 @@ static int gen8_init_scratch(struct i915_address_space *vm)
                struct drm_i915_gem_object *obj;
 
                obj = vm->alloc_pt_dma(vm, I915_GTT_PAGE_SIZE_4K);
-               if (IS_ERR(obj))
+               if (IS_ERR(obj)) {
+                       ret = PTR_ERR(obj);
                        goto free_scratch;
+               }
 
                ret = map_pt_dma(vm, obj);
                if (ret) {
@@ -676,7 +681,8 @@ static int gen8_init_scratch(struct i915_address_space *vm)
 free_scratch:
        while (i--)
                i915_gem_object_put(vm->scratch[i]);
-       return -ENOMEM;
+       vm->scratch[0] = NULL;
+       return ret;
 }
 
 static int gen8_preallocate_top_level_pdp(struct i915_ppgtt *ppgtt)
@@ -753,6 +759,7 @@ err_pd:
  */
 struct i915_ppgtt *gen8_ppgtt_create(struct intel_gt *gt)
 {
+       struct i915_page_directory *pd;
        struct i915_ppgtt *ppgtt;
        int err;
 
@@ -779,44 +786,39 @@ struct i915_ppgtt *gen8_ppgtt_create(struct intel_gt *gt)
        else
                ppgtt->vm.alloc_pt_dma = alloc_pt_dma;
 
+       ppgtt->vm.pte_encode = gen8_pte_encode;
+
+       ppgtt->vm.bind_async_flags = I915_VMA_LOCAL_BIND;
+       ppgtt->vm.insert_entries = gen8_ppgtt_insert;
+       ppgtt->vm.insert_page = gen8_ppgtt_insert_entry;
+       ppgtt->vm.allocate_va_range = gen8_ppgtt_alloc;
+       ppgtt->vm.clear_range = gen8_ppgtt_clear;
+       ppgtt->vm.foreach = gen8_ppgtt_foreach;
+       ppgtt->vm.cleanup = gen8_ppgtt_cleanup;
+
        err = gen8_init_scratch(&ppgtt->vm);
        if (err)
-               goto err_free;
+               goto err_put;
 
-       ppgtt->pd = gen8_alloc_top_pd(&ppgtt->vm);
-       if (IS_ERR(ppgtt->pd)) {
-               err = PTR_ERR(ppgtt->pd);
-               goto err_free_scratch;
+       pd = gen8_alloc_top_pd(&ppgtt->vm);
+       if (IS_ERR(pd)) {
+               err = PTR_ERR(pd);
+               goto err_put;
        }
+       ppgtt->pd = pd;
 
        if (!i915_vm_is_4lvl(&ppgtt->vm)) {
                err = gen8_preallocate_top_level_pdp(ppgtt);
                if (err)
-                       goto err_free_pd;
+                       goto err_put;
        }
 
-       ppgtt->vm.bind_async_flags = I915_VMA_LOCAL_BIND;
-       ppgtt->vm.insert_entries = gen8_ppgtt_insert;
-       ppgtt->vm.insert_page = gen8_ppgtt_insert_entry;
-       ppgtt->vm.allocate_va_range = gen8_ppgtt_alloc;
-       ppgtt->vm.clear_range = gen8_ppgtt_clear;
-       ppgtt->vm.foreach = gen8_ppgtt_foreach;
-
-       ppgtt->vm.pte_encode = gen8_pte_encode;
-
        if (intel_vgpu_active(gt->i915))
                gen8_ppgtt_notify_vgt(ppgtt, true);
 
-       ppgtt->vm.cleanup = gen8_ppgtt_cleanup;
-
        return ppgtt;
 
-err_free_pd:
-       __gen8_ppgtt_cleanup(&ppgtt->vm, ppgtt->pd,
-                            gen8_pd_top_count(&ppgtt->vm), ppgtt->vm.top);
-err_free_scratch:
-       free_scratch(&ppgtt->vm);
-err_free:
-       kfree(ppgtt);
+err_put:
+       i915_vm_put(&ppgtt->vm);
        return ERR_PTR(err);
 }
index e137dd32b5b8ba6b723258b406f009a2908b7d1d..2d3a979736cc13855afa2f2fabf6ef7a2da393b4 100644 (file)
@@ -341,6 +341,9 @@ void free_scratch(struct i915_address_space *vm)
 {
        int i;
 
+       if (!vm->scratch[0])
+               return;
+
        for (i = 0; i <= vm->top; i++)
                i915_gem_object_put(vm->scratch[i]);
 }