Skip to content

Commit 30bf066

Browse files
mkalderonjgunthorpe
authored andcommitted
RDMA/qedr: Fix doorbell bar mapping for dpi > 1
Each user_context receives a separate dpi value and thus a different address on the doorbell bar. The qedr_mmap function needs to validate the address and map the doorbell bar accordingly. The current implementation always checked against dpi=0 doorbell range leading to a wrong mapping for doorbell bar. (It entered an else case that mapped the address differently). qedr_mmap should only be used for doorbells, so the else was actually wrong in the first place. This only has an affect on arm architecture and not an issue on a x86 based architecture. This lead to doorbells not occurring on arm based systems and left applications that use more than one dpi (or several applications run simultaneously ) to hang. Fixes: ac1b36e ("qedr: Add support for user context verbs") Signed-off-by: Ariel Elior <[email protected]> Signed-off-by: Michal Kalderon <[email protected]> Reviewed-by: Leon Romanovsky <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent 8e907ed commit 30bf066

File tree

1 file changed

+29
-31
lines changed

1 file changed

+29
-31
lines changed

drivers/infiniband/hw/qedr/verbs.c

Lines changed: 29 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -401,49 +401,47 @@ int qedr_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
401401
{
402402
struct qedr_ucontext *ucontext = get_qedr_ucontext(context);
403403
struct qedr_dev *dev = get_qedr_dev(context->device);
404-
unsigned long vm_page = vma->vm_pgoff << PAGE_SHIFT;
405-
u64 unmapped_db = dev->db_phys_addr;
404+
unsigned long phys_addr = vma->vm_pgoff << PAGE_SHIFT;
406405
unsigned long len = (vma->vm_end - vma->vm_start);
407-
int rc = 0;
408-
bool found;
406+
unsigned long dpi_start;
407+
408+
dpi_start = dev->db_phys_addr + (ucontext->dpi * ucontext->dpi_size);
409409

410410
DP_DEBUG(dev, QEDR_MSG_INIT,
411-
"qedr_mmap called vm_page=0x%lx vm_pgoff=0x%lx unmapped_db=0x%llx db_size=%x, len=%lx\n",
412-
vm_page, vma->vm_pgoff, unmapped_db, dev->db_size, len);
413-
if (vma->vm_start & (PAGE_SIZE - 1)) {
414-
DP_ERR(dev, "Vma_start not page aligned = %ld\n",
415-
vma->vm_start);
411+
"mmap invoked with vm_start=0x%pK, vm_end=0x%pK,vm_pgoff=0x%pK; dpi_start=0x%pK dpi_size=0x%x\n",
412+
(void *)vma->vm_start, (void *)vma->vm_end,
413+
(void *)vma->vm_pgoff, (void *)dpi_start, ucontext->dpi_size);
414+
415+
if ((vma->vm_start & (PAGE_SIZE - 1)) || (len & (PAGE_SIZE - 1))) {
416+
DP_ERR(dev,
417+
"failed mmap, adrresses must be page aligned: start=0x%pK, end=0x%pK\n",
418+
(void *)vma->vm_start, (void *)vma->vm_end);
416419
return -EINVAL;
417420
}
418421

419-
found = qedr_search_mmap(ucontext, vm_page, len);
420-
if (!found) {
421-
DP_ERR(dev, "Vma_pgoff not found in mapped array = %ld\n",
422+
if (!qedr_search_mmap(ucontext, phys_addr, len)) {
423+
DP_ERR(dev, "failed mmap, vm_pgoff=0x%lx is not authorized\n",
422424
vma->vm_pgoff);
423425
return -EINVAL;
424426
}
425427

426-
DP_DEBUG(dev, QEDR_MSG_INIT, "Mapping doorbell bar\n");
427-
428-
if ((vm_page >= unmapped_db) && (vm_page <= (unmapped_db +
429-
dev->db_size))) {
430-
DP_DEBUG(dev, QEDR_MSG_INIT, "Mapping doorbell bar\n");
431-
if (vma->vm_flags & VM_READ) {
432-
DP_ERR(dev, "Trying to map doorbell bar for read\n");
433-
return -EPERM;
434-
}
435-
436-
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
428+
if (phys_addr < dpi_start ||
429+
((phys_addr + len) > (dpi_start + ucontext->dpi_size))) {
430+
DP_ERR(dev,
431+
"failed mmap, pages are outside of dpi; page address=0x%pK, dpi_start=0x%pK, dpi_size=0x%x\n",
432+
(void *)phys_addr, (void *)dpi_start,
433+
ucontext->dpi_size);
434+
return -EINVAL;
435+
}
437436

438-
rc = io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
439-
PAGE_SIZE, vma->vm_page_prot);
440-
} else {
441-
DP_DEBUG(dev, QEDR_MSG_INIT, "Mapping chains\n");
442-
rc = remap_pfn_range(vma, vma->vm_start,
443-
vma->vm_pgoff, len, vma->vm_page_prot);
437+
if (vma->vm_flags & VM_READ) {
438+
DP_ERR(dev, "failed mmap, cannot map doorbell bar for read\n");
439+
return -EINVAL;
444440
}
445-
DP_DEBUG(dev, QEDR_MSG_INIT, "qedr_mmap return code: %d\n", rc);
446-
return rc;
441+
442+
vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
443+
return io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, len,
444+
vma->vm_page_prot);
447445
}
448446

449447
struct ib_pd *qedr_alloc_pd(struct ib_device *ibdev,

0 commit comments

Comments
 (0)