]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
IB/core: Add UVERBS_METHOD_REG_MR on the MR object
authorYishai Hadas <yishaih@nvidia.com>
Thu, 17 Jul 2025 12:17:28 +0000 (15:17 +0300)
committerLeon Romanovsky <leon@kernel.org>
Wed, 23 Jul 2025 05:42:10 +0000 (01:42 -0400)
This new method enables us to use a single ioctl from user space which
supports the below variants of reg_mr [1].

The method will be extended in the next patches from the series with an
extra attribute to let us pass DMA handle to be used as part of the
registration.

[1] ibv_reg_mr(), ibv_reg_mr_iova(), ibv_reg_mr_iova2(),
ibv_reg_dmabuf_mr().

Signed-off-by: Yishai Hadas <yishaih@nvidia.com>
Reviewed-by: Edward Srouji <edwards@nvidia.com>
Link: https://patch.msgid.link/5a3822ceef084efe967c9752e89c58d8250337c7.1752752567.git.leon@kernel.org
Signed-off-by: Leon Romanovsky <leon@kernel.org>
drivers/infiniband/core/uverbs_std_types_mr.c
include/uapi/rdma/ib_user_ioctl_cmds.h

index 7ebc7bd3caaea4b116e3a2960841918b3125f63f..1bd4b17b5515dcee8ee07d6e750ff8fd56ad78bc 100644 (file)
@@ -266,6 +266,122 @@ static int UVERBS_HANDLER(UVERBS_METHOD_REG_DMABUF_MR)(
        return ret;
 }
 
