diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/main.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 303 |
1 files changed, 127 insertions, 176 deletions
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 9a6db2964b18..19c78be3dc41 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -212,84 +212,58 @@ static int ath_update_survey_stats(struct ath_softc *sc) | |||
212 | return ret; | 212 | return ret; |
213 | } | 213 | } |
214 | 214 | ||
215 | /* | 215 | static void __ath_cancel_work(struct ath_softc *sc) |
216 | * Set/change channels. If the channel is really being changed, it's done | ||
217 | * by reseting the chip. To accomplish this we must first cleanup any pending | ||
218 | * DMA, then restart stuff. | ||
219 | */ | ||
220 | static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | ||
221 | struct ath9k_channel *hchan) | ||
222 | { | 216 | { |
223 | struct ath_hw *ah = sc->sc_ah; | ||
224 | struct ath_common *common = ath9k_hw_common(ah); | ||
225 | struct ieee80211_conf *conf = &common->hw->conf; | ||
226 | bool fastcc = true, stopped; | ||
227 | struct ieee80211_channel *channel = hw->conf.channel; | ||
228 | struct ath9k_hw_cal_data *caldata = NULL; | ||
229 | int r; | ||
230 | |||
231 | if (sc->sc_flags & SC_OP_INVALID) | ||
232 | return -EIO; | ||
233 | |||
234 | sc->hw_busy_count = 0; | ||
235 | |||
236 | del_timer_sync(&common->ani.timer); | ||
237 | cancel_work_sync(&sc->paprd_work); | 217 | cancel_work_sync(&sc->paprd_work); |
238 | cancel_work_sync(&sc->hw_check_work); | 218 | cancel_work_sync(&sc->hw_check_work); |
239 | cancel_work_sync(&sc->hw_reset_work); | ||
240 | cancel_delayed_work_sync(&sc->tx_complete_work); | 219 | cancel_delayed_work_sync(&sc->tx_complete_work); |
241 | cancel_delayed_work_sync(&sc->hw_pll_work); | 220 | cancel_delayed_work_sync(&sc->hw_pll_work); |
221 | } | ||
242 | 222 | ||
243 | ath9k_ps_wakeup(sc); | 223 | static void ath_cancel_work(struct ath_softc *sc) |
224 | { | ||
225 | __ath_cancel_work(sc); | ||
226 | cancel_work_sync(&sc->hw_reset_work); | ||
227 | } | ||
244 | 228 | ||
245 | spin_lock_bh(&sc->sc_pcu_lock); | 229 | static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush) |
230 | { | ||
231 | struct ath_hw *ah = sc->sc_ah; | ||
232 | struct ath_common *common = ath9k_hw_common(ah); | ||
233 | bool ret; | ||
246 | 234 | ||
247 | /* | 235 | ieee80211_stop_queues(sc->hw); |
248 | * This is only performed if the channel settings have | ||
249 | * actually changed. | ||
250 | * | ||
251 | * To switch channels clear any pending DMA operations; | ||
252 | * wait long enough for the RX fifo to drain, reset the | ||
253 | * hardware at the new frequency, and then re-enable | ||
254 | * the relevant bits of the h/w. | ||
255 | */ | ||
256 | ath9k_hw_disable_interrupts(ah); | ||
257 | stopped = ath_drain_all_txq(sc, false); | ||
258 | 236 | ||
259 | if (!ath_stoprecv(sc)) | 237 | sc->hw_busy_count = 0; |
260 | stopped = false; | 238 | del_timer_sync(&common->ani.timer); |
261 | 239 | ||
262 | if (!ath9k_hw_check_alive(ah)) | 240 | ath9k_debug_samp_bb_mac(sc); |
263 | stopped = false; | 241 | ath9k_hw_disable_interrupts(ah); |
264 | 242 | ||
265 | /* XXX: do not flush receive queue here. We don't want | 243 | ret = ath_drain_all_txq(sc, retry_tx); |
266 | * to flush data frames already in queue because of | ||
267 | * changing channel. */ | ||
268 | 244 | ||
269 | if (!stopped || !(sc->sc_flags & SC_OP_OFFCHANNEL)) | 245 | if (!ath_stoprecv(sc)) |
270 | fastcc = false; | 246 | ret = false; |
271 | 247 | ||
272 | if (!(sc->sc_flags & SC_OP_OFFCHANNEL)) | 248 | if (!flush) { |
273 | caldata = &sc->caldata; | 249 | if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) |
250 | ath_rx_tasklet(sc, 0, true); | ||
251 | ath_rx_tasklet(sc, 0, false); | ||
252 | } else { | ||
253 | ath_flushrecv(sc); | ||
254 | } | ||
274 | 255 | ||
275 | ath_dbg(common, ATH_DBG_CONFIG, | 256 | return ret; |
276 | "(%u MHz) -> (%u MHz), conf_is_ht40: %d fastcc: %d\n", | 257 | } |
277 | sc->sc_ah->curchan->channel, | ||
278 | channel->center_freq, conf_is_ht40(conf), | ||
279 | fastcc); | ||
280 | 258 | ||
281 | r = ath9k_hw_reset(ah, hchan, caldata, fastcc); | 259 | static bool ath_complete_reset(struct ath_softc *sc, bool start) |
282 | if (r) { | 260 | { |
283 | ath_err(common, | 261 | struct ath_hw *ah = sc->sc_ah; |
284 | "Unable to reset channel (%u MHz), reset status %d\n", | 262 | struct ath_common *common = ath9k_hw_common(ah); |
285 | channel->center_freq, r); | ||
286 | goto ps_restore; | ||
287 | } | ||
288 | 263 | ||
289 | if (ath_startrecv(sc) != 0) { | 264 | if (ath_startrecv(sc) != 0) { |
290 | ath_err(common, "Unable to restart recv logic\n"); | 265 | ath_err(common, "Unable to restart recv logic\n"); |
291 | r = -EIO; | 266 | return false; |
292 | goto ps_restore; | ||
293 | } | 267 | } |
294 | 268 | ||
295 | ath9k_cmn_update_txpow(ah, sc->curtxpow, | 269 | ath9k_cmn_update_txpow(ah, sc->curtxpow, |
@@ -297,21 +271,93 @@ static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | |||
297 | ath9k_hw_set_interrupts(ah, ah->imask); | 271 | ath9k_hw_set_interrupts(ah, ah->imask); |
298 | ath9k_hw_enable_interrupts(ah); | 272 | ath9k_hw_enable_interrupts(ah); |
299 | 273 | ||
300 | if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) { | 274 | if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) && start) { |
301 | if (sc->sc_flags & SC_OP_BEACONS) | 275 | if (sc->sc_flags & SC_OP_BEACONS) |
302 | ath_set_beacon(sc); | 276 | ath_set_beacon(sc); |
277 | |||
303 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); | 278 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); |
304 | ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2); | 279 | ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, HZ/2); |
305 | if (!common->disable_ani) | 280 | if (!common->disable_ani) |
306 | ath_start_ani(common); | 281 | ath_start_ani(common); |
307 | } | 282 | } |
308 | 283 | ||
309 | ps_restore: | 284 | ieee80211_wake_queues(sc->hw); |
310 | ieee80211_wake_queues(hw); | 285 | |
286 | return true; | ||
287 | } | ||
288 | |||
289 | static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan, | ||
290 | bool retry_tx) | ||
291 | { | ||
292 | struct ath_hw *ah = sc->sc_ah; | ||
293 | struct ath_common *common = ath9k_hw_common(ah); | ||
294 | struct ath9k_hw_cal_data *caldata = NULL; | ||
295 | bool fastcc = true; | ||
296 | bool flush = false; | ||
297 | int r; | ||
298 | |||
299 | __ath_cancel_work(sc); | ||
300 | |||
301 | spin_lock_bh(&sc->sc_pcu_lock); | ||
311 | 302 | ||
303 | if (!(sc->sc_flags & SC_OP_OFFCHANNEL)) { | ||
304 | fastcc = false; | ||
305 | caldata = &sc->caldata; | ||
306 | } | ||
307 | |||
308 | if (!hchan) { | ||
309 | fastcc = false; | ||
310 | flush = true; | ||
311 | hchan = ah->curchan; | ||
312 | } | ||
313 | |||
314 | if (fastcc && !ath9k_hw_check_alive(ah)) | ||
315 | fastcc = false; | ||
316 | |||
317 | if (!ath_prepare_reset(sc, retry_tx, flush)) | ||
318 | fastcc = false; | ||
319 | |||
320 | ath_dbg(common, ATH_DBG_CONFIG, | ||
321 | "Reset to %u MHz, HT40: %d fastcc: %d\n", | ||
322 | hchan->channel, !!(hchan->channelFlags & (CHANNEL_HT40MINUS | | ||
323 | CHANNEL_HT40PLUS)), | ||
324 | fastcc); | ||
325 | |||
326 | r = ath9k_hw_reset(ah, hchan, caldata, fastcc); | ||
327 | if (r) { | ||
328 | ath_err(common, | ||
329 | "Unable to reset channel, reset status %d\n", r); | ||
330 | goto out; | ||
331 | } | ||
332 | |||
333 | if (!ath_complete_reset(sc, true)) | ||
334 | r = -EIO; | ||
335 | |||
336 | out: | ||
312 | spin_unlock_bh(&sc->sc_pcu_lock); | 337 | spin_unlock_bh(&sc->sc_pcu_lock); |
338 | return r; | ||
339 | } | ||
340 | |||
341 | |||
342 | /* | ||
343 | * Set/change channels. If the channel is really being changed, it's done | ||
344 | * by reseting the chip. To accomplish this we must first cleanup any pending | ||
345 | * DMA, then restart stuff. | ||
346 | */ | ||
347 | static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, | ||
348 | struct ath9k_channel *hchan) | ||
349 | { | ||
350 | int r; | ||
351 | |||
352 | if (sc->sc_flags & SC_OP_INVALID) | ||
353 | return -EIO; | ||
354 | |||
355 | ath9k_ps_wakeup(sc); | ||
356 | |||
357 | r = ath_reset_internal(sc, hchan, false); | ||
313 | 358 | ||
314 | ath9k_ps_restore(sc); | 359 | ath9k_ps_restore(sc); |
360 | |||
315 | return r; | 361 | return r; |
316 | } | 362 | } |
317 | 363 | ||
@@ -825,28 +871,13 @@ static void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
825 | channel->center_freq, r); | 871 | channel->center_freq, r); |
826 | } | 872 | } |
827 | 873 | ||
828 | ath9k_cmn_update_txpow(ah, sc->curtxpow, | 874 | ath_complete_reset(sc, true); |
829 | sc->config.txpowlimit, &sc->curtxpow); | ||
830 | if (ath_startrecv(sc) != 0) { | ||
831 | ath_err(common, "Unable to restart recv logic\n"); | ||
832 | goto out; | ||
833 | } | ||
834 | if (sc->sc_flags & SC_OP_BEACONS) | ||
835 | ath_set_beacon(sc); /* restart beacons */ | ||
836 | |||
837 | /* Re-Enable interrupts */ | ||
838 | ath9k_hw_set_interrupts(ah, ah->imask); | ||
839 | ath9k_hw_enable_interrupts(ah); | ||
840 | 875 | ||
841 | /* Enable LED */ | 876 | /* Enable LED */ |
842 | ath9k_hw_cfg_output(ah, ah->led_pin, | 877 | ath9k_hw_cfg_output(ah, ah->led_pin, |
843 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | 878 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); |
844 | ath9k_hw_set_gpio(ah, ah->led_pin, 0); | 879 | ath9k_hw_set_gpio(ah, ah->led_pin, 0); |
845 | 880 | ||
846 | ieee80211_wake_queues(hw); | ||
847 | ieee80211_queue_delayed_work(hw, &sc->hw_pll_work, HZ/2); | ||
848 | |||
849 | out: | ||
850 | spin_unlock_bh(&sc->sc_pcu_lock); | 881 | spin_unlock_bh(&sc->sc_pcu_lock); |
851 | 882 | ||
852 | ath9k_ps_restore(sc); | 883 | ath9k_ps_restore(sc); |
@@ -859,11 +890,10 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
859 | int r; | 890 | int r; |
860 | 891 | ||
861 | ath9k_ps_wakeup(sc); | 892 | ath9k_ps_wakeup(sc); |
862 | cancel_delayed_work_sync(&sc->hw_pll_work); | ||
863 | 893 | ||
864 | spin_lock_bh(&sc->sc_pcu_lock); | 894 | ath_cancel_work(sc); |
865 | 895 | ||
866 | ieee80211_stop_queues(hw); | 896 | spin_lock_bh(&sc->sc_pcu_lock); |
867 | 897 | ||
868 | /* | 898 | /* |
869 | * Keep the LED on when the radio is disabled | 899 | * Keep the LED on when the radio is disabled |
@@ -874,13 +904,7 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
874 | ath9k_hw_cfg_gpio_input(ah, ah->led_pin); | 904 | ath9k_hw_cfg_gpio_input(ah, ah->led_pin); |
875 | } | 905 | } |
876 | 906 | ||
877 | /* Disable interrupts */ | 907 | ath_prepare_reset(sc, false, true); |
878 | ath9k_hw_disable_interrupts(ah); | ||
879 | |||
880 | ath_drain_all_txq(sc, false); /* clear pending tx frames */ | ||
881 | |||
882 | ath_stoprecv(sc); /* turn off frame recv */ | ||
883 | ath_flushrecv(sc); /* flush recv queue */ | ||
884 | 908 | ||
885 | if (!ah->curchan) | 909 | if (!ah->curchan) |
886 | ah->curchan = ath9k_cmn_get_curchannel(hw, ah); | 910 | ah->curchan = ath9k_cmn_get_curchannel(hw, ah); |
@@ -902,49 +926,11 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
902 | 926 | ||
903 | static int ath_reset(struct ath_softc *sc, bool retry_tx) | 927 | static int ath_reset(struct ath_softc *sc, bool retry_tx) |
904 | { | 928 | { |
905 | struct ath_hw *ah = sc->sc_ah; | ||
906 | struct ath_common *common = ath9k_hw_common(ah); | ||
907 | struct ieee80211_hw *hw = sc->hw; | ||
908 | int r; | 929 | int r; |
909 | 930 | ||
910 | sc->hw_busy_count = 0; | ||
911 | |||
912 | ath9k_debug_samp_bb_mac(sc); | ||
913 | /* Stop ANI */ | ||
914 | |||
915 | del_timer_sync(&common->ani.timer); | ||
916 | |||
917 | ath9k_ps_wakeup(sc); | 931 | ath9k_ps_wakeup(sc); |
918 | 932 | ||
919 | ieee80211_stop_queues(hw); | 933 | r = ath_reset_internal(sc, NULL, retry_tx); |
920 | |||
921 | ath9k_hw_disable_interrupts(ah); | ||
922 | ath_drain_all_txq(sc, retry_tx); | ||
923 | |||
924 | ath_stoprecv(sc); | ||
925 | ath_flushrecv(sc); | ||
926 | |||
927 | r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false); | ||
928 | if (r) | ||
929 | ath_err(common, | ||
930 | "Unable to reset hardware; reset status %d\n", r); | ||
931 | |||
932 | if (ath_startrecv(sc) != 0) | ||
933 | ath_err(common, "Unable to start recv logic\n"); | ||
934 | |||
935 | /* | ||
936 | * We may be doing a reset in response to a request | ||
937 | * that changes the channel so update any state that | ||
938 | * might change as a result. | ||
939 | */ | ||
940 | ath9k_cmn_update_txpow(ah, sc->curtxpow, | ||
941 | sc->config.txpowlimit, &sc->curtxpow); | ||
942 | |||
943 | if ((sc->sc_flags & SC_OP_BEACONS) || !(sc->sc_flags & (SC_OP_OFFCHANNEL))) | ||
944 | ath_set_beacon(sc); /* restart beacons */ | ||
945 | |||
946 | ath9k_hw_set_interrupts(ah, ah->imask); | ||
947 | ath9k_hw_enable_interrupts(ah); | ||
948 | 934 | ||
949 | if (retry_tx) { | 935 | if (retry_tx) { |
950 | int i; | 936 | int i; |
@@ -957,12 +943,6 @@ static int ath_reset(struct ath_softc *sc, bool retry_tx) | |||
957 | } | 943 | } |
958 | } | 944 | } |
959 | 945 | ||
960 | ieee80211_wake_queues(hw); | ||
961 | |||
962 | /* Start ANI */ | ||
963 | if (!common->disable_ani) | ||
964 | ath_start_ani(common); | ||
965 | |||
966 | ath9k_ps_restore(sc); | 946 | ath9k_ps_restore(sc); |
967 | 947 | ||
968 | return r; | 948 | return r; |
@@ -972,9 +952,7 @@ void ath_reset_work(struct work_struct *work) | |||
972 | { | 952 | { |
973 | struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work); | 953 | struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work); |
974 | 954 | ||
975 | spin_lock_bh(&sc->sc_pcu_lock); | ||
976 | ath_reset(sc, true); | 955 | ath_reset(sc, true); |
977 | spin_unlock_bh(&sc->sc_pcu_lock); | ||
978 | } | 956 | } |
979 | 957 | ||
980 | void ath_hw_check(struct work_struct *work) | 958 | void ath_hw_check(struct work_struct *work) |
@@ -995,11 +973,8 @@ void ath_hw_check(struct work_struct *work) | |||
995 | ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, " | 973 | ath_dbg(common, ATH_DBG_RESET, "Possible baseband hang, " |
996 | "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1); | 974 | "busy=%d (try %d)\n", busy, sc->hw_busy_count + 1); |
997 | if (busy >= 99) { | 975 | if (busy >= 99) { |
998 | if (++sc->hw_busy_count >= 3) { | 976 | if (++sc->hw_busy_count >= 3) |
999 | spin_lock_bh(&sc->sc_pcu_lock); | 977 | ieee80211_queue_work(sc->hw, &sc->hw_reset_work); |
1000 | ath_reset(sc, true); | ||
1001 | spin_unlock_bh(&sc->sc_pcu_lock); | ||
1002 | } | ||
1003 | 978 | ||
1004 | } else if (busy >= 0) | 979 | } else if (busy >= 0) |
1005 | sc->hw_busy_count = 0; | 980 | sc->hw_busy_count = 0; |
@@ -1019,9 +994,7 @@ static void ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum) | |||
1019 | /* Rx is hung for more than 500ms. Reset it */ | 994 | /* Rx is hung for more than 500ms. Reset it */ |
1020 | ath_dbg(common, ATH_DBG_RESET, | 995 | ath_dbg(common, ATH_DBG_RESET, |
1021 | "Possible RX hang, resetting"); | 996 | "Possible RX hang, resetting"); |
1022 | spin_lock_bh(&sc->sc_pcu_lock); | 997 | ieee80211_queue_work(sc->hw, &sc->hw_reset_work); |
1023 | ath_reset(sc, true); | ||
1024 | spin_unlock_bh(&sc->sc_pcu_lock); | ||
1025 | count = 0; | 998 | count = 0; |
1026 | } | 999 | } |
1027 | } else | 1000 | } else |
@@ -1092,28 +1065,6 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1092 | goto mutex_unlock; | 1065 | goto mutex_unlock; |
1093 | } | 1066 | } |
1094 | 1067 | ||
1095 | /* | ||
1096 | * This is needed only to setup initial state | ||
1097 | * but it's best done after a reset. | ||
1098 | */ | ||
1099 | ath9k_cmn_update_txpow(ah, sc->curtxpow, | ||
1100 | sc->config.txpowlimit, &sc->curtxpow); | ||
1101 | |||
1102 | /* | ||
1103 | * Setup the hardware after reset: | ||
1104 | * The receive engine is set going. | ||
1105 | * Frame transmit is handled entirely | ||
1106 | * in the frame output path; there's nothing to do | ||
1107 | * here except setup the interrupt mask. | ||
1108 | */ | ||
1109 | if (ath_startrecv(sc) != 0) { | ||
1110 | ath_err(common, "Unable to start recv logic\n"); | ||
1111 | r = -EIO; | ||
1112 | spin_unlock_bh(&sc->sc_pcu_lock); | ||
1113 | goto mutex_unlock; | ||
1114 | } | ||
1115 | spin_unlock_bh(&sc->sc_pcu_lock); | ||
1116 | |||
1117 | /* Setup our intr mask. */ | 1068 | /* Setup our intr mask. */ |
1118 | ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL | | 1069 | ah->imask = ATH9K_INT_TX | ATH9K_INT_RXEOL | |
1119 | ATH9K_INT_RXORN | ATH9K_INT_FATAL | | 1070 | ATH9K_INT_RXORN | ATH9K_INT_FATAL | |
@@ -1136,12 +1087,14 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
1136 | 1087 | ||
1137 | /* Disable BMISS interrupt when we're not associated */ | 1088 | /* Disable BMISS interrupt when we're not associated */ |
1138 | ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); | 1089 | ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); |
1139 | ath9k_hw_set_interrupts(ah, ah->imask); | ||
1140 | ath9k_hw_enable_interrupts(ah); | ||
1141 | 1090 | ||
1142 | ieee80211_wake_queues(hw); | 1091 | if (!ath_complete_reset(sc, false)) { |
1092 | r = -EIO; | ||
1093 | spin_unlock_bh(&sc->sc_pcu_lock); | ||
1094 | goto mutex_unlock; | ||
1095 | } | ||
1143 | 1096 | ||
1144 | ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); | 1097 | spin_unlock_bh(&sc->sc_pcu_lock); |
1145 | 1098 | ||
1146 | if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) && | 1099 | if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) && |
1147 | !ah->btcoex_hw.enabled) { | 1100 | !ah->btcoex_hw.enabled) { |
@@ -1234,11 +1187,7 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
1234 | 1187 | ||
1235 | mutex_lock(&sc->mutex); | 1188 | mutex_lock(&sc->mutex); |
1236 | 1189 | ||
1237 | cancel_delayed_work_sync(&sc->tx_complete_work); | 1190 | ath_cancel_work(sc); |
1238 | cancel_delayed_work_sync(&sc->hw_pll_work); | ||
1239 | cancel_work_sync(&sc->paprd_work); | ||
1240 | cancel_work_sync(&sc->hw_check_work); | ||
1241 | cancel_work_sync(&sc->hw_reset_work); | ||
1242 | 1191 | ||
1243 | if (sc->sc_flags & SC_OP_INVALID) { | 1192 | if (sc->sc_flags & SC_OP_INVALID) { |
1244 | ath_dbg(common, ATH_DBG_ANY, "Device not present\n"); | 1193 | ath_dbg(common, ATH_DBG_ANY, "Device not present\n"); |
@@ -2349,9 +2298,11 @@ static void ath9k_flush(struct ieee80211_hw *hw, bool drop) | |||
2349 | ath9k_ps_wakeup(sc); | 2298 | ath9k_ps_wakeup(sc); |
2350 | spin_lock_bh(&sc->sc_pcu_lock); | 2299 | spin_lock_bh(&sc->sc_pcu_lock); |
2351 | drain_txq = ath_drain_all_txq(sc, false); | 2300 | drain_txq = ath_drain_all_txq(sc, false); |
2301 | spin_unlock_bh(&sc->sc_pcu_lock); | ||
2302 | |||
2352 | if (!drain_txq) | 2303 | if (!drain_txq) |
2353 | ath_reset(sc, false); | 2304 | ath_reset(sc, false); |
2354 | spin_unlock_bh(&sc->sc_pcu_lock); | 2305 | |
2355 | ath9k_ps_restore(sc); | 2306 | ath9k_ps_restore(sc); |
2356 | ieee80211_wake_queues(hw); | 2307 | ieee80211_wake_queues(hw); |
2357 | 2308 | ||