From 1234a9d8aebbf24a46ef5d323bf9074bc911423e Mon Sep 17 00:00:00 2001 From: Kalesh AP Date: Mon, 2 Mar 2026 16:30:33 +0530 Subject: [PATCH] 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 Signed-off-by: Sriharsha Basavapatna Signed-off-by: Kalesh AP Reviewed-by: Selvin Xavier Signed-off-by: Jason Gunthorpe --- drivers/infiniband/hw/bnxt_re/ib_verbs.h | 7 ++ drivers/infiniband/hw/bnxt_re/qplib_res.c | 43 +++++++ drivers/infiniband/hw/bnxt_re/qplib_res.h | 4 + drivers/infiniband/hw/bnxt_re/uapi.c | 130 ++++++++++++++++++++++ include/uapi/rdma/bnxt_re-abi.h | 29 +++++ 5 files changed, 213 insertions(+) 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__*/ -- 2.47.3