+static int UVERBS_HANDLER(UVERBS_METHOD_REG_MR)(
+       struct uverbs_attr_bundle *attrs)
+{
+       struct ib_uobject *uobj =
+               uverbs_attr_get_uobject(attrs, UVERBS_ATTR_REG_MR_HANDLE);
+       struct ib_pd *pd =
+               uverbs_attr_get_obj(attrs, UVERBS_ATTR_REG_MR_PD_HANDLE);
+       u32 valid_access_flags = IB_ACCESS_SUPPORTED;
+       u64 length, iova, fd_offset = 0, addr = 0;
+       struct ib_device *ib_dev = pd->device;
+       bool has_fd_offset = false;
+       bool has_addr = false;
+       bool has_fd = false;
+       u32 access_flags;
+       struct ib_mr *mr;
+       int fd;
+       int ret;
+
+       ret = uverbs_copy_from(&iova, attrs, UVERBS_ATTR_REG_MR_IOVA);
+       if (ret)
+               return ret;
+
+       ret = uverbs_copy_from(&length, attrs, UVERBS_ATTR_REG_MR_LENGTH);
+       if (ret)
+               return ret;
+
+       if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_REG_MR_ADDR)) {
+               ret = uverbs_copy_from(&addr, attrs,
+                                      UVERBS_ATTR_REG_MR_ADDR);
+               if (ret)
+                       return ret;
+               has_addr = true;
+       }
+
+       if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_REG_MR_FD_OFFSET)) {
+               ret = uverbs_copy_from(&fd_offset, attrs,
+                                      UVERBS_ATTR_REG_MR_FD_OFFSET);
+               if (ret)
+                       return ret;
+               has_fd_offset = true;
+       }
+
+       if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_REG_MR_FD)) {
+               ret = uverbs_get_raw_fd(&fd, attrs,
+                                       UVERBS_ATTR_REG_MR_FD);
+               if (ret)
+                       return ret;
+               has_fd = true;
+       }
+
+       if (has_fd) {
+               if (!ib_dev->ops.reg_user_mr_dmabuf)
+                       return -EOPNOTSUPP;
+
+               /* FD requires offset and can't come with addr */
+               if (!has_fd_offset || has_addr)
+                       return -EINVAL;
+
+               if ((fd_offset & ~PAGE_MASK) != (iova & ~PAGE_MASK))
+                       return -EINVAL;
+
+               valid_access_flags = IB_ACCESS_LOCAL_WRITE |
+                                    IB_ACCESS_REMOTE_READ |
+                                    IB_ACCESS_REMOTE_WRITE |
+                                    IB_ACCESS_REMOTE_ATOMIC |
+                                    IB_ACCESS_RELAXED_ORDERING;
+       } else {
+               if (!has_addr || has_fd_offset)
+                       return -EINVAL;
+
+               if ((addr & ~PAGE_MASK) != (iova & ~PAGE_MASK))
+                       return -EINVAL;
+       }
+
+       ret = uverbs_get_flags32(&access_flags, attrs,
+                                UVERBS_ATTR_REG_MR_ACCESS_FLAGS,
+                                valid_access_flags);
+       if (ret)
+               return ret;
+
+       ret = ib_check_mr_access(ib_dev, access_flags);
+       if (ret)
+               return ret;
+
+       if (has_fd)
+               mr = pd->device->ops.reg_user_mr_dmabuf(pd, fd_offset, length, iova,
+                                                       fd, access_flags, attrs);
+       else
+               mr = pd->device->ops.reg_user_mr(pd, addr, length,
+                                                iova, access_flags, NULL);
+
+       if (IS_ERR(mr))
+               return PTR_ERR(mr);
+
+       mr->device = pd->device;
+       mr->pd = pd;
+       mr->type = IB_MR_TYPE_USER;
+       mr->uobject = uobj;
+       atomic_inc(&pd->usecnt);
+       rdma_restrack_new(&mr->res, RDMA_RESTRACK_MR);
+       rdma_restrack_set_name(&mr->res, NULL);
+       rdma_restrack_add(&mr->res);
+       uobj->object = mr;
+
+       uverbs_finalize_uobj_create(attrs, UVERBS_ATTR_REG_MR_HANDLE);
+
+       ret = uverbs_copy_to(attrs, UVERBS_ATTR_REG_MR_RESP_LKEY,
+                            &mr->lkey, sizeof(mr->lkey));
+       if (ret)
+               return ret;
+
+       ret = uverbs_copy_to(attrs, UVERBS_ATTR_REG_MR_RESP_RKEY,
+                            &mr->rkey, sizeof(mr->rkey));
+       return ret;
+}
+
 DECLARE_UVERBS_NAMED_METHOD(
        UVERBS_METHOD_ADVISE_MR,
        UVERBS_ATTR_IDR(UVERBS_ATTR_ADVISE_MR_PD_HANDLE,
@@ -362,6 +478,40 @@ DECLARE_UVERBS_NAMED_METHOD(
                            UVERBS_ATTR_TYPE(u32),
                            UA_MANDATORY));
 
+DECLARE_UVERBS_NAMED_METHOD(
+       UVERBS_METHOD_REG_MR,
+       UVERBS_ATTR_IDR(UVERBS_ATTR_REG_MR_HANDLE,
+                       UVERBS_OBJECT_MR,
+                       UVERBS_ACCESS_NEW,
+                       UA_MANDATORY),
+       UVERBS_ATTR_IDR(UVERBS_ATTR_REG_MR_PD_HANDLE,
+                       UVERBS_OBJECT_PD,
+                       UVERBS_ACCESS_READ,
+                       UA_MANDATORY),
+       UVERBS_ATTR_PTR_IN(UVERBS_ATTR_REG_MR_IOVA,
+                          UVERBS_ATTR_TYPE(u64),
+                          UA_MANDATORY),
+       UVERBS_ATTR_PTR_IN(UVERBS_ATTR_REG_MR_LENGTH,
+                          UVERBS_ATTR_TYPE(u64),
+                          UA_MANDATORY),
+       UVERBS_ATTR_FLAGS_IN(UVERBS_ATTR_REG_MR_ACCESS_FLAGS,
+                            enum ib_access_flags,
+                            UA_MANDATORY),
+       UVERBS_ATTR_PTR_IN(UVERBS_ATTR_REG_MR_ADDR,
+                          UVERBS_ATTR_TYPE(u64),
+                          UA_OPTIONAL),
+       UVERBS_ATTR_PTR_IN(UVERBS_ATTR_REG_MR_FD_OFFSET,
+                          UVERBS_ATTR_TYPE(u64),
+                          UA_OPTIONAL),
+       UVERBS_ATTR_RAW_FD(UVERBS_ATTR_REG_MR_FD,
+                          UA_OPTIONAL),
+       UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_REG_MR_RESP_LKEY,
+                           UVERBS_ATTR_TYPE(u32),
+                           UA_MANDATORY),
+       UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_REG_MR_RESP_RKEY,
+                           UVERBS_ATTR_TYPE(u32),
+                           UA_MANDATORY));
+
 DECLARE_UVERBS_NAMED_METHOD_DESTROY(
        UVERBS_METHOD_MR_DESTROY,
        UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_MR_HANDLE,
@@ -376,7 +526,8 @@ DECLARE_UVERBS_NAMED_OBJECT(
        &UVERBS_METHOD(UVERBS_METHOD_DM_MR_REG),
        &UVERBS_METHOD(UVERBS_METHOD_MR_DESTROY),
        &UVERBS_METHOD(UVERBS_METHOD_QUERY_MR),
-       &UVERBS_METHOD(UVERBS_METHOD_REG_DMABUF_MR));
+       &UVERBS_METHOD(UVERBS_METHOD_REG_DMABUF_MR),
+       &UVERBS_METHOD(UVERBS_METHOD_REG_MR));
 
 const struct uapi_definition uverbs_def_obj_mr[] = {
        UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_MR,
index 5f3e5bee51b2c6b1d34cd2a4030037cf2979daad..ece923ab48a0c1a4b750dae80913d1b18f868252 100644 (file)
@@ -257,6 +257,7 @@ enum uverbs_methods_mr {
        UVERBS_METHOD_ADVISE_MR,
        UVERBS_METHOD_QUERY_MR,
        UVERBS_METHOD_REG_DMABUF_MR,
+       UVERBS_METHOD_REG_MR,
 };
 
 enum uverbs_attrs_mr_destroy_ids {
@@ -290,6 +291,19 @@ enum uverbs_attrs_reg_dmabuf_mr_cmd_attr_ids {
        UVERBS_ATTR_REG_DMABUF_MR_RESP_RKEY,
 };
 
+enum uverbs_attrs_reg_mr_cmd_attr_ids {
+       UVERBS_ATTR_REG_MR_HANDLE,
+       UVERBS_ATTR_REG_MR_PD_HANDLE,
+       UVERBS_ATTR_REG_MR_IOVA,
+       UVERBS_ATTR_REG_MR_ADDR,
+       UVERBS_ATTR_REG_MR_LENGTH,
+       UVERBS_ATTR_REG_MR_ACCESS_FLAGS,
+       UVERBS_ATTR_REG_MR_FD,
+       UVERBS_ATTR_REG_MR_FD_OFFSET,
+       UVERBS_ATTR_REG_MR_RESP_LKEY,
+       UVERBS_ATTR_REG_MR_RESP_RKEY,
+};
+
 enum uverbs_attrs_create_counters_cmd_attr_ids {
        UVERBS_ATTR_CREATE_COUNTERS_HANDLE,
 };