diff options
Diffstat (limited to 'recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.2/0080-mac80211-revert-on-channel-work-optimisations.patch')
-rw-r--r-- | recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.2/0080-mac80211-revert-on-channel-work-optimisations.patch | 635 |
1 files changed, 635 insertions, 0 deletions
diff --git a/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.2/0080-mac80211-revert-on-channel-work-optimisations.patch b/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.2/0080-mac80211-revert-on-channel-work-optimisations.patch new file mode 100644 index 00000000..eca2dda2 --- /dev/null +++ b/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.2/0080-mac80211-revert-on-channel-work-optimisations.patch | |||
@@ -0,0 +1,635 @@ | |||
1 | From 5b8206fb91b97732d80ada2e494e060d50ab30bd Mon Sep 17 00:00:00 2001 | ||
2 | From: Johannes Berg <johannes.berg@intel.com> | ||
3 | Date: Tue, 29 Nov 2011 10:20:02 +0100 | ||
4 | Subject: [PATCH 080/130] mac80211: revert on-channel work optimisations | ||
5 | |||
6 | commit e76aadc572288a158ae18ae1c10fe395c7bca066 upstream. | ||
7 | |||
8 | Backport note: | ||
9 | This patch it's a full revert of commit b23b025f "mac80211: Optimize | ||
10 | scans on current operating channel.". On upstrem revert e76aadc5 we | ||
11 | keep some bits from that commit, which are needed for upstream version | ||
12 | of mac80211. | ||
13 | |||
14 | The on-channel work optimisations have caused a | ||
15 | number of issues, and the code is unfortunately | ||
16 | very complex and almost impossible to follow. | ||
17 | Instead of attempting to put in more workarounds | ||
18 | let's just remove those optimisations, we can | ||
19 | work on them again later, after we change the | ||
20 | whole auth/assoc design. | ||
21 | |||
22 | This should fix rate_control_send_low() warnings, | ||
23 | see RH bug 731365. | ||
24 | |||
25 | Signed-off-by: Johannes Berg <johannes.berg@intel.com> | ||
26 | Signed-off-by: John W. Linville <linville@tuxdriver.com> | ||
27 | Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com> | ||
28 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | ||
29 | --- | ||
30 | net/mac80211/ieee80211_i.h | 13 +++---- | ||
31 | net/mac80211/main.c | 58 +++----------------------------- | ||
32 | net/mac80211/offchannel.c | 68 +++++++++++++++++--------------------- | ||
33 | net/mac80211/rx.c | 10 ++++- | ||
34 | net/mac80211/scan.c | 77 ++++++++++++------------------------------- | ||
35 | net/mac80211/tx.c | 3 +- | ||
36 | net/mac80211/work.c | 77 ++++++------------------------------------- | ||
37 | 7 files changed, 85 insertions(+), 221 deletions(-) | ||
38 | |||
39 | diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h | ||
40 | index ea10a51..73495f1 100644 | ||
41 | --- a/net/mac80211/ieee80211_i.h | ||
42 | +++ b/net/mac80211/ieee80211_i.h | ||
43 | @@ -702,6 +702,8 @@ struct tpt_led_trigger { | ||
44 | * well be on the operating channel | ||
45 | * @SCAN_HW_SCANNING: The hardware is scanning for us, we have no way to | ||
46 | * determine if we are on the operating channel or not | ||
47 | + * @SCAN_OFF_CHANNEL: We're off our operating channel for scanning, | ||
48 | + * gets only set in conjunction with SCAN_SW_SCANNING | ||
49 | * @SCAN_COMPLETED: Set for our scan work function when the driver reported | ||
50 | * that the scan completed. | ||
51 | * @SCAN_ABORTED: Set for our scan work function when the driver reported | ||
52 | @@ -710,6 +712,7 @@ struct tpt_led_trigger { | ||
53 | enum { | ||
54 | SCAN_SW_SCANNING, | ||
55 | SCAN_HW_SCANNING, | ||
56 | + SCAN_OFF_CHANNEL, | ||
57 | SCAN_COMPLETED, | ||
58 | SCAN_ABORTED, | ||
59 | }; | ||
60 | @@ -1140,14 +1143,10 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata); | ||
61 | void ieee80211_sched_scan_stopped_work(struct work_struct *work); | ||
62 | |||
63 | /* off-channel helpers */ | ||
64 | -bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local); | ||
65 | -void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local, | ||
66 | - bool tell_ap); | ||
67 | -void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, | ||
68 | - bool offchannel_ps_enable); | ||
69 | +void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local); | ||
70 | +void ieee80211_offchannel_stop_station(struct ieee80211_local *local); | ||
71 | void ieee80211_offchannel_return(struct ieee80211_local *local, | ||
72 | - bool enable_beaconing, | ||
73 | - bool offchannel_ps_disable); | ||
74 | + bool enable_beaconing); | ||
75 | void ieee80211_hw_roc_setup(struct ieee80211_local *local); | ||
76 | |||
77 | /* interface handling */ | ||
78 | diff --git a/net/mac80211/main.c b/net/mac80211/main.c | ||
79 | index cae4435..a7536fd 100644 | ||
80 | --- a/net/mac80211/main.c | ||
81 | +++ b/net/mac80211/main.c | ||
82 | @@ -92,47 +92,6 @@ static void ieee80211_reconfig_filter(struct work_struct *work) | ||
83 | ieee80211_configure_filter(local); | ||
84 | } | ||
85 | |||
86 | -/* | ||
87 | - * Returns true if we are logically configured to be on | ||
88 | - * the operating channel AND the hardware-conf is currently | ||
89 | - * configured on the operating channel. Compares channel-type | ||
90 | - * as well. | ||
91 | - */ | ||
92 | -bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local) | ||
93 | -{ | ||
94 | - struct ieee80211_channel *chan, *scan_chan; | ||
95 | - enum nl80211_channel_type channel_type; | ||
96 | - | ||
97 | - /* This logic needs to match logic in ieee80211_hw_config */ | ||
98 | - if (local->scan_channel) { | ||
99 | - chan = local->scan_channel; | ||
100 | - /* If scanning on oper channel, use whatever channel-type | ||
101 | - * is currently in use. | ||
102 | - */ | ||
103 | - if (chan == local->oper_channel) | ||
104 | - channel_type = local->_oper_channel_type; | ||
105 | - else | ||
106 | - channel_type = NL80211_CHAN_NO_HT; | ||
107 | - } else if (local->tmp_channel) { | ||
108 | - chan = scan_chan = local->tmp_channel; | ||
109 | - channel_type = local->tmp_channel_type; | ||
110 | - } else { | ||
111 | - chan = local->oper_channel; | ||
112 | - channel_type = local->_oper_channel_type; | ||
113 | - } | ||
114 | - | ||
115 | - if (chan != local->oper_channel || | ||
116 | - channel_type != local->_oper_channel_type) | ||
117 | - return false; | ||
118 | - | ||
119 | - /* Check current hardware-config against oper_channel. */ | ||
120 | - if ((local->oper_channel != local->hw.conf.channel) || | ||
121 | - (local->_oper_channel_type != local->hw.conf.channel_type)) | ||
122 | - return false; | ||
123 | - | ||
124 | - return true; | ||
125 | -} | ||
126 | - | ||
127 | int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | ||
128 | { | ||
129 | struct ieee80211_channel *chan, *scan_chan; | ||
130 | @@ -145,9 +104,6 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | ||
131 | |||
132 | scan_chan = local->scan_channel; | ||
133 | |||
134 | - /* If this off-channel logic ever changes, ieee80211_on_oper_channel | ||
135 | - * may need to change as well. | ||
136 | - */ | ||
137 | offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; | ||
138 | if (scan_chan) { | ||
139 | chan = scan_chan; | ||
140 | @@ -158,19 +114,17 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | ||
141 | channel_type = local->_oper_channel_type; | ||
142 | else | ||
143 | channel_type = NL80211_CHAN_NO_HT; | ||
144 | - } else if (local->tmp_channel) { | ||
145 | + local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; | ||
146 | + } else if (local->tmp_channel && | ||
147 | + local->oper_channel != local->tmp_channel) { | ||
148 | chan = scan_chan = local->tmp_channel; | ||
149 | channel_type = local->tmp_channel_type; | ||
150 | + local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; | ||
151 | } else { | ||
152 | chan = local->oper_channel; | ||
153 | channel_type = local->_oper_channel_type; | ||
154 | - } | ||
155 | - | ||
156 | - if (chan != local->oper_channel || | ||
157 | - channel_type != local->_oper_channel_type) | ||
158 | - local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; | ||
159 | - else | ||
160 | local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL; | ||
161 | + } | ||
162 | |||
163 | offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; | ||
164 | |||
165 | @@ -279,7 +233,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata, | ||
166 | |||
167 | if (changed & BSS_CHANGED_BEACON_ENABLED) { | ||
168 | if (local->quiescing || !ieee80211_sdata_running(sdata) || | ||
169 | - test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) { | ||
170 | + test_bit(SCAN_SW_SCANNING, &local->scanning)) { | ||
171 | sdata->vif.bss_conf.enable_beacon = false; | ||
172 | } else { | ||
173 | /* | ||
174 | diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c | ||
175 | index 3d41441..1b239be 100644 | ||
176 | --- a/net/mac80211/offchannel.c | ||
177 | +++ b/net/mac80211/offchannel.c | ||
178 | @@ -18,14 +18,10 @@ | ||
179 | #include "driver-trace.h" | ||
180 | |||
181 | /* | ||
182 | - * Tell our hardware to disable PS. | ||
183 | - * Optionally inform AP that we will go to sleep so that it will buffer | ||
184 | - * the frames while we are doing off-channel work. This is optional | ||
185 | - * because we *may* be doing work on-operating channel, and want our | ||
186 | - * hardware unconditionally awake, but still let the AP send us normal frames. | ||
187 | + * inform AP that we will go to sleep so that it will buffer the frames | ||
188 | + * while we scan | ||
189 | */ | ||
190 | -static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata, | ||
191 | - bool tell_ap) | ||
192 | +static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata) | ||
193 | { | ||
194 | struct ieee80211_local *local = sdata->local; | ||
195 | struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; | ||
196 | @@ -46,8 +42,8 @@ static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata, | ||
197 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | ||
198 | } | ||
199 | |||
200 | - if (tell_ap && (!local->offchannel_ps_enabled || | ||
201 | - !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK))) | ||
202 | + if (!(local->offchannel_ps_enabled) || | ||
203 | + !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)) | ||
204 | /* | ||
205 | * If power save was enabled, no need to send a nullfunc | ||
206 | * frame because AP knows that we are sleeping. But if the | ||
207 | @@ -82,9 +78,6 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata) | ||
208 | * we are sleeping, let's just enable power save mode in | ||
209 | * hardware. | ||
210 | */ | ||
211 | - /* TODO: Only set hardware if CONF_PS changed? | ||
212 | - * TODO: Should we set offchannel_ps_enabled to false? | ||
213 | - */ | ||
214 | local->hw.conf.flags |= IEEE80211_CONF_PS; | ||
215 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | ||
216 | } else if (local->hw.conf.dynamic_ps_timeout > 0) { | ||
217 | @@ -103,61 +96,63 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata) | ||
218 | ieee80211_sta_reset_conn_monitor(sdata); | ||
219 | } | ||
220 | |||
221 | -void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local, | ||
222 | - bool offchannel_ps_enable) | ||
223 | +void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local) | ||
224 | { | ||
225 | struct ieee80211_sub_if_data *sdata; | ||
226 | |||
227 | - /* | ||
228 | - * notify the AP about us leaving the channel and stop all | ||
229 | - * STA interfaces. | ||
230 | - */ | ||
231 | mutex_lock(&local->iflist_mtx); | ||
232 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
233 | if (!ieee80211_sdata_running(sdata)) | ||
234 | continue; | ||
235 | |||
236 | - if (sdata->vif.type != NL80211_IFTYPE_MONITOR) | ||
237 | - set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); | ||
238 | - | ||
239 | - /* Check to see if we should disable beaconing. */ | ||
240 | + /* disable beaconing */ | ||
241 | if (sdata->vif.type == NL80211_IFTYPE_AP || | ||
242 | sdata->vif.type == NL80211_IFTYPE_ADHOC || | ||
243 | sdata->vif.type == NL80211_IFTYPE_MESH_POINT) | ||
244 | ieee80211_bss_info_change_notify( | ||
245 | sdata, BSS_CHANGED_BEACON_ENABLED); | ||
246 | |||
247 | - if (sdata->vif.type != NL80211_IFTYPE_MONITOR) { | ||
248 | + /* | ||
249 | + * only handle non-STA interfaces here, STA interfaces | ||
250 | + * are handled in ieee80211_offchannel_stop_station(), | ||
251 | + * e.g., from the background scan state machine. | ||
252 | + * | ||
253 | + * In addition, do not stop monitor interface to allow it to be | ||
254 | + * used from user space controlled off-channel operations. | ||
255 | + */ | ||
256 | + if (sdata->vif.type != NL80211_IFTYPE_STATION && | ||
257 | + sdata->vif.type != NL80211_IFTYPE_MONITOR) { | ||
258 | + set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); | ||
259 | netif_tx_stop_all_queues(sdata->dev); | ||
260 | - if (offchannel_ps_enable && | ||
261 | - (sdata->vif.type == NL80211_IFTYPE_STATION) && | ||
262 | - sdata->u.mgd.associated) | ||
263 | - ieee80211_offchannel_ps_enable(sdata, true); | ||
264 | } | ||
265 | } | ||
266 | mutex_unlock(&local->iflist_mtx); | ||
267 | } | ||
268 | |||
269 | -void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local, | ||
270 | - bool tell_ap) | ||
271 | +void ieee80211_offchannel_stop_station(struct ieee80211_local *local) | ||
272 | { | ||
273 | struct ieee80211_sub_if_data *sdata; | ||
274 | |||
275 | + /* | ||
276 | + * notify the AP about us leaving the channel and stop all STA interfaces | ||
277 | + */ | ||
278 | mutex_lock(&local->iflist_mtx); | ||
279 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
280 | if (!ieee80211_sdata_running(sdata)) | ||
281 | continue; | ||
282 | |||
283 | - if (sdata->vif.type == NL80211_IFTYPE_STATION && | ||
284 | - sdata->u.mgd.associated) | ||
285 | - ieee80211_offchannel_ps_enable(sdata, tell_ap); | ||
286 | + if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
287 | + set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state); | ||
288 | + netif_tx_stop_all_queues(sdata->dev); | ||
289 | + if (sdata->u.mgd.associated) | ||
290 | + ieee80211_offchannel_ps_enable(sdata); | ||
291 | + } | ||
292 | } | ||
293 | mutex_unlock(&local->iflist_mtx); | ||
294 | } | ||
295 | |||
296 | void ieee80211_offchannel_return(struct ieee80211_local *local, | ||
297 | - bool enable_beaconing, | ||
298 | - bool offchannel_ps_disable) | ||
299 | + bool enable_beaconing) | ||
300 | { | ||
301 | struct ieee80211_sub_if_data *sdata; | ||
302 | |||
303 | @@ -167,8 +162,7 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, | ||
304 | continue; | ||
305 | |||
306 | /* Tell AP we're back */ | ||
307 | - if (offchannel_ps_disable && | ||
308 | - sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
309 | + if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
310 | if (sdata->u.mgd.associated) | ||
311 | ieee80211_offchannel_ps_disable(sdata); | ||
312 | } | ||
313 | @@ -188,7 +182,7 @@ void ieee80211_offchannel_return(struct ieee80211_local *local, | ||
314 | netif_tx_wake_all_queues(sdata->dev); | ||
315 | } | ||
316 | |||
317 | - /* Check to see if we should re-enable beaconing */ | ||
318 | + /* re-enable beaconing */ | ||
319 | if (enable_beaconing && | ||
320 | (sdata->vif.type == NL80211_IFTYPE_AP || | ||
321 | sdata->vif.type == NL80211_IFTYPE_ADHOC || | ||
322 | diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c | ||
323 | index fb123e2..5c51607 100644 | ||
324 | --- a/net/mac80211/rx.c | ||
325 | +++ b/net/mac80211/rx.c | ||
326 | @@ -421,10 +421,16 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx) | ||
327 | return RX_CONTINUE; | ||
328 | |||
329 | if (test_bit(SCAN_HW_SCANNING, &local->scanning) || | ||
330 | - test_bit(SCAN_SW_SCANNING, &local->scanning) || | ||
331 | local->sched_scanning) | ||
332 | return ieee80211_scan_rx(rx->sdata, skb); | ||
333 | |||
334 | + if (test_bit(SCAN_SW_SCANNING, &local->scanning)) { | ||
335 | + /* drop all the other packets during a software scan anyway */ | ||
336 | + if (ieee80211_scan_rx(rx->sdata, skb) != RX_QUEUED) | ||
337 | + dev_kfree_skb(skb); | ||
338 | + return RX_QUEUED; | ||
339 | + } | ||
340 | + | ||
341 | /* scanning finished during invoking of handlers */ | ||
342 | I802_DEBUG_INC(local->rx_handlers_drop_passive_scan); | ||
343 | return RX_DROP_UNUSABLE; | ||
344 | @@ -2858,7 +2864,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw, | ||
345 | local->dot11ReceivedFragmentCount++; | ||
346 | |||
347 | if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) || | ||
348 | - test_bit(SCAN_SW_SCANNING, &local->scanning))) | ||
349 | + test_bit(SCAN_OFF_CHANNEL, &local->scanning))) | ||
350 | status->rx_flags |= IEEE80211_RX_IN_SCAN; | ||
351 | |||
352 | if (ieee80211_is_mgmt(fc)) | ||
353 | diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c | ||
354 | index 105436d..5279300 100644 | ||
355 | --- a/net/mac80211/scan.c | ||
356 | +++ b/net/mac80211/scan.c | ||
357 | @@ -213,14 +213,6 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) | ||
358 | if (bss) | ||
359 | ieee80211_rx_bss_put(sdata->local, bss); | ||
360 | |||
361 | - /* If we are on-operating-channel, and this packet is for the | ||
362 | - * current channel, pass the pkt on up the stack so that | ||
363 | - * the rest of the stack can make use of it. | ||
364 | - */ | ||
365 | - if (ieee80211_cfg_on_oper_channel(sdata->local) | ||
366 | - && (channel == sdata->local->oper_channel)) | ||
367 | - return RX_CONTINUE; | ||
368 | - | ||
369 | dev_kfree_skb(skb); | ||
370 | return RX_QUEUED; | ||
371 | } | ||
372 | @@ -264,8 +256,6 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, | ||
373 | bool was_hw_scan) | ||
374 | { | ||
375 | struct ieee80211_local *local = hw_to_local(hw); | ||
376 | - bool on_oper_chan; | ||
377 | - bool enable_beacons = false; | ||
378 | |||
379 | lockdep_assert_held(&local->mtx); | ||
380 | |||
381 | @@ -298,25 +288,11 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted, | ||
382 | local->scanning = 0; | ||
383 | local->scan_channel = NULL; | ||
384 | |||
385 | - on_oper_chan = ieee80211_cfg_on_oper_channel(local); | ||
386 | - | ||
387 | - if (was_hw_scan || !on_oper_chan) | ||
388 | - ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
389 | - else | ||
390 | - /* Set power back to normal operating levels. */ | ||
391 | - ieee80211_hw_config(local, 0); | ||
392 | - | ||
393 | + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
394 | if (!was_hw_scan) { | ||
395 | - bool on_oper_chan2; | ||
396 | ieee80211_configure_filter(local); | ||
397 | drv_sw_scan_complete(local); | ||
398 | - on_oper_chan2 = ieee80211_cfg_on_oper_channel(local); | ||
399 | - /* We should always be on-channel at this point. */ | ||
400 | - WARN_ON(!on_oper_chan2); | ||
401 | - if (on_oper_chan2 && (on_oper_chan != on_oper_chan2)) | ||
402 | - enable_beacons = true; | ||
403 | - | ||
404 | - ieee80211_offchannel_return(local, enable_beacons, true); | ||
405 | + ieee80211_offchannel_return(local, true); | ||
406 | } | ||
407 | |||
408 | ieee80211_recalc_idle(local); | ||
409 | @@ -357,15 +333,13 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) | ||
410 | */ | ||
411 | drv_sw_scan_start(local); | ||
412 | |||
413 | + ieee80211_offchannel_stop_beaconing(local); | ||
414 | + | ||
415 | local->leave_oper_channel_time = 0; | ||
416 | local->next_scan_state = SCAN_DECISION; | ||
417 | local->scan_channel_idx = 0; | ||
418 | |||
419 | - /* We always want to use off-channel PS, even if we | ||
420 | - * are not really leaving oper-channel. Don't | ||
421 | - * tell the AP though, as long as we are on-channel. | ||
422 | - */ | ||
423 | - ieee80211_offchannel_enable_all_ps(local, false); | ||
424 | + drv_flush(local, false); | ||
425 | |||
426 | ieee80211_configure_filter(local); | ||
427 | |||
428 | @@ -508,20 +482,7 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, | ||
429 | } | ||
430 | mutex_unlock(&local->iflist_mtx); | ||
431 | |||
432 | - next_chan = local->scan_req->channels[local->scan_channel_idx]; | ||
433 | - | ||
434 | - if (ieee80211_cfg_on_oper_channel(local)) { | ||
435 | - /* We're currently on operating channel. */ | ||
436 | - if (next_chan == local->oper_channel) | ||
437 | - /* We don't need to move off of operating channel. */ | ||
438 | - local->next_scan_state = SCAN_SET_CHANNEL; | ||
439 | - else | ||
440 | - /* | ||
441 | - * We do need to leave operating channel, as next | ||
442 | - * scan is somewhere else. | ||
443 | - */ | ||
444 | - local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL; | ||
445 | - } else { | ||
446 | + if (local->scan_channel) { | ||
447 | /* | ||
448 | * we're currently scanning a different channel, let's | ||
449 | * see if we can scan another channel without interfering | ||
450 | @@ -537,6 +498,7 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, | ||
451 | * | ||
452 | * Otherwise switch back to the operating channel. | ||
453 | */ | ||
454 | + next_chan = local->scan_req->channels[local->scan_channel_idx]; | ||
455 | |||
456 | bad_latency = time_after(jiffies + | ||
457 | ieee80211_scan_get_channel_time(next_chan), | ||
458 | @@ -554,6 +516,12 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, | ||
459 | local->next_scan_state = SCAN_ENTER_OPER_CHANNEL; | ||
460 | else | ||
461 | local->next_scan_state = SCAN_SET_CHANNEL; | ||
462 | + } else { | ||
463 | + /* | ||
464 | + * we're on the operating channel currently, let's | ||
465 | + * leave that channel now to scan another one | ||
466 | + */ | ||
467 | + local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL; | ||
468 | } | ||
469 | |||
470 | *next_delay = 0; | ||
471 | @@ -562,10 +530,9 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local, | ||
472 | static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local, | ||
473 | unsigned long *next_delay) | ||
474 | { | ||
475 | - /* PS will already be in off-channel mode, | ||
476 | - * we do that once at the beginning of scanning. | ||
477 | - */ | ||
478 | - ieee80211_offchannel_stop_vifs(local, false); | ||
479 | + ieee80211_offchannel_stop_station(local); | ||
480 | + | ||
481 | + __set_bit(SCAN_OFF_CHANNEL, &local->scanning); | ||
482 | |||
483 | /* | ||
484 | * What if the nullfunc frames didn't arrive? | ||
485 | @@ -588,15 +555,15 @@ static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *loca | ||
486 | { | ||
487 | /* switch back to the operating channel */ | ||
488 | local->scan_channel = NULL; | ||
489 | - if (!ieee80211_cfg_on_oper_channel(local)) | ||
490 | - ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
491 | + ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
492 | |||
493 | /* | ||
494 | - * Re-enable vifs and beaconing. Leave PS | ||
495 | - * in off-channel state..will put that back | ||
496 | - * on-channel at the end of scanning. | ||
497 | + * Only re-enable station mode interface now; beaconing will be | ||
498 | + * re-enabled once the full scan has been completed. | ||
499 | */ | ||
500 | - ieee80211_offchannel_return(local, true, false); | ||
501 | + ieee80211_offchannel_return(local, false); | ||
502 | + | ||
503 | + __clear_bit(SCAN_OFF_CHANNEL, &local->scanning); | ||
504 | |||
505 | *next_delay = HZ / 5; | ||
506 | local->next_scan_state = SCAN_DECISION; | ||
507 | diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c | ||
508 | index 1f8b120..eff1f4e 100644 | ||
509 | --- a/net/mac80211/tx.c | ||
510 | +++ b/net/mac80211/tx.c | ||
511 | @@ -259,8 +259,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx) | ||
512 | if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED)) | ||
513 | return TX_CONTINUE; | ||
514 | |||
515 | - if (unlikely(test_bit(SCAN_SW_SCANNING, &tx->local->scanning)) && | ||
516 | - test_bit(SDATA_STATE_OFFCHANNEL, &tx->sdata->state) && | ||
517 | + if (unlikely(test_bit(SCAN_OFF_CHANNEL, &tx->local->scanning)) && | ||
518 | !ieee80211_is_probe_req(hdr->frame_control) && | ||
519 | !ieee80211_is_nullfunc(hdr->frame_control)) | ||
520 | /* | ||
521 | diff --git a/net/mac80211/work.c b/net/mac80211/work.c | ||
522 | index 6c53b6d..99165ef 100644 | ||
523 | --- a/net/mac80211/work.c | ||
524 | +++ b/net/mac80211/work.c | ||
525 | @@ -899,26 +899,6 @@ static bool ieee80211_work_ct_coexists(enum nl80211_channel_type wk_ct, | ||
526 | return false; | ||
527 | } | ||
528 | |||
529 | -static enum nl80211_channel_type | ||
530 | -ieee80211_calc_ct(enum nl80211_channel_type wk_ct, | ||
531 | - enum nl80211_channel_type oper_ct) | ||
532 | -{ | ||
533 | - switch (wk_ct) { | ||
534 | - case NL80211_CHAN_NO_HT: | ||
535 | - return oper_ct; | ||
536 | - case NL80211_CHAN_HT20: | ||
537 | - if (oper_ct != NL80211_CHAN_NO_HT) | ||
538 | - return oper_ct; | ||
539 | - return wk_ct; | ||
540 | - case NL80211_CHAN_HT40MINUS: | ||
541 | - case NL80211_CHAN_HT40PLUS: | ||
542 | - return wk_ct; | ||
543 | - } | ||
544 | - WARN_ON(1); /* shouldn't get here */ | ||
545 | - return wk_ct; | ||
546 | -} | ||
547 | - | ||
548 | - | ||
549 | static void ieee80211_work_timer(unsigned long data) | ||
550 | { | ||
551 | struct ieee80211_local *local = (void *) data; | ||
552 | @@ -969,52 +949,18 @@ static void ieee80211_work_work(struct work_struct *work) | ||
553 | } | ||
554 | |||
555 | if (!started && !local->tmp_channel) { | ||
556 | - bool on_oper_chan; | ||
557 | - bool tmp_chan_changed = false; | ||
558 | - bool on_oper_chan2; | ||
559 | - enum nl80211_channel_type wk_ct; | ||
560 | - on_oper_chan = ieee80211_cfg_on_oper_channel(local); | ||
561 | - | ||
562 | - /* Work with existing channel type if possible. */ | ||
563 | - wk_ct = wk->chan_type; | ||
564 | - if (wk->chan == local->hw.conf.channel) | ||
565 | - wk_ct = ieee80211_calc_ct(wk->chan_type, | ||
566 | - local->hw.conf.channel_type); | ||
567 | - | ||
568 | - if (local->tmp_channel) | ||
569 | - if ((local->tmp_channel != wk->chan) || | ||
570 | - (local->tmp_channel_type != wk_ct)) | ||
571 | - tmp_chan_changed = true; | ||
572 | - | ||
573 | - local->tmp_channel = wk->chan; | ||
574 | - local->tmp_channel_type = wk_ct; | ||
575 | /* | ||
576 | - * Leave the station vifs in awake mode if they | ||
577 | - * happen to be on the same channel as | ||
578 | - * the requested channel. | ||
579 | + * TODO: could optimize this by leaving the | ||
580 | + * station vifs in awake mode if they | ||
581 | + * happen to be on the same channel as | ||
582 | + * the requested channel | ||
583 | */ | ||
584 | - on_oper_chan2 = ieee80211_cfg_on_oper_channel(local); | ||
585 | - if (on_oper_chan != on_oper_chan2) { | ||
586 | - if (on_oper_chan2) { | ||
587 | - /* going off oper channel, PS too */ | ||
588 | - ieee80211_offchannel_stop_vifs(local, | ||
589 | - true); | ||
590 | - ieee80211_hw_config(local, 0); | ||
591 | - } else { | ||
592 | - /* going on channel, but leave PS | ||
593 | - * off-channel. */ | ||
594 | - ieee80211_hw_config(local, 0); | ||
595 | - ieee80211_offchannel_return(local, | ||
596 | - true, | ||
597 | - false); | ||
598 | - } | ||
599 | - } else if (tmp_chan_changed) | ||
600 | - /* Still off-channel, but on some other | ||
601 | - * channel, so update hardware. | ||
602 | - * PS should already be off-channel. | ||
603 | - */ | ||
604 | - ieee80211_hw_config(local, 0); | ||
605 | + ieee80211_offchannel_stop_beaconing(local); | ||
606 | + ieee80211_offchannel_stop_station(local); | ||
607 | |||
608 | + local->tmp_channel = wk->chan; | ||
609 | + local->tmp_channel_type = wk->chan_type; | ||
610 | + ieee80211_hw_config(local, 0); | ||
611 | started = true; | ||
612 | wk->timeout = jiffies; | ||
613 | } | ||
614 | @@ -1100,8 +1046,7 @@ static void ieee80211_work_work(struct work_struct *work) | ||
615 | * we still need to do a hardware config. Currently, | ||
616 | * we cannot be here while scanning, however. | ||
617 | */ | ||
618 | - if (!ieee80211_cfg_on_oper_channel(local)) | ||
619 | - ieee80211_hw_config(local, 0); | ||
620 | + ieee80211_hw_config(local, 0); | ||
621 | |||
622 | /* At the least, we need to disable offchannel_ps, | ||
623 | * so just go ahead and run the entire offchannel | ||
624 | @@ -1109,7 +1054,7 @@ static void ieee80211_work_work(struct work_struct *work) | ||
625 | * beaconing if we were already on-oper-channel | ||
626 | * as a future optimization. | ||
627 | */ | ||
628 | - ieee80211_offchannel_return(local, true, true); | ||
629 | + ieee80211_offchannel_return(local, true); | ||
630 | |||
631 | /* give connection some time to breathe */ | ||
632 | run_again(local, jiffies + HZ/2); | ||
633 | -- | ||
634 | 1.7.7.4 | ||
635 | |||