| From e76aadc572288a158ae18ae1c10fe395c7bca066 Mon Sep 17 00:00:00 2001 |
| From: Johannes Berg <johannes.berg@intel.com> |
| Date: Tue, 29 Nov 2011 10:20:02 +0100 |
| Subject: mac80211: revert on-channel work optimisations |
| |
| From: Johannes Berg <johannes.berg@intel.com> |
| |
| commit e76aadc572288a158ae18ae1c10fe395c7bca066 upstream. |
| |
| Backport note: |
| This patch it's a full revert of commit b23b025f "mac80211: Optimize |
| scans on current operating channel.". On upstrem revert e76aadc5 we |
| keep some bits from that commit, which are needed for upstream version |
| of mac80211. |
| |
| The on-channel work optimisations have caused a |
| number of issues, and the code is unfortunately |
| very complex and almost impossible to follow. |
| Instead of attempting to put in more workarounds |
| let's just remove those optimisations, we can |
| work on them again later, after we change the |
| whole auth/assoc design. |
| |
| This should fix rate_control_send_low() warnings, |
| see RH bug 731365. |
| |
| Signed-off-by: Johannes Berg <johannes.berg@intel.com> |
| Signed-off-by: John W. Linville <linville@tuxdriver.com> |
| Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> |
| --- |
| net/mac80211/ieee80211_i.h | 13 +++---- |
| net/mac80211/main.c | 58 +++------------------------------ |
| net/mac80211/offchannel.c | 68 ++++++++++++++++++--------------------- |
| net/mac80211/rx.c | 10 ++++- |
| net/mac80211/scan.c | 77 ++++++++++++--------------------------------- |
| net/mac80211/tx.c | 3 - |
| net/mac80211/work.c | 77 ++++++--------------------------------------- |
| 7 files changed, 85 insertions(+), 221 deletions(-) |
| |
| --- a/net/mac80211/ieee80211_i.h |
| +++ b/net/mac80211/ieee80211_i.h |
| @@ -702,6 +702,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 |
| @@ -710,6 +712,7 @@ struct tpt_led_trigger { |
| enum { |
| SCAN_SW_SCANNING, |
| SCAN_HW_SCANNING, |
| + SCAN_OFF_CHANNEL, |
| SCAN_COMPLETED, |
| SCAN_ABORTED, |
| }; |
| @@ -1140,14 +1143,10 @@ int ieee80211_request_sched_scan_stop(st |
| 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 */ |
| --- a/net/mac80211/main.c |
| +++ b/net/mac80211/main.c |
| @@ -92,47 +92,6 @@ static void ieee80211_reconfig_filter(st |
| 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 |
| |
| 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 |
| 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(st |
| |
| 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 { |
| /* |
| --- a/net/mac80211/offchannel.c |
| +++ b/net/mac80211/offchannel.c |
| @@ -18,14 +18,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; |
| @@ -46,8 +42,8 @@ static void ieee80211_offchannel_ps_enab |
| 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 |
| @@ -82,9 +78,6 @@ static void ieee80211_offchannel_ps_disa |
| * 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) { |
| @@ -103,61 +96,63 @@ static void ieee80211_offchannel_ps_disa |
| 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; |
| |
| @@ -167,8 +162,7 @@ void ieee80211_offchannel_return(struct |
| 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); |
| } |
| @@ -188,7 +182,7 @@ void ieee80211_offchannel_return(struct |
| 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 || |
| --- a/net/mac80211/rx.c |
| +++ b/net/mac80211/rx.c |
| @@ -421,10 +421,16 @@ ieee80211_rx_h_passive_scan(struct ieee8 |
| 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; |
| @@ -2858,7 +2864,7 @@ static void __ieee80211_rx_handle_packet |
| 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)) |
| --- a/net/mac80211/scan.c |
| +++ b/net/mac80211/scan.c |
| @@ -213,14 +213,6 @@ ieee80211_scan_rx(struct ieee80211_sub_i |
| 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; |
| } |
| @@ -264,8 +256,6 @@ static void __ieee80211_scan_completed(s |
| 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); |
| |
| @@ -298,25 +288,11 @@ static void __ieee80211_scan_completed(s |
| 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); |
| @@ -357,15 +333,13 @@ static int ieee80211_start_sw_scan(struc |
| */ |
| 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); |
| |
| @@ -508,20 +482,7 @@ static void ieee80211_scan_state_decisio |
| } |
| 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 |
| @@ -537,6 +498,7 @@ static void ieee80211_scan_state_decisio |
| * |
| * 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), |
| @@ -554,6 +516,12 @@ static void ieee80211_scan_state_decisio |
| 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; |
| @@ -562,10 +530,9 @@ static void ieee80211_scan_state_decisio |
| 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? |
| @@ -588,15 +555,15 @@ static void ieee80211_scan_state_enter_o |
| { |
| /* 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; |
| --- a/net/mac80211/tx.c |
| +++ b/net/mac80211/tx.c |
| @@ -259,8 +259,7 @@ ieee80211_tx_h_check_assoc(struct ieee80 |
| 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)) |
| /* |
| --- a/net/mac80211/work.c |
| +++ b/net/mac80211/work.c |
| @@ -899,26 +899,6 @@ static bool ieee80211_work_ct_coexists(e |
| 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; |
| @@ -969,52 +949,18 @@ static void ieee80211_work_work(struct w |
| } |
| |
| 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; |
| } |
| @@ -1100,8 +1046,7 @@ static void ieee80211_work_work(struct w |
| * 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 |
| @@ -1109,7 +1054,7 @@ static void ieee80211_work_work(struct w |
| * 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); |