Skip to content

Commit

Permalink
RDMA/siw: Fix broken RDMA Read Fence/Resume logic.
Browse files Browse the repository at this point in the history
commit b43a76f 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: 8b6a361 ("rdma/siw: receive path")
Fixes: a531975 ("rdma/siw: main include file")
Link: https://lore.kernel.org/r/20220130170815.1940-1-bmt@zurich.ibm.com
Reported-by: Jared Holzman <jared.holzman@excelero.com>
Signed-off-by: Bernard Metzler <bmt@zurich.ibm.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
  • Loading branch information
BernardMetzler authored and gregkh committed Feb 8, 2022
1 parent 7d9ad6f commit 035ea99
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 15 deletions.
7 changes: 1 addition & 6 deletions drivers/infiniband/sw/siw/siw.h
Original file line number Diff line number Diff line change
Expand Up @@ -644,14 +644,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;
Expand Down
20 changes: 11 additions & 9 deletions drivers/infiniband/sw/siw/siw_qp_rx.c
Original file line number Diff line number Diff line change
Expand Up @@ -1153,22 +1153,25 @@ 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",
qp_id(qp), tx_waiting->wr_status);
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;
Expand All @@ -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);

Expand Down

0 comments on commit 035ea99

Please sign in to comment.