summaryrefslogtreecommitdiffstats
path: root/sys/dev/usb/wlan/if_run.c
diff options
context:
space:
mode:
authoradrian <adrian@FreeBSD.org>2015-10-04 05:22:17 +0000
committeradrian <adrian@FreeBSD.org>2015-10-04 05:22:17 +0000
commitb30c9f839ead5c7ffeaf62cabca97b6d2ba948c8 (patch)
tree967d49110fa64108307aadb68e6eeecea2afc284 /sys/dev/usb/wlan/if_run.c
parent1224cdf37680b1a0eb3b72bfb00bc952b35d4961 (diff)
downloadFreeBSD-src-b30c9f839ead5c7ffeaf62cabca97b6d2ba948c8.zip
FreeBSD-src-b30c9f839ead5c7ffeaf62cabca97b6d2ba948c8.tar.gz
Fix run(4) mbuf queue flushing / freeing.
Ensure things are freed during interface stop, or start may end up never being able to transmit a full queue.
Diffstat (limited to 'sys/dev/usb/wlan/if_run.c')
-rw-r--r--sys/dev/usb/wlan/if_run.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/sys/dev/usb/wlan/if_run.c b/sys/dev/usb/wlan/if_run.c
index e620afd..fe9d477 100644
--- a/sys/dev/usb/wlan/if_run.c
+++ b/sys/dev/usb/wlan/if_run.c
@@ -831,6 +831,21 @@ detach:
return (ENXIO);
}
+static void
+run_drain_mbufq(struct run_softc *sc)
+{
+ struct mbuf *m;
+ struct ieee80211_node *ni;
+
+ RUN_LOCK_ASSERT(sc, MA_OWNED);
+ while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
+ ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
+ m->m_pkthdr.rcvif = NULL;
+ ieee80211_free_node(ni);
+ m_freem(m);
+ }
+}
+
static int
run_detach(device_t self)
{
@@ -852,6 +867,9 @@ run_detach(device_t self)
/* free TX list, if any */
for (i = 0; i != RUN_EP_QUEUES; i++)
run_unsetup_tx_list(sc, &sc->sc_epq[i]);
+
+ /* Free TX queue */
+ run_drain_mbufq(sc);
RUN_UNLOCK(sc);
if (sc->sc_ic.ic_softc == sc) {
@@ -862,7 +880,6 @@ run_detach(device_t self)
ieee80211_ifdetach(ic);
}
- mbufq_drain(&sc->sc_snd);
mtx_destroy(&sc->sc_mtx);
return (0);
@@ -6172,6 +6189,8 @@ run_stop(void *arg)
RUN_LOCK(sc);
+ run_drain_mbufq(sc);
+
if (sc->rx_m != NULL) {
m_free(sc->rx_m);
sc->rx_m = NULL;
OpenPOWER on IntegriCloud