From b341257f6b08b128e92992cb903801b2086ec5d7 Mon Sep 17 00:00:00 2001 From: Harish Kasiviswanathan Date: Wed, 8 Nov 2017 15:36:47 -0500 Subject: [PATCH 2192/4131] drm/amdgpu: Share eviction fence with KFD Currently, when TTM wants to evict a process BO, dma_fence_ops.enable_signaling() calls KFD call back function evict_and_restore_process(fence *eviction_fence) to prepare for eviction. This function starts a worker thread that handles suspending the process and signaling the eviction fence. However, during suspend / resume, KFD cannot reliably depend on this eviction sequence. This change is necessary to handle suspend / resume sequence by KFD. Change-Id: I342e64a4986225246d8fff21b9c96f2c844648ad Signed-off-by: Harish Kasiviswanathan --- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h | 6 ++++-- drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c | 7 +++++-- drivers/gpu/drm/amd/amdkfd/kfd_device.c | 11 ++++++++++- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 5 +++++ drivers/gpu/drm/amd/amdkfd/kfd_process.c | 6 ++++-- drivers/gpu/drm/amd/include/kgd_kfd_interface.h | 4 ++-- 6 files changed, 30 insertions(+), 9 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h index 0756fff..b4e26d9 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd.h @@ -143,7 +143,8 @@ int amdgpu_amdkfd_evict_userptr(struct kgd_mem *mem, struct mm_struct *mm); int amdgpu_amdkfd_submit_ib(struct kgd_dev *kgd, enum kgd_engine_type engine, uint32_t vmid, uint64_t gpu_addr, uint32_t *ib_cmd, uint32_t ib_len); -int amdgpu_amdkfd_gpuvm_restore_process_bos(void *process_info); +int amdgpu_amdkfd_gpuvm_restore_process_bos(void *process_info, + struct dma_fence **ef); struct kfd2kgd_calls *amdgpu_amdkfd_gfx_7_get_functions(void); struct kfd2kgd_calls *amdgpu_amdkfd_gfx_8_0_get_functions(void); struct kfd2kgd_calls *amdgpu_amdkfd_gfx_9_0_get_functions(void); @@ -205,7 +206,8 @@ int amdgpu_amdkfd_gpuvm_unmap_memory_from_gpu( struct kgd_dev *kgd, struct kgd_mem *mem, void *vm); int amdgpu_amdkfd_gpuvm_create_process_vm(struct kgd_dev *kgd, void **vm, - void **process_info); + void **process_info, + struct dma_fence **ef); void amdgpu_amdkfd_gpuvm_destroy_process_vm(struct kgd_dev *kgd, void *vm); uint32_t amdgpu_amdkfd_gpuvm_get_process_page_dir(void *vm); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c index 1ce6359..ec81a41 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_amdkfd_gpuvm.c @@ -1375,7 +1375,8 @@ static u64 get_vm_pd_gpu_offset(void *vm) } int amdgpu_amdkfd_gpuvm_create_process_vm(struct kgd_dev *kgd, void **vm, - void **process_info) + void **process_info, + struct dma_fence **ef) { int ret; struct amdkfd_vm *new_vm; @@ -1424,6 +1425,7 @@ int amdgpu_amdkfd_gpuvm_create_process_vm(struct kgd_dev *kgd, void **vm, amdgpu_amdkfd_restore_userptr_worker); *process_info = info; + *ef = dma_fence_get(&info->eviction_fence->base); } new_vm->process_info = *process_info; @@ -2274,7 +2276,7 @@ static void amdgpu_amdkfd_restore_userptr_worker(struct work_struct *work) * 8. Unreserve all BOs */ -int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info) +int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info, struct dma_fence **ef) { struct amdgpu_bo_list_entry *pd_bo_list; struct amdkfd_process_info *process_info = info; @@ -2381,6 +2383,7 @@ int amdgpu_amdkfd_gpuvm_restore_process_bos(void *info) } dma_fence_put(&process_info->eviction_fence->base); process_info->eviction_fence = new_fence; + *ef = dma_fence_get(&new_fence->base); /* Wait for validate to finish and attach new eviction fence */ list_for_each_entry(mem, &process_info->kfd_bo_list, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device.c b/drivers/gpu/drm/amd/amdkfd/kfd_device.c index 3506e6b..3cf791b 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device.c @@ -946,7 +946,7 @@ void kfd_restore_bo_worker(struct work_struct *work) */ p->last_restore_timestamp = get_jiffies_64(); - ret = pdd->dev->kfd2kgd->restore_process_bos(p->process_info); + ret = pdd->dev->kfd2kgd->restore_process_bos(p->process_info, &p->ef); if (ret) { pr_info("Restore failed, try again after %d ms\n", PROCESS_BACK_OFF_TIME_MS); @@ -1050,6 +1050,15 @@ void kfd_evict_bo_worker(struct work_struct *work) ret = quiesce_process_mm(p); if (!ret) { dma_fence_signal(eviction_work->quiesce_fence); + WARN_ONCE(eviction_work->quiesce_fence != p->ef, + "Eviction fence mismatch\n"); + dma_fence_put(p->ef); + /* TODO: quiesce_fence is same as kfd_process->ef. But + * quiesce_fence is also used to avoid starting multiple + * eviction work items. This might not be necessary and + * one of the variables could be removed + */ + p->ef = NULL; schedule_delayed_work(&p->restore_work, msecs_to_jiffies(PROCESS_RESTORE_TIME_MS)); } else diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index e263c99..bfd8952 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -725,6 +725,11 @@ struct kfd_process { /* Information used for memory eviction */ void *process_info; + /* Eviction fence that is attached to all the BOs of this process. The + * fence will be triggered during eviction and new one will be created + * during restore + */ + struct dma_fence *ef; /* Work items for evicting and restoring BOs */ struct kfd_eviction_work eviction_work; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_process.c b/drivers/gpu/drm/amd/amdkfd/kfd_process.c index f737e17..e8fe04e 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_process.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_process.c @@ -369,9 +369,11 @@ static void kfd_process_destroy_pdds(struct kfd_process *p) kfd_flush_tlb(pdd->dev, p->pasid); /* Destroy the GPUVM VM context */ - if (pdd->vm) + if (pdd->vm) { + dma_fence_put(p->ef); pdd->dev->kfd2kgd->destroy_process_vm( pdd->dev->kgd, pdd->vm); + } list_del(&pdd->per_device_list); if (pdd->qpd.cwsr_pages) { @@ -724,7 +726,7 @@ struct kfd_process_device *kfd_create_process_device_data(struct kfd_dev *dev, /* Create the GPUVM context for this specific device */ if (dev->kfd2kgd->create_process_vm(dev->kgd, &pdd->vm, - &p->process_info)) { + &p->process_info, &p->ef)) { pr_err("Failed to create process VM object\n"); goto err_create_pdd; } diff --git a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h index 99213fb..877d966 100644 --- a/drivers/gpu/drm/amd/include/kgd_kfd_interface.h +++ b/drivers/gpu/drm/amd/include/kgd_kfd_interface.h @@ -267,7 +267,7 @@ struct kfd2kgd_calls { uint32_t (*get_max_engine_clock_in_mhz)(struct kgd_dev *kgd); int (*create_process_vm)(struct kgd_dev *kgd, void **vm, - void **process_info); + void **process_info, struct dma_fence **ef); void (*destroy_process_vm)(struct kgd_dev *kgd, void *vm); int (*create_process_gpumem)(struct kgd_dev *kgd, uint64_t va, size_t size, void *vm, struct kgd_mem **mem); @@ -400,7 +400,7 @@ struct kfd2kgd_calls { int (*get_tile_config)(struct kgd_dev *kgd, struct tile_config *config); - int (*restore_process_bos)(void *process_info); + int (*restore_process_bos)(void *process_info, struct dma_fence **ef); int (*copy_mem_to_mem)(struct kgd_dev *kgd, struct kgd_mem *src_mem, uint64_t src_offset, struct kgd_mem *dst_mem, uint64_t dest_offset, uint64_t size, -- 2.7.4