From owner-svn-src-all@FreeBSD.ORG Wed Dec 11 05:32:29 2013 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [8.8.178.115]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id B0956E64; Wed, 11 Dec 2013 05:32:29 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.freebsd.org (Postfix) with ESMTPS id 9162316EF; Wed, 11 Dec 2013 05:32:29 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.7/8.14.7) with ESMTP id rBB5WTiC006662; Wed, 11 Dec 2013 05:32:29 GMT (envelope-from imp@svn.freebsd.org) Received: (from imp@localhost) by svn.freebsd.org (8.14.7/8.14.7/Submit) id rBB5WTk0006661; Wed, 11 Dec 2013 05:32:29 GMT (envelope-from imp@svn.freebsd.org) Message-Id: <201312110532.rBB5WTk0006661@svn.freebsd.org> From: Warner Losh Date: Wed, 11 Dec 2013 05:32:29 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r259212 - head/sys/arm/at91 X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.17 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 11 Dec 2013 05:32:29 -0000 Author: imp Date: Wed Dec 11 05:32:29 2013 New Revision: 259212 URL: http://svnweb.freebsd.org/changeset/base/259212 Log: 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. MFC after: 3 days Modified: head/sys/arm/at91/if_ate.c Modified: head/sys/arm/at91/if_ate.c ============================================================================== --- head/sys/arm/at91/if_ate.c Wed Dec 11 04:31:40 2013 (r259211) +++ head/sys/arm/at91/if_ate.c Wed Dec 11 05:32:29 2013 (r259212) @@ -947,10 +947,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); } } @@ -974,16 +972,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); } @@ -1118,12 +1114,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); @@ -1146,6 +1140,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. Loose 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],