diff options
author | Ben Greear <greearb@candelatech.com> | 2011-02-04 22:54:17 +0300 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2011-02-05 00:30:32 +0300 |
commit | b23b025fe246f3acc2988eb6d400df34c27cb8ae (patch) | |
tree | e1c8cd163dc4dc7c603652a9e101f8381cf66fdc /net/mac80211/work.c | |
parent | cb8d61de2d7f074654057b2b924da1efbf625ad4 (diff) | |
download | linux-b23b025fe246f3acc2988eb6d400df34c27cb8ae.tar.xz |
mac80211: Optimize scans on current operating channel.
This should decrease un-necessary flushes, on/off channel work,
and channel changes in cases where the only scanned channel is
the current operating channel.
* Removes SCAN_OFF_CHANNEL flag, uses SDATA_STATE_OFFCHANNEL
and is-scanning flags instead.
* Add helper method to determine if we are currently configured
for the operating channel.
* Do no blindly go off/on channel in work.c Instead, only call
appropriate on/off code when we really need to change channels.
Always enable offchannel-ps mode when starting work,
and disable it when we are done.
* Consolidate ieee80211_offchannel_stop_station and
ieee80211_offchannel_stop_beaconing, call it
ieee80211_offchannel_stop_vifs instead.
* Accept non-beacon frames when scanning on operating channel.
* Scan state machine optimized to minimize on/off channel
transitions. Also, when going on-channel, go ahead and
re-enable beaconing. We're going to be there for 200ms,
so seems like some useful beaconing could happen.
Always enable offchannel-ps mode when starting software
scan, and disable it when we are done.
* Grab local->mtx earlier in __ieee80211_scan_completed_finish
so that we are protected when calling hw_config(), etc.
* Pass probe-responses up the stack if scanning on local
channel, so that mlme can take a look.
Signed-off-by: Ben Greear <greearb@candelatech.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/work.c')
-rw-r--r-- | net/mac80211/work.c | 66 |
1 files changed, 55 insertions, 11 deletions
diff --git a/net/mac80211/work.c b/net/mac80211/work.c index 36305e0d06ef..6bf787a5b38a 100644 --- a/net/mac80211/work.c +++ b/net/mac80211/work.c @@ -924,18 +924,44 @@ static void ieee80211_work_work(struct work_struct *work) } if (!started && !local->tmp_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 - */ - ieee80211_offchannel_stop_beaconing(local); - ieee80211_offchannel_stop_station(local); + bool on_oper_chan; + bool tmp_chan_changed = false; + bool on_oper_chan2; + on_oper_chan = ieee80211_cfg_on_oper_channel(local); + if (local->tmp_channel) + if ((local->tmp_channel != wk->chan) || + (local->tmp_channel_type != wk->chan_type)) + tmp_chan_changed = true; local->tmp_channel = wk->chan; local->tmp_channel_type = wk->chan_type; - ieee80211_hw_config(local, 0); + /* + * Leave 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); + started = true; wk->timeout = jiffies; } @@ -1011,9 +1037,27 @@ static void ieee80211_work_work(struct work_struct *work) } if (!remain_off_channel && local->tmp_channel) { + bool on_oper_chan = ieee80211_cfg_on_oper_channel(local); local->tmp_channel = NULL; - ieee80211_hw_config(local, 0); - ieee80211_offchannel_return(local, true); + /* If tmp_channel wasn't operating channel, then + * we need to go back on-channel. + * NOTE: If we can ever be here while scannning, + * or if the hw_config() channel config logic changes, + * then we may need to do a more thorough check to see if + * we still need to do a hardware config. Currently, + * we cannot be here while scanning, however. + */ + if (ieee80211_cfg_on_oper_channel(local) && !on_oper_chan) + ieee80211_hw_config(local, 0); + + /* At the least, we need to disable offchannel_ps, + * so just go ahead and run the entire offchannel + * return logic here. We *could* skip enabling + * beaconing if we were already on-oper-channel + * as a future optimization. + */ + ieee80211_offchannel_return(local, true, true); + /* give connection some time to breathe */ run_again(local, jiffies + HZ/2); } |