aboutsummaryrefslogtreecommitdiffstats
path: root/common/recipes-kernel/linux/linux-yocto-4.19.8/1562-drm-amdgpu-free-PDs-PTs-on-demand.patch
diff options
context:
space:
mode:
Diffstat (limited to 'common/recipes-kernel/linux/linux-yocto-4.19.8/1562-drm-amdgpu-free-PDs-PTs-on-demand.patch')
-rw-r--r--common/recipes-kernel/linux/linux-yocto-4.19.8/1562-drm-amdgpu-free-PDs-PTs-on-demand.patch161
1 files changed, 161 insertions, 0 deletions
diff --git a/common/recipes-kernel/linux/linux-yocto-4.19.8/1562-drm-amdgpu-free-PDs-PTs-on-demand.patch b/common/recipes-kernel/linux/linux-yocto-4.19.8/1562-drm-amdgpu-free-PDs-PTs-on-demand.patch
new file mode 100644
index 00000000..381cd481
--- /dev/null
+++ b/common/recipes-kernel/linux/linux-yocto-4.19.8/1562-drm-amdgpu-free-PDs-PTs-on-demand.patch
@@ -0,0 +1,161 @@
+From 2c672859184181b7176a64f0052eabe6eb0260a4 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christian=20K=C3=B6nig?= <christian.koenig@amd.com>
+Date: Fri, 1 Feb 2019 14:02:10 +0100
+Subject: [PATCH 1562/2940] drm/amdgpu: free PDs/PTs on demand
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+When something is unmapped we now free the affected PDs/PTs again.
+
+Signed-off-by: Christian König <christian.koenig@amd.com>
+Reviewed-by: Felix Kuehling <Felix.Kuehling@amd.com>
+Acked-by: Huang Rui <ray.huang@amd.com>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 71 +++++++++++++++++++-------
+ 1 file changed, 53 insertions(+), 18 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+index 566d85d16d3c..2717c3b447f6 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c
+@@ -531,12 +531,31 @@ static void amdgpu_vm_pt_next(struct amdgpu_device *adev,
+ */
+ static void amdgpu_vm_pt_first_dfs(struct amdgpu_device *adev,
+ struct amdgpu_vm *vm,
++ struct amdgpu_vm_pt_cursor *start,
+ struct amdgpu_vm_pt_cursor *cursor)
+ {
+- amdgpu_vm_pt_start(adev, vm, 0, cursor);
++ if (start)
++ *cursor = *start;
++ else
++ amdgpu_vm_pt_start(adev, vm, 0, cursor);
+ while (amdgpu_vm_pt_descendant(adev, cursor));
+ }
+
++/**
++ * amdgpu_vm_pt_continue_dfs - check if the deep first search should continue
++ *
++ * @start: starting point for the search
++ * @entry: current entry
++ *
++ * Returns:
++ * True when the search should continue, false otherwise.
++ */
++static bool amdgpu_vm_pt_continue_dfs(struct amdgpu_vm_pt_cursor *start,
++ struct amdgpu_vm_pt *entry)
++{
++ return entry && (!start || entry != start->entry);
++}
++
+ /**
+ * amdgpu_vm_pt_next_dfs - get the next node for a deep first search
+ *
+@@ -562,11 +581,11 @@ static void amdgpu_vm_pt_next_dfs(struct amdgpu_device *adev,
+ /**
+ * for_each_amdgpu_vm_pt_dfs_safe - safe deep first search of all PDs/PTs
+ */
+-#define for_each_amdgpu_vm_pt_dfs_safe(adev, vm, cursor, entry) \
+- for (amdgpu_vm_pt_first_dfs((adev), (vm), &(cursor)), \
++#define for_each_amdgpu_vm_pt_dfs_safe(adev, vm, start, cursor, entry) \
++ for (amdgpu_vm_pt_first_dfs((adev), (vm), (start), &(cursor)), \
+ (entry) = (cursor).entry, amdgpu_vm_pt_next_dfs((adev), &(cursor));\
+- (entry); (entry) = (cursor).entry, \
+- amdgpu_vm_pt_next_dfs((adev), &(cursor)))
++ amdgpu_vm_pt_continue_dfs((start), (entry)); \
++ (entry) = (cursor).entry, amdgpu_vm_pt_next_dfs((adev), &(cursor)))
+
+ /**
+ * amdgpu_vm_get_pd_bo - add the VM PD to a validation list
+@@ -918,32 +937,46 @@ static int amdgpu_vm_alloc_pts(struct amdgpu_device *adev,
+ return r;
+ }
+
++/**
++ * amdgpu_vm_free_table - fre one PD/PT
++ *
++ * @entry: PDE to free
++ */
++static void amdgpu_vm_free_table(struct amdgpu_vm_pt *entry)
++{
++ if (entry->base.bo) {
++ entry->base.bo->vm_bo = NULL;
++ list_del(&entry->base.vm_status);
++ amdgpu_bo_unref(&entry->base.bo->shadow);
++ amdgpu_bo_unref(&entry->base.bo);
++ }
++ kvfree(entry->entries);
++ entry->entries = NULL;
++}
++
+ /**
+ * amdgpu_vm_free_pts - free PD/PT levels
+ *
+ * @adev: amdgpu device structure
+ * @vm: amdgpu vm structure
++ * @start: optional cursor where to start freeing PDs/PTs
+ *
+ * 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 *vm,
++ struct amdgpu_vm_pt_cursor *start)
+ {
+ struct amdgpu_vm_pt_cursor cursor;
+ struct amdgpu_vm_pt *entry;
+
+- for_each_amdgpu_vm_pt_dfs_safe(adev, vm, cursor, entry) {
++ vm->bulk_moveable = false;
+
+- if (entry->base.bo) {
+- entry->base.bo->vm_bo = NULL;
+- list_del(&entry->base.vm_status);
+- amdgpu_bo_unref(&entry->base.bo->shadow);
+- amdgpu_bo_unref(&entry->base.bo);
+- }
+- kvfree(entry->entries);
+- }
++ for_each_amdgpu_vm_pt_dfs_safe(adev, vm, start, cursor, entry)
++ amdgpu_vm_free_table(entry);
+
+- BUG_ON(vm->root.base.bo);
++ if (start)
++ amdgpu_vm_free_table(start->entry);
+ }
+
+ /**
+@@ -1339,7 +1372,7 @@ static void amdgpu_vm_invalidate_pds(struct amdgpu_device *adev,
+ struct amdgpu_vm_pt_cursor cursor;
+ struct amdgpu_vm_pt *entry;
+
+- for_each_amdgpu_vm_pt_dfs_safe(adev, vm, cursor, entry)
++ for_each_amdgpu_vm_pt_dfs_safe(adev, vm, NULL, cursor, entry)
+ if (entry->base.bo && !entry->base.moved)
+ amdgpu_vm_bo_relocated(&entry->base);
+ }
+@@ -1639,6 +1672,7 @@ static int amdgpu_vm_update_ptes(struct amdgpu_pte_update_params *params,
+ /* Mark all child entries as huge */
+ while (cursor.pfn < frag_start) {
+ cursor.entry->huge = true;
++ amdgpu_vm_free_pts(adev, params->vm, &cursor);
+ amdgpu_vm_pt_next(adev, &cursor);
+ }
+
+@@ -3175,10 +3209,11 @@ 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_pts(adev, vm);
++ amdgpu_vm_free_pts(adev, vm, NULL);
+ amdgpu_bo_unreserve(root);
+ }
+ amdgpu_bo_unref(&root);
++ WARN_ON(vm->root.base.bo);
+ dma_fence_put(vm->last_update);
+ for (i = 0; i < AMDGPU_MAX_VMHUBS; i++)
+ amdgpu_vmid_free_reserved(adev, vm, i);
+--
+2.17.1
+