mirror of
https://github.com/torvalds/linux.git
synced 2026-09-23 05:04:02 +02: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:
parent
13f9a813ee
commit
1234a9d8ae
|
|
@ -164,6 +164,13 @@ struct bnxt_re_user_mmap_entry {
|
||||||
u8 mmap_flag;
|
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 bnxt_re_flow {
|
||||||
struct ib_flow ib_flow;
|
struct ib_flow ib_flow;
|
||||||
struct bnxt_re_dev *rdev;
|
struct bnxt_re_dev *rdev;
|
||||||
|
|
|
||||||
|
|
@ -683,6 +683,49 @@ static int bnxt_qplib_alloc_pd_tbl(struct bnxt_qplib_res *res,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* DPIs */
|
/* 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,
|
int bnxt_qplib_alloc_dpi(struct bnxt_qplib_res *res,
|
||||||
struct bnxt_qplib_dpi *dpi,
|
struct bnxt_qplib_dpi *dpi,
|
||||||
void *app, u8 type)
|
void *app, u8 type)
|
||||||
|
|
|
||||||
|
|
@ -436,6 +436,10 @@ int bnxt_qplib_alloc_dpi(struct bnxt_qplib_res *res,
|
||||||
void *app, u8 type);
|
void *app, u8 type);
|
||||||
int bnxt_qplib_dealloc_dpi(struct bnxt_qplib_res *res,
|
int bnxt_qplib_dealloc_dpi(struct bnxt_qplib_res *res,
|
||||||
struct bnxt_qplib_dpi *dpi);
|
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);
|
void bnxt_qplib_cleanup_res(struct bnxt_qplib_res *res);
|
||||||
int bnxt_qplib_init_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);
|
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_GET_TOGGLE_MEM),
|
||||||
&UVERBS_METHOD(BNXT_RE_METHOD_RELEASE_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[] = {
|
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_ALLOC_PAGE),
|
||||||
UAPI_DEF_CHAIN_OBJ_TREE_NAMED(BNXT_RE_OBJECT_NOTIFY_DRV),
|
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_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_ALLOC_PAGE = (1U << UVERBS_ID_NS_SHIFT),
|
||||||
BNXT_RE_OBJECT_NOTIFY_DRV,
|
BNXT_RE_OBJECT_NOTIFY_DRV,
|
||||||
BNXT_RE_OBJECT_GET_TOGGLE_MEM,
|
BNXT_RE_OBJECT_GET_TOGGLE_MEM,
|
||||||
|
BNXT_RE_OBJECT_DBR,
|
||||||
|
BNXT_RE_OBJECT_DEFAULT_DBR,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum bnxt_re_alloc_page_type {
|
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_query_device_ex_resp {
|
||||||
struct bnxt_re_packet_pacing_caps packet_pacing_caps;
|
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__*/
|
#endif /* __BNXT_RE_UVERBS_ABI_H__*/
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user