Commit c058ecf6 authored by Steve Wise's avatar Steve Wise Committed by Jason Gunthorpe

iw_cxgb4: only insert drain cqes if wq is flushed

Only insert our special drain CQEs to support ib_drain_sq/rq() after
the wq is flushed. Otherwise, existing but not yet polled CQEs can be
returned out of order to the user application.  This can happen when the
QP has exited RTS but not yet flushed the QP, which can happen during
a normal close (vs abortive close).

In addition never count the drain CQEs when determining how many CQEs
need to be synthesized during the flush operation.  This latter issue
should never happen if the QP is properly flushed before inserting the
drain CQE, but I wanted to avoid corrupting the CQ state.  So we handle
it and log a warning once.

Fixes: 4fe7c296 ("iw_cxgb4: refactor sq/rq drain logic")
Signed-off-by: default avatarSteve Wise <swise@opengridcomputing.com>
Cc: stable@vger.kernel.org
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
parent 335ebf6f
...@@ -395,6 +395,11 @@ void c4iw_flush_hw_cq(struct c4iw_cq *chp) ...@@ -395,6 +395,11 @@ void c4iw_flush_hw_cq(struct c4iw_cq *chp)
static int cqe_completes_wr(struct t4_cqe *cqe, struct t4_wq *wq) static int cqe_completes_wr(struct t4_cqe *cqe, struct t4_wq *wq)
{ {
if (CQE_OPCODE(cqe) == C4IW_DRAIN_OPCODE) {
WARN_ONCE(1, "Unexpected DRAIN CQE qp id %u!\n", wq->sq.qid);
return 0;
}
if (CQE_OPCODE(cqe) == FW_RI_TERMINATE) if (CQE_OPCODE(cqe) == FW_RI_TERMINATE)
return 0; return 0;
......
...@@ -868,7 +868,12 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr, ...@@ -868,7 +868,12 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
qhp = to_c4iw_qp(ibqp); qhp = to_c4iw_qp(ibqp);
spin_lock_irqsave(&qhp->lock, flag); spin_lock_irqsave(&qhp->lock, flag);
if (t4_wq_in_error(&qhp->wq)) {
/*
* If the qp has been flushed, then just insert a special
* drain cqe.
*/
if (qhp->wq.flushed) {
spin_unlock_irqrestore(&qhp->lock, flag); spin_unlock_irqrestore(&qhp->lock, flag);
complete_sq_drain_wr(qhp, wr); complete_sq_drain_wr(qhp, wr);
return err; return err;
...@@ -1011,7 +1016,12 @@ int c4iw_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr, ...@@ -1011,7 +1016,12 @@ int c4iw_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
qhp = to_c4iw_qp(ibqp); qhp = to_c4iw_qp(ibqp);
spin_lock_irqsave(&qhp->lock, flag); spin_lock_irqsave(&qhp->lock, flag);
if (t4_wq_in_error(&qhp->wq)) {
/*
* If the qp has been flushed, then just insert a special
* drain cqe.
*/
if (qhp->wq.flushed) {
spin_unlock_irqrestore(&qhp->lock, flag); spin_unlock_irqrestore(&qhp->lock, flag);
complete_rq_drain_wr(qhp, wr); complete_rq_drain_wr(qhp, wr);
return err; return err;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment