summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authoradrian <adrian@FreeBSD.org>2011-06-26 13:53:24 +0000
committeradrian <adrian@FreeBSD.org>2011-06-26 13:53:24 +0000
commit46ff0e559ab79ebfbd80e88d8039edc881cfb02b (patch)
tree4e974abb1c8ba8ff2c1f4203e669d29f9ef72c0c /sys/dev
parent5c01535c7c4aeafb7ba7768538315dca39fa182c (diff)
downloadFreeBSD-src-46ff0e559ab79ebfbd80e88d8039edc881cfb02b.zip
FreeBSD-src-46ff0e559ab79ebfbd80e88d8039edc881cfb02b.tar.gz
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.
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ath/if_ath.c21
1 files changed, 21 insertions, 0 deletions
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c
index 1bca5e4..9c534c8 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
@@ -4468,6 +4476,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.
*/
ath_hal_intrset(ah, sc->sc_imask);
OpenPOWER on IntegriCloud