[PATCH 2/2] drm/amdkfd: Update RDMA implementation such that get_pages() only pins memory of a BO while dma_map() builds an sg_table from the pinned memory
Ramesh Errabolu
Ramesh.Errabolu at amd.com
Fri Jan 29 02:50:00 UTC 2021
[Why]
Enable RDMA service when platform has IOMMU ON. The handle of device
to DMA map is available only in dma_map() call context.
[How]
Update implementation get_pages() such that it only Pins memory of a
buffer object. Update implementation dma_map() to use the handle of
DMA device in building an sg_table off of the buffer object
Signed-off-by: Ramesh Errabolu <Ramesh.Errabolu at amd.com>
---
drivers/gpu/drm/amd/amdkfd/kfd_peerdirect.c | 47 +++++++++++++++++++--
drivers/gpu/drm/amd/amdkfd/kfd_rdma.c | 26 +++++++-----
2 files changed, 59 insertions(+), 14 deletions(-)
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_peerdirect.c b/drivers/gpu/drm/amd/amdkfd/kfd_peerdirect.c
index 6d7340b101ba..86b4ee710629 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_peerdirect.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_peerdirect.c
@@ -54,7 +54,6 @@
#include "kfd_priv.h"
-
/* ----------------------- PeerDirect interface ------------------------------*/
/*
@@ -281,6 +280,14 @@ static int amd_get_pages(unsigned long addr, size_t size, int write, int force,
static int amd_dma_map(struct sg_table *sg_head, void *client_context,
struct device *dma_device, int dmasync, int *nmap)
{
+ struct sg_table *sg_table_tmp;
+ struct kfd_bo *buf_obj;
+ struct kfd_dev *dev;
+ struct kgd_mem *mem;
+ uint64_t offset;
+ uint64_t length;
+ int ret;
+
/*
* NOTE/TODO:
* We could have potentially three cases for real memory
@@ -312,15 +319,33 @@ static int amd_dma_map(struct sg_table *sg_head, void *client_context,
mem_context->size);
if (!mem_context->p2p_info) {
- pr_err("No sg table were allocated\n");
+ pr_err("Buffer was not pinned\n");
return -EINVAL;
}
+ /* Retrieve the handle of buffer object embedded in amd_p2p_info */
+ buf_obj = mem_context->p2p_info->priv;
+ mem = buf_obj->mem;
+ dev = buf_obj->dev;
+ offset = mem_context->va - buf_obj->it.start;
+ length = mem_context->p2p_info->size;
+
+ /* Build sg_table for buffer being exported, including DMA mapping */
+ ret = amdgpu_amdkfd_gpuvm_get_sg_table(dev->kgd, mem,
+ offset, length, &sg_table_tmp);
+ if (ret) {
+ pr_err("Building of sg_table failed\n");
+ return -EFAULT;
+ }
+
+ /* Maintain a copy of the handle to sg_table */
+ mem_context->p2p_info->pages = sg_table_tmp;
+
/* Copy information about previosly allocated sg_table */
- *sg_head = *mem_context->p2p_info->pages;
+ *sg_head = *sg_table_tmp;
/* Return number of pages */
- *nmap = mem_context->p2p_info->pages->nents;
+ *nmap = sg_table_tmp->nents;
return 0;
}
@@ -328,6 +353,7 @@ static int amd_dma_map(struct sg_table *sg_head, void *client_context,
static int amd_dma_unmap(struct sg_table *sg_head, void *client_context,
struct device *dma_device)
{
+ struct sg_table *sg_table_tmp;
struct amd_mem_context *mem_context =
(struct amd_mem_context *)client_context;
@@ -339,6 +365,19 @@ static int amd_dma_unmap(struct sg_table *sg_head, void *client_context,
mem_context->va,
mem_context->size);
+ /* Determine if sg_table construction was successful */
+ if (!mem_context->p2p_info) {
+ pr_err("Buffer was not pinned\n");
+ return -EINVAL;
+ }
+
+ /* Free sg_table and its elements including DMA unmapping */
+ sg_table_tmp = mem_context->p2p_info->pages;
+ if (sg_table_tmp != NULL) {
+ mem_context->p2p_info->pages = NULL;
+ amdgpu_amdkfd_gpuvm_put_sg_table(sg_table_tmp);
+ }
+
/* Assume success */
return 0;
}
diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_rdma.c b/drivers/gpu/drm/amd/amdkfd/kfd_rdma.c
index ec6435aa33bd..67a9213a40b3 100644
--- a/drivers/gpu/drm/amd/amdkfd/kfd_rdma.c
+++ b/drivers/gpu/drm/amd/amdkfd/kfd_rdma.c
@@ -66,7 +66,6 @@ static int get_pages(uint64_t address, uint64_t length, struct pid *pid,
{
struct kfd_bo *buf_obj;
struct kgd_mem *mem;
- struct sg_table *sg_table_tmp;
struct kfd_dev *dev;
uint64_t last = address + length - 1;
uint64_t offset;
@@ -99,10 +98,9 @@ static int get_pages(uint64_t address, uint64_t length, struct pid *pid,
dev = buf_obj->dev;
offset = address - buf_obj->it.start;
- ret = amdgpu_amdkfd_gpuvm_pin_get_sg_table(dev->kgd, mem,
- offset, length, &sg_table_tmp);
+ ret = amdgpu_amdkfd_gpuvm_pin_bo(mem);
if (ret) {
- pr_err("amdgpu_amdkfd_gpuvm_pin_get_sg_table failed.\n");
+ pr_err("Pinning of buffer failed.\n");
*amd_p2p_data = NULL;
goto free_mem;
}
@@ -111,7 +109,6 @@ static int get_pages(uint64_t address, uint64_t length, struct pid *pid,
rdma_cb_data->amd_p2p_data.size = length;
rdma_cb_data->amd_p2p_data.pid = pid;
rdma_cb_data->amd_p2p_data.priv = buf_obj;
- rdma_cb_data->amd_p2p_data.pages = sg_table_tmp;
rdma_cb_data->amd_p2p_data.kfd_proc = p;
rdma_cb_data->free_callback = free_callback;
@@ -140,24 +137,33 @@ static int put_pages_helper(struct amd_p2p_info *p2p_data)
{
struct kfd_bo *buf_obj;
struct kfd_dev *dev;
- struct sg_table *sg_table_tmp;
struct rdma_cb *rdma_cb_data;
+ struct sg_table *sg_table_tmp;
if (!p2p_data) {
pr_err("amd_p2p_info pointer is invalid.\n");
return -EINVAL;
}
- rdma_cb_data = container_of(p2p_data, struct rdma_cb, amd_p2p_data);
+ /* Determine if sg_table been released */
+ sg_table_tmp = p2p_data->pages;
+ if (sg_table_tmp != NULL) {
+ p2p_data->pages = NULL;
+ amdgpu_amdkfd_gpuvm_put_sg_table(sg_table_tmp);
+ }
+ /* Unpin pages of buffer object */
buf_obj = p2p_data->priv;
- dev = buf_obj->dev;
- sg_table_tmp = p2p_data->pages;
+ p2p_data->priv = NULL;
+ if (buf_obj != NULL)
+ amdgpu_amdkfd_gpuvm_unpin_bo(buf_obj->mem);
+ /* Remove callback info from list of callback objects */
+ rdma_cb_data = container_of(p2p_data, struct rdma_cb, amd_p2p_data);
list_del(&rdma_cb_data->node);
kfree(rdma_cb_data);
- amdgpu_amdkfd_gpuvm_unpin_put_sg_table(buf_obj->mem, sg_table_tmp);
+ dev = buf_obj->dev;
kfd_dec_compute_active(dev);
return 0;
--
2.29.2
More information about the amd-gfx
mailing list