[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.
This commit is contained in:
adrian 2016-04-05 22:14:21 +00:00
parent a7d48b9042
commit 8eb992ff9f
2 changed files with 81 additions and 5 deletions

View File

@ -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, struct urtwn_data *data)
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, struct urtwn_data *data, int status)
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 mbuf *m,
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)) {

View File

@ -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;