aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKalle Valo <kalle.valo@nokia.com>2009-03-22 15:57:21 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-03-27 20:13:12 -0400
commit9050bdd8589c373e01e41ddbd9a192de2ff01ef0 (patch)
treea33c69c570d6db96bb54bb3b4b3eb5ea4b43d5ea
parent15b7b0629c8213905926394dc73d600e0ca250ce (diff)
mac80211: disable power save when scanning
When software scanning we need to disable power save so that all possible probe responses and beacons are received. For hardware scanning assume that hardware will take care of that and document that assumption. Signed-off-by: Kalle Valo <kalle.valo@nokia.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--include/net/mac80211.h12
-rw-r--r--net/mac80211/scan.c64
2 files changed, 69 insertions, 7 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index daa539a4287b..174dc1d7526b 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1307,11 +1307,13 @@ enum ieee80211_ampdu_mlme_action {
1307 * 1307 *
1308 * @hw_scan: Ask the hardware to service the scan request, no need to start 1308 * @hw_scan: Ask the hardware to service the scan request, no need to start
1309 * the scan state machine in stack. The scan must honour the channel 1309 * the scan state machine in stack. The scan must honour the channel
1310 * configuration done by the regulatory agent in the wiphy's registered 1310 * configuration done by the regulatory agent in the wiphy's
1311 * bands. When the scan finishes, ieee80211_scan_completed() must be 1311 * registered bands. The hardware (or the driver) needs to make sure
1312 * called; note that it also must be called when the scan cannot finish 1312 * that power save is disabled. When the scan finishes,
1313 * because the hardware is turned off! Anything else is a bug! 1313 * ieee80211_scan_completed() must be called; note that it also must
1314 * Returns a negative error code which will be seen in userspace. 1314 * be called when the scan cannot finish because the hardware is
1315 * turned off! Anything else is a bug! Returns a negative error code
1316 * which will be seen in userspace.
1315 * 1317 *
1316 * @sw_scan_start: Notifier function that is called just before a software scan 1318 * @sw_scan_start: Notifier function that is called just before a software scan
1317 * is started. Can be NULL, if the driver doesn't need this notification. 1319 * is started. Can be NULL, if the driver doesn't need this notification.
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 46f35dc6accb..3bf9839f5916 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -214,6 +214,66 @@ void ieee80211_scan_failed(struct ieee80211_local *local)
214 local->scan_req = NULL; 214 local->scan_req = NULL;
215} 215}
216 216
217/*
218 * inform AP that we will go to sleep so that it will buffer the frames
219 * while we scan
220 */
221static void ieee80211_scan_ps_enable(struct ieee80211_sub_if_data *sdata)
222{
223 struct ieee80211_local *local = sdata->local;
224 bool ps = false;
225
226 /* FIXME: what to do when local->pspolling is true? */
227
228 del_timer_sync(&local->dynamic_ps_timer);
229 cancel_work_sync(&local->dynamic_ps_enable_work);
230
231 if (local->hw.conf.flags & IEEE80211_CONF_PS) {
232 ps = true;
233 local->hw.conf.flags &= ~IEEE80211_CONF_PS;
234 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
235 }
236
237 if (!ps || !(local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK))
238 /*
239 * If power save was enabled, no need to send a nullfunc
240 * frame because AP knows that we are sleeping. But if the
241 * hardware is creating the nullfunc frame for power save
242 * status (ie. IEEE80211_HW_PS_NULLFUNC_STACK is not
243 * enabled) and power save was enabled, the firmware just
244 * sent a null frame with power save disabled. So we need
245 * to send a new nullfunc frame to inform the AP that we
246 * are again sleeping.
247 */
248 ieee80211_send_nullfunc(local, sdata, 1);
249}
250
251/* inform AP that we are awake again, unless power save is enabled */
252static void ieee80211_scan_ps_disable(struct ieee80211_sub_if_data *sdata)
253{
254 struct ieee80211_local *local = sdata->local;
255
256 if (!local->powersave)
257 ieee80211_send_nullfunc(local, sdata, 0);
258 else {
259 /*
260 * In !IEEE80211_HW_PS_NULLFUNC_STACK case the hardware
261 * will send a nullfunc frame with the powersave bit set
262 * even though the AP already knows that we are sleeping.
263 * This could be avoided by sending a null frame with power
264 * save bit disabled before enabling the power save, but
265 * this doesn't gain anything.
266 *
267 * When IEEE80211_HW_PS_NULLFUNC_STACK is enabled, no need
268 * to send a nullfunc frame because AP already knows that
269 * we are sleeping, let's just enable power save mode in
270 * hardware.
271 */
272 local->hw.conf.flags |= IEEE80211_CONF_PS;
273 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
274 }
275}
276
217void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) 277void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
218{ 278{
219 struct ieee80211_local *local = hw_to_local(hw); 279 struct ieee80211_local *local = hw_to_local(hw);
@@ -268,7 +328,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
268 /* Tell AP we're back */ 328 /* Tell AP we're back */
269 if (sdata->vif.type == NL80211_IFTYPE_STATION) { 329 if (sdata->vif.type == NL80211_IFTYPE_STATION) {
270 if (sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED) { 330 if (sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED) {
271 ieee80211_send_nullfunc(local, sdata, 0); 331 ieee80211_scan_ps_disable(sdata);
272 netif_tx_wake_all_queues(sdata->dev); 332 netif_tx_wake_all_queues(sdata->dev);
273 } 333 }
274 } else 334 } else
@@ -441,7 +501,7 @@ int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata,
441 if (sdata->vif.type == NL80211_IFTYPE_STATION) { 501 if (sdata->vif.type == NL80211_IFTYPE_STATION) {
442 if (sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED) { 502 if (sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED) {
443 netif_tx_stop_all_queues(sdata->dev); 503 netif_tx_stop_all_queues(sdata->dev);
444 ieee80211_send_nullfunc(local, sdata, 1); 504 ieee80211_scan_ps_enable(sdata);
445 } 505 }
446 } else 506 } else
447 netif_tx_stop_all_queues(sdata->dev); 507 netif_tx_stop_all_queues(sdata->dev);