If updating page table free the page table BOs, add fence to the BOs to
ensure the page table BOs are not freed and reused before TLB is
flushed.

Signed-off-by: Philip Yang <philip.y...@amd.com>
---
 drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c | 33 +++++++++++++++--------
 1 file changed, 22 insertions(+), 11 deletions(-)

diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c 
b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
index dea1a64be44d..16eb9472d469 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm_pt.c
@@ -633,8 +633,10 @@ static int amdgpu_vm_pt_alloc(struct amdgpu_device *adev,
  * amdgpu_vm_pt_free - free one PD/PT
  *
  * @entry: PDE to free
+ * @fence: fence added the freed page table BO
  */
-static void amdgpu_vm_pt_free(struct amdgpu_vm_bo_base *entry)
+static void amdgpu_vm_pt_free(struct amdgpu_vm_bo_base *entry,
+                             struct dma_fence *fence)
 {
        struct amdgpu_bo *shadow;
 
@@ -643,6 +645,9 @@ static void amdgpu_vm_pt_free(struct amdgpu_vm_bo_base 
*entry)
        shadow = amdgpu_bo_shadowed(entry->bo);
        if (shadow) {
                ttm_bo_set_bulk_move(&shadow->tbo, NULL);
+               if (fence && !dma_resv_reserve_fences(shadow->tbo.base.resv, 1))
+                       dma_resv_add_fence(shadow->tbo.base.resv, fence,
+                                          DMA_RESV_USAGE_BOOKKEEP);
                amdgpu_bo_unref(&shadow);
        }
        ttm_bo_set_bulk_move(&entry->bo->tbo, NULL);
@@ -651,6 +656,9 @@ static void amdgpu_vm_pt_free(struct amdgpu_vm_bo_base 
*entry)
        spin_lock(&entry->vm->status_lock);
        list_del(&entry->vm_status);
        spin_unlock(&entry->vm->status_lock);
+       if (fence && !dma_resv_reserve_fences(entry->bo->tbo.base.resv, 1))
+               dma_resv_add_fence(entry->bo->tbo.base.resv, fence,
+                                  DMA_RESV_USAGE_BOOKKEEP);
        amdgpu_bo_unref(&entry->bo);
 }
 
@@ -670,7 +678,7 @@ void amdgpu_vm_pt_free_work(struct work_struct *work)
        amdgpu_bo_reserve(vm->root.bo, true);
 
        list_for_each_entry_safe(entry, next, &pt_freed, vm_status)
-               amdgpu_vm_pt_free(entry);
+               amdgpu_vm_pt_free(entry, NULL);
 
        amdgpu_bo_unreserve(vm->root.bo);
 }
@@ -682,13 +690,15 @@ void amdgpu_vm_pt_free_work(struct work_struct *work)
  * @vm: amdgpu vm structure
  * @start: optional cursor where to start freeing PDs/PTs
  * @unlocked: vm resv unlock status
+ * @fence: page table fence added to the freed BOs
  *
  * Free the page directory or page table level and all sub levels.
  */
 static void amdgpu_vm_pt_free_dfs(struct amdgpu_device *adev,
                                  struct amdgpu_vm *vm,
                                  struct amdgpu_vm_pt_cursor *start,
-                                 bool unlocked)
+                                 bool unlocked,
+                                 struct dma_fence *fence)
 {
        struct amdgpu_vm_pt_cursor cursor;
        struct amdgpu_vm_bo_base *entry;
@@ -706,10 +716,10 @@ static void amdgpu_vm_pt_free_dfs(struct amdgpu_device 
*adev,
        }
 
        for_each_amdgpu_vm_pt_dfs_safe(adev, vm, start, cursor, entry)
-               amdgpu_vm_pt_free(entry);
+               amdgpu_vm_pt_free(entry, fence);
 
        if (start)
-               amdgpu_vm_pt_free(start->entry);
+               amdgpu_vm_pt_free(start->entry, fence);
 }
 
 /**
@@ -721,7 +731,7 @@ static void amdgpu_vm_pt_free_dfs(struct amdgpu_device 
*adev,
  */
 void amdgpu_vm_pt_free_root(struct amdgpu_device *adev, struct amdgpu_vm *vm)
 {
-       amdgpu_vm_pt_free_dfs(adev, vm, NULL, false);
+       amdgpu_vm_pt_free_dfs(adev, vm, NULL, false, NULL);
 }
 
 /**
@@ -905,6 +915,7 @@ int amdgpu_vm_ptes_update(struct amdgpu_vm_update_params 
*params,
        struct amdgpu_device *adev = params->adev;
        struct amdgpu_vm_pt_cursor cursor;
        uint64_t frag_start = start, frag_end;
+       struct amdgpu_vm *vm = params->vm;
        unsigned int frag;
        int r;
 
@@ -913,7 +924,7 @@ int amdgpu_vm_ptes_update(struct amdgpu_vm_update_params 
*params,
                               &frag_end);
 
        /* walk over the address space and update the PTs */
-       amdgpu_vm_pt_start(adev, params->vm, start, &cursor);
+       amdgpu_vm_pt_start(adev, vm, start, &cursor);
        while (cursor.pfn < end) {
                unsigned int shift, parent_shift, mask;
                uint64_t incr, entry_end, pe_start;
@@ -923,7 +934,7 @@ int amdgpu_vm_ptes_update(struct amdgpu_vm_update_params 
*params,
                        /* make sure that the page tables covering the
                         * address range are actually allocated
                         */
-                       r = amdgpu_vm_pt_alloc(params->adev, params->vm,
+                       r = amdgpu_vm_pt_alloc(params->adev, vm,
                                               &cursor, params->immediate);
                        if (r)
                                return r;
@@ -986,7 +997,6 @@ int amdgpu_vm_ptes_update(struct amdgpu_vm_update_params 
*params,
                entry_end = min(entry_end, end);
 
                do {
-                       struct amdgpu_vm *vm = params->vm;
                        uint64_t upd_end = min(entry_end, frag_end);
                        unsigned int nptes = (upd_end - frag_start) >> shift;
                        uint64_t upd_flags = flags | AMDGPU_PTE_FRAG(frag);
@@ -1029,9 +1039,10 @@ int amdgpu_vm_ptes_update(struct amdgpu_vm_update_params 
*params,
                                /* Make sure previous mapping is freed */
                                if (cursor.entry->bo) {
                                        params->table_freed = true;
-                                       amdgpu_vm_pt_free_dfs(adev, params->vm,
+                                       amdgpu_vm_pt_free_dfs(adev, vm,
                                                              &cursor,
-                                                             params->unlocked);
+                                                             params->unlocked,
+                                                             vm->pt_fence);
                                }
                                amdgpu_vm_pt_next(adev, &cursor);
                        }
-- 
2.35.1

Reply via email to