svn commit: r223671 - head/sys/dev/ath

Adrian Chadd adrian at FreeBSD.org
Wed Jun 29 13:21:53 UTC 2011


Author: adrian
Date: Wed Jun 29 13:21:52 2011
New Revision: 223671
URL: http://svn.freebsd.org/changeset/base/223671

Log:
  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.

Modified:
  head/sys/dev/ath/if_ath.c

Modified: head/sys/dev/ath/if_ath.c
==============================================================================
--- head/sys/dev/ath/if_ath.c	Wed Jun 29 13:12:15 2011	(r223670)
+++ head/sys/dev/ath/if_ath.c	Wed Jun 29 13:21:52 2011	(r223671)
@@ -4693,6 +4693,7 @@ ath_newstate(struct ieee80211vap *vap, e
 	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, e
 		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, e
 			 * 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:
 			/*


More information about the svn-src-head mailing list