]> xenbits.xensource.com Git - people/julieng/freebsd.git/commitdiff
Random zyd(4) fixes to bring TX handling in line with rsu, etc
authoradrian <adrian@FreeBSD.org>
Sun, 4 Oct 2015 04:44:06 +0000 (04:44 +0000)
committeradrian <adrian@FreeBSD.org>
Sun, 4 Oct 2015 04:44:06 +0000 (04:44 +0000)
* don't free buffers in the TX routine, only in transmit/raw_xmit
* free nodes + references
* .. and free those nodes/references /before/ net80211 detach

Tested:

* STA mode: zyd0: HMAC ZD1211B, FW 47.25, RF AL2230 S0, PA0 LED 0 BE0 NP1 Gain1 F0

sys/dev/usb/wlan/if_zyd.c

index 5a59d379469222a569d9f010a10407d1921ec96c..ed70d19a43e2ad49fc63b227f24c3db3e87639f0 100644 (file)
@@ -420,6 +420,22 @@ detach:
        return (ENXIO);                 /* failure */
 }
 
+static void
+zyd_drain_mbufq(struct zyd_softc *sc)
+{
+       struct mbuf *m;
+       struct ieee80211_node *ni;
+
+       ZYD_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
 zyd_detach(device_t dev)
 {
@@ -433,6 +449,7 @@ zyd_detach(device_t dev)
         */
        ZYD_LOCK(sc);
        sc->sc_flags |= ZYD_FLAG_DETACHED;
+       zyd_drain_mbufq(sc);
        STAILQ_INIT(&sc->tx_q);
        STAILQ_INIT(&sc->tx_free);
        ZYD_UNLOCK(sc);
@@ -451,7 +468,6 @@ zyd_detach(device_t dev)
 
        if (ic->ic_softc == sc)
                ieee80211_ifdetach(ic);
-       mbufq_drain(&sc->sc_snd);
        mtx_destroy(&sc->sc_mtx);
 
        return (0);
@@ -2443,7 +2459,6 @@ zyd_tx_start(struct zyd_softc *sc, struct mbuf *m0, struct ieee80211_node *ni)
        if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) {
                k = ieee80211_crypto_encap(ni, m0);
                if (k == NULL) {
-                       m_freem(m0);
                        return (ENOBUFS);
                }
                /* packet header may have moved, reset our local pointer */
@@ -2555,6 +2570,7 @@ zyd_start(struct zyd_softc *sc)
                ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
                if (zyd_tx_start(sc, m, ni) != 0) {
                        ieee80211_free_node(ni);
+                       m_freem(m);
                        if_inc_counter(ni->ni_vap->iv_ifp,
                            IFCOUNTER_OERRORS, 1);
                        break;
@@ -2592,6 +2608,7 @@ zyd_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
        if (zyd_tx_start(sc, m, ni) != 0) {
                ZYD_UNLOCK(sc);
                ieee80211_free_node(ni);
+               m_freem(m);
                return (EIO);
        }
        ZYD_UNLOCK(sc);
@@ -2738,6 +2755,7 @@ zyd_stop(struct zyd_softc *sc)
        ZYD_LOCK_ASSERT(sc, MA_OWNED);
 
        sc->sc_flags &= ~ZYD_FLAG_RUNNING;
+       zyd_drain_mbufq(sc);
 
        /*
         * Drain all the transfers, if not already drained: