Fix the TDMA nexttbtt programming for 802.11n chips.

The existing logic wrapped programming nexttbtt at 65535 TU.
This is not good enough for the 11n chips, whose nexttbtt register
(GENERIC_TIMER_0) has an initial value from 0..2^31-1 TSF.
So converting the TU to TSF had the counter wrap at (65535 << 10) TSF.

Once this wrap occured, the nexttbtt value was very very low, much
lower than the current TSF value.  At this point, the nexttbtt timer
would constantly fire, leading to the TX queue being constantly gated
open.. and when this occured, the sender was not correctly transmitting
in its slot but just able to continuously transmit.  The master would
then delay transmitting its beacon until after the air became free
(which I guess would be after the burst interval, before the next burst
interval would quickly follow) and that big delta in master beacon TX
would start causing big swings in the slot timing adjustment.

With this change, the nexttbtt value is allowed to go all the way up
to the maximum value permissable by the 32 bit representation.
I haven't yet tested it to that point; I really should.  The AR5212
HAL now filters out values above 65535 TU for the beacon configuration
(and the relevant legal values for SWBA, DBA and NEXTATIM) and the
AR5416 HAL just dutifully programs in what it should.

With this, TDMA is now useful on the 802.11n chips.

Tested:

* AR5416, AR9280 TDMA slave
* AR5413 TDMA slave
This commit is contained in:
adrian 2012-11-27 02:23:45 +00:00
parent dd88093c5e
commit c5c46f8668

View File

@ -281,7 +281,7 @@ ath_tdma_update(struct ieee80211_node *ni,
struct ath_softc *sc = ic->ic_ifp->if_softc;
struct ath_hal *ah = sc->sc_ah;
const HAL_RATE_TABLE *rt = sc->sc_currates;
u_int64_t tsf, rstamp, nextslot, nexttbtt;
u_int64_t tsf, rstamp, nextslot, nexttbtt, nexttbtt_full;
u_int32_t txtime, nextslottu;
int32_t tudelta, tsfdelta;
const struct ath_rx_status *rs;
@ -326,7 +326,11 @@ ath_tdma_update(struct ieee80211_node *ni,
rt->info[rix].shortPreamble);
/* NB: << 9 is to cvt to TU and /2 */
nextslot = (rstamp - txtime) + (sc->sc_tdmabintval << 9);
nextslottu = TSF_TO_TU(nextslot>>32, nextslot) & HAL_BEACON_PERIOD;
/*
* For 802.11n chips: nextslottu needs to be the full TSF space,
* not just 0..65535 TU.
*/
nextslottu = TSF_TO_TU(nextslot>>32, nextslot);
/*
* Retrieve the hardware NextTBTT in usecs
@ -350,7 +354,16 @@ ath_tdma_update(struct ieee80211_node *ni,
* value, tsfdelta ends up becoming very negative and all
* of the adjustments get very messed up.
*/
nexttbtt = ath_hal_getnexttbtt(ah) % (TU_TO_TSF(HAL_BEACON_PERIOD + 1));
/*
* We need to track the full nexttbtt rather than having it
* truncated at HAL_BEACON_PERIOD, as programming the
* nexttbtt (and related) registers for the 11n chips is
* actually going to take the full 32 bit space, rather than
* just 0..65535 TU.
*/
nexttbtt_full = ath_hal_getnexttbtt(ah);
nexttbtt = nexttbtt_full % (TU_TO_TSF(HAL_BEACON_PERIOD + 1));
tsfdelta = (int32_t)((nextslot % TU_TO_TSF(HAL_BEACON_PERIOD + 1)) - nexttbtt);
DPRINTF(sc, ATH_DEBUG_TDMA_TIMER,
@ -371,7 +384,7 @@ ath_tdma_update(struct ieee80211_node *ni,
TDMA_SAMPLE(sc->sc_avgtsfdeltap, 0);
TDMA_SAMPLE(sc->sc_avgtsfdeltam, 0);
}
tudelta = nextslottu - TSF_TO_TU(nexttbtt >> 32, nexttbtt);
tudelta = nextslottu - TSF_TO_TU(nexttbtt_full >> 32, nexttbtt_full);
/*
* Copy sender's timetstamp into tdma ie so they can