Add look-up for the BO by address. This is required for memory allocations where the virtual address are reserved outside of KFD and then later mapped to GPU memory.
Signed-off-by: David Yat Sin <david.yat...@amd.com> --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 41 ++++++++++++++ drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h | 5 ++ drivers/gpu/drm/amd/amdkfd/kfd_peerdirect.c | 61 +++++++++++++-------- 3 files changed, 83 insertions(+), 24 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 81afeda39667..37a2beece6ee 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -2667,8 +2667,49 @@ int amdgpu_mmap(struct file *filp, struct vm_area_struct *vma) vma->vm_ops = &amdgpu_ttm_vm_ops; return 0; } + +struct amdgpu_bo *amdgpu_bo_from_address(struct mm_struct *mm, + unsigned long addr, + unsigned long *offset, + struct amdgpu_device **adev) +{ + struct ttm_buffer_object *bo; + struct vm_area_struct *vma; + struct amdgpu_bo *abo = NULL; + + mmap_read_lock(mm); + vma = find_vma(mm, addr); + if (!vma) + goto exit; + + /* Confirm that this VMA belongs to amdgpu */ + if (vma->vm_ops != &amdgpu_ttm_vm_ops) + goto exit; + + abo = ttm_to_amdgpu_bo(vma->vm_private_data); + + if (offset) + *offset = addr - vma->vm_start; + + if (adev) + *adev = amdgpu_ttm_adev(abo->tbo.bdev); +exit: + mmap_read_unlock(mm); + return abo; +} +#else +struct amdgpu_bo *amdgpu_bo_from_address(struct mm_struct *mm, + unsigned long addr, + unsigned long *offset, + struct amdgpu_device **adev) +{ + pr_err("BO from address look-up not supported\n"); + return NULL; +} #endif /* HAVE_STRUCT_DRM_DRV_GEM_OPEN_OBJECT_CALLBACK */ + + int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset, uint64_t dst_offset, uint32_t byte_count, struct dma_resv *resv, diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h index 747c9669069a..9fbff8dec861 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.h @@ -175,6 +175,11 @@ int amdgpu_ttm_init(struct amdgpu_device *adev); void amdgpu_ttm_fini(struct amdgpu_device *adev); void amdgpu_ttm_set_buffer_funcs_status(struct amdgpu_device *adev, bool enable); + +struct amdgpu_bo *amdgpu_bo_from_address(struct mm_struct *mm, + unsigned long addr, unsigned long *offset, + struct amdgpu_device **adev); + int amdgpu_copy_buffer(struct amdgpu_ring *ring, uint64_t src_offset, uint64_t dst_offset, uint32_t byte_count, struct dma_resv *resv, diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_peerdirect.c b/drivers/gpu/drm/amd/amdkfd/kfd_peerdirect.c index ed93247d83ca..3341f40f2a23 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_peerdirect.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_peerdirect.c @@ -170,9 +170,13 @@ static int amd_acquire(unsigned long addr, size_t size, void *peer_mem_private_data, char *peer_mem_name, void **client_context) { - struct kfd_process *p; - struct kfd_bo *buf_obj; struct amd_mem_context *mem_context; + struct kfd_process *p; + struct kfd_bo *buf_obj = NULL; + struct kfd_node *dev = NULL; + struct amdgpu_bo *bo = NULL; + unsigned long offset = 0; + uint32_t flags = 0; if (peer_mem_name == rdma_name) { p = peer_mem_private_data; @@ -187,34 +191,44 @@ static int amd_acquire(unsigned long addr, size_t size, align_addr_size(&addr, &size); mutex_lock(&p->mutex); - buf_obj = kfd_process_find_bo_from_interval(p, addr, - addr + size - 1); - if (!buf_obj) { - pr_debug("Cannot find a kfd_bo for the range\n"); - goto out_unlock; + buf_obj = kfd_process_find_bo_from_interval(p, addr, addr + size - 1); + if (buf_obj) { + offset = addr - buf_obj->it.start; + bo = amdgpu_amdkfd_gpuvm_get_bo_ref(buf_obj->mem, &flags); + + dev = buf_obj->dev; + } else { + struct amdgpu_device *adev; + /* Memory was allocated via KFD without address, then mapped later */ + bo = amdgpu_bo_from_address(p->mm, addr, &offset, &adev); + if (!bo) + goto out_unlock; + + flags = bo->kfd_bo->alloc_flags; + dev = adev->kfd.dev->nodes[bo->xcp_id]; + drm_gem_object_get(&bo->tbo.base); } - /* Initialize context used for operation with given address */ mem_context = kzalloc(sizeof(*mem_context), GFP_KERNEL); - if (!mem_context) - goto out_unlock; + if (unlikely(!mem_context)) { + if (buf_obj) + amdgpu_amdkfd_gpuvm_put_bo_ref(bo); + else + drm_gem_object_put(&bo->tbo.base); - mem_context->pid = p->lead_thread->pid; - - pr_debug("addr: %#lx, size: %#lx, pid: %d\n", - addr, size, mem_context->pid); - - mem_context->va = addr; - mem_context->size = size; - mem_context->offset = addr - buf_obj->it.start; - - mem_context->bo = amdgpu_amdkfd_gpuvm_get_bo_ref(buf_obj->mem, - &mem_context->flags); - mem_context->dev = buf_obj->dev; + goto out_unlock; + } mutex_unlock(&p->mutex); + pr_debug("addr: %#lx, size: %#lx, pid: %d\n", addr, size, mem_context->pid); - pr_debug("Client context: 0x%p\n", mem_context); + mem_context->pid = p->lead_thread->pid; + mem_context->va = addr; + mem_context->size = size; + mem_context->dev = dev; + mem_context->offset = offset; + mem_context->bo = bo; + mem_context->flags = flags; /* Return pointer to allocated context */ *client_context = mem_context; @@ -223,7 +237,6 @@ static int amd_acquire(unsigned long addr, size_t size, * by AMD GPU driver */ return 1; - out_unlock: mutex_unlock(&p->mutex); return 0; -- 2.34.1