Skip to content

Commit ce9e2b9

Browse files
mrgolinnmorey
authored andcommitted
efa: Fix work request index double use
[ Upstream commit 050b787 ] When polling a CQE related to a destroyed QP, we do not update the current work queue reference, what results in "returning" the work request index of the CQE to a wrong pool. This can later result in two different inflight work requests using same index and mistakenly completing with same work request id. Fix by zeroing the work queue pointer on error and unify conditions with unsolicited completion flow. Fixes: 40ee2e2 ("efa: Introduce create extended CQ support") Reviewed-by: Daniel Kranzdorf <[email protected]> Reviewed-by: Nitzan Lavy <[email protected]> Signed-off-by: Michael Margolin <[email protected]> Signed-off-by: Nicolas Morey <[email protected]>
1 parent b75951f commit ce9e2b9

File tree

1 file changed

+19
-10
lines changed

1 file changed

+19
-10
lines changed

providers/efa/verbs.c

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -646,7 +646,13 @@ static void efa_process_cqe(struct efa_cq *cq, struct ibv_wc *wc,
646646
struct efa_io_rx_cdesc_ex *rcqe =
647647
container_of(cqe, struct efa_io_rx_cdesc_ex, base.common);
648648

649-
cq->cur_wq = &qp->rq.wq;
649+
if (EFA_GET(&cqe->flags, EFA_IO_CDESC_COMMON_UNSOLICITED)) {
650+
cq->cur_wq = NULL;
651+
wc->wr_id = 0;
652+
} else {
653+
cq->cur_wq = &qp->rq.wq;
654+
wc->wr_id = cq->cur_wq->wrid[wrid_idx];
655+
}
650656

651657
wc->byte_len = rcqe->base.length;
652658

@@ -666,9 +672,6 @@ static void efa_process_cqe(struct efa_cq *cq, struct ibv_wc *wc,
666672
wc->wc_flags |= IBV_WC_WITH_IMM;
667673
}
668674

669-
wc->wr_id = !EFA_GET(&cqe->flags, EFA_IO_CDESC_COMMON_UNSOLICITED) ?
670-
cq->cur_wq->wrid[wrid_idx] : 0;
671-
672675
rdma_tracepoint(rdma_core_efa, process_completion, cq->dev->name, wc->wr_id,
673676
wc->status, wc->opcode, wc->src_qp, wc->qp_num, wc->slid,
674677
wc->byte_len);
@@ -692,9 +695,14 @@ static void efa_process_ex_cqe(struct efa_cq *cq, struct efa_qp *qp)
692695
ibvcqx->status, efa_wc_read_opcode(ibvcqx), cqe->qp_num,
693696
UINT32_MAX, UINT16_MAX, efa_wc_read_byte_len(ibvcqx));
694697
} else {
695-
cq->cur_wq = &qp->rq.wq;
696-
ibvcqx->wr_id = !EFA_GET(&cqe->flags, EFA_IO_CDESC_COMMON_UNSOLICITED) ?
697-
cq->cur_wq->wrid[wrid_idx] : 0;
698+
if (EFA_GET(&cqe->flags, EFA_IO_CDESC_COMMON_UNSOLICITED)) {
699+
cq->cur_wq = NULL;
700+
ibvcqx->wr_id = 0;
701+
} else {
702+
cq->cur_wq = &qp->rq.wq;
703+
ibvcqx->wr_id = cq->cur_wq->wrid[wrid_idx];
704+
}
705+
698706
ibvcqx->status = to_ibv_status(cqe->status);
699707

700708
rdma_tracepoint(rdma_core_efa, process_completion, cq->dev->name, ibvcqx->wr_id,
@@ -726,6 +734,7 @@ static inline int efa_poll_sub_cq(struct efa_cq *cq, struct efa_sub_cq *sub_cq,
726734
*/
727735
*cur_qp = ctx->qp_table[qpn & ctx->qp_table_sz_m1];
728736
if (!*cur_qp) {
737+
cq->cur_wq = NULL;
729738
verbs_err(&ctx->ibvctx,
730739
"QP[%u] does not exist in QP table\n",
731740
qpn);
@@ -737,7 +746,7 @@ static inline int efa_poll_sub_cq(struct efa_cq *cq, struct efa_sub_cq *sub_cq,
737746
efa_process_ex_cqe(cq, *cur_qp);
738747
} else {
739748
efa_process_cqe(cq, wc, *cur_qp);
740-
if (!EFA_GET(&cq->cur_cqe->flags, EFA_IO_CDESC_COMMON_UNSOLICITED))
749+
if (cq->cur_wq)
741750
efa_wq_put_wrid_idx_unlocked(cq->cur_wq, cq->cur_cqe->req_id);
742751
}
743752

@@ -822,7 +831,7 @@ static int efa_next_poll(struct ibv_cq_ex *ibvcqx)
822831
struct efa_cq *cq = to_efa_cq_ex(ibvcqx);
823832
int ret;
824833

825-
if (!EFA_GET(&cq->cur_cqe->flags, EFA_IO_CDESC_COMMON_UNSOLICITED))
834+
if (cq->cur_wq)
826835
efa_wq_put_wrid_idx_unlocked(cq->cur_wq, cq->cur_cqe->req_id);
827836
ret = efa_poll_sub_cqs(cq, NULL, true);
828837

@@ -834,7 +843,7 @@ static void efa_end_poll(struct ibv_cq_ex *ibvcqx)
834843
struct efa_cq *cq = to_efa_cq_ex(ibvcqx);
835844

836845
if (cq->cur_cqe) {
837-
if (!EFA_GET(&cq->cur_cqe->flags, EFA_IO_CDESC_COMMON_UNSOLICITED))
846+
if (cq->cur_wq)
838847
efa_wq_put_wrid_idx_unlocked(cq->cur_wq, cq->cur_cqe->req_id);
839848
if (cq->db)
840849
efa_update_cq_doorbell(cq, false);

0 commit comments

Comments
 (0)