rdmatest: Fix amdp2ptest driver mmap
mmap system call parameter vma->vm_start, vm_end is mmap virtual address
start, end, vma->vm_pgoff is rdma buffer GPU address, which is used to
find the sg_table dma_address.
Handle multiple sg table nents case because sg->length is limited to max
2GB.
Change-Id: I677dd6662ee58f0b5c93f8eef32b7009e1e890d8
Signed-off-by: Philip Yang <Philip.Yang@amd.com>
Signed-off-by: Chris Freehill <cfreehil@amd.com>
[ROCm/ROCR-Runtime commit: 9d9fbceefb]
This commit is contained in:
کامیت شده توسط
Chris Freehill
والد
76fdaebea7
کامیت
609390990c
@@ -303,38 +303,27 @@ static int amdp2ptest_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
struct scatterlist *sg;
|
||||
struct va_pages_node *va_pages = NULL;
|
||||
struct amdp2ptest_pages_list *list = filp->private_data;
|
||||
size_t size = vma->vm_end - vma->vm_start;
|
||||
struct list_head *p, *n;
|
||||
uint64_t gpu_va = vma->vm_pgoff << PAGE_SHIFT;
|
||||
|
||||
MSG_INFO("Mapping to CPU user space\n");
|
||||
MSG_INFO("Begin vm_end 0x%lx, vm_start 0x%lx\n", vma->vm_end,
|
||||
vma->vm_start);
|
||||
MSG_INFO("vm_pgoff / pfn 0x%lx\n", vma->vm_pgoff);
|
||||
MSG_INFO("gpu_va / phys. address 0x%llx\n", gpu_va);
|
||||
MSG_INFO("Begin vm_start 0x%lx, vm_end 0x%lx\n", vma->vm_start, vma->vm_end);
|
||||
MSG_INFO("vm_pgoff 0x%lx\n", vma->vm_pgoff);
|
||||
MSG_INFO("gpu_va address 0x%llx\n", gpu_va);
|
||||
|
||||
if (size != PAGE_SIZE) {
|
||||
MSG_ERR("Mapping works now only per page size=%ld", PAGE_SIZE);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* This is the first very simple version of getting CPU pointer for
|
||||
* the single page.
|
||||
* The logic is the following:
|
||||
* - We get GPU VA address and enumerate list to find "get_pages"
|
||||
* node for such range
|
||||
* - Then we enumerate sg table to find the correct dma_address
|
||||
*
|
||||
* NOTE/TODO: Assumption is that the page size is 4KB to allow testing
|
||||
* of the basic logic. Eventually more complex logic must be added.
|
||||
*/
|
||||
list_for_each_safe(p, n, &list->head) {
|
||||
unsigned long addr = vma->vm_start;
|
||||
long mmap_size = vma->vm_end - vma->vm_start;
|
||||
long size;
|
||||
int ret;
|
||||
|
||||
va_pages = list_entry(p, struct va_pages_node, node);
|
||||
|
||||
if (va_pages->pages->va >= gpu_va &&
|
||||
(va_pages->pages->va + va_pages->pages->size)
|
||||
< vma->vm_end) {
|
||||
MSG_INFO("node va 0x%llx size 0x%llx\n", va_pages->pages->va,
|
||||
va_pages->pages->size);
|
||||
|
||||
if (gpu_va >= va_pages->pages->va &&
|
||||
gpu_va + size <= va_pages->pages->va + va_pages->pages->size) {
|
||||
MSG_INFO("Found node: va=0x%llx,size=0x%llx,nents %d\n",
|
||||
va_pages->pages->va,
|
||||
va_pages->pages->size,
|
||||
@@ -342,23 +331,29 @@ static int amdp2ptest_mmap(struct file *filp, struct vm_area_struct *vma)
|
||||
|
||||
for_each_sg(va_pages->pages->pages->sgl, sg,
|
||||
va_pages->pages->pages->nents, i) {
|
||||
if (va_pages->pages->va + (i * sg->length) ==
|
||||
gpu_va) {
|
||||
|
||||
MSG_INFO("Found page[%d]: dma 0x%llx\n",
|
||||
i, sg->dma_address);
|
||||
MSG_INFO("Found page[%d]: dma 0x%llx size 0x%x\n",
|
||||
i, sg->dma_address, sg->length);
|
||||
|
||||
if (remap_pfn_range(vma,
|
||||
vma->vm_start,
|
||||
sg->dma_address,
|
||||
size,
|
||||
vma->vm_page_prot)) {
|
||||
MSG_ERR("Failed remap_pfn()\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
size = min_t(unsigned long, sg->length, mmap_size);
|
||||
MSG_INFO("remap_pfn range addr 0x%lx to dma_addr 0x%llx size 0x%lx\n",
|
||||
addr, sg->dma_address, size);
|
||||
ret = remap_pfn_range(vma,
|
||||
addr,
|
||||
sg->dma_address >> PAGE_SHIFT,
|
||||
size,
|
||||
vma->vm_page_prot);
|
||||
if (ret) {
|
||||
MSG_ERR("Failed remap_pfn() size 0x%lx ret %d\n",
|
||||
size, ret);
|
||||
return ret;
|
||||
}
|
||||
addr += size;
|
||||
mmap_size -= size;
|
||||
if (mmap_size <= 0)
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
مرجع در شماره جدید
Block a user