]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
IB/core: Introduce ib_reg_user_mr
authorMoni Shoua <monis@mellanox.com>
Wed, 15 Jan 2020 12:43:32 +0000 (14:43 +0200)
committerLeon Romanovsky <leonro@mellanox.com>
Thu, 16 Jan 2020 14:14:36 +0000 (16:14 +0200)
Add ib_reg_user_mr() for kernel ULPs to register user MRs.

The common use case that uses this function is a userspace application
that allocates memory for HCA access but the responsibility to register
the memory at the HCA is on an kernel ULP. This ULP that acts as an agent
for the userspace application.

This function is intended to be used without a user context so vendor
drivers need to be aware of calling reg_user_mr() device operation with
udata equal to NULL.

Among all drivers, i40iw is the only driver which relies on presence
of udata, so check udata existence for that driver.

Signed-off-by: Moni Shoua <monis@mellanox.com>
Reviewed-by: Guy Levi <guyle@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
drivers/infiniband/core/verbs.c
drivers/infiniband/hw/efa/efa_verbs.c
drivers/infiniband/hw/i40iw/i40iw_verbs.c
include/rdma/ib_verbs.h

index dd765e176cdd593b0111e1fb1b58a3cb2f2553e7..7a69e4bbe87704bca440edbfa974a87b7cf6c30e 100644 (file)
@@ -1990,6 +1990,36 @@ EXPORT_SYMBOL(ib_resize_cq);
 
 /* Memory regions */
 
+struct ib_mr *ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
+                            u64 virt_addr, int access_flags)
+{
+       struct ib_mr *mr;
+
+       if (access_flags & IB_ACCESS_ON_DEMAND) {
+               if (!(pd->device->attrs.device_cap_flags &
+                     IB_DEVICE_ON_DEMAND_PAGING)) {
+                       pr_debug("ODP support not available\n");
+                       return ERR_PTR(-EINVAL);
+               }
+       }
+
+       mr = pd->device->ops.reg_user_mr(pd, start, length, virt_addr,
+                                        access_flags, NULL);
+
+       if (IS_ERR(mr))
+               return mr;
+
+       mr->device = pd->device;
+       mr->pd = pd;
+       mr->dm = NULL;
+       atomic_inc(&pd->usecnt);
+       mr->res.type = RDMA_RESTRACK_MR;
+       rdma_restrack_kadd(&mr->res);
+
+       return mr;
+}
+EXPORT_SYMBOL(ib_reg_user_mr);
+
 int ib_dereg_mr_user(struct ib_mr *mr, struct ib_udata *udata)
 {
        struct ib_pd *pd = mr->pd;
index 5c35aa72f5150bb4df104641eb4f49e4cefa4fed..4822f5fa12beafee09dbd309951b679cb668e7da 100644 (file)
@@ -1358,7 +1358,7 @@ struct ib_mr *efa_reg_mr(struct ib_pd *ibpd, u64 start, u64 length,
        int inline_size;
        int err;
 
-       if (udata->inlen &&
+       if (udata && udata->inlen &&
            !ib_is_udata_cleared(udata, 0, sizeof(udata->inlen))) {
                ibdev_dbg(&dev->ibdev,
                          "Incompatible ABI params, udata not cleared\n");
index 96488fb443eb59b963c35085a2293fc272618276..c335de91508faa1b46de6e2afc2d90683fb4f01d 100644 (file)
@@ -1756,6 +1756,9 @@ static struct ib_mr *i40iw_reg_user_mr(struct ib_pd *pd,
        int ret;
        int pg_shift;
 
+       if (!udata)
+               return ERR_PTR(-EOPNOTSUPP);
+
        if (iwdev->closing)
                return ERR_PTR(-ENODEV);
 
index 5608e14e3aadf893570e4189c81cb5472a27e184..170d5ec95b7930db003a8ad7f03d6460d5d5c08d 100644 (file)
@@ -4153,6 +4153,12 @@ static inline void ib_dma_free_coherent(struct ib_device *dev,
        dma_free_coherent(dev->dma_device, size, cpu_addr, dma_handle);
 }
 
+/* ib_reg_user_mr - register a memory region for virtual addresses from kernel
+ * space. This function should be called when 'current' is the owning MM.
+ */
+struct ib_mr *ib_reg_user_mr(struct ib_pd *pd, u64 start, u64 length,
+                            u64 virt_addr, int mr_access_flags);
+
 /**
  * ib_dereg_mr_user - Deregisters a memory region and removes it from the
  *   HCA translation table.