aboutsummaryrefslogtreecommitdiffstats
path: root/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1522-drm-amdkgd-Remove-permanent-pinning-of-KFD-BOs.patch
diff options
context:
space:
mode:
Diffstat (limited to 'meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1522-drm-amdkgd-Remove-permanent-pinning-of-KFD-BOs.patch')
-rw-r--r--meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1522-drm-amdkgd-Remove-permanent-pinning-of-KFD-BOs.patch282
1 files changed, 282 insertions, 0 deletions
diff --git a/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1522-drm-amdkgd-Remove-permanent-pinning-of-KFD-BOs.patch b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1522-drm-amdkgd-Remove-permanent-pinning-of-KFD-BOs.patch
new file mode 100644
index 00000000..13e630dc
--- /dev/null
+++ b/meta-amd-bsp/recipes-kernel/linux/linux-yocto-4.14.71/1522-drm-amdkgd-Remove-permanent-pinning-of-KFD-BOs.patch
@@ -0,0 +1,282 @@
+From b155dd247e44d18c81da06d77ab4b654d6440ba1 Mon Sep 17 00:00:00 2001
+From: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com>
+Date: Thu, 7 Jul 2016 12:24:45 -0400
+Subject: [PATCH 1522/4131] drm/amdkgd: Remove permanent pinning of KFD BOs
+
+Also decouple BO validate and map functions.
+
+Change-Id: I6defa6ae95e32155e487e4c35c67f9ddff53a29b
+Signed-off-by: Harish Kasiviswanathan <Harish.Kasiviswanathan@amd.com>
+---
+ drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 136 ++++++++++++++++++-----
+ 1 file changed, 108 insertions(+), 28 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+index eed9aca..3bf6e64 100644
+--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
++++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c
+@@ -290,6 +290,53 @@ static int unpin_bo(struct amdgpu_bo *bo)
+ return ret;
+ }
+
++static int amdgpu_amdkfd_bo_validate(struct amdgpu_bo *bo, uint32_t domain,
++ bool wait)
++{
++ int ret = 0;
++
++ if (!amdgpu_ttm_tt_get_usermm(bo->tbo.ttm)) {
++ amdgpu_ttm_placement_from_domain(bo, domain);
++ ret = ttm_bo_validate(&bo->tbo, &bo->placement,
++ false, false);
++ if (ret)
++ goto validate_fail;
++ if (wait)
++ ret = ttm_bo_wait(&bo->tbo, false, false);
++ } else {
++ /* Userptrs are not pinned. Therefore we can use the
++ * bo->pin_count for our version of pinning without conflict.
++ */
++ if (bo->pin_count == 0) {
++ amdgpu_ttm_placement_from_domain(bo, domain);
++ ret = ttm_bo_validate(&bo->tbo, &bo->placement,
++ true, false);
++ if (ret)
++ goto validate_fail;
++ if (wait)
++ ttm_bo_wait(&bo->tbo, false, false);
++ }
++ bo->pin_count++;
++ }
++
++validate_fail:
++ return ret;
++}
++
++static int amdgpu_amdkfd_bo_invalidate(struct amdgpu_bo *bo)
++{
++ int ret = 0;
++
++ if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) &&
++ (--bo->pin_count == 0)) {
++ amdgpu_ttm_placement_from_domain(bo, AMDGPU_GEM_DOMAIN_CPU);
++ ret = ttm_bo_validate(&bo->tbo, &bo->placement, true, false);
++ if (ret != 0)
++ pr_err("amdgpu: failed to invalidate userptr BO\n");
++ }
++ return ret;
++}
++
+ static int try_pin_pts(struct amdgpu_vm *vm)
+ {
+ int i, ret = 0;
+@@ -808,24 +855,12 @@ static int update_user_pages(struct kgd_mem *mem, struct mm_struct *mm,
+ }
+
+ static int map_bo_to_gpuvm(struct amdgpu_device *adev, struct amdgpu_bo *bo,
+- struct amdgpu_bo_va *bo_va, uint32_t domain,
++ struct amdgpu_bo_va *bo_va,
+ struct amdgpu_sync *sync)
+ {
+ struct amdgpu_vm *vm;
+ int ret;
+
+- /*
+- * We need to pin the allocated BO and PTs not yet pinned to
+- * create a mapping of virtual to MC address. PD is already pinned
+- * in amdgpu_amdkfd_gpuvm_create_process_vm().
+- */
+- /* Pin BO*/
+- ret = try_pin_bo(bo, domain);
+- if (ret != 0) {
+- pr_err("amdkfd: Failed to pin BO\n");
+- return ret;
+- }
+-
+ vm = bo_va->vm;
+ /* Pin PTs */
+ ret = try_pin_pts(vm);
+@@ -878,9 +913,7 @@ static int map_bo_to_gpuvm(struct amdgpu_device *adev, struct amdgpu_bo *bo,
+ amdgpu_vm_bo_update(adev, bo_va, NULL);
+ amdgpu_sync_fence(adev, sync, bo_va->last_pt_update);
+ err_unpin_bo:
+- /* PTs are not needed to be unpinned*/
+- unpin_bo(bo);
+-
++ amdgpu_amdkfd_bo_invalidate(bo);
+ return ret;
+ }
+
+@@ -1020,6 +1053,11 @@ int amdgpu_amdkfd_gpuvm_free_memory_of_gpu(
+ if (unlikely(ret != 0))
+ return ret;
+
++ /* The eviction fence should be removed by the last unmap.
++ * TODO: Log an error condition if the bo still has the eviction fence
++ * attached
++ */
++ amdgpu_bo_fence(mem->data2.bo, NULL, false);
+ pr_debug("Releasing BO with VA 0x%llx, size %lu bytes\n",
+ mem->data2.va,
+ mem->data2.bo->tbo.mem.size);
+@@ -1074,6 +1112,7 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
+ struct bo_vm_reservation_context ctx;
+ struct kfd_bo_va_list *bo_va_entry = NULL;
+ struct kfd_bo_va_list *bo_va_entry_aql = NULL;
++ struct amdkfd_vm *kfd_vm = (struct amdkfd_vm *)vm;
+
+ BUG_ON(kgd == NULL);
+ BUG_ON(mem == NULL);
+@@ -1116,6 +1155,25 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
+ goto update_user_pages_failed;
+ }
+
++ if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm)) {
++ ret = amdgpu_amdkfd_bo_validate(bo, domain, true);
++ if (ret) {
++ pr_debug("amdkfd: userptr: Validate failed\n");
++ goto map_bo_to_gpuvm_failed;
++ }
++ } else if (mem->data2.mapped_to_gpu_memory == 0) {
++ /* Validate BO only once. The eviction fence gets added to BO
++ * the first time it is mapped. Validate will wait for all
++ * background evictions to complete.
++ */
++ ret = amdgpu_amdkfd_bo_validate(bo, domain, true);
++ if (ret) {
++ pr_debug("amdkfd: Validate failed\n");
++ goto map_bo_to_gpuvm_failed;
++ }
++ }
++
++
+ list_for_each_entry(entry, &mem->data2.bo_va_list, bo_list) {
+ if (entry->bo_va->vm == vm && !entry->is_mapped) {
+ if (mem->data2.evicted) {
+@@ -1134,7 +1192,7 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
+ pr_debug("amdkfd: Trying to map VA 0x%llx to vm %p\n",
+ mem->data2.va, vm);
+
+- ret = map_bo_to_gpuvm(adev, bo, entry->bo_va, domain,
++ ret = map_bo_to_gpuvm(adev, bo, entry->bo_va,
+ &ctx.sync);
+ if (ret != 0) {
+ pr_err("amdkfd: Failed to map radeon bo to gpuvm\n");
+@@ -1147,6 +1205,9 @@ int amdgpu_amdkfd_gpuvm_map_memory_to_gpu(
+ }
+ }
+
++ if (amdgpu_ttm_tt_get_usermm(bo->tbo.ttm) == NULL)
++ amdgpu_bo_fence(bo, &kfd_vm->master->eviction_fence->base,
++ true);
+ unreserve_bo_and_vms(&ctx, true);
+
+ mutex_unlock(&mem->data2.lock);
+@@ -1314,8 +1375,7 @@ static int unmap_bo_from_gpuvm(struct amdgpu_device *adev,
+
+ amdgpu_vm_clear_invalids(adev, vm, sync);
+
+- /* Unpin BO*/
+- unpin_bo(bo);
++ amdgpu_amdkfd_bo_invalidate(bo);
+
+ return 0;
+ }
+@@ -1404,6 +1464,14 @@ int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu(
+ }
+ }
+
++ /* If BO is unmapped from all VMs, unfence it. It can be evicted if
++ * required.
++ * TODO: For interop this will remove fences added by graphics driver.
++ * Remove only KFD eviction fence
++ */
++ if (mem->data2.mapped_to_gpu_memory == 0)
++ amdgpu_bo_fence(mem->data2.bo, NULL, false);
++
+ if (mapped_before == mem->data2.mapped_to_gpu_memory) {
+ pr_debug("BO size %lu bytes at va 0x%llx is not mapped on GPU %x:%x.%x\n",
+ mem->data2.bo->tbo.mem.size, mem->data2.va,
+@@ -1800,7 +1868,16 @@ int amdgpu_amdkfd_gpuvm_restore_mem(struct kgd_mem *mem, struct mm_struct *mm)
+ continue;
+ }
+
+- r = map_bo_to_gpuvm(adev, mem->data2.bo, entry->bo_va, domain,
++ r = amdgpu_amdkfd_bo_validate(mem->data2.bo, domain, true);
++ if (unlikely(r != 0)) {
++ pr_err("Failed to validate BO\n");
++ entry->is_mapped = false;
++ if (ret == 0)
++ ret = r;
++ continue;
++ }
++
++ r = map_bo_to_gpuvm(adev, mem->data2.bo, entry->bo_va,
+ &ctx.sync);
+ if (unlikely(r != 0)) {
+ pr_err("Failed to map BO to gpuvm\n");
+@@ -1928,8 +2005,8 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *m_vm)
+ list_for_each_entry(entry, &ctx.list, tv.head) {
+ struct amdgpu_bo *bo = entry->robj;
+
+- amdgpu_ttm_placement_from_domain(bo, bo->prefered_domains);
+- ret = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
++ ret = amdgpu_amdkfd_bo_validate(bo, bo->prefered_domains,
++ false);
+ if (ret) {
+ pr_debug("Memory eviction: Validate failed. Try again\n");
+ goto validate_map_fail;
+@@ -1938,8 +2015,8 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *m_vm)
+ list_for_each_entry(entry, &ctx.duplicates, tv.head) {
+ struct amdgpu_bo *bo = entry->robj;
+
+- amdgpu_ttm_placement_from_domain(bo, bo->prefered_domains);
+- ret = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
++ ret = amdgpu_amdkfd_bo_validate(bo, bo->prefered_domains,
++ false);
+ if (ret) {
+ pr_debug("Memory eviction: Validate failed. Try again\n");
+ goto validate_map_fail;
+@@ -1953,7 +2030,6 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *m_vm)
+ struct amdgpu_bo *bo = entry->robj;
+
+ ttm_bo_wait(&bo->tbo, false, false);
+- amdgpu_bo_fence(bo, &master_vm->eviction_fence->base, true);
+ }
+
+
+@@ -1965,18 +2041,17 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *m_vm)
+ uint32_t domain = mem->data2.domain;
+ struct kfd_bo_va_list *bo_va_entry;
+
+- amdgpu_ttm_placement_from_domain(bo, domain);
+- ret = ttm_bo_validate(&bo->tbo, &bo->placement, false, false);
++ ret = amdgpu_amdkfd_bo_validate(bo, domain, false);
+ if (ret) {
+ pr_debug("Memory eviction: Validate failed. Try again\n");
+ goto validate_map_fail;
+ }
++
+ list_for_each_entry(bo_va_entry, &mem->data2.bo_va_list,
+ bo_list) {
+ ret = map_bo_to_gpuvm((struct amdgpu_device *)
+ bo_va_entry->kgd_dev,
+ bo, bo_va_entry->bo_va,
+- domain,
+ &ctx.sync);
+ if (ret) {
+ pr_debug("Memory eviction: Map failed. Try again\n");
+@@ -1995,6 +2070,11 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *m_vm)
+ ttm_bo_wait(&bo->tbo, false, false);
+ amdgpu_bo_fence(bo, &master_vm->eviction_fence->base, true);
+ }
++ list_for_each_entry(entry, &ctx.list, tv.head) {
++ struct amdgpu_bo *bo = entry->robj;
++
++ amdgpu_bo_fence(bo, &master_vm->eviction_fence->base, true);
++ }
+ validate_map_fail:
+ /* Add PDs to kfd_bo_list for unreserve */
+ list_splice_init(&ctx.list, &master_vm->kfd_bo_list);
+--
+2.7.4
+