diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/main.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 47df22b14cf..b52f1cf8a60 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -241,6 +241,9 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
241 | */ | 241 | */ |
242 | ath9k_hw_set_interrupts(ah, 0); | 242 | ath9k_hw_set_interrupts(ah, 0); |
243 | ath_drain_all_txq(sc, false); | 243 | ath_drain_all_txq(sc, false); |
244 | |||
245 | spin_lock_bh(&sc->rx.pcu_lock); | ||
246 | |||
244 | stopped = ath_stoprecv(sc); | 247 | stopped = ath_stoprecv(sc); |
245 | 248 | ||
246 | /* XXX: do not flush receive queue here. We don't want | 249 | /* XXX: do not flush receive queue here. We don't want |
@@ -268,6 +271,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
268 | "reset status %d\n", | 271 | "reset status %d\n", |
269 | channel->center_freq, r); | 272 | channel->center_freq, r); |
270 | spin_unlock_bh(&sc->sc_resetlock); | 273 | spin_unlock_bh(&sc->sc_resetlock); |
274 | spin_unlock_bh(&sc->rx.pcu_lock); | ||
271 | goto ps_restore; | 275 | goto ps_restore; |
272 | } | 276 | } |
273 | spin_unlock_bh(&sc->sc_resetlock); | 277 | spin_unlock_bh(&sc->sc_resetlock); |
@@ -276,9 +280,12 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
276 | ath_print(common, ATH_DBG_FATAL, | 280 | ath_print(common, ATH_DBG_FATAL, |
277 | "Unable to restart recv logic\n"); | 281 | "Unable to restart recv logic\n"); |
278 | r = -EIO; | 282 | r = -EIO; |
283 | spin_unlock_bh(&sc->rx.pcu_lock); | ||
279 | goto ps_restore; | 284 | goto ps_restore; |
280 | } | 285 | } |
281 | 286 | ||
287 | spin_unlock_bh(&sc->rx.pcu_lock); | ||
288 | |||
282 | ath_update_txpow(sc); | 289 | ath_update_txpow(sc); |
283 | ath9k_hw_set_interrupts(ah, ah->imask); | 290 | ath9k_hw_set_interrupts(ah, ah->imask); |
284 | 291 | ||
@@ -876,6 +883,7 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
876 | if (!ah->curchan) | 883 | if (!ah->curchan) |
877 | ah->curchan = ath_get_curchannel(sc, sc->hw); | 884 | ah->curchan = ath_get_curchannel(sc, sc->hw); |
878 | 885 | ||
886 | spin_lock_bh(&sc->rx.pcu_lock); | ||
879 | spin_lock_bh(&sc->sc_resetlock); | 887 | spin_lock_bh(&sc->sc_resetlock); |
880 | r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); | 888 | r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); |
881 | if (r) { | 889 | if (r) { |
@@ -890,8 +898,10 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
890 | if (ath_startrecv(sc) != 0) { | 898 | if (ath_startrecv(sc) != 0) { |
891 | ath_print(common, ATH_DBG_FATAL, | 899 | ath_print(common, ATH_DBG_FATAL, |
892 | "Unable to restart recv logic\n"); | 900 | "Unable to restart recv logic\n"); |
901 | spin_unlock_bh(&sc->rx.pcu_lock); | ||
893 | return; | 902 | return; |
894 | } | 903 | } |
904 | spin_unlock_bh(&sc->rx.pcu_lock); | ||
895 | 905 | ||
896 | if (sc->sc_flags & SC_OP_BEACONS) | 906 | if (sc->sc_flags & SC_OP_BEACONS) |
897 | ath_beacon_config(sc, NULL); /* restart beacons */ | 907 | ath_beacon_config(sc, NULL); /* restart beacons */ |
@@ -930,6 +940,9 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
930 | ath9k_hw_set_interrupts(ah, 0); | 940 | ath9k_hw_set_interrupts(ah, 0); |
931 | 941 | ||
932 | ath_drain_all_txq(sc, false); /* clear pending tx frames */ | 942 | ath_drain_all_txq(sc, false); /* clear pending tx frames */ |
943 | |||
944 | spin_lock_bh(&sc->rx.pcu_lock); | ||
945 | |||
933 | ath_stoprecv(sc); /* turn off frame recv */ | 946 | ath_stoprecv(sc); /* turn off frame recv */ |
934 | ath_flushrecv(sc); /* flush recv queue */ | 947 | ath_flushrecv(sc); /* flush recv queue */ |
935 | 948 | ||
@@ -947,6 +960,9 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
947 | spin_unlock_bh(&sc->sc_resetlock); | 960 | spin_unlock_bh(&sc->sc_resetlock); |
948 | 961 | ||
949 | ath9k_hw_phy_disable(ah); | 962 | ath9k_hw_phy_disable(ah); |
963 | |||
964 | spin_unlock_bh(&sc->rx.pcu_lock); | ||
965 | |||
950 | ath9k_hw_configpcipowersave(ah, 1, 1); | 966 | ath9k_hw_configpcipowersave(ah, 1, 1); |
951 | ath9k_ps_restore(sc); | 967 | ath9k_ps_restore(sc); |
952 | ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP); | 968 | ath9k_setpower(sc, ATH9K_PM_FULL_SLEEP); |
@@ -966,6 +982,9 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) | |||
966 | 982 | ||
967 | ath9k_hw_set_interrupts(ah, 0); | 983 | ath9k_hw_set_interrupts(ah, 0); |
968 | ath_drain_all_txq(sc, retry_tx); | 984 | ath_drain_all_txq(sc, retry_tx); |
985 | |||
986 | spin_lock_bh(&sc->rx.pcu_lock); | ||
987 | |||
969 | ath_stoprecv(sc); | 988 | ath_stoprecv(sc); |
970 | ath_flushrecv(sc); | 989 | ath_flushrecv(sc); |
971 | 990 | ||
@@ -980,6 +999,8 @@ int ath_reset(struct ath_softc *sc, bool retry_tx) | |||
980 | ath_print(common, ATH_DBG_FATAL, | 999 | ath_print(common, ATH_DBG_FATAL, |
981 | "Unable to start recv logic\n"); | 1000 | "Unable to start recv logic\n"); |
982 | 1001 | ||
1002 | spin_unlock_bh(&sc->rx.pcu_lock); | ||
1003 | |||
983 | /* | 1004 | /* |
984 | * We may be doing a reset in response to a request | 1005 | * We may be doing a reset in response to a request |
985 | * that changes the channel so update any state that | 1006 | * that changes the channel so update any state that |
@@ -1142,6 +1163,7 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1142 | * be followed by initialization of the appropriate bits | 1163 | * be followed by initialization of the appropriate bits |
1143 | * and then setup of the interrupt mask. | 1164 | * and then setup of the interrupt mask. |
1144 | */ | 1165 | */ |
1166 | spin_lock_bh(&sc->rx.pcu_lock); | ||
1145 | spin_lock_bh(&sc->sc_resetlock); | 1167 | spin_lock_bh(&sc->sc_resetlock); |
1146 | r = ath9k_hw_reset(ah, init_channel, ah->caldata, false); | 1168 | r = ath9k_hw_reset(ah, init_channel, ah->caldata, false); |
1147 | if (r) { | 1169 | if (r) { |
@@ -1150,6 +1172,7 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1150 | "(freq %u MHz)\n", r, | 1172 | "(freq %u MHz)\n", r, |
1151 | curchan->center_freq); | 1173 | curchan->center_freq); |
1152 | spin_unlock_bh(&sc->sc_resetlock); | 1174 | spin_unlock_bh(&sc->sc_resetlock); |
1175 | spin_unlock_bh(&sc->rx.pcu_lock); | ||
1153 | goto mutex_unlock; | 1176 | goto mutex_unlock; |
1154 | } | 1177 | } |
1155 | spin_unlock_bh(&sc->sc_resetlock); | 1178 | spin_unlock_bh(&sc->sc_resetlock); |
@@ -1171,8 +1194,10 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1171 | ath_print(common, ATH_DBG_FATAL, | 1194 | ath_print(common, ATH_DBG_FATAL, |
1172 | "Unable to start recv logic\n"); | 1195 | "Unable to start recv logic\n"); |
1173 | r = -EIO; | 1196 | r = -EIO; |
1197 | spin_unlock_bh(&sc->rx.pcu_lock); | ||
1174 | goto mutex_unlock; | 1198 | goto mutex_unlock; |
1175 | } | 1199 | } |
1200 | spin_unlock_bh(&sc->rx.pcu_lock); | ||
1176 | 1201 | ||
1177 | /* Setup our intr mask. */ | 1202 | /* Setup our intr mask. */ |
1178 | ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL | | 1203 | ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL | |
@@ -1371,12 +1396,14 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
1371 | * before setting the invalid flag. */ | 1396 | * before setting the invalid flag. */ |
1372 | ath9k_hw_set_interrupts(ah, 0); | 1397 | ath9k_hw_set_interrupts(ah, 0); |
1373 | 1398 | ||
1399 | spin_lock_bh(&sc->rx.pcu_lock); | ||
1374 | if (!(sc->sc_flags & SC_OP_INVALID)) { | 1400 | if (!(sc->sc_flags & SC_OP_INVALID)) { |
1375 | ath_drain_all_txq(sc, false); | 1401 | ath_drain_all_txq(sc, false); |
1376 | ath_stoprecv(sc); | 1402 | ath_stoprecv(sc); |
1377 | ath9k_hw_phy_disable(ah); | 1403 | ath9k_hw_phy_disable(ah); |
1378 | } else | 1404 | } else |
1379 | sc->rx.rxlink = NULL; | 1405 | sc->rx.rxlink = NULL; |
1406 | spin_unlock_bh(&sc->rx.pcu_lock); | ||
1380 | 1407 | ||
1381 | /* disable HAL and put h/w to sleep */ | 1408 | /* disable HAL and put h/w to sleep */ |
1382 | ath9k_hw_disable(ah); | 1409 | ath9k_hw_disable(ah); |