aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSujith Manoharan <c_manoha@qca.qualcomm.com>2014-11-15 19:41:10 -0500
committerJohn W. Linville <linville@tuxdriver.com>2014-11-17 15:32:17 -0500
commit47b6308b643302e642ca2a5cb6470926f7e1c428 (patch)
treece19c92ba18f1b0daa1845e7b9e8d59840dadd3f
parentd9092c9873739429c9e97c4bc21ead9af2fb6aa1 (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.c8
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;