diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/channel.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/channel.c | 54 |
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 | ||
762 | void ath_roc_complete(struct ath_softc *sc, bool abort) | 762 | void 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) | |||
1037 | void ath_chanctx_set_next(struct ath_softc *sc, bool force) | 1044 | void 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); | ||
1130 | out: | ||
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 | ||
1173 | void ath9k_chanctx_wake_queues(struct ath_softc *sc) | 1196 | void 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 | |||
1215 | void 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 | ||