Author: np
Date: Sat Sep  9 05:12:14 2017
New Revision: 323343
URL: https://svnweb.freebsd.org/changeset/base/323343

Log:
  cxgbe(4): Fix a couple of problems in the sge_wrq data path.
  
  - start_wrq_wr must not drain the wr_list if there are incomplete_wrs
    pending.  This can happen when a t4_wrq_tx runs between two
    start_wrq_wr.
  
  - commit_wrq_wr must examine the cookie's pidx and ndesc with the
    queue's lock held.  Otherwise there is a bad race when incomplete WRs
    are being completed and commit_wrq_wr for the WR that is ahead in the
    queue updates the next incomplete WR's cookie's pidx/ndesc but the
    commit_wrq_wr for the second one is using stale values that it read
    without the lock.
  
  MFC after:    1 week
  Sponsored by: Chelsio Communications

Modified:
  head/sys/dev/cxgbe/t4_sge.c

Modified: head/sys/dev/cxgbe/t4_sge.c
==============================================================================
--- head/sys/dev/cxgbe/t4_sge.c Sat Sep  9 03:09:02 2017        (r323342)
+++ head/sys/dev/cxgbe/t4_sge.c Sat Sep  9 05:12:14 2017        (r323343)
@@ -2354,7 +2354,7 @@ start_wrq_wr(struct sge_wrq *wrq, int len16, struct wr
 
        EQ_LOCK(eq);
 
-       if (!STAILQ_EMPTY(&wrq->wr_list))
+       if (TAILQ_EMPTY(&wrq->incomplete_wrs) && !STAILQ_EMPTY(&wrq->wr_list))
                drain_wrq_wr_list(sc, wrq);
 
        if (!STAILQ_EMPTY(&wrq->wr_list)) {
@@ -2408,9 +2408,6 @@ commit_wrq_wr(struct sge_wrq *wrq, void *w, struct wrq
                return;
        }
 
-       ndesc = cookie->ndesc;  /* Can be more than SGE_MAX_WR_NDESC here. */
-       pidx = cookie->pidx;
-       MPASS(pidx >= 0 && pidx < eq->sidx);
        if (__predict_false(w == &wrq->ss[0])) {
                int n = (eq->sidx - wrq->ss_pidx) * EQ_ESIZE;
 
@@ -2422,6 +2419,9 @@ commit_wrq_wr(struct sge_wrq *wrq, void *w, struct wrq
                wrq->tx_wrs_direct++;
 
        EQ_LOCK(eq);
+       ndesc = cookie->ndesc;  /* Can be more than SGE_MAX_WR_NDESC here. */
+       pidx = cookie->pidx;
+       MPASS(pidx >= 0 && pidx < eq->sidx);
        prev = TAILQ_PREV(cookie, wrq_incomplete_wrs, link);
        next = TAILQ_NEXT(cookie, link);
        if (prev == NULL) {
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to