aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/mwifiex/scan.c
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 /drivers/net/wireless/mwifiex/scan.c
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>
Diffstat (limited to 'drivers/net/wireless/mwifiex/scan.c')
-rw-r--r--drivers/net/wireless/mwifiex/scan.c191
1 files changed, 185 insertions, 6 deletions
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 -