aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/scan.c
diff options
context:
space:
mode:
authorBen Greear <greearb@candelatech.com>2012-04-17 13:54:16 -0400
committerJohn W. Linville <linville@tuxdriver.com>2012-04-23 15:28:33 -0400
commit8a690674e0601efbe9a7b16a5826fc522645cca3 (patch)
treec22f122d36d33a2ac446a0626a0fa4213cb9190d /net/mac80211/scan.c
parente828b9fb4f6c3513950759d5fb902db5bd054048 (diff)
mac80211: Support on-channel scan option.
This based on an idea posted by Stanislaw Gruszka, though I accept full blame for the implementation! This has been tested with ath9k. The idea is to let users scan on the current operating channel without interrupting normal traffic more than absolutely necessary (changing power level might reset some hardware, for instance). Signed-off-by: Ben Greear <greearb@candelatech.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/scan.c')
-rw-r--r--net/mac80211/scan.c95
1 files changed, 69 insertions, 26 deletions
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 45f5aa229efd..8282284f835c 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -401,6 +401,30 @@ void ieee80211_run_deferred_scan(struct ieee80211_local *local)
401 round_jiffies_relative(0)); 401 round_jiffies_relative(0));
402} 402}
403 403
404static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
405 unsigned long *next_delay)
406{
407 int i;
408 struct ieee80211_sub_if_data *sdata = local->scan_sdata;
409 enum ieee80211_band band = local->hw.conf.channel->band;
410
411 for (i = 0; i < local->scan_req->n_ssids; i++)
412 ieee80211_send_probe_req(
413 sdata, NULL,
414 local->scan_req->ssids[i].ssid,
415 local->scan_req->ssids[i].ssid_len,
416 local->scan_req->ie, local->scan_req->ie_len,
417 local->scan_req->rates[band], false,
418 local->scan_req->no_cck);
419
420 /*
421 * After sending probe requests, wait for probe responses
422 * on the channel.
423 */
424 *next_delay = IEEE80211_CHANNEL_TIME;
425 local->next_scan_state = SCAN_DECISION;
426}
427
404static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, 428static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
405 struct cfg80211_scan_request *req) 429 struct cfg80211_scan_request *req)
406{ 430{
@@ -451,10 +475,47 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
451 local->scan_req = req; 475 local->scan_req = req;
452 local->scan_sdata = sdata; 476 local->scan_sdata = sdata;
453 477
454 if (local->ops->hw_scan) 478 if (local->ops->hw_scan) {
455 __set_bit(SCAN_HW_SCANNING, &local->scanning); 479 __set_bit(SCAN_HW_SCANNING, &local->scanning);
456 else 480 } else if ((req->n_channels == 1) &&
481 (req->channels[0]->center_freq ==
482 local->hw.conf.channel->center_freq)) {
483
484 /* If we are scanning only on the current channel, then
485 * we do not need to stop normal activities
486 */
487 unsigned long next_delay;
488
489 __set_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning);
490
491 ieee80211_recalc_idle(local);
492
493 /* Notify driver scan is starting, keep order of operations
494 * same as normal software scan, in case that matters. */
495 drv_sw_scan_start(local);
496
497 ieee80211_configure_filter(local); /* accept probe-responses */
498
499 /* We need to ensure power level is at max for scanning. */
500 ieee80211_hw_config(local, 0);
501
502 if ((req->channels[0]->flags &
503 IEEE80211_CHAN_PASSIVE_SCAN) ||
504 !local->scan_req->n_ssids) {
505 next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
506 } else {
507 ieee80211_scan_state_send_probe(local, &next_delay);
508 next_delay = IEEE80211_CHANNEL_TIME;
509 }
510
511 /* Now, just wait a bit and we are all done! */
512 ieee80211_queue_delayed_work(&local->hw, &local->scan_work,
513 next_delay);
514 return 0;
515 } else {
516 /* Do normal software scan */
457 __set_bit(SCAN_SW_SCANNING, &local->scanning); 517 __set_bit(SCAN_SW_SCANNING, &local->scanning);
518 }
458 519
459 ieee80211_recalc_idle(local); 520 ieee80211_recalc_idle(local);
460 521
@@ -611,30 +672,6 @@ static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
611 local->next_scan_state = SCAN_SEND_PROBE; 672 local->next_scan_state = SCAN_SEND_PROBE;
612} 673}
613 674
614static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
615 unsigned long *next_delay)
616{
617 int i;
618 struct ieee80211_sub_if_data *sdata = local->scan_sdata;
619 enum ieee80211_band band = local->hw.conf.channel->band;
620
621 for (i = 0; i < local->scan_req->n_ssids; i++)
622 ieee80211_send_probe_req(
623 sdata, NULL,
624 local->scan_req->ssids[i].ssid,
625 local->scan_req->ssids[i].ssid_len,
626 local->scan_req->ie, local->scan_req->ie_len,
627 local->scan_req->rates[band], false,
628 local->scan_req->no_cck);
629
630 /*
631 * After sending probe requests, wait for probe responses
632 * on the channel.
633 */
634 *next_delay = IEEE80211_CHANNEL_TIME;
635 local->next_scan_state = SCAN_DECISION;
636}
637
638static void ieee80211_scan_state_suspend(struct ieee80211_local *local, 675static void ieee80211_scan_state_suspend(struct ieee80211_local *local,
639 unsigned long *next_delay) 676 unsigned long *next_delay)
640{ 677{
@@ -685,6 +722,12 @@ void ieee80211_scan_work(struct work_struct *work)
685 722
686 sdata = local->scan_sdata; 723 sdata = local->scan_sdata;
687 724
725 /* When scanning on-channel, the first-callback means completed. */
726 if (test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning)) {
727 aborted = test_and_clear_bit(SCAN_ABORTED, &local->scanning);
728 goto out_complete;
729 }
730
688 if (test_and_clear_bit(SCAN_COMPLETED, &local->scanning)) { 731 if (test_and_clear_bit(SCAN_COMPLETED, &local->scanning)) {
689 aborted = test_and_clear_bit(SCAN_ABORTED, &local->scanning); 732 aborted = test_and_clear_bit(SCAN_ABORTED, &local->scanning);
690 goto out_complete; 733 goto out_complete;