diff options
Diffstat (limited to 'drivers/gpu/drm/amd/amdkfd/kfd_svm.c')
-rw-r--r-- | drivers/gpu/drm/amd/amdkfd/kfd_svm.c | 99 |
1 files changed, 66 insertions, 33 deletions
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c index a67ba8879a56..f5913ba22174 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_svm.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_svm.c @@ -278,7 +278,7 @@ static void svm_range_free(struct svm_range *prange, bool update_mem_usage) svm_range_free_dma_mappings(prange); if (update_mem_usage && !p->xnack_enabled) { - pr_debug("unreserve mem limit: %lld\n", size); + pr_debug("unreserve prange 0x%p size: 0x%llx\n", prange, size); amdgpu_amdkfd_unreserve_mem_limit(NULL, size, KFD_IOC_ALLOC_MEM_FLAGS_USERPTR); } @@ -541,7 +541,6 @@ svm_range_vram_node_new(struct amdgpu_device *adev, struct svm_range *prange, kfree(svm_bo); return -ESRCH; } - svm_bo->svms = prange->svms; svm_bo->eviction_fence = amdgpu_amdkfd_fence_create(dma_fence_context_alloc(1), mm, @@ -2957,6 +2956,64 @@ out: return r; } +int +svm_range_switch_xnack_reserve_mem(struct kfd_process *p, bool xnack_enabled) +{ + struct svm_range *prange, *pchild; + uint64_t reserved_size = 0; + uint64_t size; + int r = 0; + + pr_debug("switching xnack from %d to %d\n", p->xnack_enabled, xnack_enabled); + + mutex_lock(&p->svms.lock); + + list_for_each_entry(prange, &p->svms.list, list) { + svm_range_lock(prange); + list_for_each_entry(pchild, &prange->child_list, child_list) { + size = (pchild->last - pchild->start + 1) << PAGE_SHIFT; + if (xnack_enabled) { + amdgpu_amdkfd_unreserve_mem_limit(NULL, size, + KFD_IOC_ALLOC_MEM_FLAGS_USERPTR); + } else { + r = amdgpu_amdkfd_reserve_mem_limit(NULL, size, + KFD_IOC_ALLOC_MEM_FLAGS_USERPTR); + if (r) + goto out_unlock; + reserved_size += size; + } + } + + size = (prange->last - prange->start + 1) << PAGE_SHIFT; + if (xnack_enabled) { + amdgpu_amdkfd_unreserve_mem_limit(NULL, size, + KFD_IOC_ALLOC_MEM_FLAGS_USERPTR); + } else { + r = amdgpu_amdkfd_reserve_mem_limit(NULL, size, + KFD_IOC_ALLOC_MEM_FLAGS_USERPTR); + if (r) + goto out_unlock; + reserved_size += size; + } +out_unlock: + svm_range_unlock(prange); + if (r) + break; + } + + if (r) + amdgpu_amdkfd_unreserve_mem_limit(NULL, reserved_size, + KFD_IOC_ALLOC_MEM_FLAGS_USERPTR); + else + /* Change xnack mode must be inside svms lock, to avoid race with + * svm_range_deferred_list_work unreserve memory in parallel. + */ + p->xnack_enabled = xnack_enabled; + + mutex_unlock(&p->svms.lock); + return r; +} + void svm_range_list_fini(struct kfd_process *p) { struct svm_range *prange; @@ -3182,28 +3239,6 @@ out: return best_loc; } -/* FIXME: This is a workaround for page locking bug when some pages are - * invalid during migration to VRAM - */ -void svm_range_prefault(struct svm_range *prange, struct mm_struct *mm, - void *owner) -{ - struct hmm_range *hmm_range; - int r; - - if (prange->validated_once) - return; - - r = amdgpu_hmm_range_get_pages(&prange->notifier, mm, NULL, - prange->start << PAGE_SHIFT, - prange->npages, &hmm_range, - false, true, owner); - if (!r) { - amdgpu_hmm_range_get_pages_done(hmm_range); - prange->validated_once = true; - } -} - /* svm_range_trigger_migration - start page migration if prefetch loc changed * @mm: current process mm_struct * @prange: svm range structure @@ -3273,7 +3308,6 @@ int svm_range_schedule_evict_svm_bo(struct amdgpu_amdkfd_fence *fence) static void svm_range_evict_svm_bo_worker(struct work_struct *work) { struct svm_range_bo *svm_bo; - struct kfd_process *p; struct mm_struct *mm; int r = 0; @@ -3281,13 +3315,12 @@ static void svm_range_evict_svm_bo_worker(struct work_struct *work) if (!svm_bo_ref_unless_zero(svm_bo)) return; /* svm_bo was freed while eviction was pending */ - /* svm_range_bo_release destroys this worker thread. So during - * the lifetime of this thread, kfd_process and mm will be valid. - */ - p = container_of(svm_bo->svms, struct kfd_process, svms); - mm = p->mm; - if (!mm) + if (mmget_not_zero(svm_bo->eviction_fence->mm)) { + mm = svm_bo->eviction_fence->mm; + } else { + svm_range_bo_unref(svm_bo); return; + } mmap_read_lock(mm); spin_lock(&svm_bo->list_lock); @@ -3305,8 +3338,7 @@ static void svm_range_evict_svm_bo_worker(struct work_struct *work) mutex_lock(&prange->migrate_mutex); do { - r = svm_migrate_vram_to_ram(prange, - svm_bo->eviction_fence->mm, + r = svm_migrate_vram_to_ram(prange, mm, KFD_MIGRATE_TRIGGER_TTM_EVICTION); } while (!r && prange->actual_loc && --retries); @@ -3324,6 +3356,7 @@ static void svm_range_evict_svm_bo_worker(struct work_struct *work) } spin_unlock(&svm_bo->list_lock); mmap_read_unlock(mm); + mmput(mm); dma_fence_signal(&svm_bo->eviction_fence->base); |