aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/channel.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/channel.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/channel.c54
1 files changed, 48 insertions, 6 deletions
diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c
index 77c99eb55834..945c89826b14 100644
--- a/drivers/net/wireless/ath/ath9k/channel.c
+++ b/drivers/net/wireless/ath/ath9k/channel.c
@@ -211,7 +211,7 @@ void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx)
211 switch (vif->type) { 211 switch (vif->type) {
212 case NL80211_IFTYPE_P2P_CLIENT: 212 case NL80211_IFTYPE_P2P_CLIENT:
213 case NL80211_IFTYPE_STATION: 213 case NL80211_IFTYPE_STATION:
214 if (vif->bss_conf.assoc) 214 if (avp->assoc)
215 active = true; 215 active = true;
216 break; 216 break;
217 default: 217 default:
@@ -761,6 +761,13 @@ void ath_offchannel_next(struct ath_softc *sc)
761 761
762void ath_roc_complete(struct ath_softc *sc, bool abort) 762void ath_roc_complete(struct ath_softc *sc, bool abort)
763{ 763{
764 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
765
766 if (abort)
767 ath_dbg(common, CHAN_CTX, "RoC aborted\n");
768 else
769 ath_dbg(common, CHAN_CTX, "RoC expired\n");
770
764 sc->offchannel.roc_vif = NULL; 771 sc->offchannel.roc_vif = NULL;
765 sc->offchannel.roc_chan = NULL; 772 sc->offchannel.roc_chan = NULL;
766 if (!abort) 773 if (!abort)
@@ -917,7 +924,7 @@ ath_chanctx_send_vif_ps_frame(struct ath_softc *sc, struct ath_vif *avp,
917 924
918 switch (vif->type) { 925 switch (vif->type) {
919 case NL80211_IFTYPE_STATION: 926 case NL80211_IFTYPE_STATION:
920 if (!vif->bss_conf.assoc) 927 if (!avp->assoc)
921 return false; 928 return false;
922 929
923 skb = ieee80211_nullfunc_get(sc->hw, vif); 930 skb = ieee80211_nullfunc_get(sc->hw, vif);
@@ -1037,9 +1044,11 @@ static void ath_offchannel_channel_change(struct ath_softc *sc)
1037void ath_chanctx_set_next(struct ath_softc *sc, bool force) 1044void ath_chanctx_set_next(struct ath_softc *sc, bool force)
1038{ 1045{
1039 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 1046 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
1047 struct ath_chanctx *old_ctx;
1040 struct timespec ts; 1048 struct timespec ts;
1041 bool measure_time = false; 1049 bool measure_time = false;
1042 bool send_ps = false; 1050 bool send_ps = false;
1051 bool queues_stopped = false;
1043 1052
1044 spin_lock_bh(&sc->chan_lock); 1053 spin_lock_bh(&sc->chan_lock);
1045 if (!sc->next_chan) { 1054 if (!sc->next_chan) {
@@ -1069,6 +1078,10 @@ void ath_chanctx_set_next(struct ath_softc *sc, bool force)
1069 getrawmonotonic(&ts); 1078 getrawmonotonic(&ts);
1070 measure_time = true; 1079 measure_time = true;
1071 } 1080 }
1081
1082 ath9k_chanctx_stop_queues(sc, sc->cur_chan);
1083 queues_stopped = true;
1084
1072 __ath9k_flush(sc->hw, ~0, true); 1085 __ath9k_flush(sc->hw, ~0, true);
1073 1086
1074 if (ath_chanctx_send_ps_frame(sc, true)) 1087 if (ath_chanctx_send_ps_frame(sc, true))
@@ -1082,6 +1095,7 @@ void ath_chanctx_set_next(struct ath_softc *sc, bool force)
1082 sc->cur_chan->tsf_val = ath9k_hw_gettsf64(sc->sc_ah); 1095 sc->cur_chan->tsf_val = ath9k_hw_gettsf64(sc->sc_ah);
1083 } 1096 }
1084 } 1097 }
1098 old_ctx = sc->cur_chan;
1085 sc->cur_chan = sc->next_chan; 1099 sc->cur_chan = sc->next_chan;
1086 sc->cur_chan->stopped = false; 1100 sc->cur_chan->stopped = false;
1087 sc->next_chan = NULL; 1101 sc->next_chan = NULL;
@@ -1104,7 +1118,16 @@ void ath_chanctx_set_next(struct ath_softc *sc, bool force)
1104 if (measure_time) 1118 if (measure_time)
1105 sc->sched.channel_switch_time = 1119 sc->sched.channel_switch_time =
1106 ath9k_hw_get_tsf_offset(&ts, NULL); 1120 ath9k_hw_get_tsf_offset(&ts, NULL);
1121 /*
1122 * A reset will ensure that all queues are woken up,
1123 * so there is no need to awaken them again.
1124 */
1125 goto out;
1107 } 1126 }
1127
1128 if (queues_stopped)
1129 ath9k_chanctx_wake_queues(sc, old_ctx);
1130out:
1108 if (send_ps) 1131 if (send_ps)
1109 ath_chanctx_send_ps_frame(sc, false); 1132 ath_chanctx_send_ps_frame(sc, false);
1110 1133
@@ -1170,18 +1193,37 @@ bool ath9k_is_chanctx_enabled(void)
1170/* Queue management */ 1193/* Queue management */
1171/********************/ 1194/********************/
1172 1195
1173void ath9k_chanctx_wake_queues(struct ath_softc *sc) 1196void ath9k_chanctx_stop_queues(struct ath_softc *sc, struct ath_chanctx *ctx)
1197{
1198 struct ath_hw *ah = sc->sc_ah;
1199 int i;
1200
1201 if (ctx == &sc->offchannel.chan) {
1202 ieee80211_stop_queue(sc->hw,
1203 sc->hw->offchannel_tx_hw_queue);
1204 } else {
1205 for (i = 0; i < IEEE80211_NUM_ACS; i++)
1206 ieee80211_stop_queue(sc->hw,
1207 ctx->hw_queue_base + i);
1208 }
1209
1210 if (ah->opmode == NL80211_IFTYPE_AP)
1211 ieee80211_stop_queue(sc->hw, sc->hw->queues - 2);
1212}
1213
1214
1215void ath9k_chanctx_wake_queues(struct ath_softc *sc, struct ath_chanctx *ctx)
1174{ 1216{
1175 struct ath_hw *ah = sc->sc_ah; 1217 struct ath_hw *ah = sc->sc_ah;
1176 int i; 1218 int i;
1177 1219
1178 if (sc->cur_chan == &sc->offchannel.chan) { 1220 if (ctx == &sc->offchannel.chan) {
1179 ieee80211_wake_queue(sc->hw, 1221 ieee80211_wake_queue(sc->hw,
1180 sc->hw->offchannel_tx_hw_queue); 1222 sc->hw->offchannel_tx_hw_queue);
1181 } else { 1223 } else {
1182 for (i = 0; i < IEEE80211_NUM_ACS; i++) 1224 for (i = 0; i < IEEE80211_NUM_ACS; i++)
1183 ieee80211_wake_queue(sc->hw, 1225 ieee80211_wake_queue(sc->hw,
1184 sc->cur_chan->hw_queue_base + i); 1226 ctx->hw_queue_base + i);
1185 } 1227 }
1186 1228
1187 if (ah->opmode == NL80211_IFTYPE_AP) 1229 if (ah->opmode == NL80211_IFTYPE_AP)
@@ -1339,7 +1381,7 @@ void ath9k_p2p_ps_timer(void *priv)
1339 rcu_read_lock(); 1381 rcu_read_lock();
1340 1382
1341 vif = avp->vif; 1383 vif = avp->vif;
1342 sta = ieee80211_find_sta(vif, vif->bss_conf.bssid); 1384 sta = ieee80211_find_sta(vif, avp->bssid);
1343 if (!sta) 1385 if (!sta)
1344 goto out; 1386 goto out;
1345 1387