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