drm/amdgpu: use dfs iterator to free PDs/PTs
authorChristian König <christian.koenig@amd.com>
Thu, 6 Sep 2018 13:35:13 +0000 (15:35 +0200)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 13 Sep 2018 20:14:09 +0000 (15:14 -0500)
Allows us to free all PDs/PTs without recursion.

Signed-off-by: Christian König <christian.koenig@amd.com>
Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com>
Reviewed-by: Junwei Zhang <Jerry.Zhang@amd.com>
Reviewed-by: Huang Rui <ray.huang@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c

index 60fa4f455b52df568a5f77d7289ebd9810b69274..139bd6347fc418afcc1f0a51d2edf714b71d5af8 100644 (file)
@@ -937,6 +937,35 @@ error_free_pt:
        return r;
 }
 
+/**
+ * amdgpu_vm_free_pts - free PD/PT levels
+ *
+ * @adev: amdgpu device structure
+ * @parent: PD/PT starting level to free
+ * @level: level of parent structure
+ *
+ * Free the page directory or page table level and all sub levels.
+ */
+static void amdgpu_vm_free_pts(struct amdgpu_device *adev,
+                              struct amdgpu_vm *vm)
+{
+       struct amdgpu_vm_pt_cursor cursor;
+       struct amdgpu_vm_pt *entry;
+
+       for_each_amdgpu_vm_pt_dfs_safe(adev, vm, cursor, entry) {
+
+               if (entry->base.bo) {
+                       list_del(&entry->base.bo_list);
+                       list_del(&entry->base.vm_status);
+                       amdgpu_bo_unref(&entry->base.bo->shadow);
+                       amdgpu_bo_unref(&entry->base.bo);
+               }
+               kvfree(entry->entries);
+       }
+
+       BUG_ON(vm->root.base.bo);
+}
+
 /**
  * amdgpu_vm_check_compute_bug - check whether asic has compute vm bug
  *
@@ -3147,36 +3176,6 @@ void amdgpu_vm_release_compute(struct amdgpu_device *adev, struct amdgpu_vm *vm)
        vm->pasid = 0;
 }
 
-/**
- * amdgpu_vm_free_levels - free PD/PT levels
- *
- * @adev: amdgpu device structure
- * @parent: PD/PT starting level to free
- * @level: level of parent structure
- *
- * Free the page directory or page table level and all sub levels.
- */
-static void amdgpu_vm_free_levels(struct amdgpu_device *adev,
-                                 struct amdgpu_vm_pt *parent,
-                                 unsigned level)
-{
-       unsigned i, num_entries = amdgpu_vm_num_entries(adev, level);
-
-       if (parent->base.bo) {
-               list_del(&parent->base.bo_list);
-               list_del(&parent->base.vm_status);
-               amdgpu_bo_unref(&parent->base.bo->shadow);
-               amdgpu_bo_unref(&parent->base.bo);
-       }
-
-       if (parent->entries)
-               for (i = 0; i < num_entries; i++)
-                       amdgpu_vm_free_levels(adev, &parent->entries[i],
-                                             level + 1);
-
-       kvfree(parent->entries);
-}
-
 /**
  * amdgpu_vm_fini - tear down a vm instance
  *
@@ -3237,8 +3236,7 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm)
        if (r) {
                dev_err(adev->dev, "Leaking page tables because BO reservation failed\n");
        } else {
-               amdgpu_vm_free_levels(adev, &vm->root,
-                                     adev->vm_manager.root_level);
+               amdgpu_vm_free_pts(adev, vm);
                amdgpu_bo_unreserve(root);
        }
        amdgpu_bo_unref(&root);