Apply patch to revert mac80211 scan optimizations (rhbz #731365)
This commit is contained in:
parent
a6a5351a6f
commit
67de50b811
11
kernel.spec
11
kernel.spec
@ -54,7 +54,7 @@ Summary: The Linux kernel
|
||||
# For non-released -rc kernels, this will be appended after the rcX and
|
||||
# gitX tags, so a 3 here would become part of release "0.rcX.gitX.3"
|
||||
#
|
||||
%global baserelease 3
|
||||
%global baserelease 4
|
||||
%global fedora_build %{baserelease}
|
||||
|
||||
# base_sublevel is the kernel version we're starting with and patching
|
||||
@ -794,6 +794,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
|
||||
@ -1457,6 +1460,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
|
||||
@ -2188,6 +2194,9 @@ fi
|
||||
# and build.
|
||||
|
||||
%changelog
|
||||
* Thu Dec 01 2011 Josh Boyer <jwboyer@redhat.com>
|
||||
- Apply patch to revert mac80211 scan optimizations (rhbz #731365)
|
||||
|
||||
* Wed Nov 30 2011 Josh Boyer <jwboyer@redhat.com>
|
||||
- Include commit 3940d6185 from JJ Ding in elantech.patch
|
||||
|
||||
|
594
mac80211_offchannel_rework_revert.patch
Normal file
594
mac80211_offchannel_rework_revert.patch
Normal file
@ -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);
|
Loading…
Reference in New Issue
Block a user