[PATCH for-next 2/4] RDMA/bnxt_re: Prepare infrastructure for larger pages for Queue memory
Selvin Xavier <[email protected]>
| Newsgroups | org.kernel.vger.linux-rdma |
|---|---|
| Message-ID | <[email protected]> |
Add page-shift/FWO helpers, firmware capability detection (dev_cap_ext_flags_1), and the fwo_offset field so CQ/QP setup can be done with page sizes more than 4K. This also enables using PBL pages of size more than 4k. Currently, the PBLs are defaulted to 4K pages. Also, update the variable type that holds the max queue entry per page to accommodate more number of pages when huge pages are used. Signed-off-by: Saravanan Vajravel <[email protected]> Signed-off-by: Selvin Xavier <[email protected]> --- drivers/infiniband/hw/bnxt_re/ib_verbs.c | 41 ++++++++++++++++++++--- drivers/infiniband/hw/bnxt_re/qplib_res.c | 21 ++++++++++++ drivers/infiniband/hw/bnxt_re/qplib_res.h | 34 +++++++++++++++++-- drivers/infiniband/hw/bnxt_re/qplib_sp.c | 3 ++ drivers/infiniband/hw/bnxt_re/qplib_sp.h | 2 ++ drivers/infiniband/hw/bnxt_re/roce_hsi.h | 4 ++- 6 files changed, 98 insertions(+), 7 deletions(-) diff --git a/drivers/infiniband/hw/bnxt_re/ib_verbs.c b/drivers/infiniband/hw/bnxt_re/ib_verbs.c index 21caf34a1dc8..430d54f8f736 100644 --- a/drivers/infiniband/hw/bnxt_re/ib_verbs.c +++ b/drivers/infiniband/hw/bnxt_re/ib_verbs.c @@ -1141,23 +1141,42 @@ static int bnxt_re_setup_swqe_size(struct bnxt_re_qp *qp, return 0; } +static int bnxt_re_get_page_shift(struct ib_umem *umem, u64 va, u64 cmask) +{ + unsigned long pgsz; + + pgsz = ib_umem_find_best_pgsz(umem, cmask, va); + if (!pgsz) + return -EINVAL; + return __ffs(pgsz); +} + static int bnxt_re_setup_sginfo(struct bnxt_re_dev *rdev, struct ib_umem *umem, struct bnxt_qplib_sg_info *sginfo) { + struct bnxt_qplib_dev_attr *dev_attr = rdev->dev_attr; unsigned long page_size; + int page_shift; if (!umem) return -EINVAL; - page_size = ib_umem_find_best_pgsz(umem, SZ_4K, 0); - if (!page_size || page_size != SZ_4K) - return -EINVAL; + if (bnxt_re_pbl_size_supported(dev_attr->dev_cap_ext_flags_1)) { + page_shift = bnxt_re_get_page_shift(umem, umem->address, dev_attr->page_size_cap); + if (page_shift < 0) + return page_shift; + } else { + page_shift = __builtin_ctz(SZ_4K); + } + page_size = BIT(page_shift); sginfo->umem = umem; sginfo->npages = ib_umem_num_dma_blocks(umem, page_size); sginfo->pgsize = page_size; - sginfo->pgshft = __builtin_ctz(page_size); + sginfo->pgshft = page_shift; + sginfo->fwo_offset = ib_umem_dma_offset(umem, page_size); + return 0; } @@ -1224,6 +1243,15 @@ static int bnxt_re_init_user_qp(struct bnxt_re_dev *rdev, struct bnxt_re_pd *pd, if (rc) goto fail; + /* + * The FWO field passed in the CREATE_QP command is expressed in 4K + * units, so the offset must be a multiple of 4K. + */ + if (qplib_qp->sq.sg_info.fwo_offset & (SZ_4K - 1)) { + rc = -EINVAL; + goto fail; + } + if (qp->qplib_qp.srq) goto done; @@ -1242,6 +1270,11 @@ static int bnxt_re_init_user_qp(struct bnxt_re_dev *rdev, struct bnxt_re_pd *pd, if (rc) goto rqfail; + if (qplib_qp->rq.sg_info.fwo_offset & (SZ_4K - 1)) { + rc = -EINVAL; + goto rqfail; + } + done: if (dbr_obj) qplib_qp->dpi = &dbr_obj->dpi; diff --git a/drivers/infiniband/hw/bnxt_re/qplib_res.c b/drivers/infiniband/hw/bnxt_re/qplib_res.c index 756f8b5f042a..9a980f561661 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_res.c +++ b/drivers/infiniband/hw/bnxt_re/qplib_res.c @@ -174,6 +174,25 @@ void bnxt_qplib_free_hwq(struct bnxt_qplib_res *res, /* All HWQs are power of 2 in size */ +/* + * At PBL_LVL_0 there is a single PBL entry and firmware uses it as the + * literal queue base address rather than walking an indirection table, + * so it never applies the FWO field for this level. Adjust fwo_offset + * directly into that entry's DMA address instead. + */ +static void bnxt_qplib_adjust_lvl0_fwo(struct bnxt_qplib_hwq *hwq, + struct bnxt_qplib_hwq_attr *hwq_attr) +{ + struct bnxt_qplib_pbl *pbl; + + if (!hwq->is_user) + return; + + pbl = &hwq->pbl[PBL_LVL_0]; + pbl->pg_map_arr[0] += hwq_attr->sginfo->fwo_offset; + hwq_attr->sginfo->fwo_offset = 0; +} + int bnxt_qplib_alloc_init_hwq(struct bnxt_qplib_hwq *hwq, struct bnxt_qplib_hwq_attr *hwq_attr) { @@ -220,6 +239,8 @@ int bnxt_qplib_alloc_init_hwq(struct bnxt_qplib_hwq *hwq, if (rc) goto fail; hwq->level = PBL_LVL_0; + if (hwq_attr->type == HWQ_TYPE_QUEUE) + bnxt_qplib_adjust_lvl0_fwo(hwq, hwq_attr); goto done; } diff --git a/drivers/infiniband/hw/bnxt_re/qplib_res.h b/drivers/infiniband/hw/bnxt_re/qplib_res.h index b925db796729..ce6823af167e 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_res.h +++ b/drivers/infiniband/hw/bnxt_re/qplib_res.h @@ -166,6 +166,8 @@ struct bnxt_qplib_sg_info { u32 npages; u32 pgshft; u32 pgsize; +#define BNXT_QPLIB_QP_FWO_SHIFT 12 /* FWO is conveyed to firmware in 4K units */ + u32 fwo_offset; /* first-word offset into huge page */ bool nopte; }; @@ -192,7 +194,7 @@ struct bnxt_qplib_hwq { u32 max_elements; u32 depth; u16 element_size; /* Size of each entry */ - u16 qe_ppg; /* queue entry per page */ + u32 qe_ppg; /* queue entry per page */ u32 prod; /* raw */ u32 cons; /* raw */ @@ -369,7 +371,7 @@ static inline u8 bnxt_qplib_base_pg_size(struct bnxt_qplib_hwq *hwq) u8 pg_size = BNXT_QPLIB_HWRM_PG_SIZE_4K; struct bnxt_qplib_pbl *pbl; - pbl = &hwq->pbl[PBL_LVL_0]; + pbl = &hwq->pbl[hwq->level]; switch (pbl->pg_size) { case ROCE_PG_SIZE_4K: pg_size = BNXT_QPLIB_HWRM_PG_SIZE_4K; @@ -639,4 +641,32 @@ static inline bool _is_modify_qp_rate_limit_supported(u16 dev_cap_ext_flags2) CREQ_QUERY_FUNC_RESP_SB_MODIFY_QP_RATE_LIMIT_SUPPORTED; } +/* PBL page size encoding values for HWRM commands */ +#define BNXT_QPLIB_HWRM_PBL_PG_SIZE_PG_4K 0x0UL +#define BNXT_QPLIB_HWRM_PBL_PG_SIZE_PG_8K 0x1UL +#define BNXT_QPLIB_HWRM_PBL_PG_SIZE_PG_64K 0x2UL +#define BNXT_QPLIB_HWRM_PBL_PG_SIZE_PG_2M 0x3UL +#define BNXT_QPLIB_HWRM_PBL_PG_SIZE_PG_8M 0x4UL +#define BNXT_QPLIB_HWRM_PBL_PG_SIZE_PG_1G 0x5UL + +/** + * bnxt_re_pbl_size_supported - check if firmware supports non-4K PBL pages + * @dev_cap_ext_flags_1: value of the dev_cap_ext_flags_1 field from QUERY_FUNC response + * + * Returns non-zero if the firmware can accept PBL pages larger than 4K. + */ +static inline int bnxt_re_pbl_size_supported(u8 dev_cap_ext_flags_1) +{ + return dev_cap_ext_flags_1 & + CREQ_QUERY_FUNC_RESP_SB_PBL_PAGE_SIZE_SUPPORTED; +} + +static inline u8 bnxt_qplib_get_pbl_page_size(struct bnxt_qplib_sg_info *sginfo) +{ + /* Only 4K PBL pages are supported for now; extend this when QP/CQ + * PBLs start using the larger page sizes sginfo can report. + */ + return BNXT_QPLIB_HWRM_PBL_PG_SIZE_PG_4K; +} + #endif /* __BNXT_QPLIB_RES_H__ */ diff --git a/drivers/infiniband/hw/bnxt_re/qplib_sp.c b/drivers/infiniband/hw/bnxt_re/qplib_sp.c index 71240f7be9e6..5fa78f156df3 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_sp.c +++ b/drivers/infiniband/hw/bnxt_re/qplib_sp.c @@ -176,8 +176,11 @@ int bnxt_qplib_get_dev_attr(struct bnxt_qplib_rcfw *rcfw) attr->max_sgid = min_t(u32, BNXT_QPLIB_NUM_GIDS_SUPPORTED, 2 * attr->max_sgid); attr->dev_cap_flags = le16_to_cpu(sb->dev_cap_flags); attr->dev_cap_flags2 = le16_to_cpu(sb->dev_cap_ext_flags_2); + attr->dev_cap_ext_flags_1 = sb->dev_cap_ext_flags_1; attr->mr_page_size_cap = BIT_ULL(28) | BIT_ULL(21) | BIT_ULL(16) | BIT_ULL(12); + /* For Queue memories */ + attr->page_size_cap = BIT_ULL(21) | BIT_ULL(16) | BIT_ULL(13) | BIT_ULL(12); if (_is_max_srq_ext_supported(attr->dev_cap_flags2)) attr->max_srq += le16_to_cpu(sb->max_srq_ext); diff --git a/drivers/infiniband/hw/bnxt_re/qplib_sp.h b/drivers/infiniband/hw/bnxt_re/qplib_sp.h index b16e12d3b7ab..5d2a5b905405 100644 --- a/drivers/infiniband/hw/bnxt_re/qplib_sp.h +++ b/drivers/infiniband/hw/bnxt_re/qplib_sp.h @@ -79,6 +79,8 @@ struct bnxt_qplib_dev_attr { u32 max_dpi; u16 rate_limit_min; u32 rate_limit_max; + u8 dev_cap_ext_flags_1; + u64 page_size_cap; }; struct bnxt_qplib_pd { diff --git a/drivers/infiniband/hw/bnxt_re/roce_hsi.h b/drivers/infiniband/hw/bnxt_re/roce_hsi.h index aac338f2afd8..c89fc54f61c3 100644 --- a/drivers/infiniband/hw/bnxt_re/roce_hsi.h +++ b/drivers/infiniband/hw/bnxt_re/roce_hsi.h @@ -2244,7 +2244,9 @@ struct creq_query_func_resp_sb { __le16 max_inline_data_var_wqe; __le32 start_qid; u8 max_msn_table_size; - u8 reserved8_1; + u8 dev_cap_ext_flags_1; + #define CREQ_QUERY_FUNC_RESP_SB_PBL_PAGE_SIZE_SUPPORTED 0x1UL + #define CREQ_QUERY_FUNC_RESP_SB_WQE_INLINE_OPTIMIZER_SUPPORTED 0x20UL __le16 dev_cap_ext_flags_2; #define CREQ_QUERY_FUNC_RESP_SB_OPTIMIZE_MODIFY_QP_SUPPORTED 0x1UL #define CREQ_QUERY_FUNC_RESP_SB_CHANGE_UDP_SRC_PORT_WQE_SUPPORTED 0x2UL -- 2.39.3