diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-scan.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-scan.c | 52 |
1 files changed, 38 insertions, 14 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c index a8437a6bc18e..031d8e21f82f 100644 --- a/drivers/net/wireless/iwlwifi/iwl-scan.c +++ b/drivers/net/wireless/iwlwifi/iwl-scan.c | |||
@@ -52,6 +52,7 @@ | |||
52 | #define IWL_PASSIVE_DWELL_TIME_52 (10) | 52 | #define IWL_PASSIVE_DWELL_TIME_52 (10) |
53 | #define IWL_PASSIVE_DWELL_BASE (100) | 53 | #define IWL_PASSIVE_DWELL_BASE (100) |
54 | #define IWL_CHANNEL_TUNE_TIME 5 | 54 | #define IWL_CHANNEL_TUNE_TIME 5 |
55 | #define MAX_SCAN_CHANNEL 50 | ||
55 | 56 | ||
56 | static int iwl_send_scan_abort(struct iwl_priv *priv) | 57 | static int iwl_send_scan_abort(struct iwl_priv *priv) |
57 | { | 58 | { |
@@ -616,7 +617,8 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv, | |||
616 | */ | 617 | */ |
617 | 618 | ||
618 | static u16 iwl_fill_probe_req(struct ieee80211_mgmt *frame, const u8 *ta, | 619 | static u16 iwl_fill_probe_req(struct ieee80211_mgmt *frame, const u8 *ta, |
619 | const u8 *ies, int ie_len, int left) | 620 | const u8 *ies, int ie_len, const u8 *ssid, |
621 | u8 ssid_len, int left) | ||
620 | { | 622 | { |
621 | int len = 0; | 623 | int len = 0; |
622 | u8 *pos = NULL; | 624 | u8 *pos = NULL; |
@@ -638,14 +640,18 @@ static u16 iwl_fill_probe_req(struct ieee80211_mgmt *frame, const u8 *ta, | |||
638 | /* ...next IE... */ | 640 | /* ...next IE... */ |
639 | pos = &frame->u.probe_req.variable[0]; | 641 | pos = &frame->u.probe_req.variable[0]; |
640 | 642 | ||
641 | /* fill in our indirect SSID IE */ | 643 | /* fill in our SSID IE */ |
642 | left -= 2; | 644 | left -= ssid_len + 2; |
643 | if (left < 0) | 645 | if (left < 0) |
644 | return 0; | 646 | return 0; |
645 | *pos++ = WLAN_EID_SSID; | 647 | *pos++ = WLAN_EID_SSID; |
646 | *pos++ = 0; | 648 | *pos++ = ssid_len; |
649 | if (ssid && ssid_len) { | ||
650 | memcpy(pos, ssid, ssid_len); | ||
651 | pos += ssid_len; | ||
652 | } | ||
647 | 653 | ||
648 | len += 2; | 654 | len += ssid_len + 2; |
649 | 655 | ||
650 | if (WARN_ON(left < ie_len)) | 656 | if (WARN_ON(left < ie_len)) |
651 | return len; | 657 | return len; |
@@ -679,6 +685,15 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
679 | u8 active_chains; | 685 | u8 active_chains; |
680 | u8 scan_tx_antennas = priv->hw_params.valid_tx_ant; | 686 | u8 scan_tx_antennas = priv->hw_params.valid_tx_ant; |
681 | int ret; | 687 | int ret; |
688 | int scan_cmd_size = sizeof(struct iwl_scan_cmd) + | ||
689 | MAX_SCAN_CHANNEL * sizeof(struct iwl_scan_channel) + | ||
690 | priv->fw->ucode_capa.max_probe_length; | ||
691 | const u8 *ssid = NULL; | ||
692 | u8 ssid_len = 0; | ||
693 | |||
694 | if (WARN_ON_ONCE(priv->scan_request && | ||
695 | priv->scan_request->n_channels > MAX_SCAN_CHANNEL)) | ||
696 | return -EINVAL; | ||
682 | 697 | ||
683 | lockdep_assert_held(&priv->mutex); | 698 | lockdep_assert_held(&priv->mutex); |
684 | 699 | ||
@@ -686,8 +701,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
686 | ctx = iwl_rxon_ctx_from_vif(vif); | 701 | ctx = iwl_rxon_ctx_from_vif(vif); |
687 | 702 | ||
688 | if (!priv->scan_cmd) { | 703 | if (!priv->scan_cmd) { |
689 | priv->scan_cmd = kmalloc(sizeof(struct iwl_scan_cmd) + | 704 | priv->scan_cmd = kmalloc(scan_cmd_size, GFP_KERNEL); |
690 | IWL_MAX_SCAN_SIZE, GFP_KERNEL); | ||
691 | if (!priv->scan_cmd) { | 705 | if (!priv->scan_cmd) { |
692 | IWL_DEBUG_SCAN(priv, | 706 | IWL_DEBUG_SCAN(priv, |
693 | "fail to allocate memory for scan\n"); | 707 | "fail to allocate memory for scan\n"); |
@@ -695,7 +709,7 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
695 | } | 709 | } |
696 | } | 710 | } |
697 | scan = priv->scan_cmd; | 711 | scan = priv->scan_cmd; |
698 | memset(scan, 0, sizeof(struct iwl_scan_cmd) + IWL_MAX_SCAN_SIZE); | 712 | memset(scan, 0, scan_cmd_size); |
699 | 713 | ||
700 | scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; | 714 | scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; |
701 | scan->quiet_time = IWL_ACTIVE_QUIET_TIME; | 715 | scan->quiet_time = IWL_ACTIVE_QUIET_TIME; |
@@ -746,10 +760,18 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
746 | if (priv->scan_request->n_ssids) { | 760 | if (priv->scan_request->n_ssids) { |
747 | int i, p = 0; | 761 | int i, p = 0; |
748 | IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); | 762 | IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); |
749 | for (i = 0; i < priv->scan_request->n_ssids; i++) { | 763 | /* |
750 | /* always does wildcard anyway */ | 764 | * The highest priority SSID is inserted to the |
751 | if (!priv->scan_request->ssids[i].ssid_len) | 765 | * probe request template. |
752 | continue; | 766 | */ |
767 | ssid_len = priv->scan_request->ssids[0].ssid_len; | ||
768 | ssid = priv->scan_request->ssids[0].ssid; | ||
769 | |||
770 | /* | ||
771 | * Invert the order of ssids, the firmware will invert | ||
772 | * it back. | ||
773 | */ | ||
774 | for (i = priv->scan_request->n_ssids - 1; i >= 1; i--) { | ||
753 | scan->direct_scan[p].id = WLAN_EID_SSID; | 775 | scan->direct_scan[p].id = WLAN_EID_SSID; |
754 | scan->direct_scan[p].len = | 776 | scan->direct_scan[p].len = |
755 | priv->scan_request->ssids[i].ssid_len; | 777 | priv->scan_request->ssids[i].ssid_len; |
@@ -883,7 +905,8 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
883 | vif->addr, | 905 | vif->addr, |
884 | priv->scan_request->ie, | 906 | priv->scan_request->ie, |
885 | priv->scan_request->ie_len, | 907 | priv->scan_request->ie_len, |
886 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); | 908 | ssid, ssid_len, |
909 | scan_cmd_size - sizeof(*scan)); | ||
887 | break; | 910 | break; |
888 | case IWL_SCAN_RADIO_RESET: | 911 | case IWL_SCAN_RADIO_RESET: |
889 | case IWL_SCAN_ROC: | 912 | case IWL_SCAN_ROC: |
@@ -891,7 +914,8 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) | |||
891 | cmd_len = iwl_fill_probe_req( | 914 | cmd_len = iwl_fill_probe_req( |
892 | (struct ieee80211_mgmt *)scan->data, | 915 | (struct ieee80211_mgmt *)scan->data, |
893 | iwl_bcast_addr, NULL, 0, | 916 | iwl_bcast_addr, NULL, 0, |
894 | IWL_MAX_SCAN_SIZE - sizeof(*scan)); | 917 | NULL, 0, |
918 | scan_cmd_size - sizeof(*scan)); | ||
895 | break; | 919 | break; |
896 | default: | 920 | default: |
897 | BUG(); | 921 | BUG(); |