From 2fd9aabb1b4c171b783a700d95f69ab946791178 Mon Sep 17 00:00:00 2001 From: Adrian Chadd Date: Sun, 26 Jun 2011 13:53:24 +0000 Subject: [PATCH] Fix beacon transmission after a channel set. The DFS code was tickling the channel set directly whilst going through the state RUN -> CSA -> RUN. This only changed the channel; it didn't go via ath_reset(). However in this driver, a channel change always causes a chip reset, which resets the beacon timer configuration and interrupt setup. This meant that data would go out but as the beacon timers never fired, beacons would never be queued. The confusing part is that sometimes the state transition was RUN -> SCAN -> CAC -> RUN (with CSA being in there sometimes); going via SCAN would clear sc_beacons and thus the transition to RUN would reprogram beacon transmission. In case someone tries debugging why suspending a device currently beaconing (versus just RX'ing beacons which is what occurs in STA mode), add a silly comment which should hopefully land them at this commit message. The call to ath_hal_reset() will be clearing the beacon config and it may not be always reset. --- sys/dev/ath/if_ath.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index 1bca5e47f525..9c534c8e2d46 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -1290,6 +1290,8 @@ ath_resume(struct ath_softc *sc) HAL_GPIO_MUX_MAC_NETWORK_LED); ath_hal_gpioset(ah, sc->sc_ledpin, !sc->sc_ledon); } + + /* XXX beacons ? */ } void @@ -1592,6 +1594,12 @@ ath_init(void *arg) sc->sc_lastani = 0; sc->sc_lastshortcal = 0; sc->sc_doresetcal = AH_FALSE; + /* + * Beacon timers were cleared here; give ath_newstate() + * a hint that the beacon timers should be poked when + * things transition to the RUN state. + */ + sc->sc_beacons = 0; /* * Setup the hardware after reset: the key cache @@ -4467,6 +4475,19 @@ ath_chan_set(struct ath_softc *sc, struct ieee80211_channel *chan) */ ath_chan_change(sc, chan); + /* + * Reset clears the beacon timers; reset them + * here if needed. + */ + if (sc->sc_beacons) { /* restart beacons */ +#ifdef IEEE80211_SUPPORT_TDMA + if (sc->sc_tdma) + ath_tdma_config(sc, NULL); + else +#endif + ath_beacon_config(sc, NULL); + } + /* * Re-enable interrupts. */