Added support for POE CQs. POE CQs will forward CQE directly to the corresponding POE channel.
In this case, the driver cannot update the QP CI, so hnsdv_update_sq_ci() is added to allow users to change the QP CI.
Signed-off-by: Chengchang Tang tangchengchang@huawei.com --- providers/hns/hns_roce_u.c | 11 ++-- providers/hns/hns_roce_u_hw_v2.c | 19 +++++++ providers/hns/hns_roce_u_verbs.c | 110 +++++++++++++++++++++++++++++++++++---- providers/hns/hnsdv.h | 22 ++++++++ providers/hns/libhns.map | 2 + 5 files changed, 150 insertions(+), 14 deletions(-)
diff --git a/providers/hns/hns_roce_u.c b/providers/hns/hns_roce_u.c index 1085b85..084385b 100644 --- a/providers/hns/hns_roce_u.c +++ b/providers/hns/hns_roce_u.c @@ -321,7 +321,8 @@ static void set_default_hw_id(struct hns_roce_context *context) }
static int query_dev_attr(struct hns_roce_context *context, - struct hns_roce_device *hr_dev) + struct hns_roce_device *hr_dev, + struct hns_roce_alloc_ucontext_resp *resp) { struct ibv_device_attr_ex attrx = {}; struct ibv_device_attr *dev_attrs = &attrx.orig_attr; @@ -339,6 +340,9 @@ static int query_dev_attr(struct hns_roce_context *context, context->max_srq_wr = dev_attrs->max_srq_wr; context->max_srq_sge = dev_attrs->max_srq_sge;
+ if (get_link_type(dev_attrs->vendor_part_id, &hr_dev->link_type)) + hr_dev->link_type = resp->mac_type; + return 0; }
@@ -390,12 +394,9 @@ static struct verbs_context *hns_roce_alloc_context(struct ibv_device *ibdev, for (i = 0; i < HNS_ROCE_SRQ_TABLE_SIZE; ++i) context->srq_table[i].refcnt = 0;
- if (query_dev_attr(context, hr_dev)) + if (query_dev_attr(context, hr_dev, &resp)) goto err_free;
- if (get_link_type(dev_attrs.vendor_part_id, &hr_dev->link_type)) - hr_dev->link_type = resp.mac_type; - if (init_dca_context(context, cmd_fd, &resp, ctx_attr, hr_dev->page_size)) goto err_free; diff --git a/providers/hns/hns_roce_u_hw_v2.c b/providers/hns/hns_roce_u_hw_v2.c index fbd02dc..688b760 100644 --- a/providers/hns/hns_roce_u_hw_v2.c +++ b/providers/hns/hns_roce_u_hw_v2.c @@ -1029,6 +1029,9 @@ static int hns_roce_u_v2_poll_cq(struct ibv_cq *ibvcq, int ne, int err = V2_CQ_OK; int npolled;
+ if (cq->flags & HNS_ROCE_CQ_FLAG_POE_EN) + return V2_CQ_POLL_ERR; + hns_roce_spin_lock(&cq->hr_lock);
if (unlikely(hns_roce_reseted(ctx))) { @@ -2202,6 +2205,9 @@ static int wc_start_poll_cq(struct ibv_cq_ex *current, if (attr->comp_mask) return EINVAL;
+ if (cq->flags & HNS_ROCE_CQ_FLAG_POE_EN) + return EOPNOTSUPP; + hns_roce_spin_lock(&cq->hr_lock);
if (unlikely(hns_roce_reseted(ctx))) { @@ -3119,6 +3125,19 @@ int hns_roce_attach_qp_ex_ops(struct ibv_qp_init_attr_ex *attr, return 0; }
+void hnsdv_update_sq_ci(struct ibv_qp *ibv_qp, uint32_t inc_cnt) +{ + struct hns_roce_qp *qp; + struct hns_roce_wq *wq; + + if (!ibv_qp) + return; + + qp = to_hr_qp(ibv_qp); + wq = &qp->sq; + wq->tail += inc_cnt & (wq->wqe_cnt - 1); +} + const struct hns_roce_u_hw hns_roce_u_hw_v2 = { .hw_version = HNS_ROCE_HW_VER2, .hw_ops = { diff --git a/providers/hns/hns_roce_u_verbs.c b/providers/hns/hns_roce_u_verbs.c index 5b86077..c7863d7 100644 --- a/providers/hns/hns_roce_u_verbs.c +++ b/providers/hns/hns_roce_u_verbs.c @@ -36,6 +36,7 @@ #include <math.h> #include <errno.h> #include <pthread.h> +#include <inttypes.h> #include <sys/mman.h> #include <ccan/ilog.h> #include <ccan/minmax.h> @@ -470,8 +471,40 @@ enum { IBV_WC_EX_WITH_CVLAN, };
+enum { + HNSDV_CQ_SUP_COMP_MASK = HNSDV_CQ_INIT_ATTR_MASK_CREATE_FLAGS, +}; + +enum { + HNSDV_CQ_SUP_CREATE_FLAGS = HNSDV_CQ_CREATE_ENABLE_POE_MODE, +}; + +static int verify_hnsdv_cq_create_attr(struct hns_roce_context *ctx, + struct hnsdv_cq_init_attr *hns_cq_attr) +{ + if (!hns_cq_attr) + return 0; + + if (!check_comp_mask(hns_cq_attr->comp_mask, HNSDV_CQ_SUP_COMP_MASK)) { + verbs_err(&ctx->ibv_ctx, "Unsupported cq comps 0x%"PRIu64"\n", + hns_cq_attr->comp_mask); + return EOPNOTSUPP; + } + + if ((hns_cq_attr->comp_mask & HNSDV_CQ_INIT_ATTR_MASK_CREATE_FLAGS) && + !check_comp_mask(hns_cq_attr->create_flags, + HNSDV_CQ_SUP_CREATE_FLAGS)) { + verbs_err(&ctx->ibv_ctx, "Unsupported cq flags 0x%"PRIu64"\n", + hns_cq_attr->create_flags); + return EOPNOTSUPP; + } + + return 0; +} + static int verify_cq_create_attr(struct ibv_cq_init_attr_ex *attr, - struct hns_roce_context *context) + struct hns_roce_context *context, + struct hnsdv_cq_init_attr *hns_cq_attr) { if (!attr->cqe || attr->cqe > context->max_cqe) return -EINVAL; @@ -495,7 +528,7 @@ static int verify_cq_create_attr(struct ibv_cq_init_attr_ex *attr, attr->cqe = max_t(uint32_t, HNS_ROCE_MIN_CQE_NUM, roundup_pow_of_two(attr->cqe));
- return 0; + return verify_hnsdv_cq_create_attr(context, hns_cq_attr); }
static int hns_roce_alloc_cq_buf(struct hns_roce_cq *cq) @@ -508,9 +541,34 @@ static int hns_roce_alloc_cq_buf(struct hns_roce_cq *cq) return 0; }
+static void set_hnsdv_cq_attr(struct hns_roce_ib_create_cq *cmd_drv, + struct hnsdv_cq_init_attr *hns_cq_attr) +{ + if (!hns_cq_attr) + return; + + if (hns_cq_attr->create_flags & HNSDV_CQ_CREATE_ENABLE_POE_MODE) { + cmd_drv->create_flags |= HNS_ROCE_CREATE_CQ_FLAGS_POE_MODE; + cmd_drv->poe_channel = hns_cq_attr->poe_channel; + } +} + +static int check_hnsdv_cq_flags(struct hnsdv_cq_init_attr *hns_cq_attr, + struct hns_roce_cq *cq) +{ + if (!hns_cq_attr) + return 0; + + if ((hns_cq_attr->create_flags & HNSDV_CQ_CREATE_ENABLE_POE_MODE) && + !(cq->flags & HNS_ROCE_CQ_FLAG_POE_EN)) + return EOPNOTSUPP; + return 0; +} + static int exec_cq_create_cmd(struct ibv_context *context, struct hns_roce_cq *cq, - struct ibv_cq_init_attr_ex *attr) + struct ibv_cq_init_attr_ex *attr, + struct hnsdv_cq_init_attr *hns_cq_attr) { struct hns_roce_create_cq_ex_resp resp_ex = {}; struct hns_roce_ib_create_cq_resp *resp_drv; @@ -525,6 +583,8 @@ static int exec_cq_create_cmd(struct ibv_context *context, cmd_drv->db_addr = (uintptr_t)cq->db; cmd_drv->cqe_size = (uintptr_t)cq->cqe_size;
+ set_hnsdv_cq_attr(cmd_drv, hns_cq_attr); + ret = ibv_cmd_create_cq_ex(context, attr, &cq->verbs_cq, &cmd_ex.ibv_cmd, sizeof(cmd_ex), &resp_ex.ibv_resp, sizeof(resp_ex), 0); @@ -534,7 +594,14 @@ static int exec_cq_create_cmd(struct ibv_context *context, cq->cqn = resp_drv->cqn; cq->flags = resp_drv->cap_flags;
- return 0; + ret = check_hnsdv_cq_flags(hns_cq_attr, cq); + if (ret) + goto flags_err; + return ret; + +flags_err: + ibv_cmd_destroy_cq(&cq->verbs_cq.cq); + return ret; }
static int hns_roce_init_cq_swc(struct hns_roce_cq *cq, @@ -581,13 +648,14 @@ static int hns_roce_cq_spinlock_init(struct ibv_context *context, }
static struct ibv_cq_ex *create_cq(struct ibv_context *context, - struct ibv_cq_init_attr_ex *attr) + struct ibv_cq_init_attr_ex *attr, + struct hnsdv_cq_init_attr *hns_cq_attr) { struct hns_roce_context *hr_ctx = to_hr_ctx(context); struct hns_roce_cq *cq; int ret;
- ret = verify_cq_create_attr(attr, hr_ctx); + ret = verify_cq_create_attr(attr, hr_ctx, hns_cq_attr); if (ret) goto err;
@@ -618,7 +686,7 @@ static struct ibv_cq_ex *create_cq(struct ibv_context *context, if (ret) goto err_swc;
- ret = exec_cq_create_cmd(context, cq, attr); + ret = exec_cq_create_cmd(context, cq, attr, hns_cq_attr); if (ret) goto err_cmd;
@@ -652,7 +720,7 @@ struct ibv_cq *hns_roce_u_create_cq(struct ibv_context *context, int cqe, .comp_vector = comp_vector, };
- cq = create_cq(context, &attr); + cq = create_cq(context, &attr, NULL); return cq ? ibv_cq_ex_to_cq(cq) : NULL; }
@@ -661,13 +729,37 @@ struct ibv_cq_ex *hns_roce_u_create_cq_ex(struct ibv_context *context, { struct ibv_cq_ex *cq;
- cq = create_cq(context, attr); + cq = create_cq(context, attr, NULL); if (cq) hns_roce_attach_cq_ex_ops(cq, attr->wc_flags);
return cq; }
+struct ibv_cq_ex *hnsdv_create_cq_ex(struct ibv_context *context, + struct ibv_cq_init_attr_ex *cq_attr, + struct hnsdv_cq_init_attr *hns_cq_attr) +{ + struct hns_roce_context *ctx = context ? to_hr_ctx(context) : NULL; + struct ibv_cq_ex *cq; + + if (!ctx || !cq_attr) { + errno = EINVAL; + return NULL; + } + + if (!is_hns_dev(context->device)) { + errno = EOPNOTSUPP; + return NULL; + } + + cq = create_cq(context, cq_attr, hns_cq_attr); + if (cq) + hns_roce_attach_cq_ex_ops(cq, cq_attr->wc_flags); + + return cq; +} + void hns_roce_u_cq_event(struct ibv_cq *cq) { to_hr_cq(cq)->arm_sn++; diff --git a/providers/hns/hnsdv.h b/providers/hns/hnsdv.h index 159edb8..c5c7c11 100644 --- a/providers/hns/hnsdv.h +++ b/providers/hns/hnsdv.h @@ -92,6 +92,28 @@ struct hnsdv_context { int hnsdv_query_device(struct ibv_context *ctx_in, struct hnsdv_context *attrs_out);
+enum hnsdv_cq_init_attr_mask { + HNSDV_CQ_INIT_ATTR_MASK_CREATE_FLAGS = 1 << 0, +}; + +enum hnsdv_cq_create_flags { + HNSDV_CQ_CREATE_ENABLE_POE_MODE = 1 << 0, +}; + +struct hnsdv_cq_init_attr { + uint64_t comp_mask; /* Use enum hnsdv_cq_init_attr_mask */ + uint64_t create_flags; /* Use enum hnsdv_cq_create_flags */ + uint8_t poe_channel; /* poe channel to use */ + uint8_t reserved[7]; +}; + +struct ibv_cq_ex *hnsdv_create_cq_ex(struct ibv_context *context, + struct ibv_cq_init_attr_ex *cq_attr, + struct hnsdv_cq_init_attr *hns_cq_attr); + +/* used in stars mode */ +void hnsdv_update_sq_ci(struct ibv_qp *qp, uint32_t inc_idx); + #ifdef __cplusplus } #endif diff --git a/providers/hns/libhns.map b/providers/hns/libhns.map index ebf28eb..27efc83 100644 --- a/providers/hns/libhns.map +++ b/providers/hns/libhns.map @@ -6,5 +6,7 @@ HNS_1.0 { hnsdv_open_device; hnsdv_create_qp; hnsdv_query_device; + hnsdv_create_cq_ex; + hnsdv_update_sq_ci; local: *; };