Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 9 Sep 2017 05:12:14 +0000 (UTC)
From:      Navdeep Parhar <np@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r323343 - head/sys/dev/cxgbe
Message-ID:  <201709090512.v895CEpW031633@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
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) {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201709090512.v895CEpW031633>