Skip to content

Commit 37e0cf3

Browse files
author
Konstantin Taranov
committed
providers/mana: UC QP support
Implement creation and destruction of UC QPs. Add processing of UC send CQEs. Signed-off-by: Konstantin Taranov <kotaranov@microsoft.com>
1 parent 4be917c commit 37e0cf3

5 files changed

Lines changed: 173 additions & 51 deletions

File tree

providers/mana/cq.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,25 @@ static inline int advance_send_completions(struct mana_qp *qp, uint32_t psn,
284284
return produced;
285285
}
286286

287+
static inline int handle_requester_cqe(struct mana_qp *qp, struct gdma_cqe *cqe, struct ibv_wc *wc)
288+
{
289+
struct mana_gdma_queue *send_queue = mana_ib_get_sreq(qp);
290+
struct shadow_wqe_header *wqe;
291+
int produced = 0;
292+
293+
while (!produced && (wqe = shadow_queue_get_next_to_consume(&qp->shadow_sq)) != NULL) {
294+
send_queue->cons_idx += wqe->posted_wqe_size_in_bu;
295+
send_queue->cons_idx &= GDMA_QUEUE_OFFSET_MASK;
296+
if (wqe->flags != MANA_NO_SIGNAL_WC) {
297+
fill_verbs_from_shadow_wqe(qp, wc, wqe);
298+
produced++;
299+
}
300+
shadow_queue_advance_consumer(&qp->shadow_sq);
301+
}
302+
303+
return produced;
304+
}
305+
287306
static inline int handle_rc_requester_cqe(struct mana_qp *qp, struct gdma_cqe *cqe,
288307
struct ibv_wc *wc, int nwc, bool *consumed)
289308
{
@@ -443,6 +462,8 @@ static inline int mana_handle_cqe(struct mana_context *ctx, struct gdma_cqe *cqe
443462
return handle_error_cqe(qp, cqe, wc, nwc, consumed);
444463
else if (cqe->rdma_cqe.cqe_type == CQE_TYPE_ARMED_CMPL)
445464
return handle_rc_requester_cqe(qp, cqe, wc, nwc, consumed);
465+
else if (cqe->is_sq && cqe->rdma_cqe.cqe_type == CQE_TYPE_UD_SEND)
466+
return handle_requester_cqe(qp, cqe, wc);
446467
else
447468
return handle_responder_cqe(qp, cqe, wc);
448469
}

providers/mana/mana.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,8 @@ enum user_queue_types {
4949
USER_RNIC_SEND_QUEUE_RESPONDER = 1,
5050
USER_RNIC_RECV_QUEUE_REQUESTER = 2,
5151
USER_RNIC_RECV_QUEUE_RESPONDER = 3,
52-
USER_RNIC_QUEUE_TYPE_MAX = 4,
52+
USER_RNIC_SEND_QUEUE_MM = 4,
53+
USER_RNIC_QUEUE_TYPE_MAX = 5,
5354
};
5455

5556
#define QUEUE_TYPE_MASK 0x3

providers/mana/qp.c

Lines changed: 137 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ DECLARE_DRV_CMD(mana_create_qp_ex, IB_USER_VERBS_EX_CMD_CREATE_QP,
3131
DECLARE_DRV_CMD(mana_create_rc_qp, IB_USER_VERBS_CMD_CREATE_QP,
3232
mana_ib_create_rc_qp, mana_ib_create_rc_qp_resp);
3333

34+
DECLARE_DRV_CMD(mana_create_uc_qp, IB_USER_VERBS_CMD_CREATE_QP,
35+
mana_ib_create_uc_qp, mana_ib_create_uc_qp_resp);
36+
3437
static struct ibv_qp *mana_create_qp_raw(struct ibv_pd *ibpd,
3538
struct ibv_qp_init_attr *attr)
3639
{
@@ -216,56 +219,149 @@ static uint32_t get_queue_size(struct ibv_qp_init_attr *attr, enum user_queue_ty
216219
uint32_t size = 0;
217220
uint32_t sges = 0;
218221

219-
if (attr->qp_type == IBV_QPT_RC) {
220-
switch (type) {
221-
case USER_RNIC_SEND_QUEUE_REQUESTER:
222-
/* WQE must have at least one SGE */
223-
/* For write with imm we need one extra SGE */
224-
sges = max(1U, attr->cap.max_send_sge) + 1;
225-
size = attr->cap.max_send_wr * get_large_wqe_size(sges);
226-
break;
227-
case USER_RNIC_SEND_QUEUE_RESPONDER:
228-
size = MANA_PAGE_SIZE;
229-
break;
230-
case USER_RNIC_RECV_QUEUE_REQUESTER:
231-
size = MANA_PAGE_SIZE;
232-
break;
233-
case USER_RNIC_RECV_QUEUE_RESPONDER:
234-
/* WQE must have at least one SGE */
235-
sges = max(1U, attr->cap.max_recv_sge);
236-
size = attr->cap.max_recv_wr * get_wqe_size(sges);
237-
break;
238-
default:
239-
return 0;
240-
}
222+
switch (type) {
223+
case USER_RNIC_SEND_QUEUE_REQUESTER:
224+
/* WQE must have at least one SGE */
225+
/* For write with imm we need one extra SGE */
226+
sges = max(1U, attr->cap.max_send_sge) + 1;
227+
size = align_hw_size(attr->cap.max_send_wr * get_large_wqe_size(sges));
228+
break;
229+
case USER_RNIC_SEND_QUEUE_RESPONDER:
230+
if (attr->qp_type == IBV_QPT_RC)
231+
size = align_hw_size(MANA_PAGE_SIZE);
232+
break;
233+
case USER_RNIC_RECV_QUEUE_REQUESTER:
234+
if (attr->qp_type == IBV_QPT_RC)
235+
size = align_hw_size(MANA_PAGE_SIZE);
236+
break;
237+
case USER_RNIC_RECV_QUEUE_RESPONDER:
238+
/* WQE must have at least one SGE */
239+
sges = max(1U, attr->cap.max_recv_sge);
240+
size = align_hw_size(attr->cap.max_recv_wr * get_wqe_size(sges));
241+
break;
242+
case USER_RNIC_SEND_QUEUE_MM:
243+
sges = max(1U, attr->cap.max_send_sge) + 1;
244+
size = align_hw_size(attr->cap.max_send_wr * get_large_wqe_size(sges));
245+
break;
246+
default:
247+
return 0;
241248
}
242249

243-
size = align_hw_size(size);
244-
245250
if (attr->qp_type == IBV_QPT_RC && type == USER_RNIC_SEND_QUEUE_REQUESTER)
246251
size += sizeof(struct mana_ib_rollback_shared_mem);
247252

248253
return size;
249254
}
250255

251-
static struct ibv_qp *mana_create_qp_rnic(struct ibv_pd *ibpd,
252-
struct ibv_qp_init_attr *attr)
256+
static int mana_create_cmd_qp_rc(struct mana_qp *qp, struct ibv_pd *ibpd,
257+
struct ibv_qp_init_attr *attr)
253258
{
254-
struct mana_context *ctx = to_mctx(ibpd->context);
255259
struct mana_ib_create_rc_qp_resp *qp_resp_drv;
256260
struct mana_create_rc_qp_resp qp_resp = {};
257261
struct mana_ib_create_rc_qp *qp_cmd_drv;
258262
struct mana_create_rc_qp qp_cmd = {};
263+
int ret, i;
264+
265+
qp_cmd_drv = &qp_cmd.drv_payload;
266+
qp_resp_drv = &qp_resp.drv_payload;
267+
268+
for (i = 0; i < USER_RNIC_QUEUE_TYPE_MAX; ++i) {
269+
if (i == USER_RNIC_SEND_QUEUE_MM)
270+
continue;
271+
qp_cmd_drv->queue_buf[i] = (uintptr_t)qp->rnic_qp.queues[i].buffer;
272+
qp_cmd_drv->queue_size[i] = qp->rnic_qp.queues[i].size;
273+
}
274+
275+
ret = ibv_cmd_create_qp(ibpd, &qp->ibqp.qp, attr, &qp_cmd.ibv_cmd,
276+
sizeof(qp_cmd), &qp_resp.ibv_resp,
277+
sizeof(qp_resp));
278+
if (ret) {
279+
verbs_err(verbs_get_ctx(ibpd->context), "Create QP failed\n");
280+
return ret;
281+
}
282+
283+
for (i = 0; i < USER_RNIC_QUEUE_TYPE_MAX; ++i) {
284+
if (i == USER_RNIC_SEND_QUEUE_MM)
285+
continue;
286+
qp->rnic_qp.queues[i].id = qp_resp_drv->queue_id[i];
287+
}
288+
289+
return 0;
290+
}
291+
292+
enum {
293+
MANA_UC_UDATA_SQR = 0,
294+
MANA_UC_UDATA_RQR = 1,
295+
MANA_UC_UDATA_SMQ = 2,
296+
};
297+
298+
static int mana_create_cmd_qp_uc(struct mana_qp *qp, struct ibv_pd *ibpd,
299+
struct ibv_qp_init_attr *attr)
300+
{
301+
struct mana_ib_create_uc_qp_resp *qp_resp_drv;
302+
struct mana_create_uc_qp_resp qp_resp = {};
303+
struct mana_ib_create_uc_qp *qp_cmd_drv;
304+
struct mana_create_uc_qp qp_cmd = {};
305+
int ret;
306+
307+
qp_cmd_drv = &qp_cmd.drv_payload;
308+
qp_resp_drv = &qp_resp.drv_payload;
309+
310+
qp_cmd_drv->queue_buf[MANA_UC_UDATA_SQR] =
311+
(uintptr_t)qp->rnic_qp.queues[USER_RNIC_SEND_QUEUE_REQUESTER].buffer;
312+
qp_cmd_drv->queue_size[MANA_UC_UDATA_SQR] =
313+
qp->rnic_qp.queues[USER_RNIC_SEND_QUEUE_REQUESTER].size;
314+
315+
qp_cmd_drv->queue_buf[MANA_UC_UDATA_RQR] =
316+
(uintptr_t)qp->rnic_qp.queues[USER_RNIC_RECV_QUEUE_RESPONDER].buffer;
317+
qp_cmd_drv->queue_size[MANA_UC_UDATA_RQR] =
318+
qp->rnic_qp.queues[USER_RNIC_RECV_QUEUE_RESPONDER].size;
319+
320+
qp_cmd_drv->queue_buf[MANA_UC_UDATA_SMQ] =
321+
(uintptr_t)qp->rnic_qp.queues[USER_RNIC_SEND_QUEUE_MM].buffer;
322+
qp_cmd_drv->queue_size[MANA_UC_UDATA_SMQ] =
323+
qp->rnic_qp.queues[USER_RNIC_SEND_QUEUE_MM].size;
324+
325+
ret = ibv_cmd_create_qp(ibpd, &qp->ibqp.qp, attr, &qp_cmd.ibv_cmd,
326+
sizeof(qp_cmd), &qp_resp.ibv_resp,
327+
sizeof(qp_resp));
328+
if (ret) {
329+
verbs_err(verbs_get_ctx(ibpd->context), "Create QP failed\n");
330+
return ret;
331+
}
332+
333+
qp->rnic_qp.queues[USER_RNIC_SEND_QUEUE_REQUESTER].id =
334+
qp_resp_drv->queue_id[MANA_UC_UDATA_SQR];
335+
qp->rnic_qp.queues[USER_RNIC_RECV_QUEUE_RESPONDER].id =
336+
qp_resp_drv->queue_id[MANA_UC_UDATA_RQR];
337+
qp->rnic_qp.queues[USER_RNIC_SEND_QUEUE_MM].id =
338+
qp_resp_drv->queue_id[MANA_UC_UDATA_SMQ];
339+
340+
return 0;
341+
}
342+
343+
static int mana_create_cmd_qp(struct mana_qp *qp, struct ibv_pd *ibpd,
344+
struct ibv_qp_init_attr *attr)
345+
{
346+
if (attr->qp_type == IBV_QPT_RC)
347+
return mana_create_cmd_qp_rc(qp, ibpd, attr);
348+
else if (attr->qp_type == IBV_QPT_UC)
349+
return mana_create_cmd_qp_uc(qp, ibpd, attr);
350+
else
351+
return -EOPNOTSUPP;
352+
}
353+
354+
static struct ibv_qp *mana_create_qp_rnic(struct ibv_pd *ibpd,
355+
struct ibv_qp_init_attr *attr)
356+
{
357+
struct mana_context *ctx = to_mctx(ibpd->context);
259358
struct mana_qp *qp;
260359
int ret, i;
261360

262361
qp = calloc(1, sizeof(*qp));
263362
if (!qp)
264363
return NULL;
265364

266-
qp_cmd_drv = &qp_cmd.drv_payload;
267-
qp_resp_drv = &qp_resp.drv_payload;
268-
269365
pthread_spin_init(&qp->sq_lock, PTHREAD_PROCESS_PRIVATE);
270366
pthread_spin_init(&qp->rq_lock, PTHREAD_PROCESS_PRIVATE);
271367
qp->sq_sig_all = attr->sq_sig_all;
@@ -291,29 +387,18 @@ static struct ibv_qp *mana_create_qp_rnic(struct ibv_pd *ibpd,
291387

292388
if (qp->rnic_qp.queues[i].size != 0 && !qp->rnic_qp.queues[i].buffer) {
293389
verbs_err(verbs_get_ctx(ibpd->context),
294-
"Failed to allocate memory for RC queue %d\n", i);
390+
"Failed to allocate memory for queue %d\n", i);
295391
errno = ENOMEM;
296392
goto destroy_queues;
297393
}
298-
299-
qp_cmd_drv->queue_buf[i] = (uintptr_t)qp->rnic_qp.queues[i].buffer;
300-
qp_cmd_drv->queue_size[i] = qp->rnic_qp.queues[i].size;
301394
}
302395

303-
mana_ib_init_rb_shmem(qp);
304-
305-
ret = ibv_cmd_create_qp(ibpd, &qp->ibqp.qp, attr, &qp_cmd.ibv_cmd,
306-
sizeof(qp_cmd), &qp_resp.ibv_resp,
307-
sizeof(qp_resp));
396+
ret = mana_create_cmd_qp(qp, ibpd, attr);
308397
if (ret) {
309-
verbs_err(verbs_get_ctx(ibpd->context), "Create QP failed\n");
310398
errno = ret;
311-
goto free_rb;
399+
goto destroy_queues;
312400
}
313401

314-
for (i = 0; i < USER_RNIC_QUEUE_TYPE_MAX; ++i)
315-
qp->rnic_qp.queues[i].id = qp_resp_drv->queue_id[i];
316-
317402
qp->ibqp.qp.qp_num = qp->rnic_qp.queues[USER_RNIC_RECV_QUEUE_RESPONDER].id;
318403

319404
ret = mana_store_qp(ctx, qp);
@@ -322,12 +407,12 @@ static struct ibv_qp *mana_create_qp_rnic(struct ibv_pd *ibpd,
322407
goto destroy_qp;
323408
}
324409

410+
mana_ib_init_rb_shmem(qp);
411+
325412
return &qp->ibqp.qp;
326413

327414
destroy_qp:
328415
ibv_cmd_destroy_qp(&qp->ibqp.qp);
329-
free_rb:
330-
mana_ib_deinit_rb_shmem(qp);
331416
destroy_queues:
332417
while (i-- > 0)
333418
mana_dealloc_mem(qp->rnic_qp.queues[i].buffer, qp->rnic_qp.queues[i].size);
@@ -346,6 +431,7 @@ struct ibv_qp *mana_create_qp(struct ibv_pd *ibpd,
346431
case IBV_QPT_RAW_PACKET:
347432
return mana_create_qp_raw(ibpd, attr);
348433
case IBV_QPT_RC:
434+
case IBV_QPT_UC:
349435
return mana_create_qp_rnic(ibpd, attr);
350436
default:
351437
verbs_err(verbs_get_ctx(ibpd->context),
@@ -382,7 +468,8 @@ static void mana_ib_modify_rnic_qp(struct mana_qp *qp, struct ibv_qp_attr *attr,
382468
if (attr_mask & IBV_QP_SQ_PSN) {
383469
qp->sq_ssn = 1;
384470
qp->sq_psn = attr->sq_psn;
385-
gdma_arm_normal_cqe(mana_ib_get_rreq(qp), attr->sq_psn);
471+
if (qp->ibqp.qp.qp_type == IBV_QPT_RC)
472+
gdma_arm_normal_cqe(mana_ib_get_rreq(qp), attr->sq_psn);
386473
}
387474
break;
388475
default:
@@ -397,7 +484,7 @@ int mana_modify_qp(struct ibv_qp *ibqp, struct ibv_qp_attr *attr, int attr_mask)
397484
struct ibv_modify_qp cmd = {};
398485
int err;
399486

400-
if (ibqp->qp_type != IBV_QPT_RC)
487+
if (ibqp->qp_type != IBV_QPT_RC && ibqp->qp_type != IBV_QPT_UC)
401488
return EOPNOTSUPP;
402489

403490
pthread_spin_lock(&qp->sq_lock);
@@ -443,7 +530,7 @@ int mana_destroy_qp(struct ibv_qp *ibqp)
443530
struct mana_context *ctx = to_mctx(ibqp->context);
444531
int ret, i;
445532

446-
if (ibqp->qp_type == IBV_QPT_RC) {
533+
if (ibqp->qp_type == IBV_QPT_RC || ibqp->qp_type == IBV_QPT_UC) {
447534
mana_remove_qp(ctx, qp);
448535
mana_drain_cqes(qp);
449536
}
@@ -459,6 +546,7 @@ int mana_destroy_qp(struct ibv_qp *ibqp)
459546
ctx->extern_alloc.free(qp->raw_qp.send_buf, ctx->extern_alloc.data);
460547
break;
461548
case IBV_QPT_RC:
549+
case IBV_QPT_UC:
462550
pthread_spin_destroy(&qp->sq_lock);
463551
pthread_spin_destroy(&qp->rq_lock);
464552
destroy_shadow_queue(&qp->shadow_sq);

providers/mana/rollback.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ static inline struct mana_ib_rollback_shared_mem
3939

4040
static inline void mana_ib_init_rb_shmem(struct mana_qp *qp)
4141
{
42+
if (qp->ibqp.qp.qp_type != IBV_QPT_RC)
43+
return;
4244
// take some bytes for rollback memory
4345
struct mana_gdma_queue *req_sq =
4446
&qp->rnic_qp.queues[USER_RNIC_SEND_QUEUE_REQUESTER];
@@ -54,6 +56,8 @@ static inline void mana_ib_init_rb_shmem(struct mana_qp *qp)
5456

5557
static inline void mana_ib_deinit_rb_shmem(struct mana_qp *qp)
5658
{
59+
if (qp->ibqp.qp.qp_type != IBV_QPT_RC)
60+
return;
5761
// return back bytes for rollback memory
5862
struct mana_gdma_queue *req_sq =
5963
&qp->rnic_qp.queues[USER_RNIC_SEND_QUEUE_REQUESTER];
@@ -62,6 +66,9 @@ static inline void mana_ib_deinit_rb_shmem(struct mana_qp *qp)
6266

6367
static inline void mana_ib_reset_rb_shmem(struct mana_qp *qp)
6468
{
69+
if (qp->ibqp.qp.qp_type != IBV_QPT_RC)
70+
return;
71+
6572
struct mana_ib_rollback_shared_mem *rb_shmem =
6673
mana_ib_get_rollback_sh_mem(qp);
6774

@@ -71,6 +78,9 @@ static inline void mana_ib_reset_rb_shmem(struct mana_qp *qp)
7178

7279
static inline void mana_ib_update_shared_mem_right_offset(struct mana_qp *qp, uint32_t offset_in_bu)
7380
{
81+
if (qp->ibqp.qp.qp_type != IBV_QPT_RC)
82+
return;
83+
7484
struct mana_ib_rollback_shared_mem *rb_shmem =
7585
mana_ib_get_rollback_sh_mem(qp);
7686

providers/mana/wr.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,7 @@ int mana_post_recv(struct ibv_qp *ibqp, struct ibv_recv_wr *wr,
191191
{
192192
switch (ibqp->qp_type) {
193193
case IBV_QPT_RC:
194+
case IBV_QPT_UC:
194195
return mana_ib_post_recv(ibqp, wr, bad);
195196
default:
196197
verbs_err(verbs_get_ctx(ibqp->context), "QPT not supported %d\n", ibqp->qp_type);
@@ -350,7 +351,7 @@ mana_ib_post_send_request(struct mana_qp *qp, struct ibv_send_wr *wr,
350351
&send_oob, oob_sge, num_sge, MTU_SIZE(qp->mtu), flags, &gdma_wqe);
351352
if (ret) {
352353
verbs_err(verbs_get_ctx(qp->ibqp.qp.context),
353-
"rc post send error, ret %d\n", ret);
354+
"post send error, ret %d\n", ret);
354355
goto cleanup;
355356
}
356357

@@ -430,6 +431,7 @@ int mana_post_send(struct ibv_qp *ibqp, struct ibv_send_wr *wr,
430431
{
431432
switch (ibqp->qp_type) {
432433
case IBV_QPT_RC:
434+
case IBV_QPT_UC:
433435
return mana_ib_post_send(ibqp, wr, bad);
434436
default:
435437
verbs_err(verbs_get_ctx(ibqp->context), "QPT not supported %d\n", ibqp->qp_type);

0 commit comments

Comments
 (0)