allocate gart shadow bo, and using shadow bo to backup gart table. Change-Id: Ib2beae9cea1ad1314c57f0fcdcc254816f39b9b2 Signed-off-by: Chunming Zhou <David1.Zhou at amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu.h | 3 ++ drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c | 47 +++++++++++++++++++++++++++++++- drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c | 15 ++++++++++ drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c | 16 +++++++++++ 4 files changed, 80 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 419a33b..2985578d 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -638,6 +638,7 @@ struct amdgpu_gart { dma_addr_t table_addr; struct amdgpu_bo *robj; void *ptr; + void *shadow_ptr; unsigned num_gpu_pages; unsigned num_cpu_pages; unsigned table_size; @@ -655,6 +656,8 @@ int amdgpu_gart_table_vram_alloc(struct amdgpu_device *adev); void amdgpu_gart_table_vram_free(struct amdgpu_device *adev); int amdgpu_gart_table_vram_pin(struct amdgpu_device *adev); void amdgpu_gart_table_vram_unpin(struct amdgpu_device *adev); +int amdgpu_gart_table_vram_shadow_pin(struct amdgpu_device *adev); +void amdgpu_gart_table_vram_shadow_unpin(struct amdgpu_device *adev); int amdgpu_gart_init(struct amdgpu_device *adev); void amdgpu_gart_fini(struct amdgpu_device *adev); int amdgpu_gart_late_init(struct amdgpu_device *adev); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c index c1f226b..b306684 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gart.c @@ -248,6 +248,9 @@ void amdgpu_gart_unbind(struct amdgpu_device *adev, unsigned offset, for (j = 0; j < (PAGE_SIZE / AMDGPU_GPU_PAGE_SIZE); j++, t++) { amdgpu_gart_set_pte_pde(adev, adev->gart.ptr, t, page_base, flags); + if (amdgpu_vm_need_backup(adev) && adev->gart.robj->shadow) + amdgpu_gart_set_pte_pde(adev, adev->gart.shadow_ptr, + t, page_base, flags); page_base += AMDGPU_GPU_PAGE_SIZE; } } @@ -293,6 +296,9 @@ int amdgpu_gart_bind(struct amdgpu_device *adev, unsigned offset, page_base = dma_addr[i]; for (j = 0; j < (PAGE_SIZE / AMDGPU_GPU_PAGE_SIZE); j++, t++) { amdgpu_gart_set_pte_pde(adev, adev->gart.ptr, t, page_base, flags); + if (amdgpu_vm_need_backup(adev) && adev->gart.robj->shadow) + amdgpu_gart_set_pte_pde(adev, adev->gart.shadow_ptr, + t, page_base, flags); page_base += AMDGPU_GPU_PAGE_SIZE; } } @@ -364,6 +370,46 @@ void amdgpu_gart_fini(struct amdgpu_device *adev) amdgpu_dummy_page_fini(adev); } +int amdgpu_gart_table_vram_shadow_pin(struct amdgpu_device *adev) +{ + uint64_t gpu_addr; + int r; + + if (!adev->gart.robj->shadow) + return -EINVAL; + + r = amdgpu_bo_reserve(adev->gart.robj->shadow, false); + if (unlikely(r != 0)) + return r; + r = amdgpu_bo_pin(adev->gart.robj->shadow, + AMDGPU_GEM_DOMAIN_GTT, &gpu_addr); + if (r) { + amdgpu_bo_unreserve(adev->gart.robj->shadow); + return r; + } + r = amdgpu_bo_kmap(adev->gart.robj->shadow, &adev->gart.shadow_ptr); + if (r) + amdgpu_bo_unpin(adev->gart.robj->shadow); + amdgpu_bo_unreserve(adev->gart.robj->shadow); + return r; +} + +void amdgpu_gart_table_vram_shadow_unpin(struct amdgpu_device *adev) +{ + int r; + + if (adev->gart.robj->shadow == NULL) + return; + + r = amdgpu_bo_reserve(adev->gart.robj->shadow, false); + if (likely(r == 0)) { + amdgpu_bo_kunmap(adev->gart.robj->shadow); + amdgpu_bo_unpin(adev->gart.robj->shadow); + amdgpu_bo_unreserve(adev->gart.robj->shadow); + adev->gart.shadow_ptr = NULL; + } +} + int amdgpu_gart_late_init(struct amdgpu_device *adev) { struct amd_sched_rq *rq; @@ -372,7 +418,6 @@ int amdgpu_gart_late_init(struct amdgpu_device *adev) rq = &ring->sched.sched_rq[AMD_SCHED_PRIORITY_RECOVER]; return amd_sched_entity_init(&ring->sched, &adev->gart.recover_entity, rq, amdgpu_sched_jobs); - } void amdgpu_gart_late_fini(struct amdgpu_device *adev) diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index 0771c04..5470a28 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c @@ -589,7 +589,21 @@ static int gmc_v7_0_gart_enable(struct amdgpu_device *adev) (unsigned)(adev->mc.gtt_size >> 20), (unsigned long long)adev->gart.table_addr); adev->gart.ready = true; + if (amdgpu_vm_need_backup(adev) && adev->gart.robj) { + r = amdgpu_bo_create_shadow(adev, adev->gart.table_size, + PAGE_SIZE, adev->gart.robj); + if (r) + goto err; + r = amdgpu_gart_table_vram_shadow_pin(adev); + if (r) + goto err; + } + return 0; +err: + amdgpu_gart_table_vram_unpin(adev); + + return r; } static int gmc_v7_0_gart_init(struct amdgpu_device *adev) @@ -634,6 +648,7 @@ static void gmc_v7_0_gart_disable(struct amdgpu_device *adev) WREG32(mmVM_L2_CNTL, tmp); WREG32(mmVM_L2_CNTL2, 0); amdgpu_gart_table_vram_unpin(adev); + amdgpu_gart_table_vram_shadow_unpin(adev); } /** diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index c26bee9..6c2b5de 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -704,7 +704,22 @@ static int gmc_v8_0_gart_enable(struct amdgpu_device *adev) (unsigned)(adev->mc.gtt_size >> 20), (unsigned long long)adev->gart.table_addr); adev->gart.ready = true; + + if (amdgpu_vm_need_backup(adev) && adev->gart.robj) { + r = amdgpu_bo_create_shadow(adev, adev->gart.table_size, + PAGE_SIZE, adev->gart.robj); + if (r) + goto err; + r = amdgpu_gart_table_vram_shadow_pin(adev); + if (r) + goto err; + } + return 0; +err: + amdgpu_gart_table_vram_unpin(adev); + + return r; } static int gmc_v8_0_gart_init(struct amdgpu_device *adev) @@ -749,6 +764,7 @@ static void gmc_v8_0_gart_disable(struct amdgpu_device *adev) WREG32(mmVM_L2_CNTL, tmp); WREG32(mmVM_L2_CNTL2, 0); amdgpu_gart_table_vram_unpin(adev); + amdgpu_gart_table_vram_shadow_unpin(adev); } /** -- 1.9.1