aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmitkumar Karwar <akarwar@marvell.com>2014-02-11 21:39:56 -0500
committerJohn W. Linville <linville@tuxdriver.com>2014-02-12 15:36:13 -0500
commit21f58d200388480547df909b5464b5aafebf299d (patch)
tree4f538ef7445b23a0f14e006e486952d1551fbc8c
parentd44b5c2f2ec54569006dc85c7dbe25ccd41cfb73 (diff)
mwifiex: implement extended scan feature
In extended scan, host gets scan results through one or multiple events instead of scan command response. Host will send next scan command when all the events are received. Legacy scan sometimes truncates scan results in a noisy environment due to buffer length limitation. This issue is addressed in extended scan. Signed-off-by: Amitkumar Karwar <akarwar@marvell.com> Signed-off-by: Bing Zhao <bzhao@marvell.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/mwifiex/cmdevt.c3
-rw-r--r--drivers/net/wireless/mwifiex/fw.h43
-rw-r--r--drivers/net/wireless/mwifiex/init.c1
-rw-r--r--drivers/net/wireless/mwifiex/main.h9
-rw-r--r--drivers/net/wireless/mwifiex/scan.c191
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmd.c3
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmdresp.c5
-rw-r--r--drivers/net/wireless/mwifiex/sta_event.c8
8 files changed, 255 insertions, 8 deletions
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c
index 1ddc8b2e3722..556cb2c74e30 100644
--- a/drivers/net/wireless/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/mwifiex/cmdevt.c
@@ -595,7 +595,8 @@ int mwifiex_send_cmd_async(struct mwifiex_private *priv, uint16_t cmd_no,
595 } 595 }
596 596
597 /* Send command */ 597 /* Send command */
598 if (cmd_no == HostCmd_CMD_802_11_SCAN) { 598 if (cmd_no == HostCmd_CMD_802_11_SCAN ||
599 cmd_no == HostCmd_CMD_802_11_SCAN_EXT) {
599 mwifiex_queue_scan_cmd(priv, cmd_node); 600 mwifiex_queue_scan_cmd(priv, cmd_node);
600 } else { 601 } else {
601 mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true); 602 mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true);
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index 9b267901832a..ed41af17b213 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -132,6 +132,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
132#define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 22) 132#define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 22)
133#define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 31) 133#define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 31)
134#define TLV_TYPE_STA_MAC_ADDR (PROPRIETARY_TLV_BASE_ID + 32) 134#define TLV_TYPE_STA_MAC_ADDR (PROPRIETARY_TLV_BASE_ID + 32)
135#define TLV_TYPE_BSSID (PROPRIETARY_TLV_BASE_ID + 35)
135#define TLV_TYPE_CHANNELBANDLIST (PROPRIETARY_TLV_BASE_ID + 42) 136#define TLV_TYPE_CHANNELBANDLIST (PROPRIETARY_TLV_BASE_ID + 42)
136#define TLV_TYPE_UAP_BEACON_PERIOD (PROPRIETARY_TLV_BASE_ID + 44) 137#define TLV_TYPE_UAP_BEACON_PERIOD (PROPRIETARY_TLV_BASE_ID + 44)
137#define TLV_TYPE_UAP_DTIM_PERIOD (PROPRIETARY_TLV_BASE_ID + 45) 138#define TLV_TYPE_UAP_DTIM_PERIOD (PROPRIETARY_TLV_BASE_ID + 45)
@@ -146,6 +147,8 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
146#define TLV_TYPE_RATE_DROP_CONTROL (PROPRIETARY_TLV_BASE_ID + 82) 147#define TLV_TYPE_RATE_DROP_CONTROL (PROPRIETARY_TLV_BASE_ID + 82)
147#define TLV_TYPE_RATE_SCOPE (PROPRIETARY_TLV_BASE_ID + 83) 148#define TLV_TYPE_RATE_SCOPE (PROPRIETARY_TLV_BASE_ID + 83)
148#define TLV_TYPE_POWER_GROUP (PROPRIETARY_TLV_BASE_ID + 84) 149#define TLV_TYPE_POWER_GROUP (PROPRIETARY_TLV_BASE_ID + 84)
150#define TLV_TYPE_BSS_SCAN_RSP (PROPRIETARY_TLV_BASE_ID + 86)
151#define TLV_TYPE_BSS_SCAN_INFO (PROPRIETARY_TLV_BASE_ID + 87)
149#define TLV_TYPE_UAP_RETRY_LIMIT (PROPRIETARY_TLV_BASE_ID + 93) 152#define TLV_TYPE_UAP_RETRY_LIMIT (PROPRIETARY_TLV_BASE_ID + 93)
150#define TLV_TYPE_WAPI_IE (PROPRIETARY_TLV_BASE_ID + 94) 153#define TLV_TYPE_WAPI_IE (PROPRIETARY_TLV_BASE_ID + 94)
151#define TLV_TYPE_UAP_MGMT_FRAME (PROPRIETARY_TLV_BASE_ID + 104) 154#define TLV_TYPE_UAP_MGMT_FRAME (PROPRIETARY_TLV_BASE_ID + 104)
@@ -295,6 +298,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
295#define HostCmd_CMD_CAU_REG_ACCESS 0x00ed 298#define HostCmd_CMD_CAU_REG_ACCESS 0x00ed
296#define HostCmd_CMD_SET_BSS_MODE 0x00f7 299#define HostCmd_CMD_SET_BSS_MODE 0x00f7
297#define HostCmd_CMD_PCIE_DESC_DETAILS 0x00fa 300#define HostCmd_CMD_PCIE_DESC_DETAILS 0x00fa
301#define HostCmd_CMD_802_11_SCAN_EXT 0x0107
298#define HostCmd_CMD_COALESCE_CFG 0x010a 302#define HostCmd_CMD_COALESCE_CFG 0x010a
299#define HostCmd_CMD_MGMT_FRAME_REG 0x010c 303#define HostCmd_CMD_MGMT_FRAME_REG 0x010c
300#define HostCmd_CMD_REMAIN_ON_CHAN 0x010d 304#define HostCmd_CMD_REMAIN_ON_CHAN 0x010d
@@ -440,6 +444,7 @@ enum P2P_MODES {
440#define EVENT_UAP_MIC_COUNTERMEASURES 0x0000004c 444#define EVENT_UAP_MIC_COUNTERMEASURES 0x0000004c
441#define EVENT_HOSTWAKE_STAIE 0x0000004d 445#define EVENT_HOSTWAKE_STAIE 0x0000004d
442#define EVENT_CHANNEL_SWITCH_ANN 0x00000050 446#define EVENT_CHANNEL_SWITCH_ANN 0x00000050
447#define EVENT_EXT_SCAN_REPORT 0x00000058
443#define EVENT_REMAIN_ON_CHAN_EXPIRED 0x0000005f 448#define EVENT_REMAIN_ON_CHAN_EXPIRED 0x0000005f
444 449
445#define EVENT_ID_MASK 0xffff 450#define EVENT_ID_MASK 0xffff
@@ -1053,6 +1058,16 @@ struct mwifiex_fixed_bcn_param {
1053 __le16 cap_info_bitmap; 1058 __le16 cap_info_bitmap;
1054} __packed; 1059} __packed;
1055 1060
1061struct mwifiex_event_scan_result {
1062 __le16 event_id;
1063 u8 bss_index;
1064 u8 bss_type;
1065 u8 more_event;
1066 u8 reserved[3];
1067 __le16 buf_size;
1068 u8 num_of_set;
1069} __packed;
1070
1056#define MWIFIEX_USER_SCAN_CHAN_MAX 50 1071#define MWIFIEX_USER_SCAN_CHAN_MAX 50
1057 1072
1058#define MWIFIEX_MAX_SSID_LIST_LENGTH 10 1073#define MWIFIEX_MAX_SSID_LIST_LENGTH 10
@@ -1122,6 +1137,28 @@ struct host_cmd_ds_802_11_scan_rsp {
1122 u8 bss_desc_and_tlv_buffer[1]; 1137 u8 bss_desc_and_tlv_buffer[1];
1123} __packed; 1138} __packed;
1124 1139
1140struct host_cmd_ds_802_11_scan_ext {
1141 u32 reserved;
1142 u8 tlv_buffer[1];
1143} __packed;
1144
1145struct mwifiex_ie_types_bss_scan_rsp {
1146 struct mwifiex_ie_types_header header;
1147 u8 bssid[ETH_ALEN];
1148 u8 frame_body[1];
1149} __packed;
1150
1151struct mwifiex_ie_types_bss_scan_info {
1152 struct mwifiex_ie_types_header header;
1153 __le16 rssi;
1154 __le16 anpi;
1155 u8 cca_busy_fraction;
1156 u8 radio_type;
1157 u8 channel;
1158 u8 reserved;
1159 __le64 tsf;
1160} __packed;
1161
1125struct host_cmd_ds_802_11_bg_scan_query { 1162struct host_cmd_ds_802_11_bg_scan_query {
1126 u8 flush; 1163 u8 flush;
1127} __packed; 1164} __packed;
@@ -1439,6 +1476,11 @@ struct host_cmd_tlv_rates {
1439 u8 rates[0]; 1476 u8 rates[0];
1440} __packed; 1477} __packed;
1441 1478
1479struct mwifiex_ie_types_bssid_list {
1480 struct mwifiex_ie_types_header header;
1481 u8 bssid[ETH_ALEN];
1482} __packed;
1483
1442struct host_cmd_tlv_bcast_ssid { 1484struct host_cmd_tlv_bcast_ssid {
1443 struct mwifiex_ie_types_header header; 1485 struct mwifiex_ie_types_header header;
1444 u8 bcast_ctl; 1486 u8 bcast_ctl;
@@ -1632,6 +1674,7 @@ struct host_cmd_ds_command {
1632 struct host_cmd_ds_802_11_ps_mode_enh psmode_enh; 1674 struct host_cmd_ds_802_11_ps_mode_enh psmode_enh;
1633 struct host_cmd_ds_802_11_hs_cfg_enh opt_hs_cfg; 1675 struct host_cmd_ds_802_11_hs_cfg_enh opt_hs_cfg;
1634 struct host_cmd_ds_802_11_scan scan; 1676 struct host_cmd_ds_802_11_scan scan;
1677 struct host_cmd_ds_802_11_scan_ext ext_scan;
1635 struct host_cmd_ds_802_11_scan_rsp scan_resp; 1678 struct host_cmd_ds_802_11_scan_rsp scan_resp;
1636 struct host_cmd_ds_802_11_bg_scan_query bg_scan_query; 1679 struct host_cmd_ds_802_11_bg_scan_query bg_scan_query;
1637 struct host_cmd_ds_802_11_bg_scan_query_rsp bg_scan_query_resp; 1680 struct host_cmd_ds_802_11_bg_scan_query_rsp bg_scan_query_resp;
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 1d0a817f2bf0..308c56fd32eb 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -281,6 +281,7 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
281 adapter->arp_filter_size = 0; 281 adapter->arp_filter_size = 0;
282 adapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX; 282 adapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX;
283 adapter->empty_tx_q_cnt = 0; 283 adapter->empty_tx_q_cnt = 0;
284 adapter->ext_scan = true;
284} 285}
285 286
286/* 287/*
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 29d27d9b5ebe..c473f54ba738 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -59,7 +59,7 @@ enum {
59 59
60#define MWIFIEX_UPLD_SIZE (2312) 60#define MWIFIEX_UPLD_SIZE (2312)
61 61
62#define MAX_EVENT_SIZE 1024 62#define MAX_EVENT_SIZE 2048
63 63
64#define ARP_FILTER_MAX_BUF_SIZE 68 64#define ARP_FILTER_MAX_BUF_SIZE 68
65 65
@@ -753,6 +753,7 @@ struct mwifiex_adapter {
753 atomic_t is_tx_received; 753 atomic_t is_tx_received;
754 atomic_t pending_bridged_pkts; 754 atomic_t pending_bridged_pkts;
755 struct semaphore *card_sem; 755 struct semaphore *card_sem;
756 bool ext_scan;
756}; 757};
757 758
758int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); 759int mwifiex_init_lock_list(struct mwifiex_adapter *adapter);
@@ -938,6 +939,12 @@ mwifiex_set_wmm_params(struct mwifiex_private *priv,
938 struct cfg80211_ap_settings *params); 939 struct cfg80211_ap_settings *params);
939void mwifiex_set_ba_params(struct mwifiex_private *priv); 940void mwifiex_set_ba_params(struct mwifiex_private *priv);
940void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv); 941void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv);
942int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv,
943 struct host_cmd_ds_command *cmd,
944 void *data_buf);
945int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv);
946int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv,
947 void *buf);
941 948
942/* 949/*
943 * This function checks if the queuing is RA based or not. 950 * This function checks if the queuing is RA based or not.
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index 3633347f50f6..c548a7d4877d 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -595,7 +595,7 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv,
595 struct mwifiex_chan_scan_param_set *tmp_chan_list; 595 struct mwifiex_chan_scan_param_set *tmp_chan_list;
596 struct mwifiex_chan_scan_param_set *start_chan; 596 struct mwifiex_chan_scan_param_set *start_chan;
597 597
598 u32 tlv_idx, rates_size; 598 u32 tlv_idx, rates_size, cmd_no;
599 u32 total_scan_time; 599 u32 total_scan_time;
600 u32 done_early; 600 u32 done_early;
601 u8 radio_type; 601 u8 radio_type;
@@ -733,9 +733,13 @@ mwifiex_scan_channel_list(struct mwifiex_private *priv,
733 733
734 /* Send the scan command to the firmware with the specified 734 /* Send the scan command to the firmware with the specified
735 cfg */ 735 cfg */
736 ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_802_11_SCAN, 736 if (priv->adapter->ext_scan)
737 HostCmd_ACT_GEN_SET, 0, 737 cmd_no = HostCmd_CMD_802_11_SCAN_EXT;
738 scan_cfg_out); 738 else
739 cmd_no = HostCmd_CMD_802_11_SCAN;
740
741 ret = mwifiex_send_cmd_async(priv, cmd_no, HostCmd_ACT_GEN_SET,
742 0, scan_cfg_out);
739 743
740 /* rate IE is updated per scan command but same starting 744 /* rate IE is updated per scan command but same starting
741 * pointer is used each time so that rate IE from earlier 745 * pointer is used each time so that rate IE from earlier
@@ -786,6 +790,7 @@ mwifiex_config_scan(struct mwifiex_private *priv,
786 struct mwifiex_adapter *adapter = priv->adapter; 790 struct mwifiex_adapter *adapter = priv->adapter;
787 struct mwifiex_ie_types_num_probes *num_probes_tlv; 791 struct mwifiex_ie_types_num_probes *num_probes_tlv;
788 struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv; 792 struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv;
793 struct mwifiex_ie_types_bssid_list *bssid_tlv;
789 u8 *tlv_pos; 794 u8 *tlv_pos;
790 u32 num_probes; 795 u32 num_probes;
791 u32 ssid_len; 796 u32 ssid_len;
@@ -848,6 +853,17 @@ mwifiex_config_scan(struct mwifiex_private *priv,
848 user_scan_in->specific_bssid, 853 user_scan_in->specific_bssid,
849 sizeof(scan_cfg_out->specific_bssid)); 854 sizeof(scan_cfg_out->specific_bssid));
850 855
856 if (adapter->ext_scan &&
857 !is_zero_ether_addr(scan_cfg_out->specific_bssid)) {
858 bssid_tlv =
859 (struct mwifiex_ie_types_bssid_list *)tlv_pos;
860 bssid_tlv->header.type = cpu_to_le16(TLV_TYPE_BSSID);
861 bssid_tlv->header.len = cpu_to_le16(ETH_ALEN);
862 memcpy(bssid_tlv->bssid, user_scan_in->specific_bssid,
863 ETH_ALEN);
864 tlv_pos += sizeof(struct mwifiex_ie_types_bssid_list);
865 }
866
851 for (i = 0; i < user_scan_in->num_ssids; i++) { 867 for (i = 0; i < user_scan_in->num_ssids; i++) {
852 ssid_len = user_scan_in->ssid_list[i].ssid_len; 868 ssid_len = user_scan_in->ssid_list[i].ssid_len;
853 869
@@ -1579,7 +1595,7 @@ done:
1579static int 1595static int
1580mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info, 1596mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info,
1581 u32 *bytes_left, u64 fw_tsf, u8 *radio_type, 1597 u32 *bytes_left, u64 fw_tsf, u8 *radio_type,
1582 bool ext_scan) 1598 bool ext_scan, s32 rssi_val)
1583{ 1599{
1584 struct mwifiex_adapter *adapter = priv->adapter; 1600 struct mwifiex_adapter *adapter = priv->adapter;
1585 struct mwifiex_chan_freq_power *cfp; 1601 struct mwifiex_chan_freq_power *cfp;
@@ -1642,6 +1658,8 @@ mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info,
1642 current_ptr += sizeof(u8); 1658 current_ptr += sizeof(u8);
1643 curr_bcn_bytes -= sizeof(u8); 1659 curr_bcn_bytes -= sizeof(u8);
1644 dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%d\n", rssi); 1660 dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%d\n", rssi);
1661 } else {
1662 rssi = rssi_val;
1645 } 1663 }
1646 1664
1647 bcn_param = (struct mwifiex_fixed_bcn_param *)current_ptr; 1665 bcn_param = (struct mwifiex_fixed_bcn_param *)current_ptr;
@@ -1914,7 +1932,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
1914 ret = mwifiex_parse_single_response_buf(priv, &bss_info, 1932 ret = mwifiex_parse_single_response_buf(priv, &bss_info,
1915 &bytes_left, 1933 &bytes_left,
1916 le64_to_cpu(fw_tsf), 1934 le64_to_cpu(fw_tsf),
1917 radio_type, false); 1935 radio_type, false, 0);
1918 if (ret) 1936 if (ret)
1919 goto check_next_scan; 1937 goto check_next_scan;
1920 } 1938 }
@@ -1925,6 +1943,167 @@ check_next_scan:
1925} 1943}
1926 1944
1927/* 1945/*
1946 * This function prepares an extended scan command to be sent to the firmware
1947 *
1948 * This uses the scan command configuration sent to the command processing
1949 * module in command preparation stage to configure a extended scan command
1950 * structure to send to firmware.
1951 */
1952int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv,
1953 struct host_cmd_ds_command *cmd,
1954 void *data_buf)
1955{
1956 struct host_cmd_ds_802_11_scan_ext *ext_scan = &cmd->params.ext_scan;
1957 struct mwifiex_scan_cmd_config *scan_cfg = data_buf;
1958
1959 memcpy(ext_scan->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len);
1960
1961 cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN_EXT);
1962
1963 /* Size is equal to the sizeof(fixed portions) + the TLV len + header */
1964 cmd->size = cpu_to_le16((u16)(sizeof(ext_scan->reserved)
1965 + scan_cfg->tlv_buf_len + S_DS_GEN));
1966
1967 return 0;
1968}
1969
1970/* This function handles the command response of extended scan */
1971int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv)
1972{
1973 dev_dbg(priv->adapter->dev, "info: EXT scan returns successfully\n");
1974 return 0;
1975}
1976
1977/* This function This function handles the event extended scan report. It
1978 * parses extended scan results and informs to cfg80211 stack.
1979 */
1980int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv,
1981 void *buf)
1982{
1983 int ret = 0;
1984 struct mwifiex_adapter *adapter = priv->adapter;
1985 u8 *bss_info;
1986 u32 bytes_left, bytes_left_for_tlv, idx;
1987 u16 type, len;
1988 struct mwifiex_ie_types_data *tlv;
1989 struct mwifiex_ie_types_bss_scan_rsp *scan_rsp_tlv;
1990 struct mwifiex_ie_types_bss_scan_info *scan_info_tlv;
1991 u8 *radio_type;
1992 u64 fw_tsf = 0;
1993 s32 rssi = 0;
1994 struct mwifiex_event_scan_result *event_scan = buf;
1995 u8 num_of_set = event_scan->num_of_set;
1996 u8 *scan_resp = buf + sizeof(struct mwifiex_event_scan_result);
1997 u16 scan_resp_size = le16_to_cpu(event_scan->buf_size);
1998
1999 if (num_of_set > MWIFIEX_MAX_AP) {
2000 dev_err(adapter->dev,
2001 "EXT_SCAN: Invalid number of AP returned (%d)!!\n",
2002 num_of_set);
2003 ret = -1;
2004 goto check_next_scan;
2005 }
2006
2007 bytes_left = scan_resp_size;
2008 dev_dbg(adapter->dev,
2009 "EXT_SCAN: size %d, returned %d APs...",
2010 scan_resp_size, num_of_set);
2011
2012 tlv = (struct mwifiex_ie_types_data *)scan_resp;
2013
2014 for (idx = 0; idx < num_of_set && bytes_left; idx++) {
2015 type = le16_to_cpu(tlv->header.type);
2016 len = le16_to_cpu(tlv->header.len);
2017 if (bytes_left < sizeof(struct mwifiex_ie_types_header) + len) {
2018 dev_err(adapter->dev, "EXT_SCAN: Error bytes left < TLV length\n");
2019 break;
2020 }
2021 scan_rsp_tlv = NULL;
2022 scan_info_tlv = NULL;
2023 bytes_left_for_tlv = bytes_left;
2024
2025 /* BSS response TLV with beacon or probe response buffer
2026 * at the initial position of each descriptor
2027 */
2028 if (type != TLV_TYPE_BSS_SCAN_RSP)
2029 break;
2030
2031 bss_info = (u8 *)tlv;
2032 scan_rsp_tlv = (struct mwifiex_ie_types_bss_scan_rsp *)tlv;
2033 tlv = (struct mwifiex_ie_types_data *)(tlv->data + len);
2034 bytes_left_for_tlv -=
2035 (len + sizeof(struct mwifiex_ie_types_header));
2036
2037 while (bytes_left_for_tlv >=
2038 sizeof(struct mwifiex_ie_types_header) &&
2039 le16_to_cpu(tlv->header.type) != TLV_TYPE_BSS_SCAN_RSP) {
2040 type = le16_to_cpu(tlv->header.type);
2041 len = le16_to_cpu(tlv->header.len);
2042 if (bytes_left_for_tlv <
2043 sizeof(struct mwifiex_ie_types_header) + len) {
2044 dev_err(adapter->dev,
2045 "EXT_SCAN: Error in processing TLV, bytes left < TLV length\n");
2046 scan_rsp_tlv = NULL;
2047 bytes_left_for_tlv = 0;
2048 continue;
2049 }
2050 switch (type) {
2051 case TLV_TYPE_BSS_SCAN_INFO:
2052 scan_info_tlv =
2053 (struct mwifiex_ie_types_bss_scan_info *)tlv;
2054 if (len !=
2055 sizeof(struct mwifiex_ie_types_bss_scan_info) -
2056 sizeof(struct mwifiex_ie_types_header)) {
2057 bytes_left_for_tlv = 0;
2058 continue;
2059 }
2060 break;
2061 default:
2062 break;
2063 }
2064 tlv = (struct mwifiex_ie_types_data *)(tlv->data + len);
2065 bytes_left -=
2066 (len + sizeof(struct mwifiex_ie_types_header));
2067 bytes_left_for_tlv -=
2068 (len + sizeof(struct mwifiex_ie_types_header));
2069 }
2070
2071 if (!scan_rsp_tlv)
2072 break;
2073
2074 /* Advance pointer to the beacon buffer length and
2075 * update the bytes count so that the function
2076 * wlan_interpret_bss_desc_with_ie() can handle the
2077 * scan buffer withut any change
2078 */
2079 bss_info += sizeof(u16);
2080 bytes_left -= sizeof(u16);
2081
2082 if (scan_info_tlv) {
2083 rssi = (s32)(s16)(le16_to_cpu(scan_info_tlv->rssi));
2084 rssi *= 100; /* Convert dBm to mBm */
2085 dev_dbg(adapter->dev,
2086 "info: InterpretIE: RSSI=%d\n", rssi);
2087 fw_tsf = le64_to_cpu(scan_info_tlv->tsf);
2088 radio_type = &scan_info_tlv->radio_type;
2089 } else {
2090 radio_type = NULL;
2091 }
2092 ret = mwifiex_parse_single_response_buf(priv, &bss_info,
2093 &bytes_left, fw_tsf,
2094 radio_type, true, rssi);
2095 if (ret)
2096 goto check_next_scan;
2097 }
2098
2099check_next_scan:
2100 if (!event_scan->more_event)
2101 mwifiex_check_next_scan_command(priv);
2102
2103 return ret;
2104}
2105
2106/*
1928 * This function prepares command for background scan query. 2107 * This function prepares command for background scan query.
1929 * 2108 *
1930 * Preparation includes - 2109 * Preparation includes -
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c
index 9208a8816b80..1b2991261538 100644
--- a/drivers/net/wireless/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/mwifiex/sta_cmd.c
@@ -1472,6 +1472,9 @@ int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no,
1472 ret = mwifiex_cmd_ibss_coalescing_status(cmd_ptr, cmd_action, 1472 ret = mwifiex_cmd_ibss_coalescing_status(cmd_ptr, cmd_action,
1473 data_buf); 1473 data_buf);
1474 break; 1474 break;
1475 case HostCmd_CMD_802_11_SCAN_EXT:
1476 ret = mwifiex_cmd_802_11_scan_ext(priv, cmd_ptr, data_buf);
1477 break;
1475 case HostCmd_CMD_MAC_REG_ACCESS: 1478 case HostCmd_CMD_MAC_REG_ACCESS:
1476 case HostCmd_CMD_BBP_REG_ACCESS: 1479 case HostCmd_CMD_BBP_REG_ACCESS:
1477 case HostCmd_CMD_RF_REG_ACCESS: 1480 case HostCmd_CMD_RF_REG_ACCESS:
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index 24523e4015cb..95e13589d2bd 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -69,6 +69,7 @@ mwifiex_process_cmdresp_error(struct mwifiex_private *priv,
69 69
70 break; 70 break;
71 case HostCmd_CMD_802_11_SCAN: 71 case HostCmd_CMD_802_11_SCAN:
72 case HostCmd_CMD_802_11_SCAN_EXT:
72 /* Cancel all pending scan command */ 73 /* Cancel all pending scan command */
73 spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); 74 spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
74 list_for_each_entry_safe(cmd_node, tmp_node, 75 list_for_each_entry_safe(cmd_node, tmp_node,
@@ -871,6 +872,10 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no,
871 ret = mwifiex_ret_802_11_scan(priv, resp); 872 ret = mwifiex_ret_802_11_scan(priv, resp);
872 adapter->curr_cmd->wait_q_enabled = false; 873 adapter->curr_cmd->wait_q_enabled = false;
873 break; 874 break;
875 case HostCmd_CMD_802_11_SCAN_EXT:
876 ret = mwifiex_ret_802_11_scan_ext(priv);
877 adapter->curr_cmd->wait_q_enabled = false;
878 break;
874 case HostCmd_CMD_802_11_BG_SCAN_QUERY: 879 case HostCmd_CMD_802_11_BG_SCAN_QUERY:
875 ret = mwifiex_ret_802_11_scan(priv, resp); 880 ret = mwifiex_ret_802_11_scan(priv, resp);
876 dev_dbg(adapter->dev, 881 dev_dbg(adapter->dev,
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c
index 8c351f71f72f..de4a6affe72e 100644
--- a/drivers/net/wireless/mwifiex/sta_event.c
+++ b/drivers/net/wireless/mwifiex/sta_event.c
@@ -331,6 +331,14 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
331 dev_dbg(adapter->dev, "event: PORT RELEASE\n"); 331 dev_dbg(adapter->dev, "event: PORT RELEASE\n");
332 break; 332 break;
333 333
334 case EVENT_EXT_SCAN_REPORT:
335 dev_dbg(adapter->dev, "event: EXT_SCAN Report\n");
336 if (adapter->ext_scan)
337 ret = mwifiex_handle_event_ext_scan_report(priv,
338 adapter->event_skb->data);
339
340 break;
341
334 case EVENT_WMM_STATUS_CHANGE: 342 case EVENT_WMM_STATUS_CHANGE:
335 dev_dbg(adapter->dev, "event: WMM status changed\n"); 343 dev_dbg(adapter->dev, "event: WMM status changed\n");
336 ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_WMM_GET_STATUS, 344 ret = mwifiex_send_cmd_async(priv, HostCmd_CMD_WMM_GET_STATUS,