]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
RDMA/bnxt_re: Support doorbell extensions
authorKalesh AP <kalesh-anakkur.purayil@broadcom.com>
Mon, 2 Mar 2026 11:00:33 +0000 (16:30 +0530)
committerJason Gunthorpe <jgg@nvidia.com>
Sun, 8 Mar 2026 10:20:25 +0000 (06:20 -0400)
Some applications may need multiple doorbells to support parallel
processing of threads that each operate on a group of resources.

The following uapi methods have been implemented in this patch.

- BNXT_RE_METHOD_DBR_ALLOC:
  This will allow the appliation to create extra doorbell regions
  and use the associated doorbell page index in CREATE_QP and
  use the associated DB address while ringing the doorbell.

- BNXT_RE_METHOD_DBR_FREE:
  Free the allocated doorbell region.

- BNXT_RE_METHOD_GET_DEFAULT_DBR:
  Return the default doorbell page index and doorbell page address
  associated with the ucontext.

Link: https://patch.msgid.link/r/20260302110036.36387-4-sriharsha.basavapatna@broadcom.com
Co-developed-by: Sriharsha Basavapatna <sriharsha.basavapatna@broadcom.com>
Signed-off-by: Sriharsha Basavapatna <sriharsha.basavapatna@broadcom.com>
Signed-off-by: Kalesh AP <kalesh-anakkur.purayil@broadcom.com>
Reviewed-by: Selvin Xavier <selvin.xavier@broadcom.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
drivers/infiniband/hw/bnxt_re/ib_verbs.h
drivers/infiniband/hw/bnxt_re/qplib_res.c
drivers/infiniband/hw/bnxt_re/qplib_res.h
drivers/infiniband/hw/bnxt_re/uapi.c
include/uapi/rdma/bnxt_re-abi.h

index a11f56730a31c5b8cabd90df2ae3ba760c65b8d1..33e0f66b39eb6d923b9791472fd2d976781ecc7e 100644 (file)
@@ -164,6 +164,13 @@ struct bnxt_re_user_mmap_entry {
        u8 mmap_flag;
 };
 
