diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-scan.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-scan.c | 54 |
1 files changed, 38 insertions, 16 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index 9ab0e412bf10..741e65ec8301 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -470,6 +470,8 @@ EXPORT_SYMBOL(iwl_init_scan_params); | |||
470 | 470 | ||
471 | static int iwl_scan_initiate(struct iwl_priv *priv) | 471 | static int iwl_scan_initiate(struct iwl_priv *priv) |
472 | { | 472 | { |
473 | WARN_ON(!mutex_is_locked(&priv->mutex)); | ||
474 | |||
473 | IWL_DEBUG_INFO(priv, "Starting scan...\n"); | 475 | IWL_DEBUG_INFO(priv, "Starting scan...\n"); |
474 | set_bit(STATUS_SCANNING, &priv->status); | 476 | set_bit(STATUS_SCANNING, &priv->status); |
475 | priv->is_internal_short_scan = false; | 477 | priv->is_internal_short_scan = false; |
@@ -547,24 +549,31 @@ EXPORT_SYMBOL(iwl_mac_hw_scan); | |||
547 | * internal short scan, this function should only been called while associated. | 549 | * internal short scan, this function should only been called while associated. |
548 | * It will reset and tune the radio to prevent possible RF related problem | 550 | * It will reset and tune the radio to prevent possible RF related problem |
549 | */ | 551 | */ |
550 | int iwl_internal_short_hw_scan(struct iwl_priv *priv) | 552 | void iwl_internal_short_hw_scan(struct iwl_priv *priv) |
551 | { | 553 | { |
552 | int ret = 0; | 554 | queue_work(priv->workqueue, &priv->start_internal_scan); |
555 | } | ||
556 | |||
557 | static void iwl_bg_start_internal_scan(struct work_struct *work) | ||
558 | { | ||
559 | struct iwl_priv *priv = | ||
560 | container_of(work, struct iwl_priv, start_internal_scan); | ||
561 | |||
562 | mutex_lock(&priv->mutex); | ||
553 | 563 | ||
554 | if (!iwl_is_ready_rf(priv)) { | 564 | if (!iwl_is_ready_rf(priv)) { |
555 | ret = -EIO; | ||
556 | IWL_DEBUG_SCAN(priv, "not ready or exit pending\n"); | 565 | IWL_DEBUG_SCAN(priv, "not ready or exit pending\n"); |
557 | goto out; | 566 | goto unlock; |
558 | } | 567 | } |
568 | |||
559 | if (test_bit(STATUS_SCANNING, &priv->status)) { | 569 | if (test_bit(STATUS_SCANNING, &priv->status)) { |
560 | IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); | 570 | IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); |
561 | ret = -EAGAIN; | 571 | goto unlock; |
562 | goto out; | ||
563 | } | 572 | } |
573 | |||
564 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { | 574 | if (test_bit(STATUS_SCAN_ABORTING, &priv->status)) { |
565 | IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n"); | 575 | IWL_DEBUG_SCAN(priv, "Scan request while abort pending\n"); |
566 | ret = -EAGAIN; | 576 | goto unlock; |
567 | goto out; | ||
568 | } | 577 | } |
569 | 578 | ||
570 | priv->scan_bands = 0; | 579 | priv->scan_bands = 0; |
@@ -577,9 +586,8 @@ int iwl_internal_short_hw_scan(struct iwl_priv *priv) | |||
577 | set_bit(STATUS_SCANNING, &priv->status); | 586 | set_bit(STATUS_SCANNING, &priv->status); |
578 | priv->is_internal_short_scan = true; | 587 | priv->is_internal_short_scan = true; |
579 | queue_work(priv->workqueue, &priv->request_scan); | 588 | queue_work(priv->workqueue, &priv->request_scan); |
580 | 589 | unlock: | |
581 | out: | 590 | mutex_unlock(&priv->mutex); |
582 | return ret; | ||
583 | } | 591 | } |
584 | EXPORT_SYMBOL(iwl_internal_short_hw_scan); | 592 | EXPORT_SYMBOL(iwl_internal_short_hw_scan); |
585 | 593 | ||
@@ -805,16 +813,29 @@ static void iwl_bg_request_scan(struct work_struct *data) | |||
805 | rate = IWL_RATE_1M_PLCP; | 813 | rate = IWL_RATE_1M_PLCP; |
806 | rate_flags = RATE_MCS_CCK_MSK; | 814 | rate_flags = RATE_MCS_CCK_MSK; |
807 | } | 815 | } |
808 | scan->good_CRC_th = 0; | 816 | scan->good_CRC_th = IWL_GOOD_CRC_TH_DISABLED; |
809 | } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) { | 817 | } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) { |
810 | band = IEEE80211_BAND_5GHZ; | 818 | band = IEEE80211_BAND_5GHZ; |
811 | rate = IWL_RATE_6M_PLCP; | 819 | rate = IWL_RATE_6M_PLCP; |
812 | /* | 820 | /* |
813 | * If active scaning is requested but a certain channel | 821 | * If active scanning is requested but a certain channel is |
814 | * is marked passive, we can do active scanning if we | 822 | * marked passive, we can do active scanning if we detect |
815 | * detect transmissions. | 823 | * transmissions. |
824 | * | ||
825 | * There is an issue with some firmware versions that triggers | ||
826 | * a sysassert on a "good CRC threshold" of zero (== disabled), | ||
827 | * on a radar channel even though this means that we should NOT | ||
828 | * send probes. | ||
829 | * | ||
830 | * The "good CRC threshold" is the number of frames that we | ||
831 | * need to receive during our dwell time on a channel before | ||
832 | * sending out probes -- setting this to a huge value will | ||
833 | * mean we never reach it, but at the same time work around | ||
834 | * the aforementioned issue. Thus use IWL_GOOD_CRC_TH_NEVER | ||
835 | * here instead of IWL_GOOD_CRC_TH_DISABLED. | ||
816 | */ | 836 | */ |
817 | scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0; | 837 | scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH_DEFAULT : |
838 | IWL_GOOD_CRC_TH_NEVER; | ||
818 | 839 | ||
819 | /* Force use of chains B and C (0x6) for scan Rx for 4965 | 840 | /* Force use of chains B and C (0x6) for scan Rx for 4965 |
820 | * Avoid A (0x1) because of its off-channel reception on A-band. | 841 | * Avoid A (0x1) because of its off-channel reception on A-band. |
@@ -965,6 +986,7 @@ void iwl_setup_scan_deferred_work(struct iwl_priv *priv) | |||
965 | INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); | 986 | INIT_WORK(&priv->scan_completed, iwl_bg_scan_completed); |
966 | INIT_WORK(&priv->request_scan, iwl_bg_request_scan); | 987 | INIT_WORK(&priv->request_scan, iwl_bg_request_scan); |
967 | INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan); | 988 | INIT_WORK(&priv->abort_scan, iwl_bg_abort_scan); |
989 | INIT_WORK(&priv->start_internal_scan, iwl_bg_start_internal_scan); | ||
968 | INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check); | 990 | INIT_DELAYED_WORK(&priv->scan_check, iwl_bg_scan_check); |
969 | } | 991 | } |
970 | EXPORT_SYMBOL(iwl_setup_scan_deferred_work); | 992 | EXPORT_SYMBOL(iwl_setup_scan_deferred_work); |