From: Junxian Huang huangjunxian6@hisilicon.com
driver inclusion category: bugfix bugzilla: https://gitee.com/src-openeuler/rdma-core/issues/I7A5YM
---------------------------------------------------------------
According to Annex17_RoCEv2 (A17.4.5.2), for RoCEv2 UD, a CQE should carry a flag that indicates if the received frame is an IPv4, IPv6 or RoCE packet. But currently, the values of the flag corresponding to these packet types haven't been defined yet in WC.
In UCX, 'sl' in ibv_wc for UD is used as the packet type flag, and the packet type values have already been defined in the UCX patch of https://github.com/openucx/ucx/commit/ed28845b88633e65d64fce8ec880060aa61bd5...
Therefore, to adapt UCX, add a create flag to hnsdv_create_qp() to allow users to choose whether they use 'sl' in ibv_wc as service level or packet type for UD. For the latter, obtain and translate the packet type from CQE and fill it to 'sl' in ibv_wc.
Signed-off-by: Junxian Huang huangjunxian6@hisilicon.com Signed-off-by: Haoyue Xu xuhaoyue1@hisilicon.com --- providers/hns/hns_roce_u.h | 11 +++++++++++ providers/hns/hns_roce_u_hw_v2.c | 32 +++++++++++++++++++++++++++++--- providers/hns/hns_roce_u_verbs.c | 16 ++++++++++++++++ providers/hns/hnsdv.h | 1 + 4 files changed, 57 insertions(+), 3 deletions(-)
diff --git a/providers/hns/hns_roce_u.h b/providers/hns/hns_roce_u.h index 41e9599..e3012e1 100644 --- a/providers/hns/hns_roce_u.h +++ b/providers/hns/hns_roce_u.h @@ -195,6 +195,12 @@ enum hns_roce_tc_map_mode { HNS_ROCE_TC_MAP_MODE_DSCP, };
+enum hns_roce_pktype { + HNS_ROCE_PKTYPE_ROCE_V1, + HNS_ROCE_PKTYPE_ROCE_V2_IPV6, + HNS_ROCE_PKTYPE_ROCE_V2_IPV4, +}; + struct hns_roce_db_page { struct hns_roce_db_page *prev, *next; struct hns_roce_buf buf; @@ -406,6 +412,11 @@ struct hns_roce_qp { void *cur_wqe; unsigned int rb_sq_head; /* roll back sq head */ struct hns_roce_sge_info sge_info; + + /* Just for UD. If not enabled, 'sl' in ibv_wc + * will be filled with 'port_type' in cqe. + */ + bool enable_ud_sl; };
struct hns_roce_av { diff --git a/providers/hns/hns_roce_u_hw_v2.c b/providers/hns/hns_roce_u_hw_v2.c index 4b0ec5c..ee2fffe 100644 --- a/providers/hns/hns_roce_u_hw_v2.c +++ b/providers/hns/hns_roce_u_hw_v2.c @@ -522,9 +522,24 @@ static void handle_recv_rq_inl(struct hns_roce_v2_cqe *cqe, handle_recv_inl_data(cqe, &(cur_qp->rq_rinl_buf), wr_num, wqe_buf); }
-static void parse_for_ud_qp(struct hns_roce_v2_cqe *cqe, struct ibv_wc *wc) +static const uint8_t pktype_for_ud[] = { + HNS_ROCE_PKTYPE_ROCE_V1, + HNS_ROCE_PKTYPE_ROCE_V2_IPV4, + HNS_ROCE_PKTYPE_ROCE_V2_IPV6 +}; + +static void parse_for_ud_qp(struct hns_roce_v2_cqe *cqe, struct ibv_wc *wc, + bool enable_ud_sl) { - wc->sl = hr_reg_read(cqe, CQE_SL); + uint8_t port_type; + + if (enable_ud_sl) { + wc->sl = hr_reg_read(cqe, CQE_SL); + } else { + port_type = hr_reg_read(cqe, CQE_PORT_TYPE); + wc->sl = pktype_for_ud[port_type]; + } + wc->src_qp = hr_reg_read(cqe, CQE_RMT_QPN); wc->slid = 0; wc->wc_flags |= hr_reg_read(cqe, CQE_GRH) ? IBV_WC_GRH : 0; @@ -554,7 +569,7 @@ static int parse_cqe_for_resp(struct hns_roce_v2_cqe *cqe, struct ibv_wc *wc, ++wq->tail;
if (hr_qp->verbs_qp.qp.qp_type == IBV_QPT_UD) - parse_for_ud_qp(cqe, wc); + parse_for_ud_qp(cqe, wc, hr_qp->enable_ud_sl);
if (hr_reg_read(cqe, CQE_CQE_INLINE)) handle_recv_cqe_inl_from_rq(cqe, hr_qp); @@ -2126,6 +2141,17 @@ static uint32_t wc_read_slid(struct ibv_cq_ex *current) static uint8_t wc_read_sl(struct ibv_cq_ex *current) { struct hns_roce_cq *cq = to_hr_cq(ibv_cq_ex_to_cq(current)); + struct hns_roce_context *ctx = to_hr_ctx(current->context); + struct hns_roce_qp *hr_qp; + uint8_t port_type; + uint32_t qpn; + + qpn = hr_reg_read(cq->cqe, CQE_LCL_QPN); + hr_qp = hns_roce_v2_find_qp(ctx, qpn); + if (hr_qp->verbs_qp.qp.qp_type == IBV_QPT_UD && !hr_qp->enable_ud_sl) { + port_type = hr_reg_read(cq->cqe, CQE_PORT_TYPE); + return pktype_for_ud[port_type]; + }
return (uint8_t)hr_reg_read(cq->cqe, CQE_SL); } diff --git a/providers/hns/hns_roce_u_verbs.c b/providers/hns/hns_roce_u_verbs.c index fa27fc1..4b641ea 100644 --- a/providers/hns/hns_roce_u_verbs.c +++ b/providers/hns/hns_roce_u_verbs.c @@ -1019,6 +1019,11 @@ static int check_qp_congest_type(struct hns_roce_context *ctx, return 0; }
+enum { + HNSDV_QP_SUP_CREATE_FLAGS = HNSDV_QP_CREATE_ENABLE_DCA_MODE | + HNSDV_QP_CREATE_ENABLE_UD_SL, +}; + static int check_hnsdv_qp_attr(struct hns_roce_context *ctx, struct hnsdv_qp_init_attr *hns_attr, struct hns_roce_cmd_flag *cmd_flag) @@ -1034,6 +1039,14 @@ static int check_hnsdv_qp_attr(struct hns_roce_context *ctx, return -EINVAL; }
+ if (hns_attr->comp_mask & HNSDV_QP_INIT_ATTR_MASK_QP_CREATE_FLAGS && + !check_comp_mask(hns_attr->create_flags, + HNSDV_QP_SUP_CREATE_FLAGS)) { + verbs_err(&ctx->ibv_ctx, "invalid create_flags 0x%x.\n", + hns_attr->create_flags); + return -EOPNOTSUPP; + } + ret = check_qp_congest_type(ctx, hns_attr, cmd_flag); if (ret) return ret; @@ -1685,6 +1698,9 @@ static struct ibv_qp *create_qp(struct ibv_context *ibv_ctx,
qp_setup_config(attr, qp, context);
+ if (hns_attr && hns_attr->create_flags & HNSDV_QP_CREATE_ENABLE_UD_SL) + qp->enable_ud_sl = true; + return &qp->verbs_qp.qp;
err_dwqe: diff --git a/providers/hns/hnsdv.h b/providers/hns/hnsdv.h index e15b428..365c314 100644 --- a/providers/hns/hnsdv.h +++ b/providers/hns/hnsdv.h @@ -43,6 +43,7 @@ struct ibv_context *hnsdv_open_device(struct ibv_device *device,
enum hnsdv_qp_create_flags { HNSDV_QP_CREATE_ENABLE_DCA_MODE = 1 << 0, + HNSDV_QP_CREATE_ENABLE_UD_SL = 1 << 1, };
enum hnsdv_qp_congest_ctrl_type { -- 2.30.0