diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/mac80211/scan.c | 136 |
1 files changed, 78 insertions, 58 deletions
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 74820656dc89..71500f1dddbc 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -474,13 +474,87 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
474 | return rc; | 474 | return rc; |
475 | } | 475 | } |
476 | 476 | ||
477 | static int ieee80211_scan_state_set_channel(struct ieee80211_local *local, | ||
478 | unsigned long *next_delay) | ||
479 | { | ||
480 | int skip; | ||
481 | struct ieee80211_channel *chan; | ||
482 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | ||
483 | |||
484 | /* if no more bands/channels left, complete scan */ | ||
485 | if (local->scan_channel_idx >= local->scan_req->n_channels) { | ||
486 | ieee80211_scan_completed(&local->hw, false); | ||
487 | return 1; | ||
488 | } | ||
489 | skip = 0; | ||
490 | chan = local->scan_req->channels[local->scan_channel_idx]; | ||
491 | |||
492 | if (chan->flags & IEEE80211_CHAN_DISABLED || | ||
493 | (sdata->vif.type == NL80211_IFTYPE_ADHOC && | ||
494 | chan->flags & IEEE80211_CHAN_NO_IBSS)) | ||
495 | skip = 1; | ||
496 | |||
497 | if (!skip) { | ||
498 | local->scan_channel = chan; | ||
499 | if (ieee80211_hw_config(local, | ||
500 | IEEE80211_CONF_CHANGE_CHANNEL)) | ||
501 | skip = 1; | ||
502 | } | ||
503 | |||
504 | /* advance state machine to next channel/band */ | ||
505 | local->scan_channel_idx++; | ||
506 | |||
507 | if (skip) | ||
508 | return 0; | ||
509 | |||
510 | /* | ||
511 | * Probe delay is used to update the NAV, cf. 11.1.3.2.2 | ||
512 | * (which unfortunately doesn't say _why_ step a) is done, | ||
513 | * but it waits for the probe delay or until a frame is | ||
514 | * received - and the received frame would update the NAV). | ||
515 | * For now, we do not support waiting until a frame is | ||
516 | * received. | ||
517 | * | ||
518 | * In any case, it is not necessary for a passive scan. | ||
519 | */ | ||
520 | if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN || | ||
521 | !local->scan_req->n_ssids) { | ||
522 | *next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; | ||
523 | return 0; | ||
524 | } | ||
525 | |||
526 | *next_delay = IEEE80211_PROBE_DELAY; | ||
527 | local->scan_state = SCAN_SEND_PROBE; | ||
528 | |||
529 | return 0; | ||
530 | } | ||
531 | |||
532 | static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, | ||
533 | unsigned long *next_delay) | ||
534 | { | ||
535 | int i; | ||
536 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | ||
537 | |||
538 | for (i = 0; i < local->scan_req->n_ssids; i++) | ||
539 | ieee80211_send_probe_req( | ||
540 | sdata, NULL, | ||
541 | local->scan_req->ssids[i].ssid, | ||
542 | local->scan_req->ssids[i].ssid_len, | ||
543 | local->scan_req->ie, local->scan_req->ie_len); | ||
544 | |||
545 | /* | ||
546 | * After sending probe requests, wait for probe responses | ||
547 | * on the channel. | ||
548 | */ | ||
549 | *next_delay = IEEE80211_CHANNEL_TIME; | ||
550 | local->scan_state = SCAN_SET_CHANNEL; | ||
551 | } | ||
552 | |||
477 | void ieee80211_scan_work(struct work_struct *work) | 553 | void ieee80211_scan_work(struct work_struct *work) |
478 | { | 554 | { |
479 | struct ieee80211_local *local = | 555 | struct ieee80211_local *local = |
480 | container_of(work, struct ieee80211_local, scan_work.work); | 556 | container_of(work, struct ieee80211_local, scan_work.work); |
481 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | 557 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; |
482 | struct ieee80211_channel *chan; | ||
483 | int skip, i; | ||
484 | unsigned long next_delay = 0; | 558 | unsigned long next_delay = 0; |
485 | 559 | ||
486 | mutex_lock(&local->scan_mtx); | 560 | mutex_lock(&local->scan_mtx); |
@@ -515,65 +589,11 @@ void ieee80211_scan_work(struct work_struct *work) | |||
515 | 589 | ||
516 | switch (local->scan_state) { | 590 | switch (local->scan_state) { |
517 | case SCAN_SET_CHANNEL: | 591 | case SCAN_SET_CHANNEL: |
518 | /* if no more bands/channels left, complete scan */ | 592 | if (ieee80211_scan_state_set_channel(local, &next_delay)) |
519 | if (local->scan_channel_idx >= local->scan_req->n_channels) { | ||
520 | ieee80211_scan_completed(&local->hw, false); | ||
521 | return; | 593 | return; |
522 | } | ||
523 | skip = 0; | ||
524 | chan = local->scan_req->channels[local->scan_channel_idx]; | ||
525 | |||
526 | if (chan->flags & IEEE80211_CHAN_DISABLED || | ||
527 | (sdata->vif.type == NL80211_IFTYPE_ADHOC && | ||
528 | chan->flags & IEEE80211_CHAN_NO_IBSS)) | ||
529 | skip = 1; | ||
530 | |||
531 | if (!skip) { | ||
532 | local->scan_channel = chan; | ||
533 | if (ieee80211_hw_config(local, | ||
534 | IEEE80211_CONF_CHANGE_CHANNEL)) | ||
535 | skip = 1; | ||
536 | } | ||
537 | |||
538 | /* advance state machine to next channel/band */ | ||
539 | local->scan_channel_idx++; | ||
540 | |||
541 | if (skip) | ||
542 | break; | ||
543 | |||
544 | /* | ||
545 | * Probe delay is used to update the NAV, cf. 11.1.3.2.2 | ||
546 | * (which unfortunately doesn't say _why_ step a) is done, | ||
547 | * but it waits for the probe delay or until a frame is | ||
548 | * received - and the received frame would update the NAV). | ||
549 | * For now, we do not support waiting until a frame is | ||
550 | * received. | ||
551 | * | ||
552 | * In any case, it is not necessary for a passive scan. | ||
553 | */ | ||
554 | if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN || | ||
555 | !local->scan_req->n_ssids) { | ||
556 | next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; | ||
557 | break; | ||
558 | } | ||
559 | |||
560 | next_delay = IEEE80211_PROBE_DELAY; | ||
561 | local->scan_state = SCAN_SEND_PROBE; | ||
562 | break; | 594 | break; |
563 | case SCAN_SEND_PROBE: | 595 | case SCAN_SEND_PROBE: |
564 | for (i = 0; i < local->scan_req->n_ssids; i++) | 596 | ieee80211_scan_state_send_probe(local, &next_delay); |
565 | ieee80211_send_probe_req( | ||
566 | sdata, NULL, | ||
567 | local->scan_req->ssids[i].ssid, | ||
568 | local->scan_req->ssids[i].ssid_len, | ||
569 | local->scan_req->ie, local->scan_req->ie_len); | ||
570 | |||
571 | /* | ||
572 | * After sending probe requests, wait for probe responses | ||
573 | * on the channel. | ||
574 | */ | ||
575 | next_delay = IEEE80211_CHANNEL_TIME; | ||
576 | local->scan_state = SCAN_SET_CHANNEL; | ||
577 | break; | 597 | break; |
578 | } | 598 | } |
579 | 599 | ||