The branch main has been updated by kib:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=b7ca46b161d869c839b1d4a544f64d5661a9082f

commit b7ca46b161d869c839b1d4a544f64d5661a9082f
Author:     Ariel Ehrenberg <[email protected]>
AuthorDate: 2026-06-04 15:07:52 +0000
Commit:     Konstantin Belousov <[email protected]>
CommitDate: 2026-07-07 11:24:38 +0000

    mlx5ib: implement the MLX5_IB_OBJECT_UAR ioctl object
    
    Import Linux upstream commit 342ee59de98a2ecdf15a46849a2534e7c808eb1f.
    
    The dynamic UAR object was declared in the ABI headers but had no handler,
    so the ioctl was rejected and dynamic-UAR contexts could not allocate a
    doorbell UAR at all.
    
    Implement the alloc and destroy methods following the upstream driver:
    grab a UAR stamped with the caller's DEVX uid, expose it to user space
    through an rdma_user_mmap entry (write-combining or non-cached as
    requested), and free it on destroy.
    
    Reviewed by:    kib
    Tested by:      Wafa Hamzah <[email protected]>
    Sponsored by:   Nvidia networking
    MFC after:      1 month
---
 sys/dev/mlx5/mlx5_ib/mlx5_ib_main.c | 163 +++++++++++++++++++++++++++++++++++-
 sys/dev/mlx5/mlx5_ifc.h             |   4 +-
 2 files changed, 164 insertions(+), 3 deletions(-)

diff --git a/sys/dev/mlx5/mlx5_ib/mlx5_ib_main.c 
b/sys/dev/mlx5/mlx5_ib/mlx5_ib_main.c
index f5c7d5cf382b..fc9af189f3fa 100644
--- a/sys/dev/mlx5/mlx5_ib/mlx5_ib_main.c
+++ b/sys/dev/mlx5/mlx5_ib/mlx5_ib_main.c
@@ -47,6 +47,12 @@
 #include <rdma/ib_smi.h>
 #include <rdma/ib_umem.h>
 #include <rdma/uverbs_ioctl.h>
+#include <rdma/uverbs_types.h>
+#include <rdma/uverbs_std_types.h>
+#define UVERBS_MODULE_NAME mlx5_ib
+#include <rdma/uverbs_named_ioctl.h>
+#include <rdma/mlx5_user_ioctl_cmds.h>
+#include <rdma/mlx5_user_ioctl_verbs.h>
 #include <linux/in.h>
 #include <linux/etherdevice.h>
 #include <dev/mlx5/fs.h>
@@ -1506,15 +1512,44 @@ static int mlx5_ib_mmap_clock_info_page(struct 
mlx5_ib_dev *dev,
        return -EOPNOTSUPP;
 }
 
+static int mlx5_cmd_uar_alloc(struct mlx5_core_dev *dev, u32 *uarn, u16 uid)
+{
+       u32 out[MLX5_ST_SZ_DW(alloc_uar_out)] = {};
+       u32 in[MLX5_ST_SZ_DW(alloc_uar_in)] = {};
+       int err;
+
+       MLX5_SET(alloc_uar_in, in, opcode, MLX5_CMD_OP_ALLOC_UAR);
+       MLX5_SET(alloc_uar_in, in, uid, uid);
+       err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
+       if (err)
+               return err;
+
+       *uarn = MLX5_GET(alloc_uar_out, out, uar);
+       return 0;
+}
+
+static int mlx5_cmd_uar_dealloc(struct mlx5_core_dev *dev, u32 uarn, u16 uid)
+{
+       u32 out[MLX5_ST_SZ_DW(dealloc_uar_out)] = {};
+       u32 in[MLX5_ST_SZ_DW(dealloc_uar_in)] = {};
+
+       MLX5_SET(dealloc_uar_in, in, opcode, MLX5_CMD_OP_DEALLOC_UAR);
+       MLX5_SET(dealloc_uar_in, in, uar, uarn);
+       MLX5_SET(dealloc_uar_in, in, uid, uid);
+       return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
+}
+
 static void mlx5_ib_mmap_free(struct rdma_user_mmap_entry *entry)
 {
        struct mlx5_user_mmap_entry *mentry = to_mmmap(entry);
        struct mlx5_ib_dev *dev = to_mdev(entry->ucontext->device);
+       struct mlx5_ib_ucontext *context = to_mucontext(entry->ucontext);
 
        switch (mentry->mmap_flag) {
        case MLX5_IB_MMAP_TYPE_UAR_WC:
        case MLX5_IB_MMAP_TYPE_UAR_NC:
-               mlx5_cmd_free_uar(dev->mdev, mentry->page_idx);
+               mlx5_cmd_uar_dealloc(dev->mdev, mentry->page_idx,
+                                    context->devx_uid);
                kfree(mentry);
                break;
        default:
@@ -3300,8 +3335,134 @@ free:
        return ARRAY_SIZE(names);
 }
 
+/*
+ * MLX5_IB_OBJECT_UAR: allocate a dedicated UAR for user space and expose it
+ * through an mmap entry.  Modern libmlx5 uses this (dynamic UAR) to obtain the
+ * UAR backing CQ/QP doorbells instead of the legacy static UAR pages.
+ */
+static int mmap_obj_cleanup(struct ib_uobject *uobject,
+                           enum rdma_remove_reason why,
+                           struct uverbs_attr_bundle *attrs)
+{
+       struct mlx5_user_mmap_entry *obj = uobject->object;
+
+       rdma_user_mmap_entry_remove(&obj->rdma_entry);
+       return 0;
+}
+
+static int UVERBS_HANDLER(MLX5_IB_METHOD_UAR_OBJ_ALLOC)(
+       struct uverbs_attr_bundle *attrs)
+{
+       struct ib_uobject *uobj = uverbs_attr_get_uobject(attrs,
+               MLX5_IB_ATTR_UAR_OBJ_ALLOC_HANDLE);
+       enum mlx5_ib_uapi_uar_alloc_type alloc_type;
+       struct mlx5_user_mmap_entry *entry;
+       struct mlx5_ib_ucontext *c;
+       struct mlx5_ib_dev *dev;
+       u32 uar_index;
+       u32 length = PAGE_SIZE;
+       u64 mmap_offset;
+       int err;
+
+       c = to_mucontext(ib_uverbs_get_ucontext(attrs));
+       if (IS_ERR(c))
+               return PTR_ERR(c);
+       dev = to_mdev(c->ibucontext.device);
+
+       err = uverbs_get_const(&alloc_type, attrs,
+                              MLX5_IB_ATTR_UAR_OBJ_ALLOC_TYPE);
+       if (err)
+               return err;
+
+       if (alloc_type != MLX5_IB_UAPI_UAR_ALLOC_TYPE_BF &&
+           alloc_type != MLX5_IB_UAPI_UAR_ALLOC_TYPE_NC)
+               return -EOPNOTSUPP;
+
+       if (alloc_type == MLX5_IB_UAPI_UAR_ALLOC_TYPE_BF && !dev->wc_support)
+               return -EOPNOTSUPP;
+
+       err = mlx5_cmd_uar_alloc(dev->mdev, &uar_index, c->devx_uid);
+       if (err)
+               return err;
+
+       entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+       if (!entry) {
+               err = -ENOMEM;
+               goto err_uar;
+       }
+
+       entry->mmap_flag = (alloc_type == MLX5_IB_UAPI_UAR_ALLOC_TYPE_NC) ?
+               MLX5_IB_MMAP_TYPE_UAR_NC : MLX5_IB_MMAP_TYPE_UAR_WC;
+       entry->page_idx = uar_index;
+       entry->address = uar_index2pfn(dev, uar_index) << PAGE_SHIFT;
+
+       err = rdma_user_mmap_entry_insert(&c->ibucontext, &entry->rdma_entry,
+                                         length);
+       if (err)
+               goto err_entry;
+
+       mmap_offset = rdma_user_mmap_get_offset(&entry->rdma_entry);
+       err = uverbs_copy_to(attrs, MLX5_IB_ATTR_UAR_OBJ_ALLOC_MMAP_OFFSET,
+                            &mmap_offset, sizeof(mmap_offset));
+       if (err)
+               goto err_insert;
+       err = uverbs_copy_to(attrs, MLX5_IB_ATTR_UAR_OBJ_ALLOC_MMAP_LENGTH,
+                            &length, sizeof(length));
+       if (err)
+               goto err_insert;
+       err = uverbs_copy_to(attrs, MLX5_IB_ATTR_UAR_OBJ_ALLOC_PAGE_ID,
+                            &uar_index, sizeof(uar_index));
+       if (err)
+               goto err_insert;
+
+       uobj->object = entry;
+       return 0;
+
+err_insert:
+       /* Removing the entry frees the UAR and the entry itself. */
+       rdma_user_mmap_entry_remove(&entry->rdma_entry);
+       return err;
+err_entry:
+       kfree(entry);
+err_uar:
+       mlx5_cmd_uar_dealloc(dev->mdev, uar_index, c->devx_uid);
+       return err;
+}
+
+DECLARE_UVERBS_NAMED_METHOD(
+       MLX5_IB_METHOD_UAR_OBJ_ALLOC,
+       UVERBS_ATTR_IDR(MLX5_IB_ATTR_UAR_OBJ_ALLOC_HANDLE,
+                       MLX5_IB_OBJECT_UAR,
+                       UVERBS_ACCESS_NEW,
+                       UA_MANDATORY),
+       UVERBS_ATTR_CONST_IN(MLX5_IB_ATTR_UAR_OBJ_ALLOC_TYPE,
+                            enum mlx5_ib_uapi_uar_alloc_type,
+                            UA_MANDATORY),
+       UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_UAR_OBJ_ALLOC_PAGE_ID,
+                           UVERBS_ATTR_TYPE(u32),
+                           UA_MANDATORY),
+       UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_UAR_OBJ_ALLOC_MMAP_LENGTH,
+                           UVERBS_ATTR_TYPE(u32),
+                           UA_MANDATORY),
+       UVERBS_ATTR_PTR_OUT(MLX5_IB_ATTR_UAR_OBJ_ALLOC_MMAP_OFFSET,
+                           UVERBS_ATTR_TYPE(u64),
+                           UA_MANDATORY));
+
+DECLARE_UVERBS_NAMED_METHOD_DESTROY(
+       MLX5_IB_METHOD_UAR_OBJ_DESTROY,
+       UVERBS_ATTR_IDR(MLX5_IB_ATTR_UAR_OBJ_DESTROY_HANDLE,
+                       MLX5_IB_OBJECT_UAR,
+                       UVERBS_ACCESS_DESTROY,
+                       UA_MANDATORY));
+
+DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_UAR,
+                           UVERBS_TYPE_ALLOC_IDR(mmap_obj_cleanup),
+                           &UVERBS_METHOD(MLX5_IB_METHOD_UAR_OBJ_ALLOC),
+                           &UVERBS_METHOD(MLX5_IB_METHOD_UAR_OBJ_DESTROY));
+
 static const struct uapi_definition mlx5_ib_defs[] = {
        UAPI_DEF_CHAIN(mlx5_ib_devx_defs),
+       UAPI_DEF_CHAIN_OBJ_TREE_NAMED(MLX5_IB_OBJECT_UAR),
        {}
 };
 
diff --git a/sys/dev/mlx5/mlx5_ifc.h b/sys/dev/mlx5/mlx5_ifc.h
index 3f75acd250da..0a3bb9b38568 100644
--- a/sys/dev/mlx5/mlx5_ifc.h
+++ b/sys/dev/mlx5/mlx5_ifc.h
@@ -7572,7 +7572,7 @@ struct mlx5_ifc_dealloc_uar_out_bits {
 
 struct mlx5_ifc_dealloc_uar_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         uid[0x10];
 
        u8         reserved_1[0x10];
        u8         op_mod[0x10];
@@ -8583,7 +8583,7 @@ struct mlx5_ifc_alloc_uar_out_bits {
 
 struct mlx5_ifc_alloc_uar_in_bits {
        u8         opcode[0x10];
-       u8         reserved_0[0x10];
+       u8         uid[0x10];
 
        u8         reserved_1[0x10];
        u8         op_mod[0x10];

Reply via email to