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>
This commit is contained in:
Kalesh AP
2026-03-02 16:30:33 +05:30
committed by Jason Gunthorpe
parent 13f9a813ee
commit 1234a9d8ae
5 changed files with 213 additions and 0 deletions

View 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;

View 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)

View 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);

View 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),
{}
};

View 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__*/