Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 22 Dec 2013 22:24:17 +0000 (UTC)
From:      Warner Losh <imp@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-releng@freebsd.org
Subject:   svn commit: r259747 - releng/10.0/sys/arm/at91
Message-ID:  <201312222224.rBMMOHOH057885@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: imp
Date: Sun Dec 22 22:24:17 2013
New Revision: 259747
URL: http://svnweb.freebsd.org/changeset/base/259747

Log:
  Merge from stable/10 r259381:
  
  MFC r259212, r259220:
  
   Fix one race and one fence post error. When the TX buffer was
   completely full, we'd not complete any of the mbufs due to the fence
   post error (this creates a large leak). When this is fixed, we still
   leak, but at a much smaller rate due to a race between ateintr and
   atestart_locked as well as an asymmetry where atestart_locked is
   called from elsewhere.  Ensure that we free in-flight packets that
   have completed there as well. Also remove needless check for NULL on
   mb, checked earlier in the loop and simplify a redundant if.
  
  Approved by:	re@ (gjb@)

Modified:
  releng/10.0/sys/arm/at91/if_ate.c
Directory Properties:
  releng/10.0/   (props changed)

Modified: releng/10.0/sys/arm/at91/if_ate.c
==============================================================================
--- releng/10.0/sys/arm/at91/if_ate.c	Sun Dec 22 22:20:17 2013	(r259746)
+++ releng/10.0/sys/arm/at91/if_ate.c	Sun Dec 22 22:24:17 2013	(r259747)
@@ -946,10 +946,8 @@ ate_intr(void *xsc)
 
 			} while (!done);
 
-			if (mb != NULL) {
-				ifp->if_ipackets++;
-				(*ifp->if_input)(ifp, mb);
-			}
+			ifp->if_ipackets++;
+			(*ifp->if_input)(ifp, mb);
 		}
 	}
 
@@ -973,16 +971,14 @@ ate_intr(void *xsc)
 				sc->tx_descs[sc->txtail + 1].status |= ETHB_TX_USED;
 		}
 
-		while (sc->txtail != sc->txhead &&
-		    sc->tx_descs[sc->txtail].status & ETHB_TX_USED ) {
-
+		while ((sc->tx_descs[sc->txtail].status & ETHB_TX_USED) &&
+		    sc->sent_mbuf[sc->txtail] != NULL) {
 			bus_dmamap_sync(sc->mtag, sc->tx_map[sc->txtail],
 			    BUS_DMASYNC_POSTWRITE);
 			bus_dmamap_unload(sc->mtag, sc->tx_map[sc->txtail]);
 			m_freem(sc->sent_mbuf[sc->txtail]);
 			sc->tx_descs[sc->txtail].addr = 0;
 			sc->sent_mbuf[sc->txtail] = NULL;
-
 			ifp->if_opackets++;
 			sc->txtail = NEXT_TX_IDX(sc, sc->txtail);
 		}
@@ -1117,12 +1113,10 @@ atestart_locked(struct ifnet *ifp)
 		 * xmit packets.  We use OACTIVE to indicate "we can stuff more
 		 * into our buffers (clear) or not (set)."
 		 */
-		if (!sc->is_emacb) {
-			/* RM9200 has only two hardware entries */
-			if (!sc->is_emacb && (RD4(sc, ETH_TSR) & ETH_TSR_BNQ) == 0) {
-				ifp->if_drv_flags |= IFF_DRV_OACTIVE;
-				return;
-			}
+		/* RM9200 has only two hardware entries */
+		if (!sc->is_emacb && (RD4(sc, ETH_TSR) & ETH_TSR_BNQ) == 0) {
+			ifp->if_drv_flags |= IFF_DRV_OACTIVE;
+			return;
 		}
 
 		IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
@@ -1145,6 +1139,21 @@ atestart_locked(struct ifnet *ifp)
 			m_freem(m);
 			continue;
 		}
+
+		/*
+		 * There's a small race between the loop in ate_intr finishing
+		 * and the check above to see if the packet was finished, as well
+		 * as when atestart gets called via other paths. Lose the race
+		 * gracefully and free the mbuf...
+		 */
+		if (sc->sent_mbuf[sc->txhead] != NULL) {
+			bus_dmamap_sync(sc->mtag, sc->tx_map[sc->txtail],
+			    BUS_DMASYNC_POSTWRITE);
+			bus_dmamap_unload(sc->mtag, sc->tx_map[sc->txtail]);
+			m_free(sc->sent_mbuf[sc->txhead]);
+			ifp->if_opackets++;
+		}
+		
 		sc->sent_mbuf[sc->txhead] = m;
 
 		bus_dmamap_sync(sc->mtag, sc->tx_map[sc->txhead],



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