diff options
author | Gabor Juhos <juhosg@openwrt.org> | 2009-07-24 11:27:21 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-07-29 15:46:03 -0400 |
commit | 96148326c4b54db5c384def1a5ab285c359d1395 (patch) | |
tree | 86985eb7ab56819992066500ad215bfea63121a0 /drivers/net/wireless/ath/ath9k/hw.c | |
parent | ff8365ca889cb86ba5bd40fe3047d047bc632f4c (diff) |
ath9k: fix race with IEEE80211_CONF_PS checks
There is a small window where the mac80211 changes the IEEE80211_CONF_PS
flag, and then informs the driver about the change. We have a race
condition if we are checking the flag in the same time. Avoid it by
introducing a local variable, and using that instead of checking the
IEEE80211_CONF_PS flag directly.
This fix the problem reported by Luis:
http://article.gmane.org/gmane.linux.kernel.wireless.general/34363
Changes-licensed-under: ISC
Signed-off-by: Gabor Juhos <juhosg@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/hw.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.c | 17 |
1 files changed, 7 insertions, 10 deletions
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index da3226994de7..e6e52f48e718 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -2863,10 +2863,8 @@ void ath9k_ps_wakeup(struct ath_softc *sc) | |||
2863 | if (++sc->ps_usecount != 1) | 2863 | if (++sc->ps_usecount != 1) |
2864 | goto unlock; | 2864 | goto unlock; |
2865 | 2865 | ||
2866 | if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) { | 2866 | if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) |
2867 | sc->sc_ah->restore_mode = sc->sc_ah->power_mode; | ||
2868 | ath9k_hw_setpower_nolock(sc->sc_ah, ATH9K_PM_AWAKE); | 2867 | ath9k_hw_setpower_nolock(sc->sc_ah, ATH9K_PM_AWAKE); |
2869 | } | ||
2870 | 2868 | ||
2871 | unlock: | 2869 | unlock: |
2872 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | 2870 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); |
@@ -2880,13 +2878,12 @@ void ath9k_ps_restore(struct ath_softc *sc) | |||
2880 | if (--sc->ps_usecount != 0) | 2878 | if (--sc->ps_usecount != 0) |
2881 | goto unlock; | 2879 | goto unlock; |
2882 | 2880 | ||
2883 | if ((sc->hw->conf.flags & IEEE80211_CONF_PS) && | 2881 | if (sc->ps_enabled && |
2884 | !(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON | | 2882 | !(sc->sc_flags & (SC_OP_WAIT_FOR_BEACON | |
2885 | SC_OP_WAIT_FOR_CAB | | 2883 | SC_OP_WAIT_FOR_CAB | |
2886 | SC_OP_WAIT_FOR_PSPOLL_DATA | | 2884 | SC_OP_WAIT_FOR_PSPOLL_DATA | |
2887 | SC_OP_WAIT_FOR_TX_ACK))) | 2885 | SC_OP_WAIT_FOR_TX_ACK))) |
2888 | ath9k_hw_setpower_nolock(sc->sc_ah, | 2886 | ath9k_hw_setpower_nolock(sc->sc_ah, ATH9K_PM_NETWORK_SLEEP); |
2889 | sc->sc_ah->restore_mode); | ||
2890 | 2887 | ||
2891 | unlock: | 2888 | unlock: |
2892 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | 2889 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); |