[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:
parent
a7d48b9042
commit
8eb992ff9f
@ -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)) {
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user