diff options
author | adrian <adrian@FreeBSD.org> | 2013-05-21 18:02:54 +0000 |
---|---|---|
committer | adrian <adrian@FreeBSD.org> | 2013-05-21 18:02:54 +0000 |
commit | c283b0b0aedb8f9857faaa84acf02ecc01957958 (patch) | |
tree | b437eb21d7076d263e6e3a1eacf56014dd3110d9 /sys | |
parent | 075c3eda472bf38f7728bc1b95cd32b998c524b9 (diff) | |
download | FreeBSD-src-c283b0b0aedb8f9857faaa84acf02ecc01957958.zip FreeBSD-src-c283b0b0aedb8f9857faaa84acf02ecc01957958.tar.gz |
Enable the use of TDMA on an 802.11n channel (with aggregation disabled,
of course.)
There's a few things that needed to happen:
* In case someone decides to set the beacon transmission rate to be
at an MCS rate, use the MCS-aware version of the duration calculation
to figure out how long the received beacon frame was.
* If TxOP enforcing is available on the hardware and we're doing TDMA,
enable it after a reset and set the TDMA guard interval to zero.
This seems to behave fine.
TODO:
* Although I haven't yet seen packet loss, the PHY errors that would be
triggered (specifically Transmit-Override-Receive) aren't enabled
by the 11n HAL. I'll have to do some work to enable these PHY errors
for debugging.
What broke:
* My recent changes to the TX queue handling has resulted in the driver
not keeping the hardware queue properly filled when doing non-aggregate
traffic. I have a patch to commit soon which fixes this situation
(albeit by reminding me about how my ath driver locking isn't working
out, sigh.)
So if you want to test this without updating to the next set of patches
that I commit, just bump the sysctl dev.ath.X.hwq_limit from 2 to 32.
Tested:
* AR5416 <-> AR5416, with ampdu disabled, HT40, 5GHz, MCS12+Short-GI.
I saw 30mbit/sec in both directions using a bidirectional UDP test.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/ath/if_ath.c | 37 | ||||
-rw-r--r-- | sys/dev/ath/if_ath_tdma.c | 47 | ||||
-rw-r--r-- | sys/dev/ath/if_athvar.h | 11 |
3 files changed, 89 insertions, 6 deletions
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 4744d75..6f5d9bf 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -670,6 +670,7 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) sc->sc_hastsfadd = ath_hal_hastsfadjust(ah); sc->sc_rxslink = ath_hal_self_linked_final_rxdesc(ah); sc->sc_rxtsf32 = ath_hal_has_long_rxdesc_tsf(ah); + sc->sc_hasenforcetxop = ath_hal_hasenforcetxop(ah); if (ath_hal_hasfastframes(ah)) ic->ic_caps |= IEEE80211_C_FF; wmodes = ath_hal_getwirelessmodes(ah); @@ -1586,6 +1587,15 @@ ath_resume(struct ath_softc *sc) /* Let spectral at in case spectral is enabled */ ath_spectral_enable(sc, ic->ic_curchan); + /* + * If we're doing TDMA, enforce the TXOP limitation for chips that + * support it. + */ + if (sc->sc_hasenforcetxop && sc->sc_tdma) + ath_hal_setenforcetxop(sc->sc_ah, 1); + else + ath_hal_setenforcetxop(sc->sc_ah, 0); + /* Restore the LED configuration */ ath_led_config(sc); ath_hal_setledstate(ah, HAL_LED_INIT); @@ -2034,6 +2044,15 @@ ath_init(void *arg) ath_spectral_enable(sc, ic->ic_curchan); /* + * If we're doing TDMA, enforce the TXOP limitation for chips that + * support it. + */ + if (sc->sc_hasenforcetxop && sc->sc_tdma) + ath_hal_setenforcetxop(sc->sc_ah, 1); + else + ath_hal_setenforcetxop(sc->sc_ah, 0); + + /* * Likewise this is set during reset so update * state cached in the driver. */ @@ -2348,6 +2367,15 @@ ath_reset(struct ifnet *ifp, ATH_RESET_TYPE reset_type) /* Let spectral at in case spectral is enabled */ ath_spectral_enable(sc, ic->ic_curchan); + /* + * If we're doing TDMA, enforce the TXOP limitation for chips that + * support it. + */ + if (sc->sc_hasenforcetxop && sc->sc_tdma) + ath_hal_setenforcetxop(sc->sc_ah, 1); + else + ath_hal_setenforcetxop(sc->sc_ah, 0); + if (ath_startrecv(sc) != 0) /* restart recv */ if_printf(ifp, "%s: unable to start recv logic\n", __func__); /* @@ -4869,6 +4897,15 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan) ath_spectral_enable(sc, chan); /* + * If we're doing TDMA, enforce the TXOP limitation for chips + * that support it. + */ + if (sc->sc_hasenforcetxop && sc->sc_tdma) + ath_hal_setenforcetxop(sc->sc_ah, 1); + else + ath_hal_setenforcetxop(sc->sc_ah, 0); + + /* * Re-enable rx framework. */ if (ath_startrecv(sc) != 0) { diff --git a/sys/dev/ath/if_ath_tdma.c b/sys/dev/ath/if_ath_tdma.c index 1d9a95f..c075d01 100644 --- a/sys/dev/ath/if_ath_tdma.c +++ b/sys/dev/ath/if_ath_tdma.c @@ -277,9 +277,19 @@ ath_tdma_config(struct ath_softc *sc, struct ieee80211vap *vap) rix = ath_tx_findrix(sc, tp->ucastrate); else rix = ath_tx_findrix(sc, tp->mcastrate); - /* XXX short preamble assumed */ - sc->sc_tdmaguard = ath_hal_computetxtime(ah, sc->sc_currates, - ifp->if_mtu + IEEE80211_MAXOVERHEAD, rix, AH_TRUE); + + /* + * If the chip supports enforcing TxOP on transmission, + * we can just delete the guard window. It isn't at all required. + */ + if (sc->sc_hasenforcetxop) { + sc->sc_tdmaguard = 0; + } else { + /* XXX short preamble assumed */ + /* XXX non-11n rate assumed */ + sc->sc_tdmaguard = ath_hal_computetxtime(ah, sc->sc_currates, + ifp->if_mtu + IEEE80211_MAXOVERHEAD, rix, AH_TRUE); + } ath_hal_intrset(ah, 0); @@ -392,8 +402,35 @@ ath_tdma_update(struct ieee80211_node *ni, * the packet just received. */ rix = rt->rateCodeToIndex[rs->rs_rate]; - txtime = ath_hal_computetxtime(ah, rt, rs->rs_datalen, rix, - rt->info[rix].shortPreamble); + + /* + * To calculate the packet duration for legacy rates, we + * only need the rix and preamble. + * + * For 11n non-aggregate frames, we also need the channel + * width and short/long guard interval. + * + * For 11n aggregate frames, the required hacks are a little + * more subtle. You need to figure out the frame duration + * for each frame, including the delimiters. However, when + * a frame isn't received successfully, we won't hear it + * (unless you enable reception of CRC errored frames), so + * your duration calculation is going to be off. + * + * However, we can assume that the beacon frames won't be + * transmitted as aggregate frames, so we should be okay. + * Just add a check to ensure that we aren't handed something + * bad. + * + * For ath_hal_pkt_txtime() - for 11n rates, shortPreamble is + * actually short guard interval. For legacy rates, + * it's short preamble. + */ + txtime = ath_hal_pkt_txtime(ah, rt, rs->rs_datalen, + rix, + !! (rs->rs_flags & HAL_RX_2040), + (rix & 0x80) ? + (! (rs->rs_flags & HAL_RX_GI)) : rt->info[rix].shortPreamble); /* NB: << 9 is to cvt to TU and /2 */ nextslot = (rstamp - txtime) + (sc->sc_tdmabintval << 9); diff --git a/sys/dev/ath/if_athvar.h b/sys/dev/ath/if_athvar.h index 02f6432..f7d262e 100644 --- a/sys/dev/ath/if_athvar.h +++ b/sys/dev/ath/if_athvar.h @@ -627,7 +627,8 @@ struct ath_softc { */ u_int32_t sc_use_ent : 1, sc_rx_stbc : 1, - sc_tx_stbc : 1; + sc_tx_stbc : 1, + sc_hasenforcetxop : 1; /* support enforce TxOP */ int sc_cabq_enable; /* Enable cabq transmission */ @@ -1256,6 +1257,14 @@ void ath_intr(void *); ath_hal_setcapability(_ah, HAL_CAP_INTMIT, \ HAL_CAP_INTMIT_ENABLE, _v, NULL) +#define ath_hal_hasenforcetxop(_ah) \ + (ath_hal_getcapability(_ah, HAL_CAP_ENFORCE_TXOP, 0, NULL) == HAL_OK) +#define ath_hal_getenforcetxop(_ah) \ + (ath_hal_getcapability(_ah, HAL_CAP_ENFORCE_TXOP, 1, NULL) == HAL_OK) +#define ath_hal_setenforcetxop(_ah, _v) \ + ath_hal_setcapability(_ah, HAL_CAP_ENFORCE_TXOP, 1, _v, NULL) + + /* EDMA definitions */ #define ath_hal_hasedma(_ah) \ (ath_hal_getcapability(_ah, HAL_CAP_ENHANCED_DMA_SUPPORT, \ |