ath9k: serialize ath9k_hw_setpower calls
authorGabor Juhos <juhosg@openwrt.org>
Wed, 15 Jul 2009 00:17:13 +0000 (20:17 -0400)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 24 Jul 2009 19:05:18 +0000 (15:05 -0400)
Because ath9k_setpower is called from various contexts, we have to
protect it against concurrent calls.

Changes-licensed-under: ISC
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/main.c

index 20bf4a7f896dcae0674b1921faa020d3fef2a545..b37eb592b5246ba6fcf3b5a36d72bb45f58f570a 100644 (file)
@@ -559,6 +559,7 @@ struct ath_softc {
        spinlock_t sc_resetlock;
        spinlock_t sc_serial_rw;
        spinlock_t ani_lock;
+       spinlock_t sc_pm_lock;
        struct mutex mutex;
 
        u8 curbssid[ETH_ALEN];
index a115c8ceabe378f2aac8ecff72f13cc75383cc96..6740a6b98a622c3ec4adc22d4088ba8555dd0c69 100644 (file)
@@ -2728,7 +2728,8 @@ static bool ath9k_hw_set_power_awake(struct ath_hw *ah, int setChip)
        return true;
 }
 
-bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode)
+static bool ath9k_hw_setpower_nolock(struct ath_hw *ah,
+                                    enum ath9k_power_mode mode)
 {
        int status = true, setChip = true;
        static const char *modes[] = {
@@ -2762,6 +2763,18 @@ bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode)
        return status;
 }
 
+bool ath9k_hw_setpower(struct ath_hw *ah, enum ath9k_power_mode mode)
+{
+       unsigned long flags;
+       bool ret;
+
+       spin_lock_irqsave(&ah->ah_sc->sc_pm_lock, flags);
+       ret = ath9k_hw_setpower_nolock(ah, mode);
+       spin_unlock_irqrestore(&ah->ah_sc->sc_pm_lock, flags);
+
+       return ret;
+}
+
 /*
  * Helper for ASPM support.
  *
index 90cecce8d5ffebf2a96fe065f8b6ab8af3ae0dba..d14f8c9cef684b669b3b171bf632318c9adc60b3 100644 (file)
@@ -1316,6 +1316,7 @@ static int ath_init(u16 devid, struct ath_softc *sc)
        spin_lock_init(&sc->sc_resetlock);
        spin_lock_init(&sc->sc_serial_rw);
        spin_lock_init(&sc->ani_lock);
+       spin_lock_init(&sc->sc_pm_lock);
        mutex_init(&sc->mutex);
        tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc);
        tasklet_init(&sc->bcon_tasklet, ath_beacon_tasklet,