]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
RDMA/uverbs: Add a common way to create CQ with umem
authorMichael Margolin <mrgolin@amazon.com>
Tue, 8 Jul 2025 20:23:06 +0000 (20:23 +0000)
committerLeon Romanovsky <leon@kernel.org>
Sun, 13 Jul 2025 08:00:34 +0000 (04:00 -0400)
Add ioctl command attributes and a common handling for the option to
create CQs with memory buffers passed from userspace. When required
attributes are supplied, create umem and provide it for driver's use.
The extension enables creation of CQs on top of preallocated CPU
virtual or device memory buffers, by supplying VA or dmabuf fd, in a
common way.
Drivers can support this flow by initializing a new create_cq_umem fp
field in their ops struct, with a function that can handle the new
parameter.

Signed-off-by: Michael Margolin <mrgolin@amazon.com>
Link: https://patch.msgid.link/20250708202308.24783-2-mrgolin@amazon.com
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
drivers/infiniband/core/device.c
drivers/infiniband/core/uverbs_std_types_cq.c
include/rdma/ib_verbs.h
include/uapi/rdma/ib_user_ioctl_cmds.h

index 1ca6a9b7ba1ac0bbd54ce9a65a05b40b1a391456..f301cdce17281471e66c8069a5085fe15a10cc57 100644 (file)
@@ -2728,6 +2728,7 @@ void ib_set_device_ops(struct ib_device *dev, const struct ib_device_ops *ops)
        SET_DEVICE_OP(dev_ops, create_ah);
        SET_DEVICE_OP(dev_ops, create_counters);
        SET_DEVICE_OP(dev_ops, create_cq);
+       SET_DEVICE_OP(dev_ops, create_cq_umem);
        SET_DEVICE_OP(dev_ops, create_flow);
        SET_DEVICE_OP(dev_ops, create_qp);
        SET_DEVICE_OP(dev_ops, create_rwq_ind_table);
index 432054f0a8a498e53ace40f072459b3984756ca0..37cd37556510406cb75457837b3f980e268a7982 100644 (file)
@@ -64,15 +64,21 @@ static int UVERBS_HANDLER(UVERBS_METHOD_CQ_CREATE)(
        struct ib_ucq_object *obj = container_of(
                uverbs_attr_get_uobject(attrs, UVERBS_ATTR_CREATE_CQ_HANDLE),
                typeof(*obj), uevent.uobject);
+       struct ib_uverbs_completion_event_file *ev_file = NULL;
        struct ib_device *ib_dev = attrs->context->device;
-       int ret;
-       u64 user_handle;
+       struct ib_umem_dmabuf *umem_dmabuf;
        struct ib_cq_init_attr attr = {};
-       struct ib_cq                   *cq;
-       struct ib_uverbs_completion_event_file    *ev_file = NULL;
        struct ib_uobject *ev_file_uobj;
+       struct ib_umem *umem = NULL;
+       u64 buffer_length;
+       u64 buffer_offset;
+       struct ib_cq *cq;
+       u64 user_handle;
+       u64 buffer_va;
+       int buffer_fd;
+       int ret;
 
-       if (!ib_dev->ops.create_cq || !ib_dev->ops.destroy_cq)
+       if ((!ib_dev->ops.create_cq && !ib_dev->ops.create_cq_umem) || !ib_dev->ops.destroy_cq)
                return -EOPNOTSUPP;
 
        ret = uverbs_copy_from(&attr.comp_vector, attrs,
@@ -112,9 +118,66 @@ static int UVERBS_HANDLER(UVERBS_METHOD_CQ_CREATE)(
        INIT_LIST_HEAD(&obj->comp_list);
        INIT_LIST_HEAD(&obj->uevent.event_list);
 
+       if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_CREATE_CQ_BUFFER_VA)) {
+
+               ret = uverbs_copy_from(&buffer_va, attrs, UVERBS_ATTR_CREATE_CQ_BUFFER_VA);
+               if (ret)
+                       goto err_event_file;
+
+               ret = uverbs_copy_from(&buffer_length, attrs, UVERBS_ATTR_CREATE_CQ_BUFFER_LENGTH);
+               if (ret)
+                       goto err_event_file;
+
+               if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_CREATE_CQ_BUFFER_FD) ||
+                   uverbs_attr_is_valid(attrs, UVERBS_ATTR_CREATE_CQ_BUFFER_OFFSET) ||
+                   !ib_dev->ops.create_cq_umem) {
+                       ret = -EINVAL;
+                       goto err_event_file;
+               }
+
+               umem = ib_umem_get(ib_dev, buffer_va, buffer_length, IB_ACCESS_LOCAL_WRITE);
+               if (IS_ERR(umem)) {
+                       ret = PTR_ERR(umem);
+                       goto err_event_file;
+               }
+       } else if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_CREATE_CQ_BUFFER_FD)) {
+
+               ret = uverbs_get_raw_fd(&buffer_fd, attrs, UVERBS_ATTR_CREATE_CQ_BUFFER_FD);
+               if (ret)
+                       goto err_event_file;
+
+               ret = uverbs_copy_from(&buffer_offset, attrs, UVERBS_ATTR_CREATE_CQ_BUFFER_OFFSET);
+               if (ret)
+                       goto err_event_file;
+
+               ret = uverbs_copy_from(&buffer_length, attrs, UVERBS_ATTR_CREATE_CQ_BUFFER_LENGTH);
+               if (ret)
+                       goto err_event_file;
+
+               if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_CREATE_CQ_BUFFER_VA) ||
+                   !ib_dev->ops.create_cq_umem) {
+                       ret = -EINVAL;
+                       goto err_event_file;
+               }
+
+               umem_dmabuf = ib_umem_dmabuf_get_pinned(ib_dev, buffer_offset, buffer_length,
+                                                       buffer_fd, IB_ACCESS_LOCAL_WRITE);
+               if (IS_ERR(umem_dmabuf)) {
+                       ret = PTR_ERR(umem_dmabuf);
+                       goto err_event_file;
+               }
+               umem = &umem_dmabuf->umem;
+       } else if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_CREATE_CQ_BUFFER_OFFSET) ||
+                  uverbs_attr_is_valid(attrs, UVERBS_ATTR_CREATE_CQ_BUFFER_LENGTH) ||
+                  !ib_dev->ops.create_cq) {
+               ret = -EINVAL;
+               goto err_event_file;
+       }
+
        cq = rdma_zalloc_drv_obj(ib_dev, ib_cq);
        if (!cq) {
                ret = -ENOMEM;
+               ib_umem_release(umem);
                goto err_event_file;
        }
 
