aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/main.c
diff options
context:
space:
mode:
authorBen Greear <greearb@candelatech.com>2011-02-04 14:54:17 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-02-04 16:30:32 -0500
commitb23b025fe246f3acc2988eb6d400df34c27cb8ae (patch)
treee1c8cd163dc4dc7c603652a9e101f8381cf66fdc /net/mac80211/main.c
parentcb8d61de2d7f074654057b2b924da1efbf625ad4 (diff)
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/main.c')
-rw-r--r--net/mac80211/main.c53
1 files changed, 47 insertions, 6 deletions
diff --git a/net/mac80211/main.c b/net/mac80211/main.c
index 09a27449f3fd..c155c0b69426 100644
--- a/net/mac80211/main.c
+++ b/net/mac80211/main.c
@@ -98,6 +98,41 @@ static void ieee80211_reconfig_filter(struct work_struct *work)
98 ieee80211_configure_filter(local); 98 ieee80211_configure_filter(local);
99} 99}
100 100
101/*
102 * Returns true if we are logically configured to be on
103 * the operating channel AND the hardware-conf is currently
104 * configured on the operating channel. Compares channel-type
105 * as well.
106 */
107bool ieee80211_cfg_on_oper_channel(struct ieee80211_local *local)
108{
109 struct ieee80211_channel *chan, *scan_chan;
110 enum nl80211_channel_type channel_type;
111
112 /* This logic needs to match logic in ieee80211_hw_config */
113 if (local->scan_channel) {
114 chan = local->scan_channel;
115 channel_type = NL80211_CHAN_NO_HT;
116 } else if (local->tmp_channel) {
117 chan = scan_chan = local->tmp_channel;
118 channel_type = local->tmp_channel_type;
119 } else {
120 chan = local->oper_channel;
121 channel_type = local->_oper_channel_type;
122 }
123
124 if (chan != local->oper_channel ||
125 channel_type != local->_oper_channel_type)
126 return false;
127
128 /* Check current hardware-config against oper_channel. */
129 if ((local->oper_channel != local->hw.conf.channel) ||
130 (local->_oper_channel_type != local->hw.conf.channel_type))
131 return false;
132
133 return true;
134}
135
101int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) 136int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
102{ 137{
103 struct ieee80211_channel *chan, *scan_chan; 138 struct ieee80211_channel *chan, *scan_chan;
@@ -110,21 +145,27 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed)
110 145
111 scan_chan = local->scan_channel; 146 scan_chan = local->scan_channel;
112 147
148 /* If this off-channel logic ever changes, ieee80211_on_oper_channel
149 * may need to change as well.
150 */
113 offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; 151 offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
114 if (scan_chan) { 152 if (scan_chan) {
115 chan = scan_chan; 153 chan = scan_chan;
116 channel_type = NL80211_CHAN_NO_HT; 154 channel_type = NL80211_CHAN_NO_HT;
117 local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL; 155 } else if (local->tmp_channel) {
118 } else if (local->tmp_channel &&
119 local->oper_channel != local->tmp_channel) {
120 chan = scan_chan = local->tmp_channel; 156 chan = scan_chan = local->tmp_channel;
121 channel_type = local->tmp_channel_type; 157 channel_type = local->tmp_channel_type;
122 local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
123 } else { 158 } else {
124 chan = local->oper_channel; 159 chan = local->oper_channel;
125 channel_type = local->_oper_channel_type; 160 channel_type = local->_oper_channel_type;
126 local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL;
127 } 161 }
162
163 if (chan != local->oper_channel ||
164 channel_type != local->_oper_channel_type)
165 local->hw.conf.flags |= IEEE80211_CONF_OFFCHANNEL;
166 else
167 local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL;
168
128 offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; 169 offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL;
129 170
130 if (offchannel_flag || chan != local->hw.conf.channel || 171 if (offchannel_flag || chan != local->hw.conf.channel ||
@@ -231,7 +272,7 @@ void ieee80211_bss_info_change_notify(struct ieee80211_sub_if_data *sdata,
231 272
232 if (changed & BSS_CHANGED_BEACON_ENABLED) { 273 if (changed & BSS_CHANGED_BEACON_ENABLED) {
233 if (local->quiescing || !ieee80211_sdata_running(sdata) || 274 if (local->quiescing || !ieee80211_sdata_running(sdata) ||
234 test_bit(SCAN_SW_SCANNING, &local->scanning)) { 275 test_bit(SDATA_STATE_OFFCHANNEL, &sdata->state)) {
235 sdata->vif.bss_conf.enable_beacon = false; 276 sdata->vif.bss_conf.enable_beacon = false;
236 } else { 277 } else {
237 /* 278 /*