[kernel/f15] Apply patch to revert mac80211 scan optimizations (rhbz #731365)
Josh Boyer
jwboyer at fedoraproject.org
Thu Dec 1 14:13:08 UTC 2011
commit ef5737b662859c1a421c0b9c8520ff7f68444925
Author: Josh Boyer <jwboyer at redhat.com>
Date: Thu Dec 1 09:10:14 2011 -0500
Apply patch to revert mac80211 scan optimizations (rhbz #731365)
kernel.spec | 11 +-
mac80211_offchannel_rework_revert.patch | 594 +++++++++++++++++++++++++++++++
2 files changed, 604 insertions(+), 1 deletions(-)
---
diff --git a/kernel.spec b/kernel.spec
index af6e07f..edf8544 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -42,7 +42,7 @@ Summary: The Linux kernel
# When changing real_sublevel below, reset this by hand to 1
# (or to 0 and then use rpmdev-bumpspec).
#
-%global baserelease 3
+%global baserelease 4
%global fedora_build %{baserelease}
# real_sublevel is the 3.x kernel version we're starting with
@@ -691,6 +691,9 @@ Patch21101: hpsa-add-irqf-shared.patch
#rhbz 755154
Patch21200: rtlwifi-fix-lps_lock-deadlock.patch
+#rhbz 731365
+Patch21220: mac80211_offchannel_rework_revert.patch
+
%endif
BuildRoot: %{_tmppath}/kernel-%{KVERREL}-root
@@ -1273,6 +1276,9 @@ ApplyPatch hpsa-add-irqf-shared.patch
#rhbz 755154
ApplyPatch rtlwifi-fix-lps_lock-deadlock.patch
+#rhbz 731365
+ApplyPatch mac80211_offchannel_rework_revert.patch
+
# END OF PATCH APPLICATIONS
%endif
@@ -1890,6 +1896,9 @@ fi
# and build.
%changelog
+* Thu Dec 01 2011 Josh Boyer <jwboyer at redhat.com>
+- Apply patch to revert mac80211 scan optimizations (rhbz #731365)
+
* Wed Nov 30 2011 Josh Boyer <jwboyer at redhat.com>
- Include commit 3940d6185 from JJ Ding in elantech.patch
diff --git a/mac80211_offchannel_rework_revert.patch b/mac80211_offchannel_rework_revert.patch
new file mode 100644
index 0000000..8597997
--- /dev/null
+++ b/mac80211_offchannel_rework_revert.patch
@@ -0,0 +1,594 @@
+diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
+index 9fab144..4f8cf7f 100644
+--- a/net/mac80211/ieee80211_i.h
++++ b/net/mac80211/ieee80211_i.h
+@@ -694,6 +694,8 @@ struct tpt_led_trigger {
+ * well be on the operating channel
+ * @SCAN_HW_SCANNING: The hardware is scanning for us, we have no way to
+ * determine if we are on the operating channel or not
++ * @SCAN_OFF_CHANNEL: We're off our operating channel for scanning,
++ * gets only set in conjunction with SCAN_SW_SCANNING
+ * @SCAN_COMPLETED: Set for our scan work function when the driver reported
+ * that the scan completed.
+ * @SCAN_ABORTED: Set for our scan work function when the driver reported
+@@ -702,6 +704,7 @@ struct tpt_led_trigger {
+ enum {
+ SCAN_SW_SCANNING,
+ SCAN_HW_SCANNING,
++ SCAN_OFF_CHANNEL,
+ SCAN_COMPLETED,
+ SCAN_ABORTED,
+ };
+@@ -1197,14 +1200,10 @@ int ieee80211_request_sched_scan_stop(struct ieee80211_sub_if_data *sdata);
+ void ieee80211_sched_scan_stopped_work(struct work_struct *work);
+
+ /* off-channel helpers */
+-bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local);
+-void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local,
+- bool tell_ap);
+-void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local,
+- bool offchannel_ps_enable);
++void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local);
++void ieee80211_offchannel_stop_station(struct ieee80211_local *local);
+ void ieee80211_offchannel_return(struct ieee80211_local *local,
+- bool enable_beaconing,
+- bool offchannel_ps_disable);
++ bool enable_beaconing);
+ void ieee80211_hw_roc_setup(struct ieee80211_local *local);
+
+ /* interface handling */
+diff --git a/net/mac80211/main.c b/net/mac80211/main.c
+index acb4423..2d607e5 100644
+--- a/net/mac80211/main.c
++++ b/net/mac80211/main.c
+@@ -92,47 +92,6 @@ static void ieee80211_reconfig_filter(struct work_struct *work)
+ ieee80211_configure_filter(local);
+ }
+
+-/*
+- * Returns true if we are logically configured to be on
+- * the operating channel AND the hardware-conf is currently
+- * configured on the operating channel. Compares channel-type
+- * as well.
+- */
+-bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local)
+-{
+- struct ieee80211_channel *chan, *scan_chan;
+- enum nl80211_channel_type channel_type;
+-
+- /* This logic needs to match logic in ieee80211_hw_config */
+- if (local->scan_channel) {
+- chan = local->scan_channel;
+- /* If scanning on oper channel, use whatever channel-type
+- * is currently in use.
+- */
+- if (chan == local->oper_channel)
+- channel_type = local->_oper_channel_type;
+- else
+- channel_type = NL80211_CHAN_NO_HT;
+- } else if (local->tmp_channel) {
+- chan = scan_chan = local->tmp_channel;
+- channel_type = local->tmp_channel_type;
+- } else {
+- chan = local->oper_channel;
+- channel_type = local->_oper_channel_type;
+- }
+-
+- if (chan != local->oper_channel ||
+- channel_type != local->_oper_channel_type)
+- return false;
+-
+- /* Check current hardware-config against oper_channel. */
+- if ((local->oper_channel != local->hw.conf.channel) ||
+- (local->_oper_channel_type != local->hw.conf.channel_type))
+- return false;
+-
+- return true;
+-}
+-
+ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
+ {
+ struct ieee80211_channel *chan, *scan_chan;
+@@ -145,9 +104,6 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
+
+ scan_chan = local->scan_channel;
+
+- /* If this off-channel logic ever changes, ieee80211_on_oper_channel
+- * may need to change as well.
+- */
+ offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
+ if (scan_chan) {
+ chan = scan_chan;
+@@ -158,19 +114,17 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
+ channel_type = local->_oper_channel_type;
+ else
+ channel_type = NL80211_CHAN_NO_HT;
+- } else if (local->tmp_channel) {
++ local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
++ } else if (local->tmp_channel &&
++ local->oper_channel != local->tmp_channel) {
+ chan = scan_chan = local->tmp_channel;
+ channel_type = local->tmp_channel_type;
++ local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
+ } else {
+ chan = local->oper_channel;
+ channel_type = local->_oper_channel_type;
+- }
+-
+- if (chan != local->oper_channel ||
+- channel_type != local->_oper_channel_type)
+- local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
+- else
+ local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL;
++ }
+
+ offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
+
+@@ -279,7 +233,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
+
+ if (changed & BSS_CHANGED_BEACON_ENABLED) {
+ if (local->quiescing || !ieee80211_sdata_running(sdata) ||
+- test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) {
++ test_bit(SCAN_SW_SCANNING, &local->scanning)) {
+ sdata->vif.bss_conf.enable_beacon = false;
+ } else {
+ /*
+diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
+index 13427b1..b4e5267 100644
+--- a/net/mac80211/offchannel.c
++++ b/net/mac80211/offchannel.c
+@@ -17,14 +17,10 @@
+ #include "driver-trace.h"
+
+ /*
+- * Tell our hardware to disable PS.
+- * Optionally inform AP that we will go to sleep so that it will buffer
+- * the frames while we are doing off-channel work. This is optional
+- * because we *may* be doing work on-operating channel, and want our
+- * hardware unconditionally awake, but still let the AP send us normal frames.
++ * inform AP that we will go to sleep so that it will buffer the frames
++ * while we scan
+ */
+-static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata,
+- bool tell_ap)
++static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata)
+ {
+ struct ieee80211_local *local = sdata->local;
+ struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+@@ -45,8 +41,8 @@ static void ieee80211_offchannel_ps_enable(struct ieee80211_sub_if_data *sdata,
+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
+ }
+
+- if (tell_ap && (!local->offchannel_ps_enabled ||
+- !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK)))
++ if (!(local->offchannel_ps_enabled) ||
++ !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK))
+ /*
+ * If power save was enabled, no need to send a nullfunc
+ * frame because AP knows that we are sleeping. But if the
+@@ -81,9 +77,6 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata)
+ * we are sleeping, let's just enable power save mode in
+ * hardware.
+ */
+- /* TODO: Only set hardware if CONF_PS changed?
+- * TODO: Should we set offchannel_ps_enabled to false?
+- */
+ local->hw.conf.flags |= IEEE80211_CONF_PS;
+ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
+ } else if (local->hw.conf.dynamic_ps_timeout > 0) {
+@@ -102,61 +95,63 @@ static void ieee80211_offchannel_ps_disable(struct ieee80211_sub_if_data *sdata)
+ ieee80211_sta_reset_conn_monitor(sdata);
+ }
+
+-void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local,
+- bool offchannel_ps_enable)
++void ieee80211_offchannel_stop_beaconing(struct ieee80211_local *local)
+ {
+ struct ieee80211_sub_if_data *sdata;
+
+- /*
+- * notify the AP about us leaving the channel and stop all
+- * STA interfaces.
+- */
+ mutex_lock(&local->iflist_mtx);
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ if (!ieee80211_sdata_running(sdata))
+ continue;
+
+- if (sdata->vif.type != NL80211_IFTYPE_MONITOR)
+- set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state);
+-
+- /* Check to see if we should disable beaconing. */
++ /* disable beaconing */
+ if (sdata->vif.type == NL80211_IFTYPE_AP ||
+ sdata->vif.type == NL80211_IFTYPE_ADHOC ||
+ sdata->vif.type == NL80211_IFTYPE_MESH_POINT)
+ ieee80211_bss_info_change_notify(
+ sdata, BSS_CHANGED_BEACON_ENABLED);
+
+- if (sdata->vif.type != NL80211_IFTYPE_MONITOR) {
++ /*
++ * only handle non-STA interfaces here, STA interfaces
++ * are handled in ieee80211_offchannel_stop_station(),
++ * e.g., from the background scan state machine.
++ *
++ * In addition, do not stop monitor interface to allow it to be
++ * used from user space controlled off-channel operations.
++ */
++ if (sdata->vif.type != NL80211_IFTYPE_STATION &&
++ sdata->vif.type != NL80211_IFTYPE_MONITOR) {
++ set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state);
+ netif_tx_stop_all_queues(sdata->dev);
+- if (offchannel_ps_enable &&
+- (sdata->vif.type == NL80211_IFTYPE_STATION) &&
+- sdata->u.mgd.associated)
+- ieee80211_offchannel_ps_enable(sdata, true);
+ }
+ }
+ mutex_unlock(&local->iflist_mtx);
+ }
+
+-void ieee80211_offchannel_enable_all_ps(struct ieee80211_local *local,
+- bool tell_ap)
++void ieee80211_offchannel_stop_station(struct ieee80211_local *local)
+ {
+ struct ieee80211_sub_if_data *sdata;
+
++ /*
++ * notify the AP about us leaving the channel and stop all STA interfaces
++ */
+ mutex_lock(&local->iflist_mtx);
+ list_for_each_entry(sdata, &local->interfaces, list) {
+ if (!ieee80211_sdata_running(sdata))
+ continue;
+
+- if (sdata->vif.type == NL80211_IFTYPE_STATION &&
+- sdata->u.mgd.associated)
+- ieee80211_offchannel_ps_enable(sdata, tell_ap);
++ if (sdata->vif.type == NL80211_IFTYPE_STATION) {
++ set_bit(SDATA_STATE_OFFCHANNEL, &sdata->state);
++ netif_tx_stop_all_queues(sdata->dev);
++ if (sdata->u.mgd.associated)
++ ieee80211_offchannel_ps_enable(sdata);
++ }
+ }
+ mutex_unlock(&local->iflist_mtx);
+ }
+
+ void ieee80211_offchannel_return(struct ieee80211_local *local,
+- bool enable_beaconing,
+- bool offchannel_ps_disable)
++ bool enable_beaconing)
+ {
+ struct ieee80211_sub_if_data *sdata;
+
+@@ -166,8 +161,7 @@ void ieee80211_offchannel_return(struct ieee80211_local *local,
+ continue;
+
+ /* Tell AP we're back */
+- if (offchannel_ps_disable &&
+- sdata->vif.type == NL80211_IFTYPE_STATION) {
++ if (sdata->vif.type == NL80211_IFTYPE_STATION) {
+ if (sdata->u.mgd.associated)
+ ieee80211_offchannel_ps_disable(sdata);
+ }
+@@ -187,7 +181,7 @@ void ieee80211_offchannel_return(struct ieee80211_local *local,
+ netif_tx_wake_all_queues(sdata->dev);
+ }
+
+- /* Check to see if we should re-enable beaconing */
++ /* re-enable beaconing */
+ if (enable_beaconing &&
+ (sdata->vif.type == NL80211_IFTYPE_AP ||
+ sdata->vif.type == NL80211_IFTYPE_ADHOC ||
+diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
+index fe2c2a7..b46880e 100644
+--- a/net/mac80211/rx.c
++++ b/net/mac80211/rx.c
+@@ -417,10 +417,16 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)
+ return RX_CONTINUE;
+
+ if (test_bit(SCAN_HW_SCANNING, &local->scanning) ||
+- test_bit(SCAN_SW_SCANNING, &local->scanning) ||
+ local->sched_scanning)
+ return ieee80211_scan_rx(rx->sdata, skb);
+
++ if (test_bit(SCAN_SW_SCANNING, &local->scanning)) {
++ /* drop all the other packets during a software scan anyway */
++ if (ieee80211_scan_rx(rx->sdata, skb) != RX_QUEUED)
++ dev_kfree_skb(skb);
++ return RX_QUEUED;
++ }
++
+ /* scanning finished during invoking of handlers */
+ I802_DEBUG_INC(local->rx_handlers_drop_passive_scan);
+ return RX_DROP_UNUSABLE;
+@@ -2771,7 +2777,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
+ local->dot11ReceivedFragmentCount++;
+
+ if (unlikely(test_bit(SCAN_HW_SCANNING, &local->scanning) ||
+- test_bit(SCAN_SW_SCANNING, &local->scanning)))
++ test_bit(SCAN_OFF_CHANNEL, &local->scanning)))
+ status->rx_flags |= IEEE80211_RX_IN_SCAN;
+
+ if (ieee80211_is_mgmt(fc))
+diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
+index 6f09eca..2ba4977 100644
+--- a/net/mac80211/scan.c
++++ b/net/mac80211/scan.c
+@@ -212,14 +212,6 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
+ if (bss)
+ ieee80211_rx_bss_put(sdata->local, bss);
+
+- /* If we are on-operating-channel, and this packet is for the
+- * current channel, pass the pkt on up the stack so that
+- * the rest of the stack can make use of it.
+- */
+- if (ieee80211_cfg_on_oper_channel(sdata->local)
+- && (channel == sdata->local->oper_channel))
+- return RX_CONTINUE;
+-
+ dev_kfree_skb(skb);
+ return RX_QUEUED;
+ }
+@@ -262,8 +254,6 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
+ bool was_hw_scan)
+ {
+ struct ieee80211_local *local = hw_to_local(hw);
+- bool on_oper_chan;
+- bool enable_beacons = false;
+
+ lockdep_assert_held(&local->mtx);
+
+@@ -296,25 +286,11 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
+ local->scanning = 0;
+ local->scan_channel = NULL;
+
+- on_oper_chan = ieee80211_cfg_on_oper_channel(local);
+-
+- if (was_hw_scan || !on_oper_chan)
+- ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
+- else
+- /* Set power back to normal operating levels. */
+- ieee80211_hw_config(local, 0);
+-
++ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
+ if (!was_hw_scan) {
+- bool on_oper_chan2;
+ ieee80211_configure_filter(local);
+ drv_sw_scan_complete(local);
+- on_oper_chan2 = ieee80211_cfg_on_oper_channel(local);
+- /* We should always be on-channel at this point. */
+- WARN_ON(!on_oper_chan2);
+- if (on_oper_chan2 && (on_oper_chan != on_oper_chan2))
+- enable_beacons = true;
+-
+- ieee80211_offchannel_return(local, enable_beacons, true);
++ ieee80211_offchannel_return(local, true);
+ }
+
+ ieee80211_recalc_idle(local);
+@@ -355,15 +331,13 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
+ */
+ drv_sw_scan_start(local);
+
++ ieee80211_offchannel_stop_beaconing(local);
++
+ local->leave_oper_channel_time = 0;
+ local->next_scan_state = SCAN_DECISION;
+ local->scan_channel_idx = 0;
+
+- /* We always want to use off-channel PS, even if we
+- * are not really leaving oper-channel. Don't
+- * tell the AP though, as long as we are on-channel.
+- */
+- ieee80211_offchannel_enable_all_ps(local, false);
++ drv_flush(local, false);
+
+ ieee80211_configure_filter(local);
+
+@@ -506,20 +480,7 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
+ }
+ mutex_unlock(&local->iflist_mtx);
+
+- next_chan = local->scan_req->channels[local->scan_channel_idx];
+-
+- if (ieee80211_cfg_on_oper_channel(local)) {
+- /* We're currently on operating channel. */
+- if (next_chan == local->oper_channel)
+- /* We don't need to move off of operating channel. */
+- local->next_scan_state = SCAN_SET_CHANNEL;
+- else
+- /*
+- * We do need to leave operating channel, as next
+- * scan is somewhere else.
+- */
+- local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL;
+- } else {
++ if (local->scan_channel) {
+ /*
+ * we're currently scanning a different channel, let's
+ * see if we can scan another channel without interfering
+@@ -535,6 +496,7 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
+ *
+ * Otherwise switch back to the operating channel.
+ */
++ next_chan = local->scan_req->channels[local->scan_channel_idx];
+
+ bad_latency = time_after(jiffies +
+ ieee80211_scan_get_channel_time(next_chan),
+@@ -552,6 +514,12 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
+ local->next_scan_state = SCAN_ENTER_OPER_CHANNEL;
+ else
+ local->next_scan_state = SCAN_SET_CHANNEL;
++ } else {
++ /*
++ * we're on the operating channel currently, let's
++ * leave that channel now to scan another one
++ */
++ local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL;
+ }
+
+ *next_delay = 0;
+@@ -560,10 +528,9 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
+ static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local,
+ unsigned long *next_delay)
+ {
+- /* PS will already be in off-channel mode,
+- * we do that once at the beginning of scanning.
+- */
+- ieee80211_offchannel_stop_vifs(local, false);
++ ieee80211_offchannel_stop_station(local);
++
++ __set_bit(SCAN_OFF_CHANNEL, &local->scanning);
+
+ /*
+ * What if the nullfunc frames didn't arrive?
+@@ -586,15 +553,15 @@ static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *loca
+ {
+ /* switch back to the operating channel */
+ local->scan_channel = NULL;
+- if (!ieee80211_cfg_on_oper_channel(local))
+- ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
++ ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
+
+ /*
+- * Re-enable vifs and beaconing. Leave PS
+- * in off-channel state..will put that back
+- * on-channel at the end of scanning.
++ * Only re-enable station mode interface now; beaconing will be
++ * re-enabled once the full scan has been completed.
+ */
+- ieee80211_offchannel_return(local, true, false);
++ ieee80211_offchannel_return(local, false);
++
++ __clear_bit(SCAN_OFF_CHANNEL, &local->scanning);
+
+ *next_delay = HZ / 5;
+ local->next_scan_state = SCAN_DECISION;
+diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
+index 8cb0d2d..54ea022 100644
+--- a/net/mac80211/tx.c
++++ b/net/mac80211/tx.c
+@@ -258,8 +258,7 @@ ieee80211_tx_h_check_assoc(struct ieee80211_tx_data *tx)
+ if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED))
+ return TX_CONTINUE;
+
+- if (unlikely(test_bit(SCAN_SW_SCANNING, &tx->local->scanning)) &&
+- test_bit(SDATA_STATE_OFFCHANNEL, &tx->sdata->state) &&
++ if (unlikely(test_bit(SCAN_OFF_CHANNEL, &tx->local->scanning)) &&
+ !ieee80211_is_probe_req(hdr->frame_control) &&
+ !ieee80211_is_nullfunc(hdr->frame_control))
+ /*
+diff --git a/net/mac80211/work.c b/net/mac80211/work.c
+index 7737f20..b76bf33 100644
+--- a/net/mac80211/work.c
++++ b/net/mac80211/work.c
+@@ -901,26 +901,6 @@ static bool ieee80211_work_ct_coexists(enum nl80211_channel_type wk_ct,
+ return false;
+ }
+
+-static enum nl80211_channel_type
+-ieee80211_calc_ct(enum nl80211_channel_type wk_ct,
+- enum nl80211_channel_type oper_ct)
+-{
+- switch (wk_ct) {
+- case NL80211_CHAN_NO_HT:
+- return oper_ct;
+- case NL80211_CHAN_HT20:
+- if (oper_ct != NL80211_CHAN_NO_HT)
+- return oper_ct;
+- return wk_ct;
+- case NL80211_CHAN_HT40MINUS:
+- case NL80211_CHAN_HT40PLUS:
+- return wk_ct;
+- }
+- WARN_ON(1); /* shouldn't get here */
+- return wk_ct;
+-}
+-
+-
+ static void ieee80211_work_timer(unsigned long data)
+ {
+ struct ieee80211_local *local = (void *) data;
+@@ -971,52 +951,18 @@ static void ieee80211_work_work(struct work_struct *work)
+ }
+
+ if (!started && !local->tmp_channel) {
+- bool on_oper_chan;
+- bool tmp_chan_changed = false;
+- bool on_oper_chan2;
+- enum nl80211_channel_type wk_ct;
+- on_oper_chan = ieee80211_cfg_on_oper_channel(local);
+-
+- /* Work with existing channel type if possible. */
+- wk_ct = wk->chan_type;
+- if (wk->chan == local->hw.conf.channel)
+- wk_ct = ieee80211_calc_ct(wk->chan_type,
+- local->hw.conf.channel_type);
+-
+- if (local->tmp_channel)
+- if ((local->tmp_channel != wk->chan) ||
+- (local->tmp_channel_type != wk_ct))
+- tmp_chan_changed = true;
+-
+- local->tmp_channel = wk->chan;
+- local->tmp_channel_type = wk_ct;
+ /*
+- * Leave the station vifs in awake mode if they
+- * happen to be on the same channel as
+- * the requested channel.
++ * TODO: could optimize this by leaving the
++ * station vifs in awake mode if they
++ * happen to be on the same channel as
++ * the requested channel
+ */
+- on_oper_chan2 = ieee80211_cfg_on_oper_channel(local);
+- if (on_oper_chan != on_oper_chan2) {
+- if (on_oper_chan2) {
+- /* going off oper channel, PS too */
+- ieee80211_offchannel_stop_vifs(local,
+- true);
+- ieee80211_hw_config(local, 0);
+- } else {
+- /* going on channel, but leave PS
+- * off-channel. */
+- ieee80211_hw_config(local, 0);
+- ieee80211_offchannel_return(local,
+- true,
+- false);
+- }
+- } else if (tmp_chan_changed)
+- /* Still off-channel, but on some other
+- * channel, so update hardware.
+- * PS should already be off-channel.
+- */
+- ieee80211_hw_config(local, 0);
++ ieee80211_offchannel_stop_beaconing(local);
++ ieee80211_offchannel_stop_station(local);
+
++ local->tmp_channel = wk->chan;
++ local->tmp_channel_type = wk->chan_type;
++ ieee80211_hw_config(local, 0);
+ started = true;
+ wk->timeout = jiffies;
+ }
+@@ -1102,8 +1048,7 @@ static void ieee80211_work_work(struct work_struct *work)
+ * we still need to do a hardware config. Currently,
+ * we cannot be here while scanning, however.
+ */
+- if (!ieee80211_cfg_on_oper_channel(local))
+- ieee80211_hw_config(local, 0);
++ ieee80211_hw_config(local, 0);
+
+ /* At the least, we need to disable offchannel_ps,
+ * so just go ahead and run the entire offchannel
+@@ -1111,7 +1056,7 @@ static void ieee80211_work_work(struct work_struct *work)
+ * beaconing if we were already on-oper-channel
+ * as a future optimization.
+ */
+- ieee80211_offchannel_return(local, true, true);
++ ieee80211_offchannel_return(local, true);
+
+ /* give connection some time to breathe */
+ run_again(local, jiffies + HZ/2);
More information about the scm-commits
mailing list