diff options
author | Sujith Manoharan <c_manoha@qca.qualcomm.com> | 2014-11-15 19:41:10 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-11-17 15:32:17 -0500 |
commit | 47b6308b643302e642ca2a5cb6470926f7e1c428 (patch) | |
tree | ce19c92ba18f1b0daa1845e7b9e8d59840dadd3f | |
parent | d9092c9873739429c9e97c4bc21ead9af2fb6aa1 (diff) |
ath9k: Move roc completion to the offchannel timer
Currently, when a roc period expires, the offchannel
timer calls ieee80211_remain_on_channel_expired(), but
the roc state is cleared only when the queued work
to switch to the operating channel gets a chance to run.
This race is a problem because mac80211 can issue a
new roc request in this window. To avoid this, handle
roc completion in the offchannel timer itself.
Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r-- | drivers/net/wireless/ath/ath9k/channel.c | 8 |
1 files changed, 2 insertions, 6 deletions
diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c index 99425fe13055..794d52016437 100644 --- a/drivers/net/wireless/ath/ath9k/channel.c +++ b/drivers/net/wireless/ath/ath9k/channel.c | |||
@@ -926,8 +926,7 @@ void ath_roc_complete(struct ath_softc *sc, bool abort) | |||
926 | 926 | ||
927 | sc->offchannel.roc_vif = NULL; | 927 | sc->offchannel.roc_vif = NULL; |
928 | sc->offchannel.roc_chan = NULL; | 928 | sc->offchannel.roc_chan = NULL; |
929 | if (abort) | 929 | ieee80211_remain_on_channel_expired(sc->hw); |
930 | ieee80211_remain_on_channel_expired(sc->hw); | ||
931 | ath_offchannel_next(sc); | 930 | ath_offchannel_next(sc); |
932 | ath9k_ps_restore(sc); | 931 | ath9k_ps_restore(sc); |
933 | } | 932 | } |
@@ -1058,10 +1057,8 @@ static void ath_offchannel_timer(unsigned long data) | |||
1058 | break; | 1057 | break; |
1059 | case ATH_OFFCHANNEL_ROC_START: | 1058 | case ATH_OFFCHANNEL_ROC_START: |
1060 | case ATH_OFFCHANNEL_ROC_WAIT: | 1059 | case ATH_OFFCHANNEL_ROC_WAIT: |
1061 | ctx = ath_chanctx_get_oper_chan(sc, false); | ||
1062 | sc->offchannel.state = ATH_OFFCHANNEL_ROC_DONE; | 1060 | sc->offchannel.state = ATH_OFFCHANNEL_ROC_DONE; |
1063 | ieee80211_remain_on_channel_expired(sc->hw); | 1061 | ath_roc_complete(sc, false); |
1064 | ath_chanctx_switch(sc, ctx, NULL); | ||
1065 | break; | 1062 | break; |
1066 | default: | 1063 | default: |
1067 | break; | 1064 | break; |
@@ -1191,7 +1188,6 @@ static void ath_offchannel_channel_change(struct ath_softc *sc) | |||
1191 | ieee80211_ready_on_channel(sc->hw); | 1188 | ieee80211_ready_on_channel(sc->hw); |
1192 | break; | 1189 | break; |
1193 | case ATH_OFFCHANNEL_ROC_DONE: | 1190 | case ATH_OFFCHANNEL_ROC_DONE: |
1194 | ath_roc_complete(sc, false); | ||
1195 | break; | 1191 | break; |
1196 | default: | 1192 | default: |
1197 | break; | 1193 | break; |