aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/work.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/work.c')
-rw-r--r--net/mac80211/work.c66
1 files changed, 55 insertions, 11 deletions
diff --git a/net/mac80211/work.c b/net/mac80211/work.c
index 36305e0d06e..6bf787a5b38 100644
--- a/net/mac80211/work.c
+++ b/net/mac80211/work.c
@@ -924,18 +924,44 @@ static void ieee80211_work_work(struct work_struct *work)
924 } 924 }
925 925
926 if (!started && !local->tmp_channel) { 926 if (!started && !local->tmp_channel) {
927 /* 927 bool on_oper_chan;
928 * TODO: could optimize this by leaving the 928 bool tmp_chan_changed = false;
929 * station vifs in awake mode if they 929 bool on_oper_chan2;
930 * happen to be on the same channel as 930 on_oper_chan = ieee80211_cfg_on_oper_channel(local);
931 * the requested channel 931 if (local->tmp_channel)
932 */ 932 if ((local->tmp_channel != wk->chan) ||
933 ieee80211_offchannel_stop_beaconing(local); 933 (local->tmp_channel_type != wk->chan_type))
934 ieee80211_offchannel_stop_station(local); 934 tmp_chan_changed = true;
935 935
936 local->tmp_channel = wk->chan; 936 local->tmp_channel = wk->chan;
937 local->tmp_channel_type = wk->chan_type; 937 local->tmp_channel_type = wk->chan_type;
938 ieee80211_hw_config(local, 0); 938 /*
939 * Leave the station vifs in awake mode if they
940 * happen to be on the same channel as
941 * the requested channel.
942 */
943 on_oper_chan2 = ieee80211_cfg_on_oper_channel(local);
944 if (on_oper_chan != on_oper_chan2) {
945 if (on_oper_chan2) {
946 /* going off oper channel, PS too */
947 ieee80211_offchannel_stop_vifs(local,
948 true);
949 ieee80211_hw_config(local, 0);
950 } else {
951 /* going on channel, but leave PS
952 * off-channel. */
953 ieee80211_hw_config(local, 0);
954 ieee80211_offchannel_return(local,
955 true,
956 false);
957 }
958 } else if (tmp_chan_changed)
959 /* Still off-channel, but on some other
960 * channel, so update hardware.
961 * PS should already be off-channel.
962 */
963 ieee80211_hw_config(local, 0);
964
939 started = true; 965 started = true;
940 wk->timeout = jiffies; 966 wk->timeout = jiffies;
941 } 967 }
@@ -1011,9 +1037,27 @@ static void ieee80211_work_work(struct work_struct *work)
1011 } 1037 }
1012 1038
1013 if (!remain_off_channel && local->tmp_channel) { 1039 if (!remain_off_channel && local->tmp_channel) {
1040 bool on_oper_chan = ieee80211_cfg_on_oper_channel(local);
1014 local->tmp_channel = NULL; 1041 local->tmp_channel = NULL;
1015 ieee80211_hw_config(local, 0); 1042 /* If tmp_channel wasn't operating channel, then
1016 ieee80211_offchannel_return(local, true); 1043 * we need to go back on-channel.
1044 * NOTE: If we can ever be here while scannning,
1045 * or if the hw_config() channel config logic changes,
1046 * then we may need to do a more thorough check to see if
1047 * we still need to do a hardware config. Currently,
1048 * we cannot be here while scanning, however.
1049 */
1050 if (ieee80211_cfg_on_oper_channel(local) && !on_oper_chan)
1051 ieee80211_hw_config(local, 0);
1052
1053 /* At the least, we need to disable offchannel_ps,
1054 * so just go ahead and run the entire offchannel
1055 * return logic here. We *could* skip enabling
1056 * beaconing if we were already on-oper-channel
1057 * as a future optimization.
1058 */
1059 ieee80211_offchannel_return(local, true, true);
1060
1017 /* give connection some time to breathe */ 1061 /* give connection some time to breathe */
1018 run_again(local, jiffies + HZ/2); 1062 run_again(local, jiffies + HZ/2);
1019 } 1063 }