Skip to content

Commit

Permalink
ath9k: race condition in SCANNING state check during ANI calibration
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Senthil Balasubramanian authored and John W. Linville committed Jul 10, 2009
1 parent f38faa3 commit e5f0921
Show file tree
Hide file tree
Showing 2 changed files with 8 additions and 4 deletions.
1 change: 1 addition & 0 deletions drivers/net/wireless/ath/ath9k/ath9k.h
Original file line number Diff line number Diff line change
Expand Up @@ -540,6 +540,7 @@ struct ath_softc {
int irq;
spinlock_t sc_resetlock;
spinlock_t sc_serial_rw;
spinlock_t ani_lock;
struct mutex mutex;

u8 curbssid[ETH_ALEN];
Expand Down
11 changes: 7 additions & 4 deletions drivers/net/wireless/ath/ath9k/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ static void ath_ani_calibrate(unsigned long data)
* don't calibrate when we're scanning.
* we are most likely not on our home channel.
*/
spin_lock(&sc->ani_lock);
if (sc->sc_flags & SC_OP_SCANNING)
goto set_timer;

Expand Down Expand Up @@ -405,6 +406,7 @@ static void ath_ani_calibrate(unsigned long data)
ath9k_ps_restore(sc);

set_timer:
spin_unlock(&sc->ani_lock);
/*
* Set timer interval based on previous results.
* The interval must be the shortest necessary to satisfy ANI,
Expand Down Expand Up @@ -1310,6 +1312,7 @@ static int ath_init(u16 devid, struct ath_softc *sc)
spin_lock_init(&sc->wiphy_lock);
spin_lock_init(&sc->sc_resetlock);
spin_lock_init(&sc->sc_serial_rw);
spin_lock_init(&sc->ani_lock);
mutex_init(&sc->mutex);
tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet,
Expand Down Expand Up @@ -2682,21 +2685,21 @@ static void ath9k_sw_scan_start(struct ieee80211_hw *hw)
aphy->state = ATH_WIPHY_SCAN;
ath9k_wiphy_pause_all_forced(sc, aphy);

mutex_lock(&sc->mutex);
spin_lock_bh(&sc->ani_lock);
sc->sc_flags |= SC_OP_SCANNING;
mutex_unlock(&sc->mutex);
spin_unlock_bh(&sc->ani_lock);
}

static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
{
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;

mutex_lock(&sc->mutex);
spin_lock_bh(&sc->ani_lock);
aphy->state = ATH_WIPHY_ACTIVE;
sc->sc_flags &= ~SC_OP_SCANNING;
sc->sc_flags |= SC_OP_FULL_RESET;
mutex_unlock(&sc->mutex);
spin_unlock_bh(&sc->ani_lock);
}

struct ieee80211_ops ath9k_ops = {
Expand Down

0 comments on commit e5f0921

Please sign in to comment.