aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/scan.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/scan.c')
-rw-r--r--net/mac80211/scan.c199
1 files changed, 77 insertions, 122 deletions
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 105436dbb90d..81863031e0a3 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -213,12 +213,7 @@ ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb)
213 if (bss) 213 if (bss)
214 ieee80211_rx_bss_put(sdata->local, bss); 214 ieee80211_rx_bss_put(sdata->local, bss);
215 215
216 /* If we are on-operating-channel, and this packet is for the 216 if (channel == sdata->local->oper_channel)
217 * current channel, pass the pkt on up the stack so that
218 * the rest of the stack can make use of it.
219 */
220 if (ieee80211_cfg_on_oper_channel(sdata->local)
221 && (channel == sdata->local->oper_channel))
222 return RX_CONTINUE; 217 return RX_CONTINUE;
223 218
224 dev_kfree_skb(skb); 219 dev_kfree_skb(skb);
@@ -264,8 +259,6 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
264 bool was_hw_scan) 259 bool was_hw_scan)
265{ 260{
266 struct ieee80211_local *local = hw_to_local(hw); 261 struct ieee80211_local *local = hw_to_local(hw);
267 bool on_oper_chan;
268 bool enable_beacons = false;
269 262
270 lockdep_assert_held(&local->mtx); 263 lockdep_assert_held(&local->mtx);
271 264
@@ -298,25 +291,13 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
298 local->scanning = 0; 291 local->scanning = 0;
299 local->scan_channel = NULL; 292 local->scan_channel = NULL;
300 293
301 on_oper_chan = ieee80211_cfg_on_oper_channel(local); 294 /* Set power back to normal operating levels. */
302 295 ieee80211_hw_config(local, 0);
303 if (was_hw_scan || !on_oper_chan)
304 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
305 else
306 /* Set power back to normal operating levels. */
307 ieee80211_hw_config(local, 0);
308 296
309 if (!was_hw_scan) { 297 if (!was_hw_scan) {
310 bool on_oper_chan2;
311 ieee80211_configure_filter(local); 298 ieee80211_configure_filter(local);
312 drv_sw_scan_complete(local); 299 drv_sw_scan_complete(local);
313 on_oper_chan2 = ieee80211_cfg_on_oper_channel(local); 300 ieee80211_offchannel_return(local, true, true);
314 /* We should always be on-channel at this point. */
315 WARN_ON(!on_oper_chan2);
316 if (on_oper_chan2 && (on_oper_chan != on_oper_chan2))
317 enable_beacons = true;
318
319 ieee80211_offchannel_return(local, enable_beacons, true);
320 } 301 }
321 302
322 ieee80211_recalc_idle(local); 303 ieee80211_recalc_idle(local);
@@ -361,11 +342,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
361 local->next_scan_state = SCAN_DECISION; 342 local->next_scan_state = SCAN_DECISION;
362 local->scan_channel_idx = 0; 343 local->scan_channel_idx = 0;
363 344
364 /* We always want to use off-channel PS, even if we 345 ieee80211_offchannel_stop_vifs(local, true);
365 * are not really leaving oper-channel. Don't
366 * tell the AP though, as long as we are on-channel.
367 */
368 ieee80211_offchannel_enable_all_ps(local, false);
369 346
370 ieee80211_configure_filter(local); 347 ieee80211_configure_filter(local);
371 348
@@ -373,8 +350,7 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local)
373 ieee80211_hw_config(local, 0); 350 ieee80211_hw_config(local, 0);
374 351
375 ieee80211_queue_delayed_work(&local->hw, 352 ieee80211_queue_delayed_work(&local->hw,
376 &local->scan_work, 353 &local->scan_work, 0);
377 IEEE80211_CHANNEL_TIME);
378 354
379 return 0; 355 return 0;
380} 356}
@@ -510,96 +486,39 @@ static void ieee80211_scan_state_decision(struct ieee80211_local *local,
510 486
511 next_chan = local->scan_req->channels[local->scan_channel_idx]; 487 next_chan = local->scan_req->channels[local->scan_channel_idx];
512 488
513 if (ieee80211_cfg_on_oper_channel(local)) {
514 /* We're currently on operating channel. */
515 if (next_chan == local->oper_channel)
516 /* We don't need to move off of operating channel. */
517 local->next_scan_state = SCAN_SET_CHANNEL;
518 else
519 /*
520 * We do need to leave operating channel, as next
521 * scan is somewhere else.
522 */
523 local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL;
524 } else {
525 /*
526 * we're currently scanning a different channel, let's
527 * see if we can scan another channel without interfering
528 * with the current traffic situation.
529 *
530 * Since we don't know if the AP has pending frames for us
531 * we can only check for our tx queues and use the current
532 * pm_qos requirements for rx. Hence, if no tx traffic occurs
533 * at all we will scan as many channels in a row as the pm_qos
534 * latency allows us to. Additionally we also check for the
535 * currently negotiated listen interval to prevent losing
536 * frames unnecessarily.
537 *
538 * Otherwise switch back to the operating channel.
539 */
540
541 bad_latency = time_after(jiffies +
542 ieee80211_scan_get_channel_time(next_chan),
543 local->leave_oper_channel_time +
544 usecs_to_jiffies(pm_qos_request(PM_QOS_NETWORK_LATENCY)));
545
546 listen_int_exceeded = time_after(jiffies +
547 ieee80211_scan_get_channel_time(next_chan),
548 local->leave_oper_channel_time +
549 usecs_to_jiffies(min_beacon_int * 1024) *
550 local->hw.conf.listen_interval);
551
552 if (associated && ( !tx_empty || bad_latency ||
553 listen_int_exceeded))
554 local->next_scan_state = SCAN_ENTER_OPER_CHANNEL;
555 else
556 local->next_scan_state = SCAN_SET_CHANNEL;
557 }
558
559 *next_delay = 0;
560}
561
562static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local,
563 unsigned long *next_delay)
564{
565 /* PS will already be in off-channel mode,
566 * we do that once at the beginning of scanning.
567 */
568 ieee80211_offchannel_stop_vifs(local, false);
569
570 /* 489 /*
571 * What if the nullfunc frames didn't arrive? 490 * we're currently scanning a different channel, let's
491 * see if we can scan another channel without interfering
492 * with the current traffic situation.
493 *
494 * Since we don't know if the AP has pending frames for us
495 * we can only check for our tx queues and use the current
496 * pm_qos requirements for rx. Hence, if no tx traffic occurs
497 * at all we will scan as many channels in a row as the pm_qos
498 * latency allows us to. Additionally we also check for the
499 * currently negotiated listen interval to prevent losing
500 * frames unnecessarily.
501 *
502 * Otherwise switch back to the operating channel.
572 */ 503 */
573 drv_flush(local, false);
574 if (local->ops->flush)
575 *next_delay = 0;
576 else
577 *next_delay = HZ / 10;
578 504
579 /* remember when we left the operating channel */ 505 bad_latency = time_after(jiffies +
580 local->leave_oper_channel_time = jiffies; 506 ieee80211_scan_get_channel_time(next_chan),
507 local->leave_oper_channel_time +
508 usecs_to_jiffies(pm_qos_request(PM_QOS_NETWORK_LATENCY)));
581 509
582 /* advance to the next channel to be scanned */ 510 listen_int_exceeded = time_after(jiffies +
583 local->next_scan_state = SCAN_SET_CHANNEL; 511 ieee80211_scan_get_channel_time(next_chan),
584} 512 local->leave_oper_channel_time +
585 513 usecs_to_jiffies(min_beacon_int * 1024) *
586static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *local, 514 local->hw.conf.listen_interval);
587 unsigned long *next_delay)
588{
589 /* switch back to the operating channel */
590 local->scan_channel = NULL;
591 if (!ieee80211_cfg_on_oper_channel(local))
592 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
593 515
594 /* 516 if (associated && (!tx_empty || bad_latency || listen_int_exceeded))
595 * Re-enable vifs and beaconing. Leave PS 517 local->next_scan_state = SCAN_SUSPEND;
596 * in off-channel state..will put that back 518 else
597 * on-channel at the end of scanning. 519 local->next_scan_state = SCAN_SET_CHANNEL;
598 */
599 ieee80211_offchannel_return(local, true, false);
600 520
601 *next_delay = HZ / 5; 521 *next_delay = 0;
602 local->next_scan_state = SCAN_DECISION;
603} 522}
604 523
605static void ieee80211_scan_state_set_channel(struct ieee80211_local *local, 524static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
@@ -613,10 +532,8 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
613 532
614 local->scan_channel = chan; 533 local->scan_channel = chan;
615 534
616 /* Only call hw-config if we really need to change channels. */ 535 if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL))
617 if (chan != local->hw.conf.channel) 536 skip = 1;
618 if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL))
619 skip = 1;
620 537
621 /* advance state machine to next channel/band */ 538 /* advance state machine to next channel/band */
622 local->scan_channel_idx++; 539 local->scan_channel_idx++;
@@ -673,6 +590,44 @@ static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
673 local->next_scan_state = SCAN_DECISION; 590 local->next_scan_state = SCAN_DECISION;
674} 591}
675 592
593static void ieee80211_scan_state_suspend(struct ieee80211_local *local,
594 unsigned long *next_delay)
595{
596 /* switch back to the operating channel */
597 local->scan_channel = NULL;
598 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
599
600 /*
601 * Re-enable vifs and beaconing. Leave PS
602 * in off-channel state..will put that back
603 * on-channel at the end of scanning.
604 */
605 ieee80211_offchannel_return(local, true, false);
606
607 *next_delay = HZ / 5;
608 /* afterwards, resume scan & go to next channel */
609 local->next_scan_state = SCAN_RESUME;
610}
611
612static void ieee80211_scan_state_resume(struct ieee80211_local *local,
613 unsigned long *next_delay)
614{
615 /* PS already is in off-channel mode */
616 ieee80211_offchannel_stop_vifs(local, false);
617
618 if (local->ops->flush) {
619 drv_flush(local, false);
620 *next_delay = 0;
621 } else
622 *next_delay = HZ / 10;
623
624 /* remember when we left the operating channel */
625 local->leave_oper_channel_time = jiffies;
626
627 /* advance to the next channel to be scanned */
628 local->next_scan_state = SCAN_DECISION;
629}
630
676void ieee80211_scan_work(struct work_struct *work) 631void ieee80211_scan_work(struct work_struct *work)
677{ 632{
678 struct ieee80211_local *local = 633 struct ieee80211_local *local =
@@ -743,11 +698,11 @@ void ieee80211_scan_work(struct work_struct *work)
743 case SCAN_SEND_PROBE: 698 case SCAN_SEND_PROBE:
744 ieee80211_scan_state_send_probe(local, &next_delay); 699 ieee80211_scan_state_send_probe(local, &next_delay);
745 break; 700 break;
746 case SCAN_LEAVE_OPER_CHANNEL: 701 case SCAN_SUSPEND:
747 ieee80211_scan_state_leave_oper_channel(local, &next_delay); 702 ieee80211_scan_state_suspend(local, &next_delay);
748 break; 703 break;
749 case SCAN_ENTER_OPER_CHANNEL: 704 case SCAN_RESUME:
750 ieee80211_scan_state_enter_oper_channel(local, &next_delay); 705 ieee80211_scan_state_resume(local, &next_delay);
751 break; 706 break;
752 } 707 }
753 } while (next_delay == 0); 708 } while (next_delay == 0);