aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-scan.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-scan.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c214
1 files changed, 54 insertions, 160 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 6330b91e37ce..e26875dbe859 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -445,13 +445,6 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
445 unsigned long flags; 445 unsigned long flags;
446 struct iwl_priv *priv = hw->priv; 446 struct iwl_priv *priv = hw->priv;
447 int ret; 447 int ret;
448 u8 *ssid = NULL;
449 size_t ssid_len = 0;
450
451 if (req->n_ssids) {
452 ssid = req->ssids[0].ssid;
453 ssid_len = req->ssids[0].ssid_len;
454 }
455 448
456 IWL_DEBUG_MAC80211(priv, "enter\n"); 449 IWL_DEBUG_MAC80211(priv, "enter\n");
457 450
@@ -485,13 +478,7 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
485 goto out_unlock; 478 goto out_unlock;
486 } 479 }
487 480
488 if (ssid_len) { 481 priv->scan_request = req;
489 priv->one_direct_scan = 1;
490 priv->direct_ssid_len = ssid_len;
491 memcpy(priv->direct_ssid, ssid, priv->direct_ssid_len);
492 } else {
493 priv->one_direct_scan = 0;
494 }
495 482
496 ret = iwl_scan_initiate(priv); 483 ret = iwl_scan_initiate(priv);
497 484
@@ -530,73 +517,14 @@ void iwl_bg_scan_check(struct work_struct *data)
530EXPORT_SYMBOL(iwl_bg_scan_check); 517EXPORT_SYMBOL(iwl_bg_scan_check);
531 518
532/** 519/**
533 * iwl_supported_rate_to_ie - fill in the supported rate in IE field
534 *
535 * return : set the bit for each supported rate insert in ie
536 */
537static u16 iwl_supported_rate_to_ie(u8 *ie, u16 supported_rate,
538 u16 basic_rate, int *left)
539{
540 u16 ret_rates = 0, bit;
541 int i;
542 u8 *cnt = ie;
543 u8 *rates = ie + 1;
544
545 for (bit = 1, i = 0; i < IWL_RATE_COUNT; i++, bit <<= 1) {
546 if (bit & supported_rate) {
547 ret_rates |= bit;
548 rates[*cnt] = iwl_rates[i].ieee |
549 ((bit & basic_rate) ? 0x80 : 0x00);
550 (*cnt)++;
551 (*left)--;
552 if ((*left <= 0) ||
553 (*cnt >= IWL_SUPPORTED_RATES_IE_LEN))
554 break;
555 }
556 }
557
558 return ret_rates;
559}
560
561
562static void iwl_ht_cap_to_ie(const struct ieee80211_supported_band *sband,
563 u8 *pos, int *left)
564{
565 struct ieee80211_ht_cap *ht_cap;
566
567 if (!sband || !sband->ht_cap.ht_supported)
568 return;
569
570 if (*left < sizeof(struct ieee80211_ht_cap))
571 return;
572
573 *pos++ = sizeof(struct ieee80211_ht_cap);
574 ht_cap = (struct ieee80211_ht_cap *) pos;
575
576 ht_cap->cap_info = cpu_to_le16(sband->ht_cap.cap);
577 memcpy(&ht_cap->mcs, &sband->ht_cap.mcs, 16);
578 ht_cap->ampdu_params_info =
579 (sband->ht_cap.ampdu_factor & IEEE80211_HT_AMPDU_PARM_FACTOR) |
580 ((sband->ht_cap.ampdu_density << 2) &
581 IEEE80211_HT_AMPDU_PARM_DENSITY);
582 *left -= sizeof(struct ieee80211_ht_cap);
583}
584
585/**
586 * iwl_fill_probe_req - fill in all required fields and IE for probe request 520 * iwl_fill_probe_req - fill in all required fields and IE for probe request
587 */ 521 */
588 522
589u16 iwl_fill_probe_req(struct iwl_priv *priv, 523u16 iwl_fill_probe_req(struct iwl_priv *priv, struct ieee80211_mgmt *frame,
590 enum ieee80211_band band, 524 const u8 *ies, int ie_len, int left)
591 struct ieee80211_mgmt *frame,
592 int left)
593{ 525{
594 int len = 0; 526 int len = 0;
595 u8 *pos = NULL; 527 u8 *pos = NULL;
596 u16 active_rates, ret_rates, cck_rates, active_rate_basic;
597 const struct ieee80211_supported_band *sband =
598 iwl_get_hw_mode(priv, band);
599
600 528
601 /* Make sure there is enough space for the probe request, 529 /* Make sure there is enough space for the probe request,
602 * two mandatory IEs and the data */ 530 * two mandatory IEs and the data */
@@ -624,62 +552,12 @@ u16 iwl_fill_probe_req(struct iwl_priv *priv,
624 552
625 len += 2; 553 len += 2;
626 554
627 /* fill in supported rate */ 555 if (WARN_ON(left < ie_len))
628 left -= 2; 556 return len;
629 if (left < 0)
630 return 0;
631
632 *pos++ = WLAN_EID_SUPP_RATES;
633 *pos = 0;
634
635 /* exclude 60M rate */
636 active_rates = priv->rates_mask;
637 active_rates &= ~IWL_RATE_60M_MASK;
638
639 active_rate_basic = active_rates & IWL_BASIC_RATES_MASK;
640
641 cck_rates = IWL_CCK_RATES_MASK & active_rates;
642 ret_rates = iwl_supported_rate_to_ie(pos, cck_rates,
643 active_rate_basic, &left);
644 active_rates &= ~ret_rates;
645
646 ret_rates = iwl_supported_rate_to_ie(pos, active_rates,
647 active_rate_basic, &left);
648 active_rates &= ~ret_rates;
649
650 len += 2 + *pos;
651 pos += (*pos) + 1;
652 557
653 if (active_rates == 0) 558 memcpy(pos, ies, ie_len);
654 goto fill_end; 559 len += ie_len;
655 560 left -= ie_len;
656 /* fill in supported extended rate */
657 /* ...next IE... */
658 left -= 2;
659 if (left < 0)
660 return 0;
661 /* ... fill it in... */
662 *pos++ = WLAN_EID_EXT_SUPP_RATES;
663 *pos = 0;
664 iwl_supported_rate_to_ie(pos, active_rates, active_rate_basic, &left);
665 if (*pos > 0) {
666 len += 2 + *pos;
667 pos += (*pos) + 1;
668 } else {
669 pos--;
670 }
671
672 fill_end:
673
674 left -= 2;
675 if (left < 0)
676 return 0;
677
678 *pos++ = WLAN_EID_HT_CAPABILITY;
679 *pos = 0;
680 iwl_ht_cap_to_ie(sband, pos, &left);
681 if (*pos > 0)
682 len += 2 + *pos;
683 561
684 return (u16)len; 562 return (u16)len;
685} 563}
@@ -699,11 +577,13 @@ static void iwl_bg_request_scan(struct work_struct *data)
699 int ret = 0; 577 int ret = 0;
700 u32 rate_flags = 0; 578 u32 rate_flags = 0;
701 u16 cmd_len; 579 u16 cmd_len;
580 u16 rx_chain = 0;
702 enum ieee80211_band band; 581 enum ieee80211_band band;
703 u8 n_probes = 2; 582 u8 n_probes = 0;
704 u8 rx_chain = priv->hw_params.valid_rx_ant; 583 u8 rx_ant = priv->hw_params.valid_rx_ant;
705 u8 rate; 584 u8 rate;
706 DECLARE_SSID_BUF(ssid); 585 bool is_active = false;
586 int chan_mod;
707 587
708 conf = ieee80211_get_hw_conf(priv->hw); 588 conf = ieee80211_get_hw_conf(priv->hw);
709 589
@@ -795,19 +675,25 @@ static void iwl_bg_request_scan(struct work_struct *data)
795 scan_suspend_time, interval); 675 scan_suspend_time, interval);
796 } 676 }
797 677
798 /* We should add the ability for user to lock to PASSIVE ONLY */ 678 if (priv->scan_request->n_ssids) {
799 if (priv->one_direct_scan) { 679 int i, p = 0;
800 IWL_DEBUG_SCAN(priv, "Start direct scan for '%s'\n", 680 IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
801 print_ssid(ssid, priv->direct_ssid, 681 for (i = 0; i < priv->scan_request->n_ssids; i++) {
802 priv->direct_ssid_len)); 682 /* always does wildcard anyway */
803 scan->direct_scan[0].id = WLAN_EID_SSID; 683 if (!priv->scan_request->ssids[i].ssid_len)
804 scan->direct_scan[0].len = priv->direct_ssid_len; 684 continue;
805 memcpy(scan->direct_scan[0].ssid, 685 scan->direct_scan[p].id = WLAN_EID_SSID;
806 priv->direct_ssid, priv->direct_ssid_len); 686 scan->direct_scan[p].len =
807 n_probes++; 687 priv->scan_request->ssids[i].ssid_len;
808 } else { 688 memcpy(scan->direct_scan[p].ssid,
809 IWL_DEBUG_SCAN(priv, "Start indirect scan.\n"); 689 priv->scan_request->ssids[i].ssid,
810 } 690 priv->scan_request->ssids[i].ssid_len);
691 n_probes++;
692 p++;
693 }
694 is_active = true;
695 } else
696 IWL_DEBUG_SCAN(priv, "Start passive scan.\n");
811 697
812 scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; 698 scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
813 scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id; 699 scan->tx_cmd.sta_id = priv->hw_params.bcast_sta_id;
@@ -817,7 +703,9 @@ static void iwl_bg_request_scan(struct work_struct *data)
817 if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) { 703 if (priv->scan_bands & BIT(IEEE80211_BAND_2GHZ)) {
818 band = IEEE80211_BAND_2GHZ; 704 band = IEEE80211_BAND_2GHZ;
819 scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK; 705 scan->flags = RXON_FLG_BAND_24G_MSK | RXON_FLG_AUTO_DETECT_MSK;
820 if (priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_PURE_40_MSK) { 706 chan_mod = le32_to_cpu(priv->active_rxon.flags & RXON_FLG_CHANNEL_MODE_MSK)
707 >> RXON_FLG_CHANNEL_MODE_POS;
708 if (chan_mod == CHANNEL_MODE_PURE_40) {
821 rate = IWL_RATE_6M_PLCP; 709 rate = IWL_RATE_6M_PLCP;
822 } else { 710 } else {
823 rate = IWL_RATE_1M_PLCP; 711 rate = IWL_RATE_1M_PLCP;
@@ -827,13 +715,18 @@ static void iwl_bg_request_scan(struct work_struct *data)
827 } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) { 715 } else if (priv->scan_bands & BIT(IEEE80211_BAND_5GHZ)) {
828 band = IEEE80211_BAND_5GHZ; 716 band = IEEE80211_BAND_5GHZ;
829 rate = IWL_RATE_6M_PLCP; 717 rate = IWL_RATE_6M_PLCP;
830 scan->good_CRC_th = IWL_GOOD_CRC_TH; 718 /*
719 * If active scaning is requested but a certain channel
720 * is marked passive, we can do active scanning if we
721 * detect transmissions.
722 */
723 scan->good_CRC_th = is_active ? IWL_GOOD_CRC_TH : 0;
831 724
832 /* Force use of chains B and C (0x6) for scan Rx for 4965 725 /* Force use of chains B and C (0x6) for scan Rx for 4965
833 * Avoid A (0x1) because of its off-channel reception on A-band. 726 * Avoid A (0x1) because of its off-channel reception on A-band.
834 */ 727 */
835 if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965) 728 if ((priv->hw_rev & CSR_HW_REV_TYPE_MSK) == CSR_HW_REV_TYPE_4965)
836 rx_chain = 0x6; 729 rx_ant = ANT_BC;
837 } else { 730 } else {
838 IWL_WARN(priv, "Invalid scan band count\n"); 731 IWL_WARN(priv, "Invalid scan band count\n");
839 goto done; 732 goto done;
@@ -845,26 +738,27 @@ static void iwl_bg_request_scan(struct work_struct *data)
845 scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags); 738 scan->tx_cmd.rate_n_flags = iwl_hw_set_rate_n_flags(rate, rate_flags);
846 739
847 /* MIMO is not used here, but value is required */ 740 /* MIMO is not used here, but value is required */
848 scan->rx_chain = RXON_RX_CHAIN_DRIVER_FORCE_MSK | 741 rx_chain |= ANT_ABC << RXON_RX_CHAIN_VALID_POS;
849 cpu_to_le16((0x7 << RXON_RX_CHAIN_VALID_POS) | 742 rx_chain |= ANT_ABC << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS;
850 (rx_chain << RXON_RX_CHAIN_FORCE_SEL_POS) | 743 rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS;
851 (0x7 << RXON_RX_CHAIN_FORCE_MIMO_SEL_POS)); 744 rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
852 745 scan->rx_chain = cpu_to_le16(rx_chain);
853 cmd_len = iwl_fill_probe_req(priv, band, 746 cmd_len = iwl_fill_probe_req(priv,
854 (struct ieee80211_mgmt *)scan->data, 747 (struct ieee80211_mgmt *)scan->data,
855 IWL_MAX_SCAN_SIZE - sizeof(*scan)); 748 priv->scan_request->ie,
749 priv->scan_request->ie_len,
750 IWL_MAX_SCAN_SIZE - sizeof(*scan));
856 751
857 scan->tx_cmd.len = cpu_to_le16(cmd_len); 752 scan->tx_cmd.len = cpu_to_le16(cmd_len);
858 753
859 if (priv->iw_mode == NL80211_IFTYPE_MONITOR) 754 if (iwl_is_monitor_mode(priv))
860 scan->filter_flags = RXON_FILTER_PROMISC_MSK; 755 scan->filter_flags = RXON_FILTER_PROMISC_MSK;
861 756
862 scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | 757 scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
863 RXON_FILTER_BCON_AWARE_MSK); 758 RXON_FILTER_BCON_AWARE_MSK);
864 759
865 scan->channel_count = 760 scan->channel_count =
866 iwl_get_channels_for_scan(priv, band, 1, /* active */ 761 iwl_get_channels_for_scan(priv, band, is_active, n_probes,
867 n_probes,
868 (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]); 762 (void *)&scan->data[le16_to_cpu(scan->tx_cmd.len)]);
869 763
870 if (scan->channel_count == 0) { 764 if (scan->channel_count == 0) {