summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoradrian <adrian@FreeBSD.org>2011-06-29 13:21:52 +0000
committeradrian <adrian@FreeBSD.org>2011-06-29 13:21:52 +0000
commitaf8134caea44022a9779218bf51c2d5bc8f2572e (patch)
tree8e72db187331c87164a26227e27e6b02068e4759
parent4a4ec8668222820c3a449bd2249c40074c542416 (diff)
downloadFreeBSD-src-af8134caea44022a9779218bf51c2d5bc8f2572e.zip
FreeBSD-src-af8134caea44022a9779218bf51c2d5bc8f2572e.tar.gz
Fix a corner case in STA beacon processing when a CSA is received but
the AP doesn't transmit beacons. If the AP requests a CSA (ie, a channel switch) and then enters CAC (channel availability check) for 60 seconds, it doesn't send beacons and it just listens for radar events (and other things which we don't do yet.) Now, ath_newstate() was not resetting the beacon timer config on a transition to the RUN state when in STA mode - it was setting sc_syncbeacon, which simply updates the beacon config from the contents of the next received beacon. This means the STA never generates beacon miss events. If the AP goes into CAC for 60 seconds and recovers, the STA will happily receive the first beacon and reconfigure timers. But if it gets a radar event after that, it'll change channel again, not notify the station that it's changed channel.. and since the station is happily waiting for the first beacon to configure the beacon timer details from, it won't ever generate a beacon miss interrupt and it'll sit there forever (or until the AP appears on that channel once again.) This change forces the last known beacon timer config to be written to hardware on a transition from CSA->RUN in STA mode. This forces bmiss events to occur and the STA will eventually (after a handful of beacon miss events) begin scanning for another access point.
-rw-r--r--sys/dev/ath/if_ath.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c
index 9c534c8..35592d9 100644
--- a/sys/dev/ath/if_ath.c
+++ b/sys/dev/ath/if_ath.c
@@ -4693,6 +4693,7 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
struct ieee80211_node *ni = NULL;
int i, error, stamode;
u_int32_t rfilt;
+ int csa_run_transition = 0;
static const HAL_LED_STATE leds[] = {
HAL_LED_INIT, /* IEEE80211_S_INIT */
HAL_LED_SCAN, /* IEEE80211_S_SCAN */
@@ -4708,6 +4709,9 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
ieee80211_state_name[vap->iv_state],
ieee80211_state_name[nstate]);
+ if (vap->iv_state == IEEE80211_S_CSA && nstate == IEEE80211_S_RUN)
+ csa_run_transition = 1;
+
callout_drain(&sc->sc_cal_ch);
ath_hal_setledstate(ah, leds[nstate]); /* set LED */
@@ -4814,8 +4818,14 @@ ath_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
* Defer beacon timer configuration to the next
* beacon frame so we have a current TSF to use
* (any TSF collected when scanning is likely old).
+ * However if it's due to a CSA -> RUN transition,
+ * force a beacon update so we pick up a lack of
+ * beacons from an AP in CAC and thus force a
+ * scan.
*/
sc->sc_syncbeacon = 1;
+ if (csa_run_transition)
+ ath_beacon_config(sc, vap);
break;
case IEEE80211_M_MONITOR:
/*
OpenPOWER on IntegriCloud