aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSenthil Balasubramanian <senthilkumar@atheros.com>2009-06-24 09:26:41 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-07-10 15:02:24 -0400
commite5f0921a9593365b506f69daa3cfd19c0ed1340b (patch)
tree517b9d993790e182918b0950413913b2dfad7f8c /drivers
parentf38faa31e0da07390d72fb67d3151e56c54871f4 (diff)
ath9k: race condition in SCANNING state check during ANI calibration
ANI calibration shouldn't be done when we are not on our home channel. This is already verified. However, it is racy. Fix this by proper spin locks. Signed-off-by: Senthil Balasubramanian <senthilkumar@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c11
2 files changed, 8 insertions, 4 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 747e046b03b0..eb9d5228cb6c 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -540,6 +540,7 @@ struct ath_softc {
540 int irq; 540 int irq;
541 spinlock_t sc_resetlock; 541 spinlock_t sc_resetlock;
542 spinlock_t sc_serial_rw; 542 spinlock_t sc_serial_rw;
543 spinlock_t ani_lock;
543 struct mutex mutex; 544 struct mutex mutex;
544 545
545 u8 curbssid[ETH_ALEN]; 546 u8 curbssid[ETH_ALEN];
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 6d63126a81f1..52dfa43bc529 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -342,6 +342,7 @@ static void ath_ani_calibrate(unsigned long data)
342 * don't calibrate when we're scanning. 342 * don't calibrate when we're scanning.
343 * we are most likely not on our home channel. 343 * we are most likely not on our home channel.
344 */ 344 */
345 spin_lock(&sc->ani_lock);
345 if (sc->sc_flags & SC_OP_SCANNING) 346 if (sc->sc_flags & SC_OP_SCANNING)
346 goto set_timer; 347 goto set_timer;
347 348
@@ -405,6 +406,7 @@ static void ath_ani_calibrate(unsigned long data)
405 ath9k_ps_restore(sc); 406 ath9k_ps_restore(sc);
406 407
407set_timer: 408set_timer:
409 spin_unlock(&sc->ani_lock);
408 /* 410 /*
409 * Set timer interval based on previous results. 411 * Set timer interval based on previous results.
410 * The interval must be the shortest necessary to satisfy ANI, 412 * The interval must be the shortest necessary to satisfy ANI,
@@ -1310,6 +1312,7 @@ static int ath_init(u16 devid, struct ath_softc *sc)
1310 spin_lock_init(&sc->wiphy_lock); 1312 spin_lock_init(&sc->wiphy_lock);
1311 spin_lock_init(&sc->sc_resetlock); 1313 spin_lock_init(&sc->sc_resetlock);
1312 spin_lock_init(&sc->sc_serial_rw); 1314 spin_lock_init(&sc->sc_serial_rw);
1315 spin_lock_init(&sc->ani_lock);
1313 mutex_init(&sc->mutex); 1316 mutex_init(&sc->mutex);
1314 tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); 1317 tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
1315 tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet, 1318 tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet,
@@ -2682,9 +2685,9 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
2682 aphy->state = ATH_WIPHY_SCAN; 2685 aphy->state = ATH_WIPHY_SCAN;
2683 ath9k_wiphy_pause_all_forced(sc, aphy); 2686 ath9k_wiphy_pause_all_forced(sc, aphy);
2684 2687
2685 mutex_lock(&sc->mutex); 2688 spin_lock_bh(&sc->ani_lock);
2686 sc->sc_flags |= SC_OP_SCANNING; 2689 sc->sc_flags |= SC_OP_SCANNING;
2687 mutex_unlock(&sc->mutex); 2690 spin_unlock_bh(&sc->ani_lock);
2688} 2691}
2689 2692
2690static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) 2693static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
@@ -2692,11 +2695,11 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
2692 struct ath_wiphy *aphy = hw->priv; 2695 struct ath_wiphy *aphy = hw->priv;
2693 struct ath_softc *sc = aphy->sc; 2696 struct ath_softc *sc = aphy->sc;
2694 2697
2695 mutex_lock(&sc->mutex); 2698 spin_lock_bh(&sc->ani_lock);
2696 aphy->state = ATH_WIPHY_ACTIVE; 2699 aphy->state = ATH_WIPHY_ACTIVE;
2697 sc->sc_flags &= ~SC_OP_SCANNING; 2700 sc->sc_flags &= ~SC_OP_SCANNING;
2698 sc->sc_flags |= SC_OP_FULL_RESET; 2701 sc->sc_flags |= SC_OP_FULL_RESET;
2699 mutex_unlock(&sc->mutex); 2702 spin_unlock_bh(&sc->ani_lock);
2700} 2703}
2701 2704
2702struct ieee80211_ops ath9k_ops = { 2705struct ieee80211_ops ath9k_ops = {