Skip to content

Commit 999a0a2

Browse files
201608ybsrleon
authored andcommitted
RDMA/erdma: Support UD QPs and UD WRs
The iWARP protocol supports only RC QPs previously. Now we add UD QPs and UD WRs support for the RoCEv2 protocol. Signed-off-by: Boshi Yu <boshiyu@linux.alibaba.com> Link: https://patch.msgid.link/20241211020930.68833-9-boshiyu@linux.alibaba.com Reviewed-by: Cheng Xu <chengyou@linux.alibaba.com> Signed-off-by: Leon Romanovsky <leon@kernel.org>
1 parent 1cccbd3 commit 999a0a2

File tree

4 files changed

+136
-21
lines changed

4 files changed

+136
-21
lines changed

drivers/infiniband/hw/erdma/erdma_cq.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,22 @@ static const struct {
105105
{ ERDMA_WC_RETRY_EXC_ERR, IB_WC_RETRY_EXC_ERR, ERDMA_WC_VENDOR_NO_ERR },
106106
};
107107

108+
static void erdma_process_ud_cqe(struct erdma_cqe *cqe, struct ib_wc *wc)
109+
{
110+
u32 ud_info;
111+
112+
wc->wc_flags |= (IB_WC_GRH | IB_WC_WITH_NETWORK_HDR_TYPE);
113+
ud_info = be32_to_cpu(cqe->ud.info);
114+
wc->network_hdr_type = FIELD_GET(ERDMA_CQE_NTYPE_MASK, ud_info);
115+
if (wc->network_hdr_type == ERDMA_NETWORK_TYPE_IPV4)
116+
wc->network_hdr_type = RDMA_NETWORK_IPV4;
117+
else
118+
wc->network_hdr_type = RDMA_NETWORK_IPV6;
119+
wc->src_qp = FIELD_GET(ERDMA_CQE_SQPN_MASK, ud_info);
120+
wc->sl = FIELD_GET(ERDMA_CQE_SL_MASK, ud_info);
121+
wc->pkey_index = 0;
122+
}
123+
108124
#define ERDMA_POLLCQ_NO_QP 1
109125

110126
static int erdma_poll_one_cqe(struct erdma_cq *cq, struct ib_wc *wc)
@@ -168,6 +184,10 @@ static int erdma_poll_one_cqe(struct erdma_cq *cq, struct ib_wc *wc)
168184
wc->wc_flags |= IB_WC_WITH_INVALIDATE;
169185
}
170186

187+
if (erdma_device_rocev2(dev) &&
188+
(qp->ibqp.qp_type == IB_QPT_UD || qp->ibqp.qp_type == IB_QPT_GSI))
189+
erdma_process_ud_cqe(cqe, wc);
190+
171191
if (syndrome >= ERDMA_NUM_WC_STATUS)
172192
syndrome = ERDMA_WC_GENERAL_ERR;
173193

drivers/infiniband/hw/erdma/erdma_hw.h

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,11 @@ struct erdma_cmdq_query_qp_req_rocev2 {
374374
u32 qpn;
375375
};
376376

