diff --git a/sys/dev/ath/if_ath_beacon.c b/sys/dev/ath/if_ath_beacon.c index 1d1aa26831c..629457d45be 100644 --- a/sys/dev/ath/if_ath_beacon.c +++ b/sys/dev/ath/if_ath_beacon.c @@ -964,10 +964,30 @@ ath_beacon_config(struct ath_softc *sc, struct ieee80211vap *vap) /* NB: the beacon interval is kept internally in TU's */ intval = ni->ni_intval & HAL_BEACON_PERIOD; } + + + /* + * Note: rounding up to the next intval can cause problems. + * + * In STA mode with powersave enabled, beacons are only received + * whenever the beacon timer fires to wake up the hardware. + * Now, if this is rounded up to the next intval, it assumes + * that the AP has started transmitting beacons at TSF values that + * are multiples of intval, versus say being 25 TU off. + * + * I'm not sure why nexttbtt is rounded up to the intval. + * If we sync against a beacon that is way out, we should + * take a beacon miss and re-sync against the next beacon. + * + * So for now - don't round up if we're in STA mode. + * Maybe later (when someone eventually does powersave+IBSS, + * powersave+MBSS) this can be flipped on for those too. + */ if (nexttbtt == 0) /* e.g. for ap mode */ nexttbtt = intval; - else if (intval) /* NB: can be 0 for monitor mode */ + else if ((ic->ic_opmode != IEEE80211_M_STA) && intval) /* NB: can be 0 for monitor mode */ nexttbtt = roundup(nexttbtt, intval); + DPRINTF(sc, ATH_DEBUG_BEACON, "%s: nexttbtt %u intval %u (%u)\n", __func__, nexttbtt, intval, ni->ni_intval); if (ic->ic_opmode == IEEE80211_M_STA && !sc->sc_swbmiss) {