aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/main.c41
-rw-r--r--net/mac80211/offchannel.c9
-rw-r--r--net/mac80211/scan.c4
-rw-r--r--net/mac80211/work.c99
5 files changed, 13 insertions, 142 deletions
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index a785d61defe1..bdefa6ba3f4c 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1220,13 +1220,11 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata);
1220void ieee80211_sched_scan_stopped_work(struct work_struct *work); 1220void ieee80211_sched_scan_stopped_work(struct work_struct *work);
1221 1221
1222/* off-channel helpers */ 1222/* off-channel helpers */
1223bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local);
1224void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local, 1223void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local,
1225 bool tell_ap); 1224 bool tell_ap);
1226void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, 1225void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local,
1227 bool offchannel_ps_enable); 1226 bool offchannel_ps_enable);
1228void ieee80211_offchannel_return(struct ieee80211_local *local, 1227void ieee80211_offchannel_return(struct ieee80211_local *local,
1229 bool enable_beaconing,
1230 bool offchannel_ps_disable); 1228 bool offchannel_ps_disable);
1231void ieee80211_hw_roc_setup(struct ieee80211_local *local); 1229void ieee80211_hw_roc_setup(struct ieee80211_local *local);
1232 1230
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index dddedfad5404..944bed35d923 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -92,47 +92,6 @@ static void ieee80211_reconfig_filter(struct work_struct *work)
92 ieee80211_configure_filter(local); 92 ieee80211_configure_filter(local);
93} 93}
94 94
95/*
96 * Returns true if we are logically configured to be on
97 * the operating channel AND the hardware-conf is currently
98 * configured on the operating channel. Compares channel-type
99 * as well.
100 */
101bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local)
102{
103 struct ieee80211_channel *chan;
104 enum nl80211_channel_type channel_type;
105
106 /* This logic needs to match logic in ieee80211_hw_config */
107 if (local->scan_channel) {
108 chan = local->scan_channel;
109 /* If scanning on oper channel, use whatever channel-type
110 * is currently in use.
111 */
112 if (chan == local->oper_channel)
113 channel_type = local->_oper_channel_type;
114 else
115 channel_type = NL80211_CHAN_NO_HT;
116 } else if (local->tmp_channel) {
117 chan = local->tmp_channel;
118 channel_type = local->tmp_channel_type;
119 } else {
120 chan = local->oper_channel;
121 channel_type = local->_oper_channel_type;
122 }
123
124 if (chan != local->oper_channel ||
125 channel_type != local->_oper_channel_type)
126 return false;
127
128 /* Check current hardware-config against oper_channel. */
129 if (local->oper_channel != local->hw.conf.channel ||
130 local->_oper_channel_type != local->hw.conf.channel_type)
131 return false;
132
133 return true;
134}
135
136int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) 95int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
137{ 96{
138 struct ieee80211_channel *chan; 97 struct ieee80211_channel *chan;
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index ebd8cccac8f2..e4330d843575 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -156,7 +156,6 @@ void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local,
156} 156}
157 157
158void ieee80211_offchannel_return(struct ieee80211_local *local, 158void ieee80211_offchannel_return(struct ieee80211_local *local,
159 bool enable_beaconing,
160 bool offchannel_ps_disable) 159 bool offchannel_ps_disable)
161{ 160{
162 struct ieee80211_sub_if_data *sdata; 161 struct ieee80211_sub_if_data *sdata;
@@ -188,11 +187,9 @@ void ieee80211_offchannel_return(struct ieee80211_local *local,
188 netif_tx_wake_all_queues(sdata->dev); 187 netif_tx_wake_all_queues(sdata->dev);
189 } 188 }
190 189
191 /* Check to see if we should re-enable beaconing */ 190 if (sdata->vif.type == NL80211_IFTYPE_AP ||
192 if (enable_beaconing && 191 sdata->vif.type == NL80211_IFTYPE_ADHOC ||
193 (sdata->vif.type == NL80211_IFTYPE_AP || 192 sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
194 sdata->vif.type == NL80211_IFTYPE_ADHOC ||
195 sdata->vif.type == NL80211_IFTYPE_MESH_POINT))
196 ieee80211_bss_info_change_notify( 193 ieee80211_bss_info_change_notify(
197 sdata, BSS_CHANGED_BEACON_ENABLED); 194 sdata, BSS_CHANGED_BEACON_ENABLED);
198 } 195 }
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 81863031e0a3..2c5041cc71f8 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -297,7 +297,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
297 if (!was_hw_scan) { 297 if (!was_hw_scan) {
298 ieee80211_configure_filter(local); 298 ieee80211_configure_filter(local);
299 drv_sw_scan_complete(local); 299 drv_sw_scan_complete(local);
300 ieee80211_offchannel_return(local, true, true); 300 ieee80211_offchannel_return(local, true);
301 } 301 }
302 302
303 ieee80211_recalc_idle(local); 303 ieee80211_recalc_idle(local);
@@ -602,7 +602,7 @@ static void ieee80211_scan_state_suspend(struct ieee80211_local *local,
602 * in off-channel state..will put that back 602 * in off-channel state..will put that back
603 * on-channel at the end of scanning. 603 * on-channel at the end of scanning.
604 */ 604 */
605 ieee80211_offchannel_return(local, true, false); 605 ieee80211_offchannel_return(local, false);
606 606
607 *next_delay = HZ / 5; 607 *next_delay = HZ / 5;
608 /* afterwards, resume scan & go to next channel */ 608 /* afterwards, resume scan & go to next channel */
diff --git a/net/mac80211/work.c b/net/mac80211/work.c
index 6884a2d986dc..c6dd01a05291 100644
--- a/net/mac80211/work.c
+++ b/net/mac80211/work.c
@@ -862,44 +862,6 @@ static void ieee80211_work_rx_queued_mgmt(struct ieee80211_local *local,
862 kfree_skb(skb); 862 kfree_skb(skb);
863} 863}
864 864
865static bool ieee80211_work_ct_coexists(enum nl80211_channel_type wk_ct,
866 enum nl80211_channel_type oper_ct)
867{
868 switch (wk_ct) {
869 case NL80211_CHAN_NO_HT:
870 return true;
871 case NL80211_CHAN_HT20:
872 if (oper_ct != NL80211_CHAN_NO_HT)
873 return true;
874 return false;
875 case NL80211_CHAN_HT40MINUS:
876 case NL80211_CHAN_HT40PLUS:
877 return (wk_ct == oper_ct);
878 }
879 WARN_ON(1); /* shouldn't get here */
880 return false;
881}
882
883static enum nl80211_channel_type
884ieee80211_calc_ct(enum nl80211_channel_type wk_ct,
885 enum nl80211_channel_type oper_ct)
886{
887 switch (wk_ct) {
888 case NL80211_CHAN_NO_HT:
889 return oper_ct;
890 case NL80211_CHAN_HT20:
891 if (oper_ct != NL80211_CHAN_NO_HT)
892 return oper_ct;
893 return wk_ct;
894 case NL80211_CHAN_HT40MINUS:
895 case NL80211_CHAN_HT40PLUS:
896 return wk_ct;
897 }
898 WARN_ON(1); /* shouldn't get here */
899 return wk_ct;
900}
901
902
903static void ieee80211_work_timer(unsigned long data) 865static void ieee80211_work_timer(unsigned long data)
904{ 866{
905 struct ieee80211_local *local = (void *) data; 867 struct ieee80211_local *local = (void *) data;
@@ -950,40 +912,12 @@ static void ieee80211_work_work(struct work_struct *work)
950 } 912 }
951 913
952 if (!started && !local->tmp_channel) { 914 if (!started && !local->tmp_channel) {
953 bool on_oper_chan, on_oper_chan2; 915 ieee80211_offchannel_stop_vifs(local, true);
954 enum nl80211_channel_type wk_ct;
955
956 on_oper_chan = ieee80211_cfg_on_oper_channel(local);
957
958 /* Work with existing channel type if possible. */
959 wk_ct = wk->chan_type;
960 if (wk->chan == local->hw.conf.channel)
961 wk_ct = ieee80211_calc_ct(wk->chan_type,
962 local->hw.conf.channel_type);
963 916
964 local->tmp_channel = wk->chan; 917 local->tmp_channel = wk->chan;
965 local->tmp_channel_type = wk_ct; 918 local->tmp_channel_type = wk->chan_type;
966 /* 919
967 * Leave the station vifs in awake mode if they 920 ieee80211_hw_config(local, 0);
968 * happen to be on the same channel as
969 * the requested channel.
970 */
971 on_oper_chan2 = ieee80211_cfg_on_oper_channel(local);
972 if (on_oper_chan != on_oper_chan2) {
973 if (on_oper_chan2) {
974 /* going off oper channel, PS too */
975 ieee80211_offchannel_stop_vifs(local,
976 true);
977 ieee80211_hw_config(local, 0);
978 } else {
979 /* going on channel, but leave PS
980 * off-channel. */
981 ieee80211_hw_config(local, 0);
982 ieee80211_offchannel_return(local,
983 true,
984 false);
985 }
986 }
987 921
988 started = true; 922 started = true;
989 wk->timeout = jiffies; 923 wk->timeout = jiffies;
@@ -1052,34 +986,17 @@ static void ieee80211_work_work(struct work_struct *work)
1052 list_for_each_entry(wk, &local->work_list, list) { 986 list_for_each_entry(wk, &local->work_list, list) {
1053 if (!wk->started) 987 if (!wk->started)
1054 continue; 988 continue;
1055 if (wk->chan != local->tmp_channel) 989 if (wk->chan != local->tmp_channel ||
1056 continue; 990 wk->chan_type != local->tmp_channel_type)
1057 if (!ieee80211_work_ct_coexists(wk->chan_type,
1058 local->tmp_channel_type))
1059 continue; 991 continue;
1060 remain_off_channel = true; 992 remain_off_channel = true;
1061 } 993 }
1062 994
1063 if (!remain_off_channel && local->tmp_channel) { 995 if (!remain_off_channel && local->tmp_channel) {
1064 local->tmp_channel = NULL; 996 local->tmp_channel = NULL;
1065 /* If tmp_channel wasn't operating channel, then 997 ieee80211_hw_config(local, 0);
1066 * we need to go back on-channel.
1067 * NOTE: If we can ever be here while scannning,
1068 * or if the hw_config() channel config logic changes,
1069 * then we may need to do a more thorough check to see if
1070 * we still need to do a hardware config. Currently,
1071 * we cannot be here while scanning, however.
1072 */
1073 if (!ieee80211_cfg_on_oper_channel(local))
1074 ieee80211_hw_config(local, 0);
1075 998
1076 /* At the least, we need to disable offchannel_ps, 999 ieee80211_offchannel_return(local, true);
1077 * so just go ahead and run the entire offchannel
1078 * return logic here. We *could* skip enabling
1079 * beaconing if we were already on-oper-channel
1080 * as a future optimization.
1081 */
1082 ieee80211_offchannel_return(local, true, true);
1083 1000
1084 /* give connection some time to breathe */ 1001 /* give connection some time to breathe */
1085 run_again(local, jiffies + HZ/2); 1002 run_again(local, jiffies + HZ/2);