377+
enum erdma_qp_type {
378+
ERDMA_QPT_RC = 0,
379+
ERDMA_QPT_UD = 1,
380+
};
381+
377382
/* create qp cfg0 */
378383
#define ERDMA_CMD_CREATE_QP_SQ_DEPTH_MASK GENMASK(31, 20)
379384
#define ERDMA_CMD_CREATE_QP_QPN_MASK GENMASK(19, 0)
@@ -382,6 +387,9 @@ struct erdma_cmdq_query_qp_req_rocev2 {
382387
#define ERDMA_CMD_CREATE_QP_RQ_DEPTH_MASK GENMASK(31, 20)
383388
#define ERDMA_CMD_CREATE_QP_PD_MASK GENMASK(19, 0)
384389

390+
/* create qp cfg2 */
391+
#define ERDMA_CMD_CREATE_QP_TYPE_MASK GENMASK(3, 0)
392+
385393
/* create qp cqn_mtt_cfg */
386394
#define ERDMA_CMD_CREATE_QP_PAGE_SIZE_MASK GENMASK(31, 28)
387395
#define ERDMA_CMD_CREATE_QP_DB_CFG_MASK BIT(25)
@@ -415,6 +423,7 @@ struct erdma_cmdq_create_qp_req {
415423
u64 rq_mtt_entry[3];
416424

417425
u32 db_cfg;
426+
u32 cfg2;
418427
};
419428

420429
struct erdma_cmdq_destroy_qp_req {
@@ -522,6 +531,10 @@ enum {
522531
#define ERDMA_CQE_QTYPE_RQ 1
523532
#define ERDMA_CQE_QTYPE_CMDQ 2
524533

534+
#define ERDMA_CQE_NTYPE_MASK BIT(31)
535+
#define ERDMA_CQE_SL_MASK GENMASK(27, 20)
536+
#define ERDMA_CQE_SQPN_MASK GENMASK(19, 0)
537+
525538
struct erdma_cqe {
526539
__be32 hdr;
527540
__be32 qe_idx;
@@ -531,7 +544,16 @@ struct erdma_cqe {
531544
__be32 inv_rkey;
532545
};
533546
__be32 size;
534-
__be32 rsvd[3];
547+
union {
548+
struct {
549+
__be32 rsvd[3];
550+
} rc;
551+
552+
struct {
553+
__be32 rsvd[2];
554+
__be32 info;
555+
} ud;
556+
};
535557
};
536558

537559
struct erdma_sge {
@@ -583,7 +605,7 @@ struct erdma_write_sqe {
583605
struct erdma_sge sgl[];
584606
};
585607

586-
struct erdma_send_sqe {
608+
struct erdma_send_sqe_rc {
587609
__le64 hdr;
588610
union {
589611
__be32 imm_data;
@@ -594,6 +616,17 @@ struct erdma_send_sqe {
594616
struct erdma_sge sgl[];
595617
};
596618

619+
struct erdma_send_sqe_ud {
620+
__le64 hdr;
621+
__be32 imm_data;
622+
__le32 length;
623+
__le32 qkey;
624+
__le32 dst_qpn;
625+
__le32 ahn;
626+
__le32 rsvd;
627+
struct erdma_sge sgl[];
628+
};
629+
597630
struct erdma_readreq_sqe {
598631
__le64 hdr;
599632
__le32 invalid_stag;

drivers/infiniband/hw/erdma/erdma_qp.c

Lines changed: 57 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -398,17 +398,57 @@ static int fill_sgl(struct erdma_qp *qp, const struct ib_send_wr *send_wr,
398398
return 0;
399399
}
400400

401+
static void init_send_sqe_rc(struct erdma_qp *qp, struct erdma_send_sqe_rc *sqe,
402+
const struct ib_send_wr *wr, u32 *hw_op)
403+
{
404+
u32 op = ERDMA_OP_SEND;
405+
406+
if (wr->opcode == IB_WR_SEND_WITH_IMM) {
407+
op = ERDMA_OP_SEND_WITH_IMM;
408+
sqe->imm_data = wr->ex.imm_data;
409+
} else if (op == IB_WR_SEND_WITH_INV) {
410+
op = ERDMA_OP_SEND_WITH_INV;
411+
sqe->invalid_stag = cpu_to_le32(wr->ex.invalidate_rkey);
412+
}
413+
414+
*hw_op = op;
415+
}
416+
417+
static void init_send_sqe_ud(struct erdma_qp *qp, struct erdma_send_sqe_ud *sqe,
418+
const struct ib_send_wr *wr, u32 *hw_op)
419+
{
420+
const struct ib_ud_wr *uwr = ud_wr(wr);
421+
struct erdma_ah *ah = to_eah(uwr->ah);
422+
u32 op = ERDMA_OP_SEND;
423+
424+
if (wr->opcode == IB_WR_SEND_WITH_IMM) {
425+
op = ERDMA_OP_SEND_WITH_IMM;
426+
sqe->imm_data = wr->ex.imm_data;
427+
}
428+
429+
*hw_op = op;
430+
431+
sqe->ahn = cpu_to_le32(ah->ahn);
432+
sqe->dst_qpn = cpu_to_le32(uwr->remote_qpn);
433+
/* Not allowed to send control qkey */
434+
if (uwr->remote_qkey & 0x80000000)
435+
sqe->qkey = cpu_to_le32(qp->attrs.rocev2.qkey);
436+
else
437+
sqe->qkey = cpu_to_le32(uwr->remote_qkey);
438+
}
439+
401440
static int erdma_push_one_sqe(struct erdma_qp *qp, u16 *pi,
402441
const struct ib_send_wr *send_wr)
403442
{
404443
u32 wqe_size, wqebb_cnt, hw_op, flags, sgl_offset;
405444
u32 idx = *pi & (qp->attrs.sq_size - 1);
406445
enum ib_wr_opcode op = send_wr->opcode;
446+
struct erdma_send_sqe_rc *rc_send_sqe;
447+
struct erdma_send_sqe_ud *ud_send_sqe;
407448
struct erdma_atomic_sqe *atomic_sqe;
408449
struct erdma_readreq_sqe *read_sqe;
409450
struct erdma_reg_mr_sqe *regmr_sge;
410451
struct erdma_write_sqe *write_sqe;
411-
struct erdma_send_sqe *send_sqe;
412452
struct ib_rdma_wr *rdma_wr;
413453
struct erdma_sge *sge;
414454
__le32 *length_field;
@@ -417,6 +457,10 @@ static int erdma_push_one_sqe(struct erdma_qp *qp, u16 *pi,
417457
u32 attrs;
418458
int ret;
419459

460+
if (qp->ibqp.qp_type != IB_QPT_RC && send_wr->opcode != IB_WR_SEND &&
461+
send_wr->opcode != IB_WR_SEND_WITH_IMM)
462+
return -EINVAL;
463+
420464
entry = get_queue_entry(qp->kern_qp.sq_buf, idx, qp->attrs.sq_size,
421465
SQEBB_SHIFT);
422466

@@ -490,21 +534,20 @@ static int erdma_push_one_sqe(struct erdma_qp *qp, u16 *pi,
490534
case IB_WR_SEND:
491535
case IB_WR_SEND_WITH_IMM:
492536
case IB_WR_SEND_WITH_INV:
493-
send_sqe = (struct erdma_send_sqe *)entry;
494-
hw_op = ERDMA_OP_SEND;
495-
if (op == IB_WR_SEND_WITH_IMM) {
496-
hw_op = ERDMA_OP_SEND_WITH_IMM;
497-
send_sqe->imm_data = send_wr->ex.imm_data;
498-
} else if (op == IB_WR_SEND_WITH_INV) {
499-
hw_op = ERDMA_OP_SEND_WITH_INV;
500-
send_sqe->invalid_stag =
501-
cpu_to_le32(send_wr->ex.invalidate_rkey);
537+
if (qp->ibqp.qp_type == IB_QPT_RC) {
538+
rc_send_sqe = (struct erdma_send_sqe_rc *)entry;
539+
init_send_sqe_rc(qp, rc_send_sqe, send_wr, &hw_op);
540+
length_field = &rc_send_sqe->length;
541+
wqe_size = sizeof(struct erdma_send_sqe_rc);
542+
} else {
543+
ud_send_sqe = (struct erdma_send_sqe_ud *)entry;
544+
init_send_sqe_ud(qp, ud_send_sqe, send_wr, &hw_op);
545+
length_field = &ud_send_sqe->length;
546+
wqe_size = sizeof(struct erdma_send_sqe_ud);
502547
}
503-
wqe_hdr |= FIELD_PREP(ERDMA_SQE_HDR_OPCODE_MASK, hw_op);
504-
length_field = &send_sqe->length;
505-
wqe_size = sizeof(struct erdma_send_sqe);
506-
sgl_offset = wqe_size;
507548

549+
sgl_offset = wqe_size;
550+
wqe_hdr |= FIELD_PREP(ERDMA_SQE_HDR_OPCODE_MASK, hw_op);
508551
break;
509552
case IB_WR_REG_MR:
510553
wqe_hdr |=

drivers/infiniband/hw/erdma/erdma_verbs.c

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,13 @@ static int create_qp_cmd(struct erdma_ucontext *uctx, struct erdma_qp *qp)
5555
ilog2(qp->attrs.rq_size)) |
5656
FIELD_PREP(ERDMA_CMD_CREATE_QP_PD_MASK, pd->pdn);
5757

58+
if (qp->ibqp.qp_type == IB_QPT_RC)
59+
req.cfg2 = FIELD_PREP(ERDMA_CMD_CREATE_QP_TYPE_MASK,
60+
ERDMA_QPT_RC);
61+
else
62+
req.cfg2 = FIELD_PREP(ERDMA_CMD_CREATE_QP_TYPE_MASK,
63+
ERDMA_QPT_UD);
64+
5865
if (rdma_is_kernel_res(&qp->ibqp.res)) {
5966
u32 pgsz_range = ilog2(SZ_1M) - ERDMA_HW_PAGE_SHIFT;
6067

@@ -481,7 +488,11 @@ static int erdma_qp_validate_cap(struct erdma_dev *dev,
481488
static int erdma_qp_validate_attr(struct erdma_dev *dev,
482489
struct ib_qp_init_attr *attrs)
483490
{
484-
if (attrs->qp_type != IB_QPT_RC)
491+
if (erdma_device_iwarp(dev) && attrs->qp_type != IB_QPT_RC)
492+
return -EOPNOTSUPP;
493+
494+
if (erdma_device_rocev2(dev) && attrs->qp_type != IB_QPT_RC &&
495+
attrs->qp_type != IB_QPT_UD && attrs->qp_type != IB_QPT_GSI)
485496
return -EOPNOTSUPP;
486497

487498
if (attrs->srq)
@@ -959,7 +970,8 @@ int erdma_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
959970
udata, struct erdma_ucontext, ibucontext);
960971
struct erdma_ureq_create_qp ureq;
961972
struct erdma_uresp_create_qp uresp;
962-
int ret;
973+
void *old_entry;
974+
int ret = 0;
963975

964976
ret = erdma_qp_validate_cap(dev, attrs);
965977
if (ret)
@@ -978,9 +990,16 @@ int erdma_create_qp(struct ib_qp *ibqp, struct ib_qp_init_attr *attrs,
978990
kref_init(&qp->ref);
979991
init_completion(&qp->safe_free);
980992

981-
ret = xa_alloc_cyclic(&dev->qp_xa, &qp->ibqp.qp_num, qp,
982-
XA_LIMIT(1, dev->attrs.max_qp - 1),
983-
&dev->next_alloc_qpn, GFP_KERNEL);
993+
if (qp->ibqp.qp_type == IB_QPT_GSI) {
994+
old_entry = xa_store(&dev->qp_xa, 1, qp, GFP_KERNEL);
995+
if (xa_is_err(old_entry))
996+
ret = xa_err(old_entry);
997+
} else {
998+
ret = xa_alloc_cyclic(&dev->qp_xa, &qp->ibqp.qp_num, qp,
999+
XA_LIMIT(1, dev->attrs.max_qp - 1),
1000+
&dev->next_alloc_qpn, GFP_KERNEL);
1001+
}
1002+
9841003
if (ret < 0) {
9851004
ret = -ENOMEM;
9861005
goto err_out;

0 commit comments

Comments
 (0)