svn commit: r297596 - head/sys/dev/urtwn
Adrian Chadd
adrian at FreeBSD.org
Tue Apr 5 22:14:23 UTC 2016
Author: adrian
Date: Tue Apr 5 22:14:21 2016
New Revision: 297596
URL: https://svnweb.freebsd.org/changeset/base/297596
Log:
[urtwn] first cut of getting the fast-frames / amsdu support in shape.
The urtwn hardware transmits FF/A-MSDU just fine - it takes an 802.11
frame and will dutifully send the thing.
So:
* bump RX queue up from 1. Why's it 1? That's really silly.
* Add the "software A-MSDU" encap capability bit.
* bump the TX buffer size up so we can at least send A-MSDU frames.
* track active frames submitted to the NIC - we can't make assumptions
about how many are in flight in the NIC though. For 88E parts we
could use per-packet TX indication, but for R92 parts we can't.
So, just fake it somewhat.
* Kick the transmit queue when we finish reception; try to avoid stalls.
* Kick the FF queue a little more regularly.
A-MSDU TX won't happen until the net80211 side is done, but atheros
fast-frames support should now work.
Tested:
* urtwn0: MAC/BB RTL8188EU, RF 6052 1T1R ; A-MSDU transmit.
Modified:
head/sys/dev/urtwn/if_urtwn.c
head/sys/dev/urtwn/if_urtwnvar.h
Modified: head/sys/dev/urtwn/if_urtwn.c
==============================================================================
--- head/sys/dev/urtwn/if_urtwn.c Tue Apr 5 22:01:56 2016 (r297595)
+++ head/sys/dev/urtwn/if_urtwn.c Tue Apr 5 22:14:21 2016 (r297596)
@@ -70,6 +70,9 @@ __FBSDID("$FreeBSD$");
#include <net80211/ieee80211_regdomain.h>
#include <net80211/ieee80211_radiotap.h>
#include <net80211/ieee80211_ratectl.h>
+#ifdef IEEE80211_SUPPORT_SUPERG
+#include <net80211/ieee80211_superg.h>
+#endif
#include <dev/usb/usb.h>
#include <dev/usb/usbdi.h>
@@ -577,6 +580,8 @@ urtwn_attach(device_t self)
#endif
| IEEE80211_C_WPA /* 802.11i */
| IEEE80211_C_WME /* 802.11e */
+ | IEEE80211_C_SWAMSDUTX /* Do software A-MSDU TX */
+ | IEEE80211_C_FF /* Atheros fast-frames */
;
ic->ic_cryptocaps =
@@ -894,6 +899,15 @@ urtwn_report_intr(struct usb_xfer *xfer,
buf = data->buf;
stat = (struct r92c_rx_stat *)buf;
+ /*
+ * For 88E chips we can tie the FF flushing here;
+ * this is where we do know exactly how deep the
+ * transmit queue is.
+ *
+ * But it won't work for R92 chips, so we can't
+ * take the easy way out.
+ */
+
if (sc->chip & URTWN_CHIP_88E) {
int report_sel = MS(le32toh(stat->rxdw3), R88E_RXDW3_RPT);
@@ -1101,7 +1115,7 @@ tr_setup:
data = STAILQ_FIRST(&sc->sc_rx_inactive);
if (data == NULL) {
KASSERT(m == NULL, ("mbuf isn't NULL"));
- return;
+ goto finish;
}
STAILQ_REMOVE_HEAD(&sc->sc_rx_inactive, next);
STAILQ_INSERT_TAIL(&sc->sc_rx_active, data, next);
@@ -1131,7 +1145,6 @@ tr_setup:
(void)ieee80211_input_all(ic, m, rssi - nf,
nf);
}
-
URTWN_LOCK(sc);
m = next;
}
@@ -1150,6 +1163,20 @@ tr_setup:
}
break;
}
+finish:
+ /* Finished receive; age anything left on the FF queue by a little bump */
+ /*
+ * XXX TODO: just make this a callout timer schedule so we can
+ * flush the FF staging queue if we're approaching idle.
+ */
+#ifdef IEEE80211_SUPPORT_SUPERG
+ URTWN_UNLOCK(sc);
+ ieee80211_ff_age_all(ic, 1);
+ URTWN_LOCK(sc);
+#endif
+
+ /* Kick-start more transmit in case we stalled */
+ urtwn_start(sc);
}
static void
@@ -1161,6 +1188,9 @@ urtwn_txeof(struct urtwn_softc *sc, stru
if (data->ni != NULL) /* not a beacon frame */
ieee80211_tx_complete(data->ni, data->m, status);
+ if (sc->sc_tx_n_active > 0)
+ sc->sc_tx_n_active--;
+
data->ni = NULL;
data->m = NULL;
@@ -1269,6 +1299,9 @@ static void
urtwn_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error)
{
struct urtwn_softc *sc = usbd_xfer_softc(xfer);
+#ifdef IEEE80211_SUPPORT_SUPERG
+ struct ieee80211com *ic = &sc->sc_ic;
+#endif
struct urtwn_data *data;
URTWN_ASSERT_LOCKED(sc);
@@ -1287,12 +1320,14 @@ tr_setup:
if (data == NULL) {
URTWN_DPRINTF(sc, URTWN_DEBUG_XMIT,
"%s: empty pending queue\n", __func__);
+ sc->sc_tx_n_active = 0;
goto finish;
}
STAILQ_REMOVE_HEAD(&sc->sc_tx_pending, next);
STAILQ_INSERT_TAIL(&sc->sc_tx_active, data, next);
usbd_xfer_set_frame_data(xfer, 0, data->buf, data->buflen);
usbd_transfer_submit(xfer);
+ sc->sc_tx_n_active++;
break;
default:
data = STAILQ_FIRST(&sc->sc_tx_active);
@@ -1307,6 +1342,35 @@ tr_setup:
break;
}
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 <= 1) {
+ /* XXX ew - net80211 should defer this for us! */
+
+ /*
+ * Note: this sc_tx_n_active currently tracks
+ * the number of pending transmit submissions
+ * and not the actual depth of the TX frames
+ * pending to the hardware. That means that
+ * we're going to end up with some sub-optimal
+ * aggregation behaviour.
+ */
+ /*
+ * XXX TODO: just make this a callout timer schedule so we can
+ * flush the FF staging queue if we're approaching idle.
+ */
+ URTWN_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);
+ URTWN_LOCK(sc);
+ }
+#endif
/* Kick-start more transmit */
urtwn_start(sc);
}
@@ -3153,6 +3217,11 @@ urtwn_start(struct urtwn_softc *sc)
}
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
m->m_pkthdr.rcvif = NULL;
+
+ URTWN_DPRINTF(sc, URTWN_DEBUG_XMIT, "%s: called; m=%p\n",
+ __func__,
+ m);
+
if (urtwn_tx_data(sc, ni, m, bf) != 0) {
if_inc_counter(ni->ni_vap->iv_ifp,
IFCOUNTER_OERRORS, 1);
@@ -5326,6 +5395,10 @@ urtwn_raw_xmit(struct ieee80211_node *ni
struct urtwn_data *bf;
int error;
+ URTWN_DPRINTF(sc, URTWN_DEBUG_XMIT, "%s: called; m=%p\n",
+ __func__,
+ m);
+
/* prevent management frames from being sent if we're not ready */
URTWN_LOCK(sc);
if (!(sc->sc_flags & URTWN_RUNNING)) {
Modified: head/sys/dev/urtwn/if_urtwnvar.h
==============================================================================
--- head/sys/dev/urtwn/if_urtwnvar.h Tue Apr 5 22:01:56 2016 (r297595)
+++ head/sys/dev/urtwn/if_urtwnvar.h Tue Apr 5 22:14:21 2016 (r297596)
@@ -17,12 +17,14 @@
* $FreeBSD$
*/
-#define URTWN_RX_LIST_COUNT 1
+#define URTWN_RX_LIST_COUNT 64
#define URTWN_TX_LIST_COUNT 8
#define URTWN_HOST_CMD_RING_COUNT 32
-#define URTWN_RXBUFSZ (16 * 1024)
-#define URTWN_TXBUFSZ (sizeof(struct r92c_tx_desc) + IEEE80211_MAX_LEN)
+#define URTWN_RXBUFSZ (8 * 1024)
+//#define URTWN_TXBUFSZ (sizeof(struct r92c_tx_desc) + IEEE80211_MAX_LEN)
+/* Leave enough space for an A-MSDU frame */
+#define URTWN_TXBUFSZ (16 * 1024)
#define URTWN_RX_DESC_SIZE (sizeof(struct r92c_rx_stat))
#define URTWN_TX_DESC_SIZE (sizeof(struct r92c_tx_desc))
@@ -195,6 +197,7 @@ struct urtwn_softc {
urtwn_datahead sc_rx_inactive;
struct urtwn_data sc_tx[URTWN_TX_LIST_COUNT];
urtwn_datahead sc_tx_active;
+ int sc_tx_n_active;
urtwn_datahead sc_tx_inactive;
urtwn_datahead sc_tx_pending;
More information about the svn-src-all
mailing list