summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKalesh AP <kalesh-anakkur.purayil@broadcom.com>2026-03-02 14:00:33 +0300
committerJason Gunthorpe <jgg@nvidia.com>2026-03-08 13:20:25 +0300
commit1234a9d8aebbf24a46ef5d323bf9074bc911423e (patch)
treefad6e1cbe978ca3628f5e963b62b8da058f16ff1
parent13f9a813eee5836e92b83fd41dc09ef8c4aee92d (diff)
downloadlinux-1234a9d8aebbf24a46ef5d323bf9074bc911423e.tar.xz
RDMA/bnxt_re: Support doorbell extensions
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>
-rw-r--r--drivers/infiniband/hw/bnxt_re/ib_verbs.h7
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_res.c43
-rw-r--r--drivers/infiniband/hw/bnxt_re/qplib_res.h4
-rw-r--r--drivers/infiniband/hw/bnxt_re/uapi.c130
-rw-r--r--include/uapi/rdma/bnxt_re-abi.h29
5 files changed, 213 insertions, 0 deletions
diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.h b/drivers/infiniband/hw/bnxt_re/ib_verbs.h
index a11f56730a31..33e0f66b39eb 100644
--- a/drivers/infiniband/hw/bnxt_re/ib_verbs.h
+++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.h
@@ -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;
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_res.c b/drivers/infiniband/hw/bnxt_re/qplib_res.c
index fa6b8cd137e5..95e0489c53c3 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_res.c
+++ b/drivers/infiniband/hw/bnxt_re/qplib_res.c
@@ -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)
diff --git a/drivers/infiniband/hw/bnxt_re/qplib_res.h b/drivers/infiniband/hw/bnxt_re/qplib_res.h
index f01c1bb1fcb4..ffe31c952d50 100644
--- a/drivers/infiniband/hw/bnxt_re/qplib_res.h
+++ b/drivers/infiniband/hw/bnxt_re/qplib_res.h
@@ -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);
diff --git a/drivers/infiniband/hw/bnxt_re/uapi.c b/drivers/infiniband/hw/bnxt_re/uapi.c
index 0145882e49f6..3eaee7101615 100644
--- a/drivers/infiniband/hw/bnxt_re/uapi.c
+++ b/drivers/infiniband/hw/bnxt_re/uapi.c
@@ -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),
{}
};
diff --git a/include/uapi/rdma/bnxt_re-abi.h b/include/uapi/rdma/bnxt_re-abi.h
index f24edf1c75eb..ef14e24836b1 100644
--- a/include/uapi/rdma/bnxt_re-abi.h
+++ b/include/uapi/rdma/bnxt_re-abi.h
@@ -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__*/