@@ -128,7 +191,8 @@ static int UVERBS_HANDLER(UVERBS_METHOD_CQ_CREATE)(
        rdma_restrack_new(&cq->res, RDMA_RESTRACK_CQ);
        rdma_restrack_set_name(&cq->res, NULL);
 
-       ret = ib_dev->ops.create_cq(cq, &attr, attrs);
+       ret = umem ? ib_dev->ops.create_cq_umem(cq, &attr, umem, attrs) :
+               ib_dev->ops.create_cq(cq, &attr, attrs);
        if (ret)
                goto err_free;
 
@@ -180,6 +244,17 @@ DECLARE_UVERBS_NAMED_METHOD(
                       UVERBS_OBJECT_ASYNC_EVENT,
                       UVERBS_ACCESS_READ,
                       UA_OPTIONAL),
+       UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_CQ_BUFFER_VA,
+                          UVERBS_ATTR_TYPE(u64),
+                          UA_OPTIONAL),
+       UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_CQ_BUFFER_LENGTH,
+                          UVERBS_ATTR_TYPE(u64),
+                          UA_OPTIONAL),
+       UVERBS_ATTR_RAW_FD(UVERBS_ATTR_CREATE_CQ_BUFFER_FD,
+                          UA_OPTIONAL),
+       UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_CQ_BUFFER_OFFSET,
+                          UVERBS_ATTR_TYPE(u64),
+                          UA_OPTIONAL),
        UVERBS_ATTR_UHW());
 
 static int UVERBS_HANDLER(UVERBS_METHOD_CQ_DESTROY)(
index 1d123812a1f94d428541dc06d92c7891fd85a0b0..3fb1c963eeb01db61539d5623d2c83b465a5df62 100644 (file)
@@ -2486,6 +2486,10 @@ struct ib_device_ops {
        int (*destroy_qp)(struct ib_qp *qp, struct ib_udata *udata);
        int (*create_cq)(struct ib_cq *cq, const struct ib_cq_init_attr *attr,
                         struct uverbs_attr_bundle *attrs);
+       int (*create_cq_umem)(struct ib_cq *cq,
+                             const struct ib_cq_init_attr *attr,
+                             struct ib_umem *umem,
+                             struct uverbs_attr_bundle *attrs);
        int (*modify_cq)(struct ib_cq *cq, u16 cq_count, u16 cq_period);
        int (*destroy_cq)(struct ib_cq *cq, struct ib_udata *udata);
        int (*resize_cq)(struct ib_cq *cq, int cqe, struct ib_udata *udata);
index ac7b162611ed27556875ced5b59a75f4df2e2764..5f3e5bee51b2c6b1d34cd2a4030037cf2979daad 100644 (file)
@@ -105,6 +105,10 @@ enum uverbs_attrs_create_cq_cmd_attr_ids {
        UVERBS_ATTR_CREATE_CQ_FLAGS,
        UVERBS_ATTR_CREATE_CQ_RESP_CQE,
        UVERBS_ATTR_CREATE_CQ_EVENT_FD,
+       UVERBS_ATTR_CREATE_CQ_BUFFER_VA,
+       UVERBS_ATTR_CREATE_CQ_BUFFER_LENGTH,
+       UVERBS_ATTR_CREATE_CQ_BUFFER_FD,
+       UVERBS_ATTR_CREATE_CQ_BUFFER_OFFSET,
 };
 
 enum uverbs_attrs_destroy_cq_cmd_attr_ids {