aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKalderon, Michal <Michal.Kalderon@cavium.com>2018-05-15 08:13:33 -0400
committerJason Gunthorpe <jgg@mellanox.com>2018-05-23 17:12:14 -0400
commit30bf066cd9989fef34aeeef9080368867fe42be7 (patch)
tree2a5a2a726b03f279d23e10f3837d562cefab8c41
parent8e907ed4882714fd13cfe670681fc6cb5284c780 (diff)
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: ac1b36e55a51 ("qedr: Add support for user context verbs") Signed-off-by: Ariel Elior <Ariel.Elior@cavium.com> Signed-off-by: Michal Kalderon <Michal.Kalderon@cavium.com> Reviewed-by: Leon Romanovsky <leonro@mellanox.com> Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
-rw-r--r--drivers/infiniband/hw/qedr/verbs.c60
1 files changed, 29 insertions, 31 deletions
diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c
index 7d3763b2e01c..3f9afc02d166 100644
--- a/drivers/infiniband/hw/qedr/verbs.c
+++ b/drivers/infiniband/hw/qedr/verbs.c
@@ -401,49 +401,47 @@ int qedr_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
401{ 401{
402 struct qedr_ucontext *ucontext = get_qedr_ucontext(context); 402 struct qedr_ucontext *ucontext = get_qedr_ucontext(context);
403 struct qedr_dev *dev = get_qedr_dev(context->device); 403 struct qedr_dev *dev = get_qedr_dev(context->device);
404 unsigned long vm_page = vma->vm_pgoff << PAGE_SHIFT; 404 unsigned long phys_addr = vma->vm_pgoff << PAGE_SHIFT;
405 u64 unmapped_db = dev->db_phys_addr;
406 unsigned long len = (vma->vm_end - vma->vm_start); 405 unsigned long len = (vma->vm_end - vma->vm_start);
407 int rc = 0; 406 unsigned long dpi_start;
408 bool found; 407
408 dpi_start = dev->db_phys_addr + (ucontext->dpi * ucontext->dpi_size);
409 409
410 DP_DEBUG(dev, QEDR_MSG_INIT, 410 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", 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 vm_page, vma->vm_pgoff, unmapped_db, dev->db_size, len); 412 (void *)vma->vm_start, (void *)vma->vm_end,
413 if (vma->vm_start & (PAGE_SIZE - 1)) { 413 (void *)vma->vm_pgoff, (void *)dpi_start, ucontext->dpi_size);
414 DP_ERR(dev, "Vma_start not page aligned = %ld\n", 414
415 vma->vm_start); 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);
416 return -EINVAL; 419 return -EINVAL;
417 } 420 }
418 421
419 found = qedr_search_mmap(ucontext, vm_page, len); 422 if (!qedr_search_mmap(ucontext, phys_addr, len)) {
420 if (!found) { 423 DP_ERR(dev, "failed mmap, vm_pgoff=0x%lx is not authorized\n",
421 DP_ERR(dev, "Vma_pgoff not found in mapped array = %ld\n",
422 vma->vm_pgoff); 424 vma->vm_pgoff);
423 return -EINVAL; 425 return -EINVAL;
424 } 426 }
425 427
426 DP_DEBUG(dev, QEDR_MSG_INIT, "Mapping doorbell bar\n"); 428 if (phys_addr < dpi_start ||
427 429 ((phys_addr + len) > (dpi_start + ucontext->dpi_size))) {
428 if ((vm_page >= unmapped_db) && (vm_page <= (unmapped_db + 430 DP_ERR(dev,
429 dev->db_size))) { 431 "failed mmap, pages are outside of dpi; page address=0x%pK, dpi_start=0x%pK, dpi_size=0x%x\n",
430 DP_DEBUG(dev, QEDR_MSG_INIT, "Mapping doorbell bar\n"); 432 (void *)phys_addr, (void *)dpi_start,
431 if (vma->vm_flags & VM_READ) { 433 ucontext->dpi_size);
432 DP_ERR(dev, "Trying to map doorbell bar for read\n"); 434 return -EINVAL;
433 return -EPERM; 435 }
434 }
435
436 vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
437 436
438 rc = io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, 437 if (vma->vm_flags & VM_READ) {
439 PAGE_SIZE, vma->vm_page_prot); 438 DP_ERR(dev, "failed mmap, cannot map doorbell bar for read\n");
440 } else { 439 return -EINVAL;
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);
444 } 440 }
445 DP_DEBUG(dev, QEDR_MSG_INIT, "qedr_mmap return code: %d\n", rc); 441
446 return rc; 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);
447} 445}
448 446
449struct ib_pd *qedr_alloc_pd(struct ib_device *ibdev, 447struct ib_pd *qedr_alloc_pd(struct ib_device *ibdev,