diff options
author | avos <avos@FreeBSD.org> | 2016-06-24 23:36:22 +0000 |
---|---|---|
committer | avos <avos@FreeBSD.org> | 2016-06-24 23:36:22 +0000 |
commit | 34ea438ec398ffe3fa9e5029d1e5a99d19eed24b (patch) | |
tree | a580c87e2c423f4debc5e39fc91667df02d9fbfe | |
parent | 70951739503fef6ff99a71f0515ee1eba2dbf895 (diff) | |
download | FreeBSD-src-34ea438ec398ffe3fa9e5029d1e5a99d19eed24b.zip FreeBSD-src-34ea438ec398ffe3fa9e5029d1e5a99d19eed24b.tar.gz |
urtwn: fix memory leak on device restart
Free data buffers every time when device is stopped, not when
it is detached; they are allocated at the initialization stage.
How-to-reproduce:
1) ifconfig wlan0 create wlandev urtwn0 up
2) vmstat -m | grep USBdev
3) service netif restart
4) vmstat -m | grep USBdev
Also, remove usbd_transfer_drain() call; it is already called by
usbd_transfer_unsetup().
Tested with RTL8188CUS, STA mode.
Approved by: re (marius)
-rw-r--r-- | sys/dev/urtwn/if_urtwn.c | 30 |
1 files changed, 9 insertions, 21 deletions
diff --git a/sys/dev/urtwn/if_urtwn.c b/sys/dev/urtwn/if_urtwn.c index 6ca31fa..eacc8bb 100644 --- a/sys/dev/urtwn/if_urtwn.c +++ b/sys/dev/urtwn/if_urtwn.c @@ -683,7 +683,6 @@ urtwn_detach(device_t self) { struct urtwn_softc *sc = device_get_softc(self); struct ieee80211com *ic = &sc->sc_ic; - unsigned int x; /* Prevent further ioctls. */ URTWN_LOCK(sc); @@ -698,26 +697,6 @@ urtwn_detach(device_t self) /* stop all USB transfers */ usbd_transfer_unsetup(sc->sc_xfer, URTWN_N_TRANSFER); - /* Prevent further allocations from RX/TX data lists. */ - URTWN_LOCK(sc); - STAILQ_INIT(&sc->sc_tx_active); - STAILQ_INIT(&sc->sc_tx_inactive); - STAILQ_INIT(&sc->sc_tx_pending); - - STAILQ_INIT(&sc->sc_rx_active); - STAILQ_INIT(&sc->sc_rx_inactive); - URTWN_UNLOCK(sc); - - /* drain USB transfers */ - for (x = 0; x != URTWN_N_TRANSFER; x++) - usbd_transfer_drain(sc->sc_xfer[x]); - - /* Free data buffers. */ - URTWN_LOCK(sc); - urtwn_free_tx_list(sc); - urtwn_free_rx_list(sc); - URTWN_UNLOCK(sc); - if (ic->ic_softc == sc) { ieee80211_draintask(ic, &sc->cmdq_task); ieee80211_ifdetach(ic); @@ -1359,12 +1338,19 @@ static void urtwn_free_rx_list(struct urtwn_softc *sc) { urtwn_free_list(sc, sc->sc_rx, URTWN_RX_LIST_COUNT); + + STAILQ_INIT(&sc->sc_rx_active); + STAILQ_INIT(&sc->sc_rx_inactive); } static void urtwn_free_tx_list(struct urtwn_softc *sc) { urtwn_free_list(sc, sc->sc_tx, URTWN_TX_LIST_COUNT); + + STAILQ_INIT(&sc->sc_tx_active); + STAILQ_INIT(&sc->sc_tx_inactive); + STAILQ_INIT(&sc->sc_tx_pending); } static void @@ -5579,6 +5565,8 @@ urtwn_stop(struct urtwn_softc *sc) urtwn_abort_xfers(sc); urtwn_drain_mbufq(sc); + urtwn_free_tx_list(sc); + urtwn_free_rx_list(sc); urtwn_power_off(sc); URTWN_UNLOCK(sc); } |