Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit bc5d3e8b authored by Bernard Metzler's avatar Bernard Metzler Committed by Greg Kroah-Hartman
Browse files

RDMA/siw: Fix broken RDMA Read Fence/Resume logic.

commit b43a76f423aa304037603fd6165c4a534d2c09a7 upstream.

Code unconditionally resumed fenced SQ processing after next RDMA Read
completion, even if other RDMA Read responses are still outstanding, or
ORQ is full. Also adds comments for better readability of fence
processing, and removes orq_get_tail() helper, which is not needed
anymore.

Fixes: 8b6a361b ("rdma/siw: receive path")
Fixes: a5319752 ("rdma/siw: main include file")
Link: https://lore.kernel.org/r/20220130170815.1940-1-bmt@zurich.ibm.com


Reported-by: default avatarJared Holzman <jared.holzman@excelero.com>
Signed-off-by: default avatarBernard Metzler <bmt@zurich.ibm.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@nvidia.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 60af6e68
Loading
Loading
Loading
Loading
+1 −6
Original line number Diff line number Diff line
@@ -658,14 +658,9 @@ static inline struct siw_sqe *orq_get_current(struct siw_qp *qp)
	return &qp->orq[qp->orq_get % qp->attrs.orq_size];
}

static inline struct siw_sqe *orq_get_tail(struct siw_qp *qp)
{
	return &qp->orq[qp->orq_put % qp->attrs.orq_size];
}

static inline struct siw_sqe *orq_get_free(struct siw_qp *qp)
{
	struct siw_sqe *orq_e = orq_get_tail(qp);
	struct siw_sqe *orq_e = &qp->orq[qp->orq_put % qp->attrs.orq_size];

	if (READ_ONCE(orq_e->flags) == 0)
		return orq_e;
+11 −9
Original line number Diff line number Diff line
@@ -1153,11 +1153,12 @@ static int siw_check_tx_fence(struct siw_qp *qp)

	spin_lock_irqsave(&qp->orq_lock, flags);

	rreq = orq_get_current(qp);

	/* free current orq entry */
	rreq = orq_get_current(qp);
	WRITE_ONCE(rreq->flags, 0);

	qp->orq_get++;

	if (qp->tx_ctx.orq_fence) {
		if (unlikely(tx_waiting->wr_status != SIW_WR_QUEUED)) {
			pr_warn("siw: [QP %u]: fence resume: bad status %d\n",
@@ -1165,10 +1166,12 @@ static int siw_check_tx_fence(struct siw_qp *qp)
			rv = -EPROTO;
			goto out;
		}
		/* resume SQ processing */
		/* resume SQ processing, if possible */
		if (tx_waiting->sqe.opcode == SIW_OP_READ ||
		    tx_waiting->sqe.opcode == SIW_OP_READ_LOCAL_INV) {
			rreq = orq_get_tail(qp);

			/* SQ processing was stopped because of a full ORQ */
			rreq = orq_get_free(qp);
			if (unlikely(!rreq)) {
				pr_warn("siw: [QP %u]: no ORQE\n", qp_id(qp));
				rv = -EPROTO;
@@ -1181,15 +1184,14 @@ static int siw_check_tx_fence(struct siw_qp *qp)
			resume_tx = 1;

		} else if (siw_orq_empty(qp)) {
			/*
			 * SQ processing was stopped by fenced work request.
			 * Resume since all previous Read's are now completed.
			 */
			qp->tx_ctx.orq_fence = 0;
			resume_tx = 1;
		} else {
			pr_warn("siw: [QP %u]: fence resume: orq idx: %d:%d\n",
				qp_id(qp), qp->orq_get, qp->orq_put);
			rv = -EPROTO;
		}
	}
	qp->orq_get++;
out:
	spin_unlock_irqrestore(&qp->orq_lock, flags);