]> xenbits.xensource.com Git - people/julieng/freebsd.git/commitdiff
if_otus fixes; add fast-frames support.
authoradrian <adrian@FreeBSD.org>
Mon, 28 Sep 2015 01:09:48 +0000 (01:09 +0000)
committeradrian <adrian@FreeBSD.org>
Mon, 28 Sep 2015 01:09:48 +0000 (01:09 +0000)
Fast-frames:

* include opt_wlan.h ; tsk to not doing it earlier;
* add a tx pending tracking counter for seeing how deep
  the hardware TX queue is;
* add the frame aging code from if_ath;
* add fast-frames capability to the driver setup.

Bugs:

* free the buffers (and node references) before
  detaching net80211 state.  This prevents a use-after-free in
  the node free path where we've destroyed net80211 underneath it.

sys/dev/otus/if_otus.c
sys/dev/otus/if_otusreg.h

index 2343953598c148694c3f66c98c9d302614b2c56c..e60157adda9d7c1f2917e85c33835ec37f618acc 100644 (file)
@@ -24,6 +24,8 @@
 #include <sys/cdefs.h>
 __FBSDID("$FreeBSD$");
 
+#include "opt_wlan.h"
+
 #include <sys/param.h>
 #include <sys/endian.h>
 #include <sys/sockio.h>
@@ -60,6 +62,9 @@ __FBSDID("$FreeBSD$");
 #include <net80211/ieee80211_radiotap.h>
 #include <net80211/ieee80211_ratectl.h>
 #include <net80211/ieee80211_input.h>
+#ifdef IEEE80211_SUPPORT_SUPERG
+#include <net80211/ieee80211_superg.h>
+#endif
 
 #include <dev/usb/usb.h>
 #include <dev/usb/usbdi.h>
@@ -340,6 +345,7 @@ otus_detach(device_t self)
        taskqueue_drain(taskqueue_thread, &sc->tx_task);
        taskqueue_drain(taskqueue_thread, &sc->wme_update_task);
 
+       otus_close_pipes(sc);
 #if 0
        /* Wait for all queued asynchronous commands to complete. */
        usb_rem_wait_task(sc->sc_udev, &sc->sc_task);
@@ -348,7 +354,6 @@ otus_detach(device_t self)
 #endif
 
        ieee80211_ifdetach(ic);
-       otus_close_pipes(sc);
        mtx_destroy(&sc->sc_mtx);
        return 0;
 }
@@ -949,9 +954,12 @@ fail:      otus_close_pipes(sc);
 void
 otus_close_pipes(struct otus_softc *sc)
 {
+
+       OTUS_LOCK(sc);
        otus_free_tx_cmd_list(sc);
        otus_free_tx_list(sc);
        otus_free_rx_list(sc);
+       OTUS_UNLOCK(sc);
 
        usbd_transfer_unsetup(sc->sc_xfer, OTUS_N_XFER);
 }
@@ -1838,6 +1846,9 @@ tr_setup:
                        } else
                                (void)ieee80211_input_mimo_all(ic, m, NULL);
                }
+#ifdef IEEE80211_SUPPORT_SUPERG
+               ieee80211_ff_age_all(ic, 100);
+#endif
                OTUS_LOCK(sc);
                break;
        default:
@@ -1866,6 +1877,14 @@ otus_txeof(struct usb_xfer *xfer, struct otus_data *data)
 
        OTUS_LOCK_ASSERT(sc);
 
+       if (sc->sc_tx_n_active == 0) {
+               device_printf(sc->sc_dev,
+                   "%s: completed but tx_active=0\n",
+                   __func__);
+       } else {
+               sc->sc_tx_n_active--;
+       }
+
        if (data->m) {
                /* XXX status? */
                /* XXX we get TX status via the RX path.. */
@@ -1926,6 +1945,7 @@ tr_setup:
                if (data == NULL) {
                        OTUS_DPRINTF(sc, OTUS_DEBUG_XMIT,
                            "%s: empty pending queue sc %p\n", __func__, sc);
+                       sc->sc_tx_n_active = 0;
                        goto finish;
                }
                STAILQ_REMOVE_HEAD(&sc->sc_tx_pending[which], next);
@@ -1934,6 +1954,7 @@ tr_setup:
                OTUS_DPRINTF(sc, OTUS_DEBUG_XMIT,
                    "%s: submitting transfer %p\n", __func__, data);
                usbd_transfer_submit(xfer);
+               sc->sc_tx_n_active++;
                break;
        default:
                data = STAILQ_FIRST(&sc->sc_tx_active[which]);
@@ -1952,6 +1973,22 @@ tr_setup:
        }
 
 finish:
+#ifdef IEEE80211_SUPPORT_SUPERG
+       /*
+        * If the TX active queue drops below a certain
+        * threshold, ensure we age fast-frames out so they're
+        * transmitted.
+        */
+       if (sc->sc_tx_n_active < 2) {
+               /* XXX ew - net80211 should defer this for us! */
+               OTUS_UNLOCK(sc);
+               ieee80211_ff_flush(ic, WME_AC_VO);
+               ieee80211_ff_flush(ic, WME_AC_VI);
+               ieee80211_ff_flush(ic, WME_AC_BE);
+               ieee80211_ff_flush(ic, WME_AC_BK);
+               OTUS_LOCK(sc);
+       }
+#endif
        /* Kick TX */
        otus_tx_start(sc);
 }
index 35924529c554421585175c41de0da6dd26e30bdd..4f11b8dfd772ceafa385ea1e3b044c3ccbb41bab 100644 (file)
@@ -984,6 +984,10 @@ struct otus_softc {
        /* current noisefloor, from SET_FREQUENCY */
        int                             sc_nf[OTUS_NUM_CHAINS];
 
+       /* How many pending, active transmit frames */
+       int                             sc_tx_n_pending;
+       int                             sc_tx_n_active;
+
        const uint32_t                  *phy_vals;
 
        struct {