+struct bnxt_re_dbr_obj {
+       struct bnxt_re_dev *rdev;
+       struct bnxt_qplib_dpi dpi;
+       struct bnxt_re_user_mmap_entry *entry;
+       atomic_t usecnt; /* QPs using this dbr */
+};
+
 struct bnxt_re_flow {
        struct ib_flow          ib_flow;
        struct bnxt_re_dev      *rdev;
index fa6b8cd137e5c6d84371a0c306aff58be75c30b8..95e0489c53c37194f0e9388c26a40ffec763e9bf 100644 (file)
@@ -683,6 +683,49 @@ static int bnxt_qplib_alloc_pd_tbl(struct bnxt_qplib_res *res,
 }
 
 /* DPIs */
+int bnxt_qplib_alloc_uc_dpi(struct bnxt_qplib_res *res, struct bnxt_qplib_dpi *dpi)
+{
+       struct bnxt_qplib_dpi_tbl *dpit = &res->dpi_tbl;
+       struct bnxt_qplib_reg_desc *reg;
+       u32 bit_num;
+       int rc = 0;
+
+       reg = &dpit->wcreg;
+       mutex_lock(&res->dpi_tbl_lock);
+       bit_num = find_first_bit(dpit->tbl, dpit->max);
+       if (bit_num >= dpit->max) {
+               rc = -ENOMEM;
+               goto unlock;
+       }
+       /* Found unused DPI */
+       clear_bit(bit_num, dpit->tbl);
+       dpi->bit = bit_num;
+       dpi->dpi = bit_num + (reg->offset - dpit->ucreg.offset) / PAGE_SIZE;
+       dpi->umdbr = reg->bar_base + reg->offset + bit_num * PAGE_SIZE;
+unlock:
+       mutex_unlock(&res->dpi_tbl_lock);
+       return rc;
+}
+
+int bnxt_qplib_free_uc_dpi(struct bnxt_qplib_res *res, struct bnxt_qplib_dpi *dpi)
+{
+       struct bnxt_qplib_dpi_tbl *dpit = &res->dpi_tbl;
+       int rc = 0;
+
+       mutex_lock(&res->dpi_tbl_lock);
+       if (dpi->bit >= dpit->max) {
+               rc = -EINVAL;
+               goto unlock;
+       }
+
+       if (test_and_set_bit(dpi->bit, dpit->tbl))
+               rc = -EINVAL;
+       memset(dpi, 0, sizeof(*dpi));
+unlock:
+       mutex_unlock(&res->dpi_tbl_lock);
+       return rc;
+}
+
 int bnxt_qplib_alloc_dpi(struct bnxt_qplib_res *res,
                         struct bnxt_qplib_dpi *dpi,
                         void *app, u8 type)
index f01c1bb1fcb467dfd0dfff2adba6857b26e78c38..ffe31c952d50f145868ff0b01f2130825a1cd145 100644 (file)
@@ -436,6 +436,10 @@ int bnxt_qplib_alloc_dpi(struct bnxt_qplib_res *res,
                         void *app, u8 type);
 int bnxt_qplib_dealloc_dpi(struct bnxt_qplib_res *res,
                           struct bnxt_qplib_dpi *dpi);
+int bnxt_qplib_alloc_uc_dpi(struct bnxt_qplib_res *res,
+                           struct bnxt_qplib_dpi *dpi);
+int bnxt_qplib_free_uc_dpi(struct bnxt_qplib_res *res,
+                          struct bnxt_qplib_dpi *dpi);
 void bnxt_qplib_cleanup_res(struct bnxt_qplib_res *res);
 int bnxt_qplib_init_res(struct bnxt_qplib_res *res);
 void bnxt_qplib_free_res(struct bnxt_qplib_res *res);
index 0145882e49f6ed28134e76bc5ff142f1877e77cf..3eaee7101615bf078c9b82dd88503f02410a8558 100644 (file)
@@ -331,9 +331,139 @@ DECLARE_UVERBS_NAMED_OBJECT(BNXT_RE_OBJECT_GET_TOGGLE_MEM,
                            &UVERBS_METHOD(BNXT_RE_METHOD_GET_TOGGLE_MEM),
                            &UVERBS_METHOD(BNXT_RE_METHOD_RELEASE_TOGGLE_MEM));
 
+static int UVERBS_HANDLER(BNXT_RE_METHOD_DBR_ALLOC)(struct uverbs_attr_bundle *attrs)
+{
+       struct bnxt_re_db_region dbr = {};
+       struct bnxt_re_ucontext *uctx;
+       struct bnxt_re_dbr_obj *obj;
+       struct ib_ucontext *ib_uctx;
+       struct bnxt_qplib_dpi *dpi;
+       struct bnxt_re_dev *rdev;
+       struct ib_uobject *uobj;
+       u64 mmap_offset;
+       int ret;
+
+       ib_uctx = ib_uverbs_get_ucontext(attrs);
+       if (IS_ERR(ib_uctx))
+               return PTR_ERR(ib_uctx);
+
+       uctx = container_of(ib_uctx, struct bnxt_re_ucontext, ib_uctx);
+       rdev = uctx->rdev;
+       uobj = uverbs_attr_get_uobject(attrs, BNXT_RE_ALLOC_DBR_HANDLE);
+
+       obj = kzalloc_obj(*obj);
+       if (!obj)
+               return -ENOMEM;
+
+       dpi = &obj->dpi;
+       ret = bnxt_qplib_alloc_uc_dpi(&rdev->qplib_res, dpi);
+       if (ret)
+               goto free_mem;
+
+       obj->entry = bnxt_re_mmap_entry_insert(uctx, dpi->umdbr,
+                                              BNXT_RE_MMAP_UC_DB,
+                                              &mmap_offset);
+       if (!obj->entry) {
+               ret = -ENOMEM;
+               goto free_dpi;
+       }
+
+       obj->rdev = rdev;
+       uobj->object = obj;
+       uverbs_finalize_uobj_create(attrs, BNXT_RE_ALLOC_DBR_HANDLE);
+
+       dbr.umdbr = dpi->umdbr;
+       dbr.dpi = dpi->dpi;
+       ret = uverbs_copy_to_struct_or_zero(attrs, BNXT_RE_ALLOC_DBR_ATTR,
+                                           &dbr, sizeof(dbr));
+       if (ret)
+               return ret;
+
+       ret = uverbs_copy_to(attrs, BNXT_RE_ALLOC_DBR_OFFSET,
+                            &mmap_offset, sizeof(mmap_offset));
+       if (ret)
+               return ret;
+       return 0;
+free_dpi:
+       bnxt_qplib_free_uc_dpi(&rdev->qplib_res, dpi);
+free_mem:
+       kfree(obj);
+       return ret;
+}
+
+static int bnxt_re_dbr_cleanup(struct ib_uobject *uobject,
+                              enum rdma_remove_reason why,
+                              struct uverbs_attr_bundle *attrs)
+{
+       struct bnxt_re_dbr_obj *obj = uobject->object;
+       struct bnxt_re_dev *rdev = obj->rdev;
+
+       rdma_user_mmap_entry_remove(&obj->entry->rdma_entry);
+       bnxt_qplib_free_uc_dpi(&rdev->qplib_res, &obj->dpi);
+       return 0;
+}
+
+static int UVERBS_HANDLER(BNXT_RE_METHOD_GET_DEFAULT_DBR)(struct uverbs_attr_bundle *attrs)
+{
+       struct bnxt_re_db_region dpi = {};
+       struct bnxt_re_ucontext *uctx;
+       struct ib_ucontext *ib_uctx;
+       int ret;
+
+       ib_uctx = ib_uverbs_get_ucontext(attrs);
+       if (IS_ERR(ib_uctx))
+               return PTR_ERR(ib_uctx);
+
+       uctx = container_of(ib_uctx, struct bnxt_re_ucontext, ib_uctx);
+       dpi.umdbr = uctx->dpi.umdbr;
+       dpi.dpi = uctx->dpi.dpi;
+
+       ret = uverbs_copy_to_struct_or_zero(attrs, BNXT_RE_DEFAULT_DBR_ATTR,
+                                           &dpi, sizeof(dpi));
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
+DECLARE_UVERBS_NAMED_METHOD(BNXT_RE_METHOD_DBR_ALLOC,
+                           UVERBS_ATTR_IDR(BNXT_RE_ALLOC_DBR_HANDLE,
+                                           BNXT_RE_OBJECT_DBR,
+                                           UVERBS_ACCESS_NEW,
+                                           UA_MANDATORY),
+                           UVERBS_ATTR_PTR_OUT(BNXT_RE_ALLOC_DBR_ATTR,
+                                               UVERBS_ATTR_STRUCT(struct bnxt_re_db_region,
+                                                                  umdbr),
+                                                                  UA_MANDATORY),
+                           UVERBS_ATTR_PTR_OUT(BNXT_RE_ALLOC_DBR_OFFSET,
+                                               UVERBS_ATTR_TYPE(u64),
+                                               UA_MANDATORY));
+
+DECLARE_UVERBS_NAMED_METHOD_DESTROY(BNXT_RE_METHOD_DBR_FREE,
+                                   UVERBS_ATTR_IDR(BNXT_RE_FREE_DBR_HANDLE,
+                                                   BNXT_RE_OBJECT_DBR,
+                                                   UVERBS_ACCESS_DESTROY,
+                                                   UA_MANDATORY));
+
+DECLARE_UVERBS_NAMED_OBJECT(BNXT_RE_OBJECT_DBR,
+                           UVERBS_TYPE_ALLOC_IDR(bnxt_re_dbr_cleanup),
+                           &UVERBS_METHOD(BNXT_RE_METHOD_DBR_ALLOC),
+                           &UVERBS_METHOD(BNXT_RE_METHOD_DBR_FREE));
+
+DECLARE_UVERBS_NAMED_METHOD(BNXT_RE_METHOD_GET_DEFAULT_DBR,
+                           UVERBS_ATTR_PTR_OUT(BNXT_RE_DEFAULT_DBR_ATTR,
+                                               UVERBS_ATTR_STRUCT(struct bnxt_re_db_region,
+                                                                  umdbr),
+                                               UA_MANDATORY));
+
+DECLARE_UVERBS_GLOBAL_METHODS(BNXT_RE_OBJECT_DEFAULT_DBR,
+                             &UVERBS_METHOD(BNXT_RE_METHOD_GET_DEFAULT_DBR));
+
 const struct uapi_definition bnxt_re_uapi_defs[] = {
        UAPI_DEF_CHAIN_OBJ_TREE_NAMED(BNXT_RE_OBJECT_ALLOC_PAGE),
        UAPI_DEF_CHAIN_OBJ_TREE_NAMED(BNXT_RE_OBJECT_NOTIFY_DRV),
        UAPI_DEF_CHAIN_OBJ_TREE_NAMED(BNXT_RE_OBJECT_GET_TOGGLE_MEM),
+       UAPI_DEF_CHAIN_OBJ_TREE_NAMED(BNXT_RE_OBJECT_DBR),
+       UAPI_DEF_CHAIN_OBJ_TREE_NAMED(BNXT_RE_OBJECT_DEFAULT_DBR),
        {}
 };
index f24edf1c75eb366c07183fe18814c9a5ae812afd..ef14e24836b12e23eb59668d6a5532c6c700143f 100644 (file)
@@ -163,6 +163,8 @@ enum bnxt_re_objects {
        BNXT_RE_OBJECT_ALLOC_PAGE = (1U << UVERBS_ID_NS_SHIFT),
        BNXT_RE_OBJECT_NOTIFY_DRV,
        BNXT_RE_OBJECT_GET_TOGGLE_MEM,
+       BNXT_RE_OBJECT_DBR,
+       BNXT_RE_OBJECT_DEFAULT_DBR,
 };
 
 enum bnxt_re_alloc_page_type {
@@ -231,4 +233,31 @@ struct bnxt_re_packet_pacing_caps {
 struct bnxt_re_query_device_ex_resp {
        struct bnxt_re_packet_pacing_caps packet_pacing_caps;
 };
+
+struct bnxt_re_db_region {
+       __u32 dpi;
+       __u32 reserved;
+       __aligned_u64 umdbr;
+};
+
+enum bnxt_re_obj_dbr_alloc_attrs {
+       BNXT_RE_ALLOC_DBR_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
+       BNXT_RE_ALLOC_DBR_ATTR,
+       BNXT_RE_ALLOC_DBR_OFFSET,
+};
+
+enum bnxt_re_obj_dbr_free_attrs {
+       BNXT_RE_FREE_DBR_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
+};
+
+enum bnxt_re_obj_default_dbr_attrs {
+       BNXT_RE_DEFAULT_DBR_ATTR = (1U << UVERBS_ID_NS_SHIFT),
+};
+
+enum bnxt_re_obj_dpi_methods {
+       BNXT_RE_METHOD_DBR_ALLOC = (1U << UVERBS_ID_NS_SHIFT),
+       BNXT_RE_METHOD_DBR_FREE,
+       BNXT_RE_METHOD_GET_DEFAULT_DBR,
+};
+
 #endif /* __BNXT_RE_UVERBS_ABI_H__*/