iw_cxgb4: only insert drain cqes if wq is flushed
authorSteve Wise <swise@opengridcomputing.com>
Mon, 27 Nov 2017 21:16:32 +0000 (13:16 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 20 Dec 2017 09:10:21 +0000 (10:10 +0100)
commit c058ecf6e455fac7346d46197a02398ead90851f upstream.

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: 4fe7c2962e11 ("iw_cxgb4: refactor sq/rq drain logic")
Signed-off-by: Steve Wise <swise@opengridcomputing.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/infiniband/hw/cxgb4/cq.c
drivers/infiniband/hw/cxgb4/qp.c

index be07da1997e68ea0a2bcc157a67a34cbd27bc4e7..eae8ea81c6e27184ab30dc73ccea5ff57157fe4f 100644 (file)
@@ -410,6 +410,11 @@ next_cqe:
 
 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)
                return 0;
 
index cb7fc0d35d1d14efff512c2ef9101304532121ad..e69453665a174a00390f43a10da2ab336c86630d 100644 (file)
@@ -868,7 +868,12 @@ int c4iw_post_send(struct ib_qp *ibqp, struct ib_send_wr *wr,
 
        qhp = to_c4iw_qp(ibqp);
        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);
                complete_sq_drain_wr(qhp, wr);
                return err;
@@ -1012,7 +1017,12 @@ int c4iw_post_receive(struct ib_qp *ibqp, struct ib_recv_wr *wr,
 
        qhp = to_c4iw_qp(ibqp);
        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);
                complete_rq_drain_wr(qhp, wr);
                return err;