mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-16 05:31:37 -04:00
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:
committed by
Jason Gunthorpe
parent
13f9a813ee
commit
1234a9d8ae
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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),
|
||||
{}
|
||||
};
|
||||
|
||||
@@ -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__*/
|
||||
|
||||
Reference in New Issue
Block a user