diff options
Diffstat (limited to 'net/mac80211/scan.c')
-rw-r--r-- | net/mac80211/scan.c | 375 |
1 files changed, 243 insertions, 132 deletions
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index 2a8d09ad17ff..039901109fa1 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -18,7 +18,6 @@ | |||
18 | #include <linux/if_arp.h> | 18 | #include <linux/if_arp.h> |
19 | #include <linux/rtnetlink.h> | 19 | #include <linux/rtnetlink.h> |
20 | #include <net/mac80211.h> | 20 | #include <net/mac80211.h> |
21 | #include <net/iw_handler.h> | ||
22 | 21 | ||
23 | #include "ieee80211_i.h" | 22 | #include "ieee80211_i.h" |
24 | #include "driver-ops.h" | 23 | #include "driver-ops.h" |
@@ -26,7 +25,7 @@ | |||
26 | 25 | ||
27 | #define IEEE80211_PROBE_DELAY (HZ / 33) | 26 | #define IEEE80211_PROBE_DELAY (HZ / 33) |
28 | #define IEEE80211_CHANNEL_TIME (HZ / 33) | 27 | #define IEEE80211_CHANNEL_TIME (HZ / 33) |
29 | #define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 5) | 28 | #define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 8) |
30 | 29 | ||
31 | struct ieee80211_bss * | 30 | struct ieee80211_bss * |
32 | ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, | 31 | ieee80211_rx_bss_get(struct ieee80211_local *local, u8 *bssid, int freq, |
@@ -121,23 +120,10 @@ ieee80211_bss_info_update(struct ieee80211_local *local, | |||
121 | return bss; | 120 | return bss; |
122 | } | 121 | } |
123 | 122 | ||
124 | void ieee80211_rx_bss_remove(struct ieee80211_sub_if_data *sdata, u8 *bssid, | ||
125 | int freq, u8 *ssid, u8 ssid_len) | ||
126 | { | ||
127 | struct ieee80211_bss *bss; | ||
128 | struct ieee80211_local *local = sdata->local; | ||
129 | |||
130 | bss = ieee80211_rx_bss_get(local, bssid, freq, ssid, ssid_len); | ||
131 | if (bss) { | ||
132 | cfg80211_unlink_bss(local->hw.wiphy, (void *)bss); | ||
133 | ieee80211_rx_bss_put(local, bss); | ||
134 | } | ||
135 | } | ||
136 | |||
137 | ieee80211_rx_result | 123 | ieee80211_rx_result |
138 | ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb, | 124 | ieee80211_scan_rx(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb) |
139 | struct ieee80211_rx_status *rx_status) | ||
140 | { | 125 | { |
126 | struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb); | ||
141 | struct ieee80211_mgmt *mgmt; | 127 | struct ieee80211_mgmt *mgmt; |
142 | struct ieee80211_bss *bss; | 128 | struct ieee80211_bss *bss; |
143 | u8 *elements; | 129 | u8 *elements; |
@@ -278,7 +264,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
278 | 264 | ||
279 | mutex_lock(&local->scan_mtx); | 265 | mutex_lock(&local->scan_mtx); |
280 | 266 | ||
281 | if (WARN_ON(!local->hw_scanning && !local->sw_scanning)) { | 267 | if (WARN_ON(!local->scanning)) { |
282 | mutex_unlock(&local->scan_mtx); | 268 | mutex_unlock(&local->scan_mtx); |
283 | return; | 269 | return; |
284 | } | 270 | } |
@@ -288,16 +274,16 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
288 | return; | 274 | return; |
289 | } | 275 | } |
290 | 276 | ||
291 | if (local->hw_scanning) | 277 | if (test_bit(SCAN_HW_SCANNING, &local->scanning)) |
292 | ieee80211_restore_scan_ies(local); | 278 | ieee80211_restore_scan_ies(local); |
293 | 279 | ||
294 | if (local->scan_req != &local->int_scan_req) | 280 | if (local->scan_req != local->int_scan_req) |
295 | cfg80211_scan_done(local->scan_req, aborted); | 281 | cfg80211_scan_done(local->scan_req, aborted); |
296 | local->scan_req = NULL; | 282 | local->scan_req = NULL; |
283 | local->scan_sdata = NULL; | ||
297 | 284 | ||
298 | was_hw_scan = local->hw_scanning; | 285 | was_hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning); |
299 | local->hw_scanning = false; | 286 | local->scanning = 0; |
300 | local->sw_scanning = false; | ||
301 | local->scan_channel = NULL; | 287 | local->scan_channel = NULL; |
302 | 288 | ||
303 | /* we only have to protect scan_req and hw/sw scan */ | 289 | /* we only have to protect scan_req and hw/sw scan */ |
@@ -307,16 +293,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
307 | if (was_hw_scan) | 293 | if (was_hw_scan) |
308 | goto done; | 294 | goto done; |
309 | 295 | ||
310 | netif_tx_lock_bh(local->mdev); | 296 | ieee80211_configure_filter(local); |
311 | netif_addr_lock(local->mdev); | ||
312 | local->filter_flags &= ~FIF_BCN_PRBRESP_PROMISC; | ||
313 | drv_configure_filter(local, FIF_BCN_PRBRESP_PROMISC, | ||
314 | &local->filter_flags, | ||
315 | local->mdev->mc_count, | ||
316 | local->mdev->mc_list); | ||
317 | |||
318 | netif_addr_unlock(local->mdev); | ||
319 | netif_tx_unlock_bh(local->mdev); | ||
320 | 297 | ||
321 | drv_sw_scan_complete(local); | 298 | drv_sw_scan_complete(local); |
322 | 299 | ||
@@ -327,7 +304,7 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted) | |||
327 | 304 | ||
328 | /* Tell AP we're back */ | 305 | /* Tell AP we're back */ |
329 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 306 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
330 | if (sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED) { | 307 | if (sdata->u.mgd.associated) { |
331 | ieee80211_scan_ps_disable(sdata); | 308 | ieee80211_scan_ps_disable(sdata); |
332 | netif_tx_wake_all_queues(sdata->dev); | 309 | netif_tx_wake_all_queues(sdata->dev); |
333 | } | 310 | } |
@@ -382,30 +359,24 @@ static int ieee80211_start_sw_scan(struct ieee80211_local *local) | |||
382 | ieee80211_bss_info_change_notify( | 359 | ieee80211_bss_info_change_notify( |
383 | sdata, BSS_CHANGED_BEACON_ENABLED); | 360 | sdata, BSS_CHANGED_BEACON_ENABLED); |
384 | 361 | ||
385 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 362 | /* |
386 | if (sdata->u.mgd.flags & IEEE80211_STA_ASSOCIATED) { | 363 | * only handle non-STA interfaces here, STA interfaces |
387 | netif_tx_stop_all_queues(sdata->dev); | 364 | * are handled in the scan state machine |
388 | ieee80211_scan_ps_enable(sdata); | 365 | */ |
389 | } | 366 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
390 | } else | ||
391 | netif_tx_stop_all_queues(sdata->dev); | 367 | netif_tx_stop_all_queues(sdata->dev); |
392 | } | 368 | } |
393 | mutex_unlock(&local->iflist_mtx); | 369 | mutex_unlock(&local->iflist_mtx); |
394 | 370 | ||
395 | local->scan_state = SCAN_SET_CHANNEL; | 371 | local->next_scan_state = SCAN_DECISION; |
396 | local->scan_channel_idx = 0; | 372 | local->scan_channel_idx = 0; |
397 | 373 | ||
398 | netif_addr_lock_bh(local->mdev); | 374 | ieee80211_configure_filter(local); |
399 | local->filter_flags |= FIF_BCN_PRBRESP_PROMISC; | ||
400 | drv_configure_filter(local, FIF_BCN_PRBRESP_PROMISC, | ||
401 | &local->filter_flags, | ||
402 | local->mdev->mc_count, | ||
403 | local->mdev->mc_list); | ||
404 | netif_addr_unlock_bh(local->mdev); | ||
405 | 375 | ||
406 | /* TODO: start scan as soon as all nullfunc frames are ACKed */ | 376 | /* TODO: start scan as soon as all nullfunc frames are ACKed */ |
407 | queue_delayed_work(local->hw.workqueue, &local->scan_work, | 377 | ieee80211_queue_delayed_work(&local->hw, |
408 | IEEE80211_CHANNEL_TIME); | 378 | &local->scan_work, |
379 | IEEE80211_CHANNEL_TIME); | ||
409 | 380 | ||
410 | return 0; | 381 | return 0; |
411 | } | 382 | } |
@@ -441,20 +412,18 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
441 | local->scan_req = req; | 412 | local->scan_req = req; |
442 | local->scan_sdata = sdata; | 413 | local->scan_sdata = sdata; |
443 | 414 | ||
444 | if (req != &local->int_scan_req && | 415 | if (req != local->int_scan_req && |
445 | sdata->vif.type == NL80211_IFTYPE_STATION && | 416 | sdata->vif.type == NL80211_IFTYPE_STATION && |
446 | (ifmgd->state == IEEE80211_STA_MLME_DIRECT_PROBE || | 417 | !list_empty(&ifmgd->work_list)) { |
447 | ifmgd->state == IEEE80211_STA_MLME_AUTHENTICATE || | 418 | /* actually wait for the work it's doing to finish/time out */ |
448 | ifmgd->state == IEEE80211_STA_MLME_ASSOCIATE)) { | ||
449 | /* actually wait for the assoc to finish/time out */ | ||
450 | set_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request); | 419 | set_bit(IEEE80211_STA_REQ_SCAN, &ifmgd->request); |
451 | return 0; | 420 | return 0; |
452 | } | 421 | } |
453 | 422 | ||
454 | if (local->ops->hw_scan) | 423 | if (local->ops->hw_scan) |
455 | local->hw_scanning = true; | 424 | __set_bit(SCAN_HW_SCANNING, &local->scanning); |
456 | else | 425 | else |
457 | local->sw_scanning = true; | 426 | __set_bit(SCAN_SW_SCANNING, &local->scanning); |
458 | /* | 427 | /* |
459 | * Kicking off the scan need not be protected, | 428 | * Kicking off the scan need not be protected, |
460 | * only the scan variable stuff, since now | 429 | * only the scan variable stuff, since now |
@@ -477,11 +446,9 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
477 | mutex_lock(&local->scan_mtx); | 446 | mutex_lock(&local->scan_mtx); |
478 | 447 | ||
479 | if (rc) { | 448 | if (rc) { |
480 | if (local->ops->hw_scan) { | 449 | if (local->ops->hw_scan) |
481 | local->hw_scanning = false; | ||
482 | ieee80211_restore_scan_ies(local); | 450 | ieee80211_restore_scan_ies(local); |
483 | } else | 451 | local->scanning = 0; |
484 | local->sw_scanning = false; | ||
485 | 452 | ||
486 | ieee80211_recalc_idle(local); | 453 | ieee80211_recalc_idle(local); |
487 | 454 | ||
@@ -492,13 +459,195 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata, | |||
492 | return rc; | 459 | return rc; |
493 | } | 460 | } |
494 | 461 | ||
462 | static int ieee80211_scan_state_decision(struct ieee80211_local *local, | ||
463 | unsigned long *next_delay) | ||
464 | { | ||
465 | bool associated = false; | ||
466 | struct ieee80211_sub_if_data *sdata; | ||
467 | |||
468 | /* if no more bands/channels left, complete scan and advance to the idle state */ | ||
469 | if (local->scan_channel_idx >= local->scan_req->n_channels) { | ||
470 | ieee80211_scan_completed(&local->hw, false); | ||
471 | return 1; | ||
472 | } | ||
473 | |||
474 | /* check if at least one STA interface is associated */ | ||
475 | mutex_lock(&local->iflist_mtx); | ||
476 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
477 | if (!netif_running(sdata->dev)) | ||
478 | continue; | ||
479 | |||
480 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
481 | if (sdata->u.mgd.associated) { | ||
482 | associated = true; | ||
483 | break; | ||
484 | } | ||
485 | } | ||
486 | } | ||
487 | mutex_unlock(&local->iflist_mtx); | ||
488 | |||
489 | if (local->scan_channel) { | ||
490 | /* | ||
491 | * we're currently scanning a different channel, let's | ||
492 | * switch back to the operating channel now if at least | ||
493 | * one interface is associated. Otherwise just scan the | ||
494 | * next channel | ||
495 | */ | ||
496 | if (associated) | ||
497 | local->next_scan_state = SCAN_ENTER_OPER_CHANNEL; | ||
498 | else | ||
499 | local->next_scan_state = SCAN_SET_CHANNEL; | ||
500 | } else { | ||
501 | /* | ||
502 | * we're on the operating channel currently, let's | ||
503 | * leave that channel now to scan another one | ||
504 | */ | ||
505 | local->next_scan_state = SCAN_LEAVE_OPER_CHANNEL; | ||
506 | } | ||
507 | |||
508 | *next_delay = 0; | ||
509 | return 0; | ||
510 | } | ||
511 | |||
512 | static void ieee80211_scan_state_leave_oper_channel(struct ieee80211_local *local, | ||
513 | unsigned long *next_delay) | ||
514 | { | ||
515 | struct ieee80211_sub_if_data *sdata; | ||
516 | |||
517 | /* | ||
518 | * notify the AP about us leaving the channel and stop all STA interfaces | ||
519 | */ | ||
520 | mutex_lock(&local->iflist_mtx); | ||
521 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
522 | if (!netif_running(sdata->dev)) | ||
523 | continue; | ||
524 | |||
525 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
526 | netif_tx_stop_all_queues(sdata->dev); | ||
527 | if (sdata->u.mgd.associated) | ||
528 | ieee80211_scan_ps_enable(sdata); | ||
529 | } | ||
530 | } | ||
531 | mutex_unlock(&local->iflist_mtx); | ||
532 | |||
533 | __set_bit(SCAN_OFF_CHANNEL, &local->scanning); | ||
534 | |||
535 | /* advance to the next channel to be scanned */ | ||
536 | *next_delay = HZ / 10; | ||
537 | local->next_scan_state = SCAN_SET_CHANNEL; | ||
538 | } | ||
539 | |||
540 | static void ieee80211_scan_state_enter_oper_channel(struct ieee80211_local *local, | ||
541 | unsigned long *next_delay) | ||
542 | { | ||
543 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | ||
544 | |||
545 | /* switch back to the operating channel */ | ||
546 | local->scan_channel = NULL; | ||
547 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | ||
548 | |||
549 | /* | ||
550 | * notify the AP about us being back and restart all STA interfaces | ||
551 | */ | ||
552 | mutex_lock(&local->iflist_mtx); | ||
553 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
554 | if (!netif_running(sdata->dev)) | ||
555 | continue; | ||
556 | |||
557 | /* Tell AP we're back */ | ||
558 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | ||
559 | if (sdata->u.mgd.associated) | ||
560 | ieee80211_scan_ps_disable(sdata); | ||
561 | netif_tx_wake_all_queues(sdata->dev); | ||
562 | } | ||
563 | } | ||
564 | mutex_unlock(&local->iflist_mtx); | ||
565 | |||
566 | __clear_bit(SCAN_OFF_CHANNEL, &local->scanning); | ||
567 | |||
568 | *next_delay = HZ / 5; | ||
569 | local->next_scan_state = SCAN_DECISION; | ||
570 | } | ||
571 | |||
572 | static void ieee80211_scan_state_set_channel(struct ieee80211_local *local, | ||
573 | unsigned long *next_delay) | ||
574 | { | ||
575 | int skip; | ||
576 | struct ieee80211_channel *chan; | ||
577 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | ||
578 | |||
579 | skip = 0; | ||
580 | chan = local->scan_req->channels[local->scan_channel_idx]; | ||
581 | |||
582 | if (chan->flags & IEEE80211_CHAN_DISABLED || | ||
583 | (sdata->vif.type == NL80211_IFTYPE_ADHOC && | ||
584 | chan->flags & IEEE80211_CHAN_NO_IBSS)) | ||
585 | skip = 1; | ||
586 | |||
587 | if (!skip) { | ||
588 | local->scan_channel = chan; | ||
589 | if (ieee80211_hw_config(local, | ||
590 | IEEE80211_CONF_CHANGE_CHANNEL)) | ||
591 | skip = 1; | ||
592 | } | ||
593 | |||
594 | /* advance state machine to next channel/band */ | ||
595 | local->scan_channel_idx++; | ||
596 | |||
597 | if (skip) { | ||
598 | /* if we skip this channel return to the decision state */ | ||
599 | local->next_scan_state = SCAN_DECISION; | ||
600 | return; | ||
601 | } | ||
602 | |||
603 | /* | ||
604 | * Probe delay is used to update the NAV, cf. 11.1.3.2.2 | ||
605 | * (which unfortunately doesn't say _why_ step a) is done, | ||
606 | * but it waits for the probe delay or until a frame is | ||
607 | * received - and the received frame would update the NAV). | ||
608 | * For now, we do not support waiting until a frame is | ||
609 | * received. | ||
610 | * | ||
611 | * In any case, it is not necessary for a passive scan. | ||
612 | */ | ||
613 | if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN || | ||
614 | !local->scan_req->n_ssids) { | ||
615 | *next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; | ||
616 | local->next_scan_state = SCAN_DECISION; | ||
617 | return; | ||
618 | } | ||
619 | |||
620 | /* active scan, send probes */ | ||
621 | *next_delay = IEEE80211_PROBE_DELAY; | ||
622 | local->next_scan_state = SCAN_SEND_PROBE; | ||
623 | } | ||
624 | |||
625 | static void ieee80211_scan_state_send_probe(struct ieee80211_local *local, | ||
626 | unsigned long *next_delay) | ||
627 | { | ||
628 | int i; | ||
629 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | ||
630 | |||
631 | for (i = 0; i < local->scan_req->n_ssids; i++) | ||
632 | ieee80211_send_probe_req( | ||
633 | sdata, NULL, | ||
634 | local->scan_req->ssids[i].ssid, | ||
635 | local->scan_req->ssids[i].ssid_len, | ||
636 | local->scan_req->ie, local->scan_req->ie_len); | ||
637 | |||
638 | /* | ||
639 | * After sending probe requests, wait for probe responses | ||
640 | * on the channel. | ||
641 | */ | ||
642 | *next_delay = IEEE80211_CHANNEL_TIME; | ||
643 | local->next_scan_state = SCAN_DECISION; | ||
644 | } | ||
645 | |||
495 | void ieee80211_scan_work(struct work_struct *work) | 646 | void ieee80211_scan_work(struct work_struct *work) |
496 | { | 647 | { |
497 | struct ieee80211_local *local = | 648 | struct ieee80211_local *local = |
498 | container_of(work, struct ieee80211_local, scan_work.work); | 649 | container_of(work, struct ieee80211_local, scan_work.work); |
499 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; | 650 | struct ieee80211_sub_if_data *sdata = local->scan_sdata; |
500 | struct ieee80211_channel *chan; | ||
501 | int skip, i; | ||
502 | unsigned long next_delay = 0; | 651 | unsigned long next_delay = 0; |
503 | 652 | ||
504 | mutex_lock(&local->scan_mtx); | 653 | mutex_lock(&local->scan_mtx); |
@@ -507,11 +656,12 @@ void ieee80211_scan_work(struct work_struct *work) | |||
507 | return; | 656 | return; |
508 | } | 657 | } |
509 | 658 | ||
510 | if (local->scan_req && !(local->sw_scanning || local->hw_scanning)) { | 659 | if (local->scan_req && !local->scanning) { |
511 | struct cfg80211_scan_request *req = local->scan_req; | 660 | struct cfg80211_scan_request *req = local->scan_req; |
512 | int rc; | 661 | int rc; |
513 | 662 | ||
514 | local->scan_req = NULL; | 663 | local->scan_req = NULL; |
664 | local->scan_sdata = NULL; | ||
515 | 665 | ||
516 | rc = __ieee80211_start_scan(sdata, req); | 666 | rc = __ieee80211_start_scan(sdata, req); |
517 | mutex_unlock(&local->scan_mtx); | 667 | mutex_unlock(&local->scan_mtx); |
@@ -531,72 +681,32 @@ void ieee80211_scan_work(struct work_struct *work) | |||
531 | return; | 681 | return; |
532 | } | 682 | } |
533 | 683 | ||
534 | switch (local->scan_state) { | 684 | /* |
535 | case SCAN_SET_CHANNEL: | 685 | * as long as no delay is required advance immediately |
536 | /* if no more bands/channels left, complete scan */ | 686 | * without scheduling a new work |
537 | if (local->scan_channel_idx >= local->scan_req->n_channels) { | 687 | */ |
538 | ieee80211_scan_completed(&local->hw, false); | 688 | do { |
539 | return; | 689 | switch (local->next_scan_state) { |
540 | } | 690 | case SCAN_DECISION: |
541 | skip = 0; | 691 | if (ieee80211_scan_state_decision(local, &next_delay)) |
542 | chan = local->scan_req->channels[local->scan_channel_idx]; | 692 | return; |
543 | |||
544 | if (chan->flags & IEEE80211_CHAN_DISABLED || | ||
545 | (sdata->vif.type == NL80211_IFTYPE_ADHOC && | ||
546 | chan->flags & IEEE80211_CHAN_NO_IBSS)) | ||
547 | skip = 1; | ||
548 | |||
549 | if (!skip) { | ||
550 | local->scan_channel = chan; | ||
551 | if (ieee80211_hw_config(local, | ||
552 | IEEE80211_CONF_CHANGE_CHANNEL)) | ||
553 | skip = 1; | ||
554 | } | ||
555 | |||
556 | /* advance state machine to next channel/band */ | ||
557 | local->scan_channel_idx++; | ||
558 | |||
559 | if (skip) | ||
560 | break; | 693 | break; |
561 | 694 | case SCAN_SET_CHANNEL: | |
562 | /* | 695 | ieee80211_scan_state_set_channel(local, &next_delay); |
563 | * Probe delay is used to update the NAV, cf. 11.1.3.2.2 | 696 | break; |
564 | * (which unfortunately doesn't say _why_ step a) is done, | 697 | case SCAN_SEND_PROBE: |
565 | * but it waits for the probe delay or until a frame is | 698 | ieee80211_scan_state_send_probe(local, &next_delay); |
566 | * received - and the received frame would update the NAV). | 699 | break; |
567 | * For now, we do not support waiting until a frame is | 700 | case SCAN_LEAVE_OPER_CHANNEL: |
568 | * received. | 701 | ieee80211_scan_state_leave_oper_channel(local, &next_delay); |
569 | * | 702 | break; |
570 | * In any case, it is not necessary for a passive scan. | 703 | case SCAN_ENTER_OPER_CHANNEL: |
571 | */ | 704 | ieee80211_scan_state_enter_oper_channel(local, &next_delay); |
572 | if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN || | ||
573 | !local->scan_req->n_ssids) { | ||
574 | next_delay = IEEE80211_PASSIVE_CHANNEL_TIME; | ||
575 | break; | 705 | break; |
576 | } | 706 | } |
707 | } while (next_delay == 0); | ||
577 | 708 | ||
578 | next_delay = IEEE80211_PROBE_DELAY; | 709 | ieee80211_queue_delayed_work(&local->hw, &local->scan_work, next_delay); |
579 | local->scan_state = SCAN_SEND_PROBE; | ||
580 | break; | ||
581 | case SCAN_SEND_PROBE: | ||
582 | for (i = 0; i < local->scan_req->n_ssids; i++) | ||
583 | ieee80211_send_probe_req( | ||
584 | sdata, NULL, | ||
585 | local->scan_req->ssids[i].ssid, | ||
586 | local->scan_req->ssids[i].ssid_len, | ||
587 | local->scan_req->ie, local->scan_req->ie_len); | ||
588 | |||
589 | /* | ||
590 | * After sending probe requests, wait for probe responses | ||
591 | * on the channel. | ||
592 | */ | ||
593 | next_delay = IEEE80211_CHANNEL_TIME; | ||
594 | local->scan_state = SCAN_SET_CHANNEL; | ||
595 | break; | ||
596 | } | ||
597 | |||
598 | queue_delayed_work(local->hw.workqueue, &local->scan_work, | ||
599 | next_delay); | ||
600 | } | 710 | } |
601 | 711 | ||
602 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, | 712 | int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata, |
@@ -623,10 +733,10 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, | |||
623 | if (local->scan_req) | 733 | if (local->scan_req) |
624 | goto unlock; | 734 | goto unlock; |
625 | 735 | ||
626 | memcpy(local->int_scan_req.ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN); | 736 | memcpy(local->int_scan_req->ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN); |
627 | local->int_scan_req.ssids[0].ssid_len = ssid_len; | 737 | local->int_scan_req->ssids[0].ssid_len = ssid_len; |
628 | 738 | ||
629 | ret = __ieee80211_start_scan(sdata, &sdata->local->int_scan_req); | 739 | ret = __ieee80211_start_scan(sdata, sdata->local->int_scan_req); |
630 | unlock: | 740 | unlock: |
631 | mutex_unlock(&local->scan_mtx); | 741 | mutex_unlock(&local->scan_mtx); |
632 | return ret; | 742 | return ret; |
@@ -634,7 +744,7 @@ int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata, | |||
634 | 744 | ||
635 | void ieee80211_scan_cancel(struct ieee80211_local *local) | 745 | void ieee80211_scan_cancel(struct ieee80211_local *local) |
636 | { | 746 | { |
637 | bool swscan; | 747 | bool abortscan; |
638 | 748 | ||
639 | cancel_delayed_work_sync(&local->scan_work); | 749 | cancel_delayed_work_sync(&local->scan_work); |
640 | 750 | ||
@@ -643,9 +753,10 @@ void ieee80211_scan_cancel(struct ieee80211_local *local) | |||
643 | * queued -- mostly at suspend under RTNL. | 753 | * queued -- mostly at suspend under RTNL. |
644 | */ | 754 | */ |
645 | mutex_lock(&local->scan_mtx); | 755 | mutex_lock(&local->scan_mtx); |
646 | swscan = local->sw_scanning; | 756 | abortscan = test_bit(SCAN_SW_SCANNING, &local->scanning) || |
757 | (!local->scanning && local->scan_req); | ||
647 | mutex_unlock(&local->scan_mtx); | 758 | mutex_unlock(&local->scan_mtx); |
648 | 759 | ||
649 | if (swscan) | 760 | if (abortscan) |
650 | ieee80211_scan_completed(&local->hw, true); | 761 | ieee80211_scan_completed(&local->hw, true); |
651 | } | 762 | } |