summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoravos <avos@FreeBSD.org>2016-06-24 23:36:22 +0000
committeravos <avos@FreeBSD.org>2016-06-24 23:36:22 +0000
commit34ea438ec398ffe3fa9e5029d1e5a99d19eed24b (patch)
treea580c87e2c423f4debc5e39fc91667df02d9fbfe
parent70951739503fef6ff99a71f0515ee1eba2dbf895 (diff)
downloadFreeBSD-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.c30
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);
}
OpenPOWER on IntegriCloud