RDMA/qedr: Use the common mmap API
authorMichal Kalderon <michal.kalderon@marvell.com>
Wed, 30 Oct 2019 09:44:15 +0000 (11:44 +0200)
committerJason Gunthorpe <jgg@mellanox.com>
Wed, 6 Nov 2019 17:08:01 +0000 (13:08 -0400)
Remove all functions related to mmap from qedr and use the common API.

Link: https://lore.kernel.org/r/20191030094417.16866-7-michal.kalderon@marvell.com
Signed-off-by: Ariel Elior <ariel.elior@marvell.com>
Signed-off-by: Michal Kalderon <michal.kalderon@marvell.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
drivers/infiniband/hw/qedr/main.c
drivers/infiniband/hw/qedr/qedr.h
drivers/infiniband/hw/qedr/verbs.c
drivers/infiniband/hw/qedr/verbs.h

index 1ff5407270d2c0c66f88aa98469db38b15114b74..03fd168cccc0fcfad93dc4a6fc466e4a49cffe00 100644 (file)
@@ -212,6 +212,7 @@ static const struct ib_device_ops qedr_dev_ops = {
        .get_link_layer = qedr_link_layer,
        .map_mr_sg = qedr_map_mr_sg,
        .mmap = qedr_mmap,
+       .mmap_free = qedr_mmap_free,
        .modify_port = qedr_modify_port,
        .modify_qp = qedr_modify_qp,
        .modify_srq = qedr_modify_srq,
index 8e927f6c152035851a5bf03c1a6615062a086a74..6ef39dccba21b3343ec26367f58aac7cf39d146f 100644 (file)
@@ -231,14 +231,10 @@ struct qedr_ucontext {
        struct qedr_dev *dev;
        struct qedr_pd *pd;
        void __iomem *dpi_addr;
+       struct rdma_user_mmap_entry *db_mmap_entry;
        u64 dpi_phys_addr;
        u32 dpi_size;
        u16 dpi;
-
-       struct list_head mm_head;
-
-       /* Lock to protect mm list */
-       struct mutex mm_list_lock;
 };
 
 union db_prod64 {
@@ -301,14 +297,6 @@ struct qedr_pd {
        struct qedr_ucontext *uctx;
 };
 
-struct qedr_mm {
-       struct {
-               u64 phy_addr;
-               unsigned long len;
-       } key;
-       struct list_head entry;
-};
-
 union db_prod32 {
        struct rdma_pwm_val16_data data;
        u32 raw;
@@ -491,6 +479,15 @@ struct qedr_mr {
        u32 npages;
 };
 
+struct qedr_user_mmap_entry {
+       struct rdma_user_mmap_entry rdma_entry;
+       struct qedr_dev *dev;
+       u64 io_address;
+       size_t length;
+       u16 dpi;
+       u8 mmap_flag;
+};
+
 #define SET_FIELD2(value, name, flag) ((value) |= ((flag) << (name ## _SHIFT)))
 
 #define QEDR_RESP_IMM  (RDMA_CQE_RESPONDER_IMM_FLG_MASK << \
@@ -589,4 +586,11 @@ static inline struct qedr_srq *get_qedr_srq(struct ib_srq *ibsrq)
 {
        return container_of(ibsrq, struct qedr_srq, ibsrq);
 }
+
+static inline struct qedr_user_mmap_entry *
+get_qedr_mmap_entry(struct rdma_user_mmap_entry *rdma_entry)
+{
+       return container_of(rdma_entry, struct qedr_user_mmap_entry,
+                           rdma_entry);
+}
 #endif
index 8b4240c1cc7633fed5fcd91a7b0d34c3885dbc7e..903cd934eb53782c216f8740d2bc76dd79dbccf7 100644 (file)
 
 #define DB_ADDR_SHIFT(addr)            ((addr) << DB_PWM_ADDR_OFFSET_SHIFT)
 
+enum {
+       QEDR_USER_MMAP_IO_WC = 0,
+};
+
 static inline int qedr_ib_copy_to_udata(struct ib_udata *udata, void *src,
                                        size_t len)
 {
@@ -257,60 +261,6 @@ int qedr_modify_port(struct ib_device *ibdev, u8 port, int mask,
        return 0;
 }
 
-static int qedr_add_mmap(struct qedr_ucontext *uctx, u64 phy_addr,
-                        unsigned long len)
-{
-       struct qedr_mm *mm;
-
-       mm = kzalloc(sizeof(*mm), GFP_KERNEL);
-       if (!mm)
-               return -ENOMEM;
-
-       mm->key.phy_addr = phy_addr;
-       /* This function might be called with a length which is not a multiple
-        * of PAGE_SIZE, while the mapping is PAGE_SIZE grained and the kernel
-        * forces this granularity by increasing the requested size if needed.
-        * When qedr_mmap is called, it will search the list with the updated
-        * length as a key. To prevent search failures, the length is rounded up
-        * in advance to PAGE_SIZE.
-        */
-       mm->key.len = roundup(len, PAGE_SIZE);
-       INIT_LIST_HEAD(&mm->entry);
-
-       mutex_lock(&uctx->mm_list_lock);
-       list_add(&mm->entry, &uctx->mm_head);
-       mutex_unlock(&uctx->mm_list_lock);
-
-       DP_DEBUG(uctx->dev, QEDR_MSG_MISC,
-                "added (addr=0x%llx,len=0x%lx) for ctx=%p\n",
-                (unsigned long long)mm->key.phy_addr,
-                (unsigned long)mm->key.len, uctx);
-
-       return 0;
-}
-
-static bool qedr_search_mmap(struct qedr_ucontext *uctx, u64 phy_addr,
-                            unsigned long len)
-{
-       bool found = false;
-       struct qedr_mm *mm;
-
-       mutex_lock(&uctx->mm_list_lock);
-       list_for_each_entry(mm, &uctx->mm_head, entry) {
-               if (len != mm->key.len || phy_addr != mm->key.phy_addr)
-                       continue;
-
-               found = true;
-               break;
-       }
-       mutex_unlock(&uctx->mm_list_lock);
-       DP_DEBUG(uctx->dev, QEDR_MSG_MISC,
-                "searched for (addr=0x%llx,len=0x%lx) for ctx=%p, result=%d\n",
-                mm->key.phy_addr, mm->key.len, uctx, found);
-
-       return found;
-}
-
 int qedr_alloc_ucontext(struct ib_ucontext *uctx, struct ib_udata *udata)
 {
        struct ib_device *ibdev = uctx->device;
@@ -319,6 +269,7 @@ int qedr_alloc_ucontext(struct ib_ucontext *uctx, struct ib_udata *udata)
        struct qedr_alloc_ucontext_resp uresp = {};
        struct qedr_dev *dev = get_qedr_dev(ibdev);
        struct qed_rdma_add_user_out_params oparams;
+       struct qedr_user_mmap_entry *entry;
 
        if (!udata)
                return -EFAULT;
@@ -335,13 +286,29 @@ int qedr_alloc_ucontext(struct ib_ucontext *uctx, struct ib_udata *udata)
        ctx->dpi_addr = oparams.dpi_addr;
        ctx->dpi_phys_addr = oparams.dpi_phys_addr;
        ctx->dpi_size = oparams.dpi_size;
-       INIT_LIST_HEAD(&ctx->mm_head);
-       mutex_init(&ctx->mm_list_lock);
+       entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+       if (!entry) {
+               rc = -ENOMEM;
+               goto err;
+       }
+
+       entry->io_address = ctx->dpi_phys_addr;
+       entry->length = ctx->dpi_size;
+       entry->mmap_flag = QEDR_USER_MMAP_IO_WC;
+       entry->dpi = ctx->dpi;
+       entry->dev = dev;
+       rc = rdma_user_mmap_entry_insert(uctx, &entry->rdma_entry,
+                                        ctx->dpi_size);
+       if (rc) {
+               kfree(entry);
+               goto err;
+       }
+       ctx->db_mmap_entry = &entry->rdma_entry;
 
        uresp.dpm_enabled = dev->user_dpm_enabled;
        uresp.wids_enabled = 1;
        uresp.wid_count = oparams.wid_count;
-       uresp.db_pa = ctx->dpi_phys_addr;
+       uresp.db_pa = rdma_user_mmap_get_offset(ctx->db_mmap_entry);
        uresp.db_size = ctx->dpi_size;
        uresp.max_send_wr = dev->attr.max_sqe;
        uresp.max_recv_wr = dev->attr.max_rqe;
@@ -353,82 +320,86 @@ int qedr_alloc_ucontext(struct ib_ucontext *uctx, struct ib_udata *udata)
 
        rc = qedr_ib_copy_to_udata(udata, &uresp, sizeof(uresp));
        if (rc)
-               return rc;
+               goto err;
 
        ctx->dev = dev;
 
-       rc = qedr_add_mmap(ctx, ctx->dpi_phys_addr, ctx->dpi_size);
-       if (rc)
-               return rc;
-
        DP_DEBUG(dev, QEDR_MSG_INIT, "Allocating user context %p\n",
                 &ctx->ibucontext);
        return 0;
+
+err:
+       if (!ctx->db_mmap_entry)
+               dev->ops->rdma_remove_user(dev->rdma_ctx, ctx->dpi);
+       else
+               rdma_user_mmap_entry_remove(ctx->db_mmap_entry);
+
+       return rc;
 }
 
 void qedr_dealloc_ucontext(struct ib_ucontext *ibctx)
 {
        struct qedr_ucontext *uctx = get_qedr_ucontext(ibctx);
-       struct qedr_mm *mm, *tmp;
 
        DP_DEBUG(uctx->dev, QEDR_MSG_INIT, "Deallocating user context %p\n",
                 uctx);
-       uctx->dev->ops->rdma_remove_user(uctx->dev->rdma_ctx, uctx->dpi);
-
-       list_for_each_entry_safe(mm, tmp, &uctx->mm_head, entry) {
-               DP_DEBUG(uctx->dev, QEDR_MSG_MISC,
-                        "deleted (addr=0x%llx,len=0x%lx) for ctx=%p\n",
-                        mm->key.phy_addr, mm->key.len, uctx);
-               list_del(&mm->entry);
-               kfree(mm);
-       }
+
+       rdma_user_mmap_entry_remove(uctx->db_mmap_entry);
 }
 
-int qedr_mmap(struct ib_ucontext *context, struct vm_area_struct *vma)
+void qedr_mmap_free(struct rdma_user_mmap_entry *rdma_entry)
 {
-       struct qedr_ucontext *ucontext = get_qedr_ucontext(context);
-       struct qedr_dev *dev = get_qedr_dev(context->device);
-       unsigned long phys_addr = vma->vm_pgoff << PAGE_SHIFT;
-       unsigned long len = (vma->vm_end - vma->vm_start);
-       unsigned long dpi_start;
+       struct qedr_user_mmap_entry *entry = get_qedr_mmap_entry(rdma_entry);
+       struct qedr_dev *dev = entry->dev;
 
-       dpi_start = dev->db_phys_addr + (ucontext->dpi * ucontext->dpi_size);
+       if (entry->mmap_flag == QEDR_USER_MMAP_IO_WC)
+               dev->ops->rdma_remove_user(dev->rdma_ctx, entry->dpi);
 
-       DP_DEBUG(dev, QEDR_MSG_INIT,
-                "mmap invoked with vm_start=0x%pK, vm_end=0x%pK,vm_pgoff=0x%pK; dpi_start=0x%pK dpi_size=0x%x\n",
-                (void *)vma->vm_start, (void *)vma->vm_end,
-                (void *)vma->vm_pgoff, (void *)dpi_start, ucontext->dpi_size);
+       kfree(entry);
+}
 
-       if ((vma->vm_start & (PAGE_SIZE - 1)) || (len & (PAGE_SIZE - 1))) {
-               DP_ERR(dev,
-                      "failed mmap, addresses must be page aligned: start=0x%pK, end=0x%pK\n",
-                      (void *)vma->vm_start, (void *)vma->vm_end);
-               return -EINVAL;
-       }
+int qedr_mmap(struct ib_ucontext *ucontext, struct vm_area_struct *vma)
+{
+       struct ib_device *dev = ucontext->device;
+       size_t length = vma->vm_end - vma->vm_start;
+       struct rdma_user_mmap_entry *rdma_entry;
+       struct qedr_user_mmap_entry *entry;
+       int rc = 0;
+       u64 pfn;
 
-       if (!qedr_search_mmap(ucontext, phys_addr, len)) {
-               DP_ERR(dev, "failed mmap, vm_pgoff=0x%lx is not authorized\n",
-                      vma->vm_pgoff);
-               return -EINVAL;
-       }
+       ibdev_dbg(dev,
+                 "start %#lx, end %#lx, length = %#zx, pgoff = %#lx\n",
+                 vma->vm_start, vma->vm_end, length, vma->vm_pgoff);
 
-       if (phys_addr < dpi_start ||
-           ((phys_addr + len) > (dpi_start + ucontext->dpi_size))) {
-               DP_ERR(dev,
-                      "failed mmap, pages are outside of dpi; page address=0x%pK, dpi_start=0x%pK, dpi_size=0x%x\n",
-                      (void *)phys_addr, (void *)dpi_start,
-                      ucontext->dpi_size);
+       rdma_entry = rdma_user_mmap_entry_get(ucontext, vma);
+       if (!rdma_entry) {
+               ibdev_dbg(dev, "pgoff[%#lx] does not have valid entry\n",
+                         vma->vm_pgoff);
                return -EINVAL;
        }
-
-       if (vma->vm_flags & VM_READ) {
-               DP_ERR(dev, "failed mmap, cannot map doorbell bar for read\n");
-               return -EINVAL;
+       entry = get_qedr_mmap_entry(rdma_entry);
+       ibdev_dbg(dev,
+                 "Mapping address[%#llx], length[%#zx], mmap_flag[%d]\n",
+                 entry->io_address, length, entry->mmap_flag);
+
+       switch (entry->mmap_flag) {
+       case QEDR_USER_MMAP_IO_WC:
+               pfn = entry->io_address >> PAGE_SHIFT;
+               rc = rdma_user_mmap_io(ucontext, vma, pfn, length,
+                                      pgprot_writecombine(vma->vm_page_prot),
+                                      rdma_entry);
+               break;
+       default:
+               rc = -EINVAL;
        }
 
-       vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot);
-       return io_remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff, len,
-                                 vma->vm_page_prot);
+       if (rc)
+               ibdev_dbg(dev,
+                         "Couldn't mmap address[%#llx] length[%#zx] mmap_flag[%d] err[%d]\n",
+                         entry->io_address, length, entry->mmap_flag, rc);
+
+       rdma_user_mmap_entry_put(rdma_entry);
+       return rc;
 }
 
 int qedr_alloc_pd(struct ib_pd *ibpd, struct ib_udata *udata)
index 9aaa90283d6e36cd2b92d8cfcea9bbf3dcf59af4..3606e97e95da8d72279c3e001744687dcf7d85c8 100644 (file)
@@ -46,7 +46,8 @@ int qedr_query_pkey(struct ib_device *, u8 port, u16 index, u16 *pkey);
 int qedr_alloc_ucontext(struct ib_ucontext *uctx, struct ib_udata *udata);
 void qedr_dealloc_ucontext(struct ib_ucontext *uctx);
 
-int qedr_mmap(struct ib_ucontext *, struct vm_area_struct *vma);
+int qedr_mmap(struct ib_ucontext *ucontext, struct vm_area_struct *vma);
+void qedr_mmap_free(struct rdma_user_mmap_entry *rdma_entry);
 int qedr_alloc_pd(struct ib_pd *pd, struct ib_udata *udata);
 void qedr_dealloc_pd(struct ib_pd *pd, struct ib_udata *udata);