aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorBob Copeland <me@bobcopeland.com>2009-07-04 12:59:52 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-07-10 15:02:29 -0400
commit21800491cc5c48e9f1084a6f524a0da7c2525cc6 (patch)
tree5453e16a1c423f8541b819947d90760000f08a00 /drivers
parentcec8db23011d2a0a5ec101a0263d79678adf21ba (diff)
ath5k: rework beacon configuration
Using the enable_beacon flag allows some simplifications and fixes some corner cases in beacon handling. This change adds a state variable for beaconing in ath5k_beacon_config and handles both enabling and disabling, thus eliminating the need for ath5k_beacon_disable. We also now configure the beacon when any of the beacon parameters change, so ath5k_beacon_reconfig is no longer needed (its mmiowb gets moved to ath5k_beacon_config). Finally, by locking around the whole config function, we don't need to worry about clearing the interrupt mask register before installing the new mask. The upshot is this correctly disables beaconing when the interfaces are taken down, it fixes a potential restarting of beaconing when ath5k_reset() is called, and ensures that updates to the beacon interval take effect immediately. Signed-off-by: Bob Copeland <me@bobcopeland.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c59
-rw-r--r--drivers/net/wireless/ath/ath5k/base.h1
2 files changed, 20 insertions, 40 deletions
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index 87ebc461d74a..482932979c9b 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -2093,13 +2093,6 @@ err_unmap:
2093 return ret; 2093 return ret;
2094} 2094}
2095 2095
2096static void ath5k_beacon_disable(struct ath5k_softc *sc)
2097{
2098 sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA);
2099 ath5k_hw_set_imr(sc->ah, sc->imask);
2100 ath5k_hw_stop_tx_dma(sc->ah, sc->bhalq);
2101}
2102
2103/* 2096/*
2104 * Transmit a beacon frame at SWBA. Dynamic updates to the 2097 * Transmit a beacon frame at SWBA. Dynamic updates to the
2105 * frame contents are done as needed and the slot time is 2098 * frame contents are done as needed and the slot time is
@@ -2293,13 +2286,11 @@ ath5k_beacon_config(struct ath5k_softc *sc)
2293 struct ath5k_hw *ah = sc->ah; 2286 struct ath5k_hw *ah = sc->ah;
2294 unsigned long flags; 2287 unsigned long flags;
2295 2288
2296 ath5k_hw_set_imr(ah, 0); 2289 spin_lock_irqsave(&sc->block, flags);
2297 sc->bmisscount = 0; 2290 sc->bmisscount = 0;
2298 sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA); 2291 sc->imask &= ~(AR5K_INT_BMISS | AR5K_INT_SWBA);
2299 2292
2300 if (sc->opmode == NL80211_IFTYPE_ADHOC || 2293 if (sc->enable_beacon) {
2301 sc->opmode == NL80211_IFTYPE_MESH_POINT ||
2302 sc->opmode == NL80211_IFTYPE_AP) {
2303 /* 2294 /*
2304 * In IBSS mode we use a self-linked tx descriptor and let the 2295 * In IBSS mode we use a self-linked tx descriptor and let the
2305 * hardware send the beacons automatically. We have to load it 2296 * hardware send the beacons automatically. We have to load it
@@ -2312,16 +2303,17 @@ ath5k_beacon_config(struct ath5k_softc *sc)
2312 sc->imask |= AR5K_INT_SWBA; 2303 sc->imask |= AR5K_INT_SWBA;
2313 2304
2314 if (sc->opmode == NL80211_IFTYPE_ADHOC) { 2305 if (sc->opmode == NL80211_IFTYPE_ADHOC) {
2315 if (ath5k_hw_hasveol(ah)) { 2306 if (ath5k_hw_hasveol(ah))
2316 spin_lock_irqsave(&sc->block, flags);
2317 ath5k_beacon_send(sc); 2307 ath5k_beacon_send(sc);
2318 spin_unlock_irqrestore(&sc->block, flags);
2319 }
2320 } else 2308 } else
2321 ath5k_beacon_update_timers(sc, -1); 2309 ath5k_beacon_update_timers(sc, -1);
2310 } else {
2311 ath5k_hw_stop_tx_dma(sc->ah, sc->bhalq);
2322 } 2312 }
2323 2313
2324 ath5k_hw_set_imr(ah, sc->imask); 2314 ath5k_hw_set_imr(ah, sc->imask);
2315 mmiowb();
2316 spin_unlock_irqrestore(&sc->block, flags);
2325} 2317}
2326 2318
2327static void ath5k_tasklet_beacon(unsigned long data) 2319static void ath5k_tasklet_beacon(unsigned long data)
@@ -2806,7 +2798,6 @@ ath5k_remove_interface(struct ieee80211_hw *hw,
2806 goto end; 2798 goto end;
2807 2799
2808 ath5k_hw_set_lladdr(sc->ah, mac); 2800 ath5k_hw_set_lladdr(sc->ah, mac);
2809 ath5k_beacon_disable(sc);
2810 sc->vif = NULL; 2801 sc->vif = NULL;
2811end: 2802end:
2812 mutex_unlock(&sc->lock); 2803 mutex_unlock(&sc->lock);
@@ -3135,25 +3126,6 @@ out:
3135 return ret; 3126 return ret;
3136} 3127}
3137 3128
3138/*
3139 * Update the beacon and reconfigure the beacon queues.
3140 */
3141static void
3142ath5k_beacon_reconfig(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
3143{
3144 int ret;
3145 unsigned long flags;
3146 struct ath5k_softc *sc = hw->priv;
3147
3148 spin_lock_irqsave(&sc->block, flags);
3149 ret = ath5k_beacon_update(hw, vif);
3150 spin_unlock_irqrestore(&sc->block, flags);
3151 if (ret == 0) {
3152 ath5k_beacon_config(sc);
3153 mmiowb();
3154 }
3155}
3156
3157static void 3129static void
3158set_beacon_filter(struct ieee80211_hw *hw, bool enable) 3130set_beacon_filter(struct ieee80211_hw *hw, bool enable)
3159{ 3131{
@@ -3176,6 +3148,7 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
3176{ 3148{
3177 struct ath5k_softc *sc = hw->priv; 3149 struct ath5k_softc *sc = hw->priv;
3178 struct ath5k_hw *ah = sc->ah; 3150 struct ath5k_hw *ah = sc->ah;
3151 unsigned long flags;
3179 3152
3180 mutex_lock(&sc->lock); 3153 mutex_lock(&sc->lock);
3181 if (WARN_ON(sc->vif != vif)) 3154 if (WARN_ON(sc->vif != vif))
@@ -3201,13 +3174,19 @@ static void ath5k_bss_info_changed(struct ieee80211_hw *hw,
3201 AR5K_LED_ASSOC : AR5K_LED_INIT); 3174 AR5K_LED_ASSOC : AR5K_LED_INIT);
3202 } 3175 }
3203 3176
3204 if (changes & BSS_CHANGED_BEACON && 3177 if (changes & BSS_CHANGED_BEACON) {
3205 (vif->type == NL80211_IFTYPE_ADHOC || 3178 spin_lock_irqsave(&sc->block, flags);
3206 vif->type == NL80211_IFTYPE_MESH_POINT || 3179 ath5k_beacon_update(hw, vif);
3207 vif->type == NL80211_IFTYPE_AP)) { 3180 spin_unlock_irqrestore(&sc->block, flags);
3208 ath5k_beacon_reconfig(hw, vif);
3209 } 3181 }
3210 3182
3183 if (changes & BSS_CHANGED_BEACON_ENABLED)
3184 sc->enable_beacon = bss_conf->enable_beacon;
3185
3186 if (changes & (BSS_CHANGED_BEACON | BSS_CHANGED_BEACON_ENABLED |
3187 BSS_CHANGED_BEACON_INT))
3188 ath5k_beacon_config(sc);
3189
3211 unlock: 3190 unlock:
3212 mutex_unlock(&sc->lock); 3191 mutex_unlock(&sc->lock);
3213} 3192}
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h
index 65e75fb54482..778e422946ab 100644
--- a/drivers/net/wireless/ath/ath5k/base.h
+++ b/drivers/net/wireless/ath/ath5k/base.h
@@ -190,6 +190,7 @@ struct ath5k_softc {
190 struct timer_list calib_tim; /* calibration timer */ 190 struct timer_list calib_tim; /* calibration timer */
191 int power_level; /* Requested tx power in dbm */ 191 int power_level; /* Requested tx power in dbm */
192 bool assoc; /* assocate state */ 192 bool assoc; /* assocate state */
193 bool enable_beacon; /* true if beacons are on */
193}; 194};
194 195
195#define ath5k_hw_hasbssidmask(_ah) \ 196#define ath5k_hw_hasbssidmask(_ah) \