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.c52
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
56static int iwl_send_scan_abort(struct iwl_priv *priv) 57static 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
618static u16 iwl_fill_probe_req(struct ieee80211_mgmt *frame, const u8 *ta, 619static 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();