summaryrefslogtreecommitdiffstats
path: root/recipes-kernel/linux/linux-ti33x-psp-3.2/3.2.2/0080-mac80211-revert-on-channel-work-optimisations.patch
diff options
context:
space:
mode:
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.patch635
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 @@
1From 5b8206fb91b97732d80ada2e494e060d50ab30bd Mon Sep 17 00:00:00 2001
2From: Johannes Berg <johannes.berg@intel.com>
3Date: Tue, 29 Nov 2011 10:20:02 +0100
4Subject: [PATCH 080/130] mac80211: revert on-channel work optimisations
5
6commit e76aadc572288a158ae18ae1c10fe395c7bca066 upstream.
7
8Backport note:
9This patch it's a full revert of commit b23b025f "mac80211: Optimize
10scans on current operating channel.". On upstrem revert e76aadc5 we
11keep some bits from that commit, which are needed for upstream version
12of mac80211.
13
14The on-channel work optimisations have caused a
15number of issues, and the code is unfortunately
16very complex and almost impossible to follow.
17Instead of attempting to put in more workarounds
18let's just remove those optimisations, we can
19work on them again later, after we change the
20whole auth/assoc design.
21
22This should fix rate_control_send_low() warnings,
23see RH bug 731365.
24
25Signed-off-by: Johannes Berg <johannes.berg@intel.com>
26Signed-off-by: John W. Linville <linville@tuxdriver.com>
27Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
28Signed-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
39diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
40index 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 */
78diff --git a/net/mac80211/main.c b/net/mac80211/main.c
79index 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 /*
174diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
175index 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 ||
322diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
323index 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))
353diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
354index 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;
507diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
508index 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 /*
521diff --git a/net/mac80211/work.c b/net/mac80211/work.c
522index 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--
6341.7.7.4
635