diff options
author | loos <loos@FreeBSD.org> | 2013-09-06 12:47:14 +0000 |
---|---|---|
committer | loos <loos@FreeBSD.org> | 2013-09-06 12:47:14 +0000 |
commit | 3263427a2eb3c2dcf28cdcc849a9b31fa8db4895 (patch) | |
tree | 7e7b79970afd83d0421d0c44a09435fb320fad7e /sys/mips | |
parent | 63750491ac270cc819615c6479c8fdaa65916dc4 (diff) | |
download | FreeBSD-src-3263427a2eb3c2dcf28cdcc849a9b31fa8db4895.zip FreeBSD-src-3263427a2eb3c2dcf28cdcc849a9b31fa8db4895.tar.gz |
Fix the leakage of dma tags on if_arge. The leak occur when arge_start()
add some packet(s) to tx ring and arge_stop() is called before receive the
sent packet interrupt from hardware. Fix arge_stop() to unload the in use
dma tags and free the associated mbuf.
PR: 178319, 163670
Approved by: adrian (mentor)
Diffstat (limited to 'sys/mips')
-rw-r--r-- | sys/mips/atheros/if_arge.c | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/sys/mips/atheros/if_arge.c b/sys/mips/atheros/if_arge.c index 21b945f..aabab52 100644 --- a/sys/mips/atheros/if_arge.c +++ b/sys/mips/atheros/if_arge.c @@ -142,6 +142,7 @@ static int arge_resume(device_t); static int arge_rx_ring_init(struct arge_softc *); static void arge_rx_ring_free(struct arge_softc *sc); static int arge_tx_ring_init(struct arge_softc *); +static void arge_tx_ring_free(struct arge_softc *); #ifdef DEVICE_POLLING static int arge_poll(struct ifnet *, enum poll_cmd, int); #endif @@ -1278,6 +1279,7 @@ arge_stop(struct arge_softc *sc) /* Flush FIFO and free any existing mbufs */ arge_flush_ddr(sc); arge_rx_ring_free(sc); + arge_tx_ring_free(sc); } @@ -1708,6 +1710,30 @@ arge_tx_ring_init(struct arge_softc *sc) } /* + * Free the Tx ring, unload any pending dma transaction and free the mbuf. + */ +static void +arge_tx_ring_free(struct arge_softc *sc) +{ + struct arge_txdesc *txd; + int i; + + /* Free the Tx buffers. */ + for (i = 0; i < ARGE_TX_RING_COUNT; i++) { + txd = &sc->arge_cdata.arge_txdesc[i]; + if (txd->tx_dmamap) { + bus_dmamap_sync(sc->arge_cdata.arge_tx_tag, + txd->tx_dmamap, BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(sc->arge_cdata.arge_tx_tag, + txd->tx_dmamap); + } + if (txd->tx_m) + m_freem(txd->tx_m); + txd->tx_m = NULL; + } +} + +/* * Initialize the RX descriptors and allocate mbufs for them. Note that * we arrange the descriptors in a closed ring, so that the last descriptor * points back to the first. |