cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

scan.c (88173B)


      1/*
      2 * NXP Wireless LAN device driver: scan ioctl and command handling
      3 *
      4 * Copyright 2011-2020 NXP
      5 *
      6 * This software file (the "File") is distributed by NXP
      7 * under the terms of the GNU General Public License Version 2, June 1991
      8 * (the "License").  You may use, redistribute and/or modify this File in
      9 * accordance with the terms and conditions of the License, a copy of which
     10 * is available by writing to the Free Software Foundation, Inc.,
     11 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
     12 * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
     13 *
     14 * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
     15 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
     16 * ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
     17 * this warranty disclaimer.
     18 */
     19
     20#include "decl.h"
     21#include "ioctl.h"
     22#include "util.h"
     23#include "fw.h"
     24#include "main.h"
     25#include "11n.h"
     26#include "cfg80211.h"
     27
     28/* The maximum number of channels the firmware can scan per command */
     29#define MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN   14
     30
     31#define MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD	4
     32
     33/* Memory needed to store a max sized Channel List TLV for a firmware scan */
     34#define CHAN_TLV_MAX_SIZE  (sizeof(struct mwifiex_ie_types_header)         \
     35				+ (MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN     \
     36				*sizeof(struct mwifiex_chan_scan_param_set)))
     37
     38/* Memory needed to store supported rate */
     39#define RATE_TLV_MAX_SIZE   (sizeof(struct mwifiex_ie_types_rates_param_set) \
     40				+ HOSTCMD_SUPPORTED_RATES)
     41
     42/* Memory needed to store a max number/size WildCard SSID TLV for a firmware
     43	scan */
     44#define WILDCARD_SSID_TLV_MAX_SIZE  \
     45	(MWIFIEX_MAX_SSID_LIST_LENGTH *					\
     46		(sizeof(struct mwifiex_ie_types_wildcard_ssid_params)	\
     47			+ IEEE80211_MAX_SSID_LEN))
     48
     49/* Maximum memory needed for a mwifiex_scan_cmd_config with all TLVs at max */
     50#define MAX_SCAN_CFG_ALLOC (sizeof(struct mwifiex_scan_cmd_config)        \
     51				+ sizeof(struct mwifiex_ie_types_num_probes)   \
     52				+ sizeof(struct mwifiex_ie_types_htcap)       \
     53				+ CHAN_TLV_MAX_SIZE                 \
     54				+ RATE_TLV_MAX_SIZE                 \
     55				+ WILDCARD_SSID_TLV_MAX_SIZE)
     56
     57
     58union mwifiex_scan_cmd_config_tlv {
     59	/* Scan configuration (variable length) */
     60	struct mwifiex_scan_cmd_config config;
     61	/* Max allocated block */
     62	u8 config_alloc_buf[MAX_SCAN_CFG_ALLOC];
     63};
     64
     65enum cipher_suite {
     66	CIPHER_SUITE_TKIP,
     67	CIPHER_SUITE_CCMP,
     68	CIPHER_SUITE_MAX
     69};
     70static u8 mwifiex_wpa_oui[CIPHER_SUITE_MAX][4] = {
     71	{ 0x00, 0x50, 0xf2, 0x02 },	/* TKIP */
     72	{ 0x00, 0x50, 0xf2, 0x04 },	/* AES  */
     73};
     74static u8 mwifiex_rsn_oui[CIPHER_SUITE_MAX][4] = {
     75	{ 0x00, 0x0f, 0xac, 0x02 },	/* TKIP */
     76	{ 0x00, 0x0f, 0xac, 0x04 },	/* AES  */
     77};
     78
     79static void
     80_dbg_security_flags(int log_level, const char *func, const char *desc,
     81		    struct mwifiex_private *priv,
     82		    struct mwifiex_bssdescriptor *bss_desc)
     83{
     84	_mwifiex_dbg(priv->adapter, log_level,
     85		     "info: %s: %s:\twpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s\tEncMode=%#x privacy=%#x\n",
     86		     func, desc,
     87		     bss_desc->bcn_wpa_ie ?
     88		     bss_desc->bcn_wpa_ie->vend_hdr.element_id : 0,
     89		     bss_desc->bcn_rsn_ie ?
     90		     bss_desc->bcn_rsn_ie->ieee_hdr.element_id : 0,
     91		     priv->sec_info.wep_enabled ? "e" : "d",
     92		     priv->sec_info.wpa_enabled ? "e" : "d",
     93		     priv->sec_info.wpa2_enabled ? "e" : "d",
     94		     priv->sec_info.encryption_mode,
     95		     bss_desc->privacy);
     96}
     97#define dbg_security_flags(mask, desc, priv, bss_desc) \
     98	_dbg_security_flags(MWIFIEX_DBG_##mask, desc, __func__, priv, bss_desc)
     99
    100static bool
    101has_ieee_hdr(struct ieee_types_generic *ie, u8 key)
    102{
    103	return (ie && ie->ieee_hdr.element_id == key);
    104}
    105
    106static bool
    107has_vendor_hdr(struct ieee_types_vendor_specific *ie, u8 key)
    108{
    109	return (ie && ie->vend_hdr.element_id == key);
    110}
    111
    112/*
    113 * This function parses a given IE for a given OUI.
    114 *
    115 * This is used to parse a WPA/RSN IE to find if it has
    116 * a given oui in PTK.
    117 */
    118static u8
    119mwifiex_search_oui_in_ie(struct ie_body *iebody, u8 *oui)
    120{
    121	u8 count;
    122
    123	count = iebody->ptk_cnt[0];
    124
    125	/* There could be multiple OUIs for PTK hence
    126	   1) Take the length.
    127	   2) Check all the OUIs for AES.
    128	   3) If one of them is AES then pass success. */
    129	while (count) {
    130		if (!memcmp(iebody->ptk_body, oui, sizeof(iebody->ptk_body)))
    131			return MWIFIEX_OUI_PRESENT;
    132
    133		--count;
    134		if (count)
    135			iebody = (struct ie_body *) ((u8 *) iebody +
    136						sizeof(iebody->ptk_body));
    137	}
    138
    139	pr_debug("info: %s: OUI is not found in PTK\n", __func__);
    140	return MWIFIEX_OUI_NOT_PRESENT;
    141}
    142
    143/*
    144 * This function checks if a given OUI is present in a RSN IE.
    145 *
    146 * The function first checks if a RSN IE is present or not in the
    147 * BSS descriptor. It tries to locate the OUI only if such an IE is
    148 * present.
    149 */
    150static u8
    151mwifiex_is_rsn_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
    152{
    153	u8 *oui;
    154	struct ie_body *iebody;
    155	u8 ret = MWIFIEX_OUI_NOT_PRESENT;
    156
    157	if (has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN)) {
    158		iebody = (struct ie_body *)
    159			 (((u8 *) bss_desc->bcn_rsn_ie->data) +
    160			  RSN_GTK_OUI_OFFSET);
    161		oui = &mwifiex_rsn_oui[cipher][0];
    162		ret = mwifiex_search_oui_in_ie(iebody, oui);
    163		if (ret)
    164			return ret;
    165	}
    166	return ret;
    167}
    168
    169/*
    170 * This function checks if a given OUI is present in a WPA IE.
    171 *
    172 * The function first checks if a WPA IE is present or not in the
    173 * BSS descriptor. It tries to locate the OUI only if such an IE is
    174 * present.
    175 */
    176static u8
    177mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher)
    178{
    179	u8 *oui;
    180	struct ie_body *iebody;
    181	u8 ret = MWIFIEX_OUI_NOT_PRESENT;
    182
    183	if (has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC)) {
    184		iebody = (struct ie_body *)((u8 *)bss_desc->bcn_wpa_ie->data +
    185					    WPA_GTK_OUI_OFFSET);
    186		oui = &mwifiex_wpa_oui[cipher][0];
    187		ret = mwifiex_search_oui_in_ie(iebody, oui);
    188		if (ret)
    189			return ret;
    190	}
    191	return ret;
    192}
    193
    194/*
    195 * This function compares two SSIDs and checks if they match.
    196 */
    197s32
    198mwifiex_ssid_cmp(struct cfg80211_ssid *ssid1, struct cfg80211_ssid *ssid2)
    199{
    200	if (!ssid1 || !ssid2 || (ssid1->ssid_len != ssid2->ssid_len))
    201		return -1;
    202	return memcmp(ssid1->ssid, ssid2->ssid, ssid1->ssid_len);
    203}
    204
    205/*
    206 * This function checks if wapi is enabled in driver and scanned network is
    207 * compatible with it.
    208 */
    209static bool
    210mwifiex_is_bss_wapi(struct mwifiex_private *priv,
    211		    struct mwifiex_bssdescriptor *bss_desc)
    212{
    213	if (priv->sec_info.wapi_enabled &&
    214	    has_ieee_hdr(bss_desc->bcn_wapi_ie, WLAN_EID_BSS_AC_ACCESS_DELAY))
    215		return true;
    216	return false;
    217}
    218
    219/*
    220 * This function checks if driver is configured with no security mode and
    221 * scanned network is compatible with it.
    222 */
    223static bool
    224mwifiex_is_bss_no_sec(struct mwifiex_private *priv,
    225		      struct mwifiex_bssdescriptor *bss_desc)
    226{
    227	if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
    228	    !priv->sec_info.wpa2_enabled &&
    229	    !has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC) &&
    230	    !has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN) &&
    231	    !priv->sec_info.encryption_mode && !bss_desc->privacy) {
    232		return true;
    233	}
    234	return false;
    235}
    236
    237/*
    238 * This function checks if static WEP is enabled in driver and scanned network
    239 * is compatible with it.
    240 */
    241static bool
    242mwifiex_is_bss_static_wep(struct mwifiex_private *priv,
    243			  struct mwifiex_bssdescriptor *bss_desc)
    244{
    245	if (priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
    246	    !priv->sec_info.wpa2_enabled && bss_desc->privacy) {
    247		return true;
    248	}
    249	return false;
    250}
    251
    252/*
    253 * This function checks if wpa is enabled in driver and scanned network is
    254 * compatible with it.
    255 */
    256static bool
    257mwifiex_is_bss_wpa(struct mwifiex_private *priv,
    258		   struct mwifiex_bssdescriptor *bss_desc)
    259{
    260	if (!priv->sec_info.wep_enabled && priv->sec_info.wpa_enabled &&
    261	    !priv->sec_info.wpa2_enabled &&
    262	    has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC)
    263	   /*
    264	    * Privacy bit may NOT be set in some APs like
    265	    * LinkSys WRT54G && bss_desc->privacy
    266	    */
    267	 ) {
    268		dbg_security_flags(INFO, "WPA", priv, bss_desc);
    269		return true;
    270	}
    271	return false;
    272}
    273
    274/*
    275 * This function checks if wpa2 is enabled in driver and scanned network is
    276 * compatible with it.
    277 */
    278static bool
    279mwifiex_is_bss_wpa2(struct mwifiex_private *priv,
    280		    struct mwifiex_bssdescriptor *bss_desc)
    281{
    282	if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
    283	    priv->sec_info.wpa2_enabled &&
    284	    has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN)) {
    285		/*
    286		 * Privacy bit may NOT be set in some APs like
    287		 * LinkSys WRT54G && bss_desc->privacy
    288		 */
    289		dbg_security_flags(INFO, "WAP2", priv, bss_desc);
    290		return true;
    291	}
    292	return false;
    293}
    294
    295/*
    296 * This function checks if adhoc AES is enabled in driver and scanned network is
    297 * compatible with it.
    298 */
    299static bool
    300mwifiex_is_bss_adhoc_aes(struct mwifiex_private *priv,
    301			 struct mwifiex_bssdescriptor *bss_desc)
    302{
    303	if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
    304	    !priv->sec_info.wpa2_enabled &&
    305	    !has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC) &&
    306	    !has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN) &&
    307	    !priv->sec_info.encryption_mode && bss_desc->privacy) {
    308		return true;
    309	}
    310	return false;
    311}
    312
    313/*
    314 * This function checks if dynamic WEP is enabled in driver and scanned network
    315 * is compatible with it.
    316 */
    317static bool
    318mwifiex_is_bss_dynamic_wep(struct mwifiex_private *priv,
    319			   struct mwifiex_bssdescriptor *bss_desc)
    320{
    321	if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled &&
    322	    !priv->sec_info.wpa2_enabled &&
    323	    !has_vendor_hdr(bss_desc->bcn_wpa_ie, WLAN_EID_VENDOR_SPECIFIC) &&
    324	    !has_ieee_hdr(bss_desc->bcn_rsn_ie, WLAN_EID_RSN) &&
    325	    priv->sec_info.encryption_mode && bss_desc->privacy) {
    326		dbg_security_flags(INFO, "dynamic", priv, bss_desc);
    327		return true;
    328	}
    329	return false;
    330}
    331
    332/*
    333 * This function checks if a scanned network is compatible with the driver
    334 * settings.
    335 *
    336 *   WEP     WPA    WPA2   ad-hoc encrypt                  Network
    337 * enabled enabled enabled  AES    mode   Privacy WPA WPA2 Compatible
    338 *    0       0       0      0     NONE      0     0   0   yes No security
    339 *    0       1       0      0      x        1x    1   x   yes WPA (disable
    340 *                                                         HT if no AES)
    341 *    0       0       1      0      x        1x    x   1   yes WPA2 (disable
    342 *                                                         HT if no AES)
    343 *    0       0       0      1     NONE      1     0   0   yes Ad-hoc AES
    344 *    1       0       0      0     NONE      1     0   0   yes Static WEP
    345 *                                                         (disable HT)
    346 *    0       0       0      0    !=NONE     1     0   0   yes Dynamic WEP
    347 *
    348 * Compatibility is not matched while roaming, except for mode.
    349 */
    350static s32
    351mwifiex_is_network_compatible(struct mwifiex_private *priv,
    352			      struct mwifiex_bssdescriptor *bss_desc, u32 mode)
    353{
    354	struct mwifiex_adapter *adapter = priv->adapter;
    355
    356	bss_desc->disable_11n = false;
    357
    358	/* Don't check for compatibility if roaming */
    359	if (priv->media_connected &&
    360	    (priv->bss_mode == NL80211_IFTYPE_STATION) &&
    361	    (bss_desc->bss_mode == NL80211_IFTYPE_STATION))
    362		return 0;
    363
    364	if (priv->wps.session_enable) {
    365		mwifiex_dbg(adapter, IOCTL,
    366			    "info: return success directly in WPS period\n");
    367		return 0;
    368	}
    369
    370	if (bss_desc->chan_sw_ie_present) {
    371		mwifiex_dbg(adapter, INFO,
    372			    "Don't connect to AP with WLAN_EID_CHANNEL_SWITCH\n");
    373		return -1;
    374	}
    375
    376	if (mwifiex_is_bss_wapi(priv, bss_desc)) {
    377		mwifiex_dbg(adapter, INFO,
    378			    "info: return success for WAPI AP\n");
    379		return 0;
    380	}
    381
    382	if (bss_desc->bss_mode == mode) {
    383		if (mwifiex_is_bss_no_sec(priv, bss_desc)) {
    384			/* No security */
    385			return 0;
    386		} else if (mwifiex_is_bss_static_wep(priv, bss_desc)) {
    387			/* Static WEP enabled */
    388			mwifiex_dbg(adapter, INFO,
    389				    "info: Disable 11n in WEP mode.\n");
    390			bss_desc->disable_11n = true;
    391			return 0;
    392		} else if (mwifiex_is_bss_wpa(priv, bss_desc)) {
    393			/* WPA enabled */
    394			if (((priv->adapter->config_bands & BAND_GN ||
    395			      priv->adapter->config_bands & BAND_AN) &&
    396			     bss_desc->bcn_ht_cap) &&
    397			    !mwifiex_is_wpa_oui_present(bss_desc,
    398							 CIPHER_SUITE_CCMP)) {
    399
    400				if (mwifiex_is_wpa_oui_present
    401						(bss_desc, CIPHER_SUITE_TKIP)) {
    402					mwifiex_dbg(adapter, INFO,
    403						    "info: Disable 11n if AES\t"
    404						    "is not supported by AP\n");
    405					bss_desc->disable_11n = true;
    406				} else {
    407					return -1;
    408				}
    409			}
    410			return 0;
    411		} else if (mwifiex_is_bss_wpa2(priv, bss_desc)) {
    412			/* WPA2 enabled */
    413			if (((priv->adapter->config_bands & BAND_GN ||
    414			      priv->adapter->config_bands & BAND_AN) &&
    415			     bss_desc->bcn_ht_cap) &&
    416			    !mwifiex_is_rsn_oui_present(bss_desc,
    417							CIPHER_SUITE_CCMP)) {
    418
    419				if (mwifiex_is_rsn_oui_present
    420						(bss_desc, CIPHER_SUITE_TKIP)) {
    421					mwifiex_dbg(adapter, INFO,
    422						    "info: Disable 11n if AES\t"
    423						    "is not supported by AP\n");
    424					bss_desc->disable_11n = true;
    425				} else {
    426					return -1;
    427				}
    428			}
    429			return 0;
    430		} else if (mwifiex_is_bss_adhoc_aes(priv, bss_desc)) {
    431			/* Ad-hoc AES enabled */
    432			return 0;
    433		} else if (mwifiex_is_bss_dynamic_wep(priv, bss_desc)) {
    434			/* Dynamic WEP enabled */
    435			return 0;
    436		}
    437
    438		/* Security doesn't match */
    439		dbg_security_flags(ERROR, "failed", priv, bss_desc);
    440		return -1;
    441	}
    442
    443	/* Mode doesn't match */
    444	return -1;
    445}
    446
    447/*
    448 * This function creates a channel list for the driver to scan, based
    449 * on region/band information.
    450 *
    451 * This routine is used for any scan that is not provided with a
    452 * specific channel list to scan.
    453 */
    454static int
    455mwifiex_scan_create_channel_list(struct mwifiex_private *priv,
    456				 const struct mwifiex_user_scan_cfg
    457							*user_scan_in,
    458				 struct mwifiex_chan_scan_param_set
    459							*scan_chan_list,
    460				 u8 filtered_scan)
    461{
    462	enum nl80211_band band;
    463	struct ieee80211_supported_band *sband;
    464	struct ieee80211_channel *ch;
    465	struct mwifiex_adapter *adapter = priv->adapter;
    466	int chan_idx = 0, i;
    467
    468	for (band = 0; (band < NUM_NL80211_BANDS) ; band++) {
    469
    470		if (!priv->wdev.wiphy->bands[band])
    471			continue;
    472
    473		sband = priv->wdev.wiphy->bands[band];
    474
    475		for (i = 0; (i < sband->n_channels) ; i++) {
    476			ch = &sband->channels[i];
    477			if (ch->flags & IEEE80211_CHAN_DISABLED)
    478				continue;
    479			scan_chan_list[chan_idx].radio_type = band;
    480
    481			if (user_scan_in &&
    482			    user_scan_in->chan_list[0].scan_time)
    483				scan_chan_list[chan_idx].max_scan_time =
    484					cpu_to_le16((u16) user_scan_in->
    485					chan_list[0].scan_time);
    486			else if ((ch->flags & IEEE80211_CHAN_NO_IR) ||
    487				 (ch->flags & IEEE80211_CHAN_RADAR))
    488				scan_chan_list[chan_idx].max_scan_time =
    489					cpu_to_le16(adapter->passive_scan_time);
    490			else
    491				scan_chan_list[chan_idx].max_scan_time =
    492					cpu_to_le16(adapter->active_scan_time);
    493
    494			if (ch->flags & IEEE80211_CHAN_NO_IR)
    495				scan_chan_list[chan_idx].chan_scan_mode_bitmap
    496					|= (MWIFIEX_PASSIVE_SCAN |
    497					    MWIFIEX_HIDDEN_SSID_REPORT);
    498			else
    499				scan_chan_list[chan_idx].chan_scan_mode_bitmap
    500					&= ~MWIFIEX_PASSIVE_SCAN;
    501			scan_chan_list[chan_idx].chan_number =
    502							(u32) ch->hw_value;
    503
    504			scan_chan_list[chan_idx].chan_scan_mode_bitmap
    505					|= MWIFIEX_DISABLE_CHAN_FILT;
    506
    507			if (filtered_scan &&
    508			    !((ch->flags & IEEE80211_CHAN_NO_IR) ||
    509			      (ch->flags & IEEE80211_CHAN_RADAR)))
    510				scan_chan_list[chan_idx].max_scan_time =
    511				cpu_to_le16(adapter->specific_scan_time);
    512
    513			chan_idx++;
    514		}
    515
    516	}
    517	return chan_idx;
    518}
    519
    520/* This function creates a channel list tlv for bgscan config, based
    521 * on region/band information.
    522 */
    523static int
    524mwifiex_bgscan_create_channel_list(struct mwifiex_private *priv,
    525				   const struct mwifiex_bg_scan_cfg
    526						*bgscan_cfg_in,
    527				   struct mwifiex_chan_scan_param_set
    528						*scan_chan_list)
    529{
    530	enum nl80211_band band;
    531	struct ieee80211_supported_band *sband;
    532	struct ieee80211_channel *ch;
    533	struct mwifiex_adapter *adapter = priv->adapter;
    534	int chan_idx = 0, i;
    535
    536	for (band = 0; (band < NUM_NL80211_BANDS); band++) {
    537		if (!priv->wdev.wiphy->bands[band])
    538			continue;
    539
    540		sband = priv->wdev.wiphy->bands[band];
    541
    542		for (i = 0; (i < sband->n_channels) ; i++) {
    543			ch = &sband->channels[i];
    544			if (ch->flags & IEEE80211_CHAN_DISABLED)
    545				continue;
    546			scan_chan_list[chan_idx].radio_type = band;
    547
    548			if (bgscan_cfg_in->chan_list[0].scan_time)
    549				scan_chan_list[chan_idx].max_scan_time =
    550					cpu_to_le16((u16)bgscan_cfg_in->
    551					chan_list[0].scan_time);
    552			else if (ch->flags & IEEE80211_CHAN_NO_IR)
    553				scan_chan_list[chan_idx].max_scan_time =
    554					cpu_to_le16(adapter->passive_scan_time);
    555			else
    556				scan_chan_list[chan_idx].max_scan_time =
    557					cpu_to_le16(adapter->
    558						    specific_scan_time);
    559
    560			if (ch->flags & IEEE80211_CHAN_NO_IR)
    561				scan_chan_list[chan_idx].chan_scan_mode_bitmap
    562					|= MWIFIEX_PASSIVE_SCAN;
    563			else
    564				scan_chan_list[chan_idx].chan_scan_mode_bitmap
    565					&= ~MWIFIEX_PASSIVE_SCAN;
    566
    567			scan_chan_list[chan_idx].chan_number =
    568							(u32)ch->hw_value;
    569			chan_idx++;
    570		}
    571	}
    572	return chan_idx;
    573}
    574
    575/* This function appends rate TLV to scan config command. */
    576static int
    577mwifiex_append_rate_tlv(struct mwifiex_private *priv,
    578			struct mwifiex_scan_cmd_config *scan_cfg_out,
    579			u8 radio)
    580{
    581	struct mwifiex_ie_types_rates_param_set *rates_tlv;
    582	u8 rates[MWIFIEX_SUPPORTED_RATES], *tlv_pos;
    583	u32 rates_size;
    584
    585	memset(rates, 0, sizeof(rates));
    586
    587	tlv_pos = (u8 *)scan_cfg_out->tlv_buf + scan_cfg_out->tlv_buf_len;
    588
    589	if (priv->scan_request)
    590		rates_size = mwifiex_get_rates_from_cfg80211(priv, rates,
    591							     radio);
    592	else
    593		rates_size = mwifiex_get_supported_rates(priv, rates);
    594
    595	mwifiex_dbg(priv->adapter, CMD,
    596		    "info: SCAN_CMD: Rates size = %d\n",
    597		rates_size);
    598	rates_tlv = (struct mwifiex_ie_types_rates_param_set *)tlv_pos;
    599	rates_tlv->header.type = cpu_to_le16(WLAN_EID_SUPP_RATES);
    600	rates_tlv->header.len = cpu_to_le16((u16) rates_size);
    601	memcpy(rates_tlv->rates, rates, rates_size);
    602	scan_cfg_out->tlv_buf_len += sizeof(rates_tlv->header) + rates_size;
    603
    604	return rates_size;
    605}
    606
    607/*
    608 * This function constructs and sends multiple scan config commands to
    609 * the firmware.
    610 *
    611 * Previous routines in the code flow have created a scan command configuration
    612 * with any requested TLVs.  This function splits the channel TLV into maximum
    613 * channels supported per scan lists and sends the portion of the channel TLV,
    614 * along with the other TLVs, to the firmware.
    615 */
    616static int
    617mwifiex_scan_channel_list(struct mwifiex_private *priv,
    618			  u32 max_chan_per_scan, u8 filtered_scan,
    619			  struct mwifiex_scan_cmd_config *scan_cfg_out,
    620			  struct mwifiex_ie_types_chan_list_param_set
    621			  *chan_tlv_out,
    622			  struct mwifiex_chan_scan_param_set *scan_chan_list)
    623{
    624	struct mwifiex_adapter *adapter = priv->adapter;
    625	int ret = 0;
    626	struct mwifiex_chan_scan_param_set *tmp_chan_list;
    627	struct mwifiex_chan_scan_param_set *start_chan;
    628	u32 tlv_idx, rates_size, cmd_no;
    629	u32 total_scan_time;
    630	u32 done_early;
    631	u8 radio_type;
    632
    633	if (!scan_cfg_out || !chan_tlv_out || !scan_chan_list) {
    634		mwifiex_dbg(priv->adapter, ERROR,
    635			    "info: Scan: Null detect: %p, %p, %p\n",
    636			    scan_cfg_out, chan_tlv_out, scan_chan_list);
    637		return -1;
    638	}
    639
    640	/* Check csa channel expiry before preparing scan list */
    641	mwifiex_11h_get_csa_closed_channel(priv);
    642
    643	chan_tlv_out->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
    644
    645	/* Set the temp channel struct pointer to the start of the desired
    646	   list */
    647	tmp_chan_list = scan_chan_list;
    648
    649	/* Loop through the desired channel list, sending a new firmware scan
    650	   commands for each max_chan_per_scan channels (or for 1,6,11
    651	   individually if configured accordingly) */
    652	while (tmp_chan_list->chan_number) {
    653
    654		tlv_idx = 0;
    655		total_scan_time = 0;
    656		radio_type = 0;
    657		chan_tlv_out->header.len = 0;
    658		start_chan = tmp_chan_list;
    659		done_early = false;
    660
    661		/*
    662		 * Construct the Channel TLV for the scan command.  Continue to
    663		 * insert channel TLVs until:
    664		 *   - the tlv_idx hits the maximum configured per scan command
    665		 *   - the next channel to insert is 0 (end of desired channel
    666		 *     list)
    667		 *   - done_early is set (controlling individual scanning of
    668		 *     1,6,11)
    669		 */
    670		while (tlv_idx < max_chan_per_scan &&
    671		       tmp_chan_list->chan_number && !done_early) {
    672
    673			if (tmp_chan_list->chan_number == priv->csa_chan) {
    674				tmp_chan_list++;
    675				continue;
    676			}
    677
    678			radio_type = tmp_chan_list->radio_type;
    679			mwifiex_dbg(priv->adapter, INFO,
    680				    "info: Scan: Chan(%3d), Radio(%d),\t"
    681				    "Mode(%d, %d), Dur(%d)\n",
    682				    tmp_chan_list->chan_number,
    683				    tmp_chan_list->radio_type,
    684				    tmp_chan_list->chan_scan_mode_bitmap
    685				    & MWIFIEX_PASSIVE_SCAN,
    686				    (tmp_chan_list->chan_scan_mode_bitmap
    687				    & MWIFIEX_DISABLE_CHAN_FILT) >> 1,
    688				    le16_to_cpu(tmp_chan_list->max_scan_time));
    689
    690			/* Copy the current channel TLV to the command being
    691			   prepared */
    692			memcpy(chan_tlv_out->chan_scan_param + tlv_idx,
    693			       tmp_chan_list,
    694			       sizeof(chan_tlv_out->chan_scan_param));
    695
    696			/* Increment the TLV header length by the size
    697			   appended */
    698			le16_unaligned_add_cpu(&chan_tlv_out->header.len,
    699					       sizeof(
    700						chan_tlv_out->chan_scan_param));
    701
    702			/*
    703			 * The tlv buffer length is set to the number of bytes
    704			 * of the between the channel tlv pointer and the start
    705			 * of the tlv buffer.  This compensates for any TLVs
    706			 * that were appended before the channel list.
    707			 */
    708			scan_cfg_out->tlv_buf_len = (u32) ((u8 *) chan_tlv_out -
    709							scan_cfg_out->tlv_buf);
    710
    711			/* Add the size of the channel tlv header and the data
    712			   length */
    713			scan_cfg_out->tlv_buf_len +=
    714				(sizeof(chan_tlv_out->header)
    715				 + le16_to_cpu(chan_tlv_out->header.len));
    716
    717			/* Increment the index to the channel tlv we are
    718			   constructing */
    719			tlv_idx++;
    720
    721			/* Count the total scan time per command */
    722			total_scan_time +=
    723				le16_to_cpu(tmp_chan_list->max_scan_time);
    724
    725			done_early = false;
    726
    727			/* Stop the loop if the *current* channel is in the
    728			   1,6,11 set and we are not filtering on a BSSID
    729			   or SSID. */
    730			if (!filtered_scan &&
    731			    (tmp_chan_list->chan_number == 1 ||
    732			     tmp_chan_list->chan_number == 6 ||
    733			     tmp_chan_list->chan_number == 11))
    734				done_early = true;
    735
    736			/* Increment the tmp pointer to the next channel to
    737			   be scanned */
    738			tmp_chan_list++;
    739
    740			/* Stop the loop if the *next* channel is in the 1,6,11
    741			   set.  This will cause it to be the only channel
    742			   scanned on the next interation */
    743			if (!filtered_scan &&
    744			    (tmp_chan_list->chan_number == 1 ||
    745			     tmp_chan_list->chan_number == 6 ||
    746			     tmp_chan_list->chan_number == 11))
    747				done_early = true;
    748		}
    749
    750		/* The total scan time should be less than scan command timeout
    751		   value */
    752		if (total_scan_time > MWIFIEX_MAX_TOTAL_SCAN_TIME) {
    753			mwifiex_dbg(priv->adapter, ERROR,
    754				    "total scan time %dms\t"
    755				    "is over limit (%dms), scan skipped\n",
    756				    total_scan_time,
    757				    MWIFIEX_MAX_TOTAL_SCAN_TIME);
    758			ret = -1;
    759			break;
    760		}
    761
    762		rates_size = mwifiex_append_rate_tlv(priv, scan_cfg_out,
    763						     radio_type);
    764
    765		priv->adapter->scan_channels = start_chan;
    766
    767		/* Send the scan command to the firmware with the specified
    768		   cfg */
    769		if (priv->adapter->ext_scan)
    770			cmd_no = HostCmd_CMD_802_11_SCAN_EXT;
    771		else
    772			cmd_no = HostCmd_CMD_802_11_SCAN;
    773
    774		ret = mwifiex_send_cmd(priv, cmd_no, HostCmd_ACT_GEN_SET,
    775				       0, scan_cfg_out, false);
    776
    777		/* rate IE is updated per scan command but same starting
    778		 * pointer is used each time so that rate IE from earlier
    779		 * scan_cfg_out->buf is overwritten with new one.
    780		 */
    781		scan_cfg_out->tlv_buf_len -=
    782			    sizeof(struct mwifiex_ie_types_header) + rates_size;
    783
    784		if (ret) {
    785			mwifiex_cancel_pending_scan_cmd(adapter);
    786			break;
    787		}
    788	}
    789
    790	if (ret)
    791		return -1;
    792
    793	return 0;
    794}
    795
    796/*
    797 * This function constructs a scan command configuration structure to use
    798 * in scan commands.
    799 *
    800 * Application layer or other functions can invoke network scanning
    801 * with a scan configuration supplied in a user scan configuration structure.
    802 * This structure is used as the basis of one or many scan command configuration
    803 * commands that are sent to the command processing module and eventually to the
    804 * firmware.
    805 *
    806 * This function creates a scan command configuration structure  based on the
    807 * following user supplied parameters (if present):
    808 *      - SSID filter
    809 *      - BSSID filter
    810 *      - Number of Probes to be sent
    811 *      - Channel list
    812 *
    813 * If the SSID or BSSID filter is not present, the filter is disabled/cleared.
    814 * If the number of probes is not set, adapter default setting is used.
    815 */
    816static void
    817mwifiex_config_scan(struct mwifiex_private *priv,
    818		    const struct mwifiex_user_scan_cfg *user_scan_in,
    819		    struct mwifiex_scan_cmd_config *scan_cfg_out,
    820		    struct mwifiex_ie_types_chan_list_param_set **chan_list_out,
    821		    struct mwifiex_chan_scan_param_set *scan_chan_list,
    822		    u8 *max_chan_per_scan, u8 *filtered_scan,
    823		    u8 *scan_current_only)
    824{
    825	struct mwifiex_adapter *adapter = priv->adapter;
    826	struct mwifiex_ie_types_num_probes *num_probes_tlv;
    827	struct mwifiex_ie_types_scan_chan_gap *chan_gap_tlv;
    828	struct mwifiex_ie_types_random_mac *random_mac_tlv;
    829	struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv;
    830	struct mwifiex_ie_types_bssid_list *bssid_tlv;
    831	u8 *tlv_pos;
    832	u32 num_probes;
    833	u32 ssid_len;
    834	u32 chan_idx;
    835	u32 scan_type;
    836	u16 scan_dur;
    837	u8 channel;
    838	u8 radio_type;
    839	int i;
    840	u8 ssid_filter;
    841	struct mwifiex_ie_types_htcap *ht_cap;
    842	struct mwifiex_ie_types_bss_mode *bss_mode;
    843	const u8 zero_mac[6] = {0, 0, 0, 0, 0, 0};
    844
    845	/* The tlv_buf_len is calculated for each scan command.  The TLVs added
    846	   in this routine will be preserved since the routine that sends the
    847	   command will append channelTLVs at *chan_list_out.  The difference
    848	   between the *chan_list_out and the tlv_buf start will be used to
    849	   calculate the size of anything we add in this routine. */
    850	scan_cfg_out->tlv_buf_len = 0;
    851
    852	/* Running tlv pointer.  Assigned to chan_list_out at end of function
    853	   so later routines know where channels can be added to the command
    854	   buf */
    855	tlv_pos = scan_cfg_out->tlv_buf;
    856
    857	/* Initialize the scan as un-filtered; the flag is later set to TRUE
    858	   below if a SSID or BSSID filter is sent in the command */
    859	*filtered_scan = false;
    860
    861	/* Initialize the scan as not being only on the current channel.  If
    862	   the channel list is customized, only contains one channel, and is
    863	   the active channel, this is set true and data flow is not halted. */
    864	*scan_current_only = false;
    865
    866	if (user_scan_in) {
    867		u8 tmpaddr[ETH_ALEN];
    868
    869		/* Default the ssid_filter flag to TRUE, set false under
    870		   certain wildcard conditions and qualified by the existence
    871		   of an SSID list before marking the scan as filtered */
    872		ssid_filter = true;
    873
    874		/* Set the BSS type scan filter, use Adapter setting if
    875		   unset */
    876		scan_cfg_out->bss_mode =
    877			(u8)(user_scan_in->bss_mode ?: adapter->scan_mode);
    878
    879		/* Set the number of probes to send, use Adapter setting
    880		   if unset */
    881		num_probes = user_scan_in->num_probes ?: adapter->scan_probes;
    882
    883		/*
    884		 * Set the BSSID filter to the incoming configuration,
    885		 * if non-zero.  If not set, it will remain disabled
    886		 * (all zeros).
    887		 */
    888		memcpy(scan_cfg_out->specific_bssid,
    889		       user_scan_in->specific_bssid,
    890		       sizeof(scan_cfg_out->specific_bssid));
    891
    892		memcpy(tmpaddr, scan_cfg_out->specific_bssid, ETH_ALEN);
    893
    894		if (adapter->ext_scan &&
    895		    !is_zero_ether_addr(tmpaddr)) {
    896			bssid_tlv =
    897				(struct mwifiex_ie_types_bssid_list *)tlv_pos;
    898			bssid_tlv->header.type = cpu_to_le16(TLV_TYPE_BSSID);
    899			bssid_tlv->header.len = cpu_to_le16(ETH_ALEN);
    900			memcpy(bssid_tlv->bssid, user_scan_in->specific_bssid,
    901			       ETH_ALEN);
    902			tlv_pos += sizeof(struct mwifiex_ie_types_bssid_list);
    903		}
    904
    905		for (i = 0; i < user_scan_in->num_ssids; i++) {
    906			ssid_len = user_scan_in->ssid_list[i].ssid_len;
    907
    908			wildcard_ssid_tlv =
    909				(struct mwifiex_ie_types_wildcard_ssid_params *)
    910				tlv_pos;
    911			wildcard_ssid_tlv->header.type =
    912				cpu_to_le16(TLV_TYPE_WILDCARDSSID);
    913			wildcard_ssid_tlv->header.len = cpu_to_le16(
    914				(u16) (ssid_len + sizeof(wildcard_ssid_tlv->
    915							 max_ssid_length)));
    916
    917			/*
    918			 * max_ssid_length = 0 tells firmware to perform
    919			 * specific scan for the SSID filled, whereas
    920			 * max_ssid_length = IEEE80211_MAX_SSID_LEN is for
    921			 * wildcard scan.
    922			 */
    923			if (ssid_len)
    924				wildcard_ssid_tlv->max_ssid_length = 0;
    925			else
    926				wildcard_ssid_tlv->max_ssid_length =
    927							IEEE80211_MAX_SSID_LEN;
    928
    929			if (!memcmp(user_scan_in->ssid_list[i].ssid,
    930				    "DIRECT-", 7))
    931				wildcard_ssid_tlv->max_ssid_length = 0xfe;
    932
    933			memcpy(wildcard_ssid_tlv->ssid,
    934			       user_scan_in->ssid_list[i].ssid, ssid_len);
    935
    936			tlv_pos += (sizeof(wildcard_ssid_tlv->header)
    937				+ le16_to_cpu(wildcard_ssid_tlv->header.len));
    938
    939			mwifiex_dbg(adapter, INFO,
    940				    "info: scan: ssid[%d]: %s, %d\n",
    941				    i, wildcard_ssid_tlv->ssid,
    942				    wildcard_ssid_tlv->max_ssid_length);
    943
    944			/* Empty wildcard ssid with a maxlen will match many or
    945			   potentially all SSIDs (maxlen == 32), therefore do
    946			   not treat the scan as
    947			   filtered. */
    948			if (!ssid_len && wildcard_ssid_tlv->max_ssid_length)
    949				ssid_filter = false;
    950		}
    951
    952		/*
    953		 *  The default number of channels sent in the command is low to
    954		 *  ensure the response buffer from the firmware does not
    955		 *  truncate scan results.  That is not an issue with an SSID
    956		 *  or BSSID filter applied to the scan results in the firmware.
    957		 */
    958		memcpy(tmpaddr, scan_cfg_out->specific_bssid, ETH_ALEN);
    959		if ((i && ssid_filter) ||
    960		    !is_zero_ether_addr(tmpaddr))
    961			*filtered_scan = true;
    962
    963		if (user_scan_in->scan_chan_gap) {
    964			mwifiex_dbg(adapter, INFO,
    965				    "info: scan: channel gap = %d\n",
    966				    user_scan_in->scan_chan_gap);
    967			*max_chan_per_scan =
    968					MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN;
    969
    970			chan_gap_tlv = (void *)tlv_pos;
    971			chan_gap_tlv->header.type =
    972					 cpu_to_le16(TLV_TYPE_SCAN_CHANNEL_GAP);
    973			chan_gap_tlv->header.len =
    974				    cpu_to_le16(sizeof(chan_gap_tlv->chan_gap));
    975			chan_gap_tlv->chan_gap =
    976				     cpu_to_le16((user_scan_in->scan_chan_gap));
    977			tlv_pos +=
    978				  sizeof(struct mwifiex_ie_types_scan_chan_gap);
    979		}
    980
    981		if (!ether_addr_equal(user_scan_in->random_mac, zero_mac)) {
    982			random_mac_tlv = (void *)tlv_pos;
    983			random_mac_tlv->header.type =
    984					 cpu_to_le16(TLV_TYPE_RANDOM_MAC);
    985			random_mac_tlv->header.len =
    986				    cpu_to_le16(sizeof(random_mac_tlv->mac));
    987			ether_addr_copy(random_mac_tlv->mac,
    988					user_scan_in->random_mac);
    989			tlv_pos +=
    990				  sizeof(struct mwifiex_ie_types_random_mac);
    991		}
    992	} else {
    993		scan_cfg_out->bss_mode = (u8) adapter->scan_mode;
    994		num_probes = adapter->scan_probes;
    995	}
    996
    997	/*
    998	 *  If a specific BSSID or SSID is used, the number of channels in the
    999	 *  scan command will be increased to the absolute maximum.
   1000	 */
   1001	if (*filtered_scan) {
   1002		*max_chan_per_scan = MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN;
   1003	} else {
   1004		if (!priv->media_connected)
   1005			*max_chan_per_scan = MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD;
   1006		else
   1007			*max_chan_per_scan =
   1008					MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD / 2;
   1009	}
   1010
   1011	if (adapter->ext_scan) {
   1012		bss_mode = (struct mwifiex_ie_types_bss_mode *)tlv_pos;
   1013		bss_mode->header.type = cpu_to_le16(TLV_TYPE_BSS_MODE);
   1014		bss_mode->header.len = cpu_to_le16(sizeof(bss_mode->bss_mode));
   1015		bss_mode->bss_mode = scan_cfg_out->bss_mode;
   1016		tlv_pos += sizeof(bss_mode->header) +
   1017			   le16_to_cpu(bss_mode->header.len);
   1018	}
   1019
   1020	/* If the input config or adapter has the number of Probes set,
   1021	   add tlv */
   1022	if (num_probes) {
   1023
   1024		mwifiex_dbg(adapter, INFO,
   1025			    "info: scan: num_probes = %d\n",
   1026			    num_probes);
   1027
   1028		num_probes_tlv = (struct mwifiex_ie_types_num_probes *) tlv_pos;
   1029		num_probes_tlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES);
   1030		num_probes_tlv->header.len =
   1031			cpu_to_le16(sizeof(num_probes_tlv->num_probes));
   1032		num_probes_tlv->num_probes = cpu_to_le16((u16) num_probes);
   1033
   1034		tlv_pos += sizeof(num_probes_tlv->header) +
   1035			le16_to_cpu(num_probes_tlv->header.len);
   1036
   1037	}
   1038
   1039	if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info) &&
   1040	    (priv->adapter->config_bands & BAND_GN ||
   1041	     priv->adapter->config_bands & BAND_AN)) {
   1042		ht_cap = (struct mwifiex_ie_types_htcap *) tlv_pos;
   1043		memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap));
   1044		ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY);
   1045		ht_cap->header.len =
   1046				cpu_to_le16(sizeof(struct ieee80211_ht_cap));
   1047		radio_type =
   1048			mwifiex_band_to_radio_type(priv->adapter->config_bands);
   1049		mwifiex_fill_cap_info(priv, radio_type, &ht_cap->ht_cap);
   1050		tlv_pos += sizeof(struct mwifiex_ie_types_htcap);
   1051	}
   1052
   1053	/* Append vendor specific IE TLV */
   1054	mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_SCAN, &tlv_pos);
   1055
   1056	/*
   1057	 * Set the output for the channel TLV to the address in the tlv buffer
   1058	 *   past any TLVs that were added in this function (SSID, num_probes).
   1059	 *   Channel TLVs will be added past this for each scan command,
   1060	 *   preserving the TLVs that were previously added.
   1061	 */
   1062	*chan_list_out =
   1063		(struct mwifiex_ie_types_chan_list_param_set *) tlv_pos;
   1064
   1065	if (user_scan_in && user_scan_in->chan_list[0].chan_number) {
   1066
   1067		mwifiex_dbg(adapter, INFO,
   1068			    "info: Scan: Using supplied channel list\n");
   1069
   1070		for (chan_idx = 0;
   1071		     chan_idx < MWIFIEX_USER_SCAN_CHAN_MAX &&
   1072		     user_scan_in->chan_list[chan_idx].chan_number;
   1073		     chan_idx++) {
   1074
   1075			channel = user_scan_in->chan_list[chan_idx].chan_number;
   1076			scan_chan_list[chan_idx].chan_number = channel;
   1077
   1078			radio_type =
   1079				user_scan_in->chan_list[chan_idx].radio_type;
   1080			scan_chan_list[chan_idx].radio_type = radio_type;
   1081
   1082			scan_type = user_scan_in->chan_list[chan_idx].scan_type;
   1083
   1084			if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
   1085				scan_chan_list[chan_idx].chan_scan_mode_bitmap
   1086					|= (MWIFIEX_PASSIVE_SCAN |
   1087					    MWIFIEX_HIDDEN_SSID_REPORT);
   1088			else
   1089				scan_chan_list[chan_idx].chan_scan_mode_bitmap
   1090					&= ~MWIFIEX_PASSIVE_SCAN;
   1091
   1092			scan_chan_list[chan_idx].chan_scan_mode_bitmap
   1093				|= MWIFIEX_DISABLE_CHAN_FILT;
   1094
   1095			if (user_scan_in->chan_list[chan_idx].scan_time) {
   1096				scan_dur = (u16) user_scan_in->
   1097					chan_list[chan_idx].scan_time;
   1098			} else {
   1099				if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
   1100					scan_dur = adapter->passive_scan_time;
   1101				else if (*filtered_scan)
   1102					scan_dur = adapter->specific_scan_time;
   1103				else
   1104					scan_dur = adapter->active_scan_time;
   1105			}
   1106
   1107			scan_chan_list[chan_idx].min_scan_time =
   1108				cpu_to_le16(scan_dur);
   1109			scan_chan_list[chan_idx].max_scan_time =
   1110				cpu_to_le16(scan_dur);
   1111		}
   1112
   1113		/* Check if we are only scanning the current channel */
   1114		if ((chan_idx == 1) &&
   1115		    (user_scan_in->chan_list[0].chan_number ==
   1116		     priv->curr_bss_params.bss_descriptor.channel)) {
   1117			*scan_current_only = true;
   1118			mwifiex_dbg(adapter, INFO,
   1119				    "info: Scan: Scanning current channel only\n");
   1120		}
   1121	} else {
   1122		mwifiex_dbg(adapter, INFO,
   1123			    "info: Scan: Creating full region channel list\n");
   1124		mwifiex_scan_create_channel_list(priv, user_scan_in,
   1125						 scan_chan_list,
   1126						 *filtered_scan);
   1127	}
   1128
   1129}
   1130
   1131/*
   1132 * This function inspects the scan response buffer for pointers to
   1133 * expected TLVs.
   1134 *
   1135 * TLVs can be included at the end of the scan response BSS information.
   1136 *
   1137 * Data in the buffer is parsed pointers to TLVs that can potentially
   1138 * be passed back in the response.
   1139 */
   1140static void
   1141mwifiex_ret_802_11_scan_get_tlv_ptrs(struct mwifiex_adapter *adapter,
   1142				     struct mwifiex_ie_types_data *tlv,
   1143				     u32 tlv_buf_size, u32 req_tlv_type,
   1144				     struct mwifiex_ie_types_data **tlv_data)
   1145{
   1146	struct mwifiex_ie_types_data *current_tlv;
   1147	u32 tlv_buf_left;
   1148	u32 tlv_type;
   1149	u32 tlv_len;
   1150
   1151	current_tlv = tlv;
   1152	tlv_buf_left = tlv_buf_size;
   1153	*tlv_data = NULL;
   1154
   1155	mwifiex_dbg(adapter, INFO,
   1156		    "info: SCAN_RESP: tlv_buf_size = %d\n",
   1157		    tlv_buf_size);
   1158
   1159	while (tlv_buf_left >= sizeof(struct mwifiex_ie_types_header)) {
   1160
   1161		tlv_type = le16_to_cpu(current_tlv->header.type);
   1162		tlv_len = le16_to_cpu(current_tlv->header.len);
   1163
   1164		if (sizeof(tlv->header) + tlv_len > tlv_buf_left) {
   1165			mwifiex_dbg(adapter, ERROR,
   1166				    "SCAN_RESP: TLV buffer corrupt\n");
   1167			break;
   1168		}
   1169
   1170		if (req_tlv_type == tlv_type) {
   1171			switch (tlv_type) {
   1172			case TLV_TYPE_TSFTIMESTAMP:
   1173				mwifiex_dbg(adapter, INFO,
   1174					    "info: SCAN_RESP: TSF\t"
   1175					    "timestamp TLV, len = %d\n",
   1176					    tlv_len);
   1177				*tlv_data = current_tlv;
   1178				break;
   1179			case TLV_TYPE_CHANNELBANDLIST:
   1180				mwifiex_dbg(adapter, INFO,
   1181					    "info: SCAN_RESP: channel\t"
   1182					    "band list TLV, len = %d\n",
   1183					    tlv_len);
   1184				*tlv_data = current_tlv;
   1185				break;
   1186			default:
   1187				mwifiex_dbg(adapter, ERROR,
   1188					    "SCAN_RESP: unhandled TLV = %d\n",
   1189					    tlv_type);
   1190				/* Give up, this seems corrupted */
   1191				return;
   1192			}
   1193		}
   1194
   1195		if (*tlv_data)
   1196			break;
   1197
   1198
   1199		tlv_buf_left -= (sizeof(tlv->header) + tlv_len);
   1200		current_tlv =
   1201			(struct mwifiex_ie_types_data *) (current_tlv->data +
   1202							  tlv_len);
   1203
   1204	}			/* while */
   1205}
   1206
   1207/*
   1208 * This function parses provided beacon buffer and updates
   1209 * respective fields in bss descriptor structure.
   1210 */
   1211int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
   1212				    struct mwifiex_bssdescriptor *bss_entry)
   1213{
   1214	u8 element_id;
   1215	struct ieee_types_fh_param_set *fh_param_set;
   1216	struct ieee_types_ds_param_set *ds_param_set;
   1217	struct ieee_types_cf_param_set *cf_param_set;
   1218	struct ieee_types_ibss_param_set *ibss_param_set;
   1219	u8 *current_ptr;
   1220	u8 *rate;
   1221	u8 element_len;
   1222	u16 total_ie_len;
   1223	u8 bytes_to_copy;
   1224	u8 rate_size;
   1225	u8 found_data_rate_ie;
   1226	u32 bytes_left;
   1227	struct ieee_types_vendor_specific *vendor_ie;
   1228	const u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 };
   1229	const u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
   1230
   1231	found_data_rate_ie = false;
   1232	rate_size = 0;
   1233	current_ptr = bss_entry->beacon_buf;
   1234	bytes_left = bss_entry->beacon_buf_size;
   1235
   1236	/* Process variable IE */
   1237	while (bytes_left >= 2) {
   1238		element_id = *current_ptr;
   1239		element_len = *(current_ptr + 1);
   1240		total_ie_len = element_len + sizeof(struct ieee_types_header);
   1241
   1242		if (bytes_left < total_ie_len) {
   1243			mwifiex_dbg(adapter, ERROR,
   1244				    "err: InterpretIE: in processing\t"
   1245				    "IE, bytes left < IE length\n");
   1246			return -EINVAL;
   1247		}
   1248		switch (element_id) {
   1249		case WLAN_EID_SSID:
   1250			if (element_len > IEEE80211_MAX_SSID_LEN)
   1251				return -EINVAL;
   1252			bss_entry->ssid.ssid_len = element_len;
   1253			memcpy(bss_entry->ssid.ssid, (current_ptr + 2),
   1254			       element_len);
   1255			mwifiex_dbg(adapter, INFO,
   1256				    "info: InterpretIE: ssid: %-32s\n",
   1257				    bss_entry->ssid.ssid);
   1258			break;
   1259
   1260		case WLAN_EID_SUPP_RATES:
   1261			if (element_len > MWIFIEX_SUPPORTED_RATES)
   1262				return -EINVAL;
   1263			memcpy(bss_entry->data_rates, current_ptr + 2,
   1264			       element_len);
   1265			memcpy(bss_entry->supported_rates, current_ptr + 2,
   1266			       element_len);
   1267			rate_size = element_len;
   1268			found_data_rate_ie = true;
   1269			break;
   1270
   1271		case WLAN_EID_FH_PARAMS:
   1272			if (total_ie_len < sizeof(*fh_param_set))
   1273				return -EINVAL;
   1274			fh_param_set =
   1275				(struct ieee_types_fh_param_set *) current_ptr;
   1276			memcpy(&bss_entry->phy_param_set.fh_param_set,
   1277			       fh_param_set,
   1278			       sizeof(struct ieee_types_fh_param_set));
   1279			break;
   1280
   1281		case WLAN_EID_DS_PARAMS:
   1282			if (total_ie_len < sizeof(*ds_param_set))
   1283				return -EINVAL;
   1284			ds_param_set =
   1285				(struct ieee_types_ds_param_set *) current_ptr;
   1286
   1287			bss_entry->channel = ds_param_set->current_chan;
   1288
   1289			memcpy(&bss_entry->phy_param_set.ds_param_set,
   1290			       ds_param_set,
   1291			       sizeof(struct ieee_types_ds_param_set));
   1292			break;
   1293
   1294		case WLAN_EID_CF_PARAMS:
   1295			if (total_ie_len < sizeof(*cf_param_set))
   1296				return -EINVAL;
   1297			cf_param_set =
   1298				(struct ieee_types_cf_param_set *) current_ptr;
   1299			memcpy(&bss_entry->ss_param_set.cf_param_set,
   1300			       cf_param_set,
   1301			       sizeof(struct ieee_types_cf_param_set));
   1302			break;
   1303
   1304		case WLAN_EID_IBSS_PARAMS:
   1305			if (total_ie_len < sizeof(*ibss_param_set))
   1306				return -EINVAL;
   1307			ibss_param_set =
   1308				(struct ieee_types_ibss_param_set *)
   1309				current_ptr;
   1310			memcpy(&bss_entry->ss_param_set.ibss_param_set,
   1311			       ibss_param_set,
   1312			       sizeof(struct ieee_types_ibss_param_set));
   1313			break;
   1314
   1315		case WLAN_EID_ERP_INFO:
   1316			if (!element_len)
   1317				return -EINVAL;
   1318			bss_entry->erp_flags = *(current_ptr + 2);
   1319			break;
   1320
   1321		case WLAN_EID_PWR_CONSTRAINT:
   1322			if (!element_len)
   1323				return -EINVAL;
   1324			bss_entry->local_constraint = *(current_ptr + 2);
   1325			bss_entry->sensed_11h = true;
   1326			break;
   1327
   1328		case WLAN_EID_CHANNEL_SWITCH:
   1329			bss_entry->chan_sw_ie_present = true;
   1330			fallthrough;
   1331		case WLAN_EID_PWR_CAPABILITY:
   1332		case WLAN_EID_TPC_REPORT:
   1333		case WLAN_EID_QUIET:
   1334			bss_entry->sensed_11h = true;
   1335		    break;
   1336
   1337		case WLAN_EID_EXT_SUPP_RATES:
   1338			/*
   1339			 * Only process extended supported rate
   1340			 * if data rate is already found.
   1341			 * Data rate IE should come before
   1342			 * extended supported rate IE
   1343			 */
   1344			if (found_data_rate_ie) {
   1345				if ((element_len + rate_size) >
   1346				    MWIFIEX_SUPPORTED_RATES)
   1347					bytes_to_copy =
   1348						(MWIFIEX_SUPPORTED_RATES -
   1349						 rate_size);
   1350				else
   1351					bytes_to_copy = element_len;
   1352
   1353				rate = (u8 *) bss_entry->data_rates;
   1354				rate += rate_size;
   1355				memcpy(rate, current_ptr + 2, bytes_to_copy);
   1356
   1357				rate = (u8 *) bss_entry->supported_rates;
   1358				rate += rate_size;
   1359				memcpy(rate, current_ptr + 2, bytes_to_copy);
   1360			}
   1361			break;
   1362
   1363		case WLAN_EID_VENDOR_SPECIFIC:
   1364			vendor_ie = (struct ieee_types_vendor_specific *)
   1365					current_ptr;
   1366
   1367			/* 802.11 requires at least 3-byte OUI. */
   1368			if (element_len < sizeof(vendor_ie->vend_hdr.oui.oui))
   1369				return -EINVAL;
   1370
   1371			/* Not long enough for a match? Skip it. */
   1372			if (element_len < sizeof(wpa_oui))
   1373				break;
   1374
   1375			if (!memcmp(&vendor_ie->vend_hdr.oui, wpa_oui,
   1376				    sizeof(wpa_oui))) {
   1377				bss_entry->bcn_wpa_ie =
   1378					(struct ieee_types_vendor_specific *)
   1379					current_ptr;
   1380				bss_entry->wpa_offset = (u16)
   1381					(current_ptr - bss_entry->beacon_buf);
   1382			} else if (!memcmp(&vendor_ie->vend_hdr.oui, wmm_oui,
   1383				    sizeof(wmm_oui))) {
   1384				if (total_ie_len ==
   1385				    sizeof(struct ieee_types_wmm_parameter) ||
   1386				    total_ie_len ==
   1387				    sizeof(struct ieee_types_wmm_info))
   1388					/*
   1389					 * Only accept and copy the WMM IE if
   1390					 * it matches the size expected for the
   1391					 * WMM Info IE or the WMM Parameter IE.
   1392					 */
   1393					memcpy((u8 *) &bss_entry->wmm_ie,
   1394					       current_ptr, total_ie_len);
   1395			}
   1396			break;
   1397		case WLAN_EID_RSN:
   1398			bss_entry->bcn_rsn_ie =
   1399				(struct ieee_types_generic *) current_ptr;
   1400			bss_entry->rsn_offset = (u16) (current_ptr -
   1401							bss_entry->beacon_buf);
   1402			break;
   1403		case WLAN_EID_BSS_AC_ACCESS_DELAY:
   1404			bss_entry->bcn_wapi_ie =
   1405				(struct ieee_types_generic *) current_ptr;
   1406			bss_entry->wapi_offset = (u16) (current_ptr -
   1407							bss_entry->beacon_buf);
   1408			break;
   1409		case WLAN_EID_HT_CAPABILITY:
   1410			bss_entry->bcn_ht_cap = (struct ieee80211_ht_cap *)
   1411					(current_ptr +
   1412					sizeof(struct ieee_types_header));
   1413			bss_entry->ht_cap_offset = (u16) (current_ptr +
   1414					sizeof(struct ieee_types_header) -
   1415					bss_entry->beacon_buf);
   1416			break;
   1417		case WLAN_EID_HT_OPERATION:
   1418			bss_entry->bcn_ht_oper =
   1419				(struct ieee80211_ht_operation *)(current_ptr +
   1420					sizeof(struct ieee_types_header));
   1421			bss_entry->ht_info_offset = (u16) (current_ptr +
   1422					sizeof(struct ieee_types_header) -
   1423					bss_entry->beacon_buf);
   1424			break;
   1425		case WLAN_EID_VHT_CAPABILITY:
   1426			bss_entry->disable_11ac = false;
   1427			bss_entry->bcn_vht_cap =
   1428				(void *)(current_ptr +
   1429					 sizeof(struct ieee_types_header));
   1430			bss_entry->vht_cap_offset =
   1431					(u16)((u8 *)bss_entry->bcn_vht_cap -
   1432					      bss_entry->beacon_buf);
   1433			break;
   1434		case WLAN_EID_VHT_OPERATION:
   1435			bss_entry->bcn_vht_oper =
   1436				(void *)(current_ptr +
   1437					 sizeof(struct ieee_types_header));
   1438			bss_entry->vht_info_offset =
   1439					(u16)((u8 *)bss_entry->bcn_vht_oper -
   1440					      bss_entry->beacon_buf);
   1441			break;
   1442		case WLAN_EID_BSS_COEX_2040:
   1443			bss_entry->bcn_bss_co_2040 = current_ptr;
   1444			bss_entry->bss_co_2040_offset =
   1445				(u16) (current_ptr - bss_entry->beacon_buf);
   1446			break;
   1447		case WLAN_EID_EXT_CAPABILITY:
   1448			bss_entry->bcn_ext_cap = current_ptr;
   1449			bss_entry->ext_cap_offset =
   1450				(u16) (current_ptr - bss_entry->beacon_buf);
   1451			break;
   1452		case WLAN_EID_OPMODE_NOTIF:
   1453			bss_entry->oper_mode = (void *)current_ptr;
   1454			bss_entry->oper_mode_offset =
   1455					(u16)((u8 *)bss_entry->oper_mode -
   1456					      bss_entry->beacon_buf);
   1457			break;
   1458		default:
   1459			break;
   1460		}
   1461
   1462		current_ptr += total_ie_len;
   1463		bytes_left -= total_ie_len;
   1464
   1465	}	/* while (bytes_left > 2) */
   1466	return 0;
   1467}
   1468
   1469/*
   1470 * This function converts radio type scan parameter to a band configuration
   1471 * to be used in join command.
   1472 */
   1473static u8
   1474mwifiex_radio_type_to_band(u8 radio_type)
   1475{
   1476	switch (radio_type) {
   1477	case HostCmd_SCAN_RADIO_TYPE_A:
   1478		return BAND_A;
   1479	case HostCmd_SCAN_RADIO_TYPE_BG:
   1480	default:
   1481		return BAND_G;
   1482	}
   1483}
   1484
   1485/*
   1486 * This is an internal function used to start a scan based on an input
   1487 * configuration.
   1488 *
   1489 * This uses the input user scan configuration information when provided in
   1490 * order to send the appropriate scan commands to firmware to populate or
   1491 * update the internal driver scan table.
   1492 */
   1493int mwifiex_scan_networks(struct mwifiex_private *priv,
   1494			  const struct mwifiex_user_scan_cfg *user_scan_in)
   1495{
   1496	int ret;
   1497	struct mwifiex_adapter *adapter = priv->adapter;
   1498	struct cmd_ctrl_node *cmd_node;
   1499	union mwifiex_scan_cmd_config_tlv *scan_cfg_out;
   1500	struct mwifiex_ie_types_chan_list_param_set *chan_list_out;
   1501	struct mwifiex_chan_scan_param_set *scan_chan_list;
   1502	u8 filtered_scan;
   1503	u8 scan_current_chan_only;
   1504	u8 max_chan_per_scan;
   1505
   1506	if (adapter->scan_processing) {
   1507		mwifiex_dbg(adapter, WARN,
   1508			    "cmd: Scan already in process...\n");
   1509		return -EBUSY;
   1510	}
   1511
   1512	if (priv->scan_block) {
   1513		mwifiex_dbg(adapter, WARN,
   1514			    "cmd: Scan is blocked during association...\n");
   1515		return -EBUSY;
   1516	}
   1517
   1518	if (test_bit(MWIFIEX_SURPRISE_REMOVED, &adapter->work_flags) ||
   1519	    test_bit(MWIFIEX_IS_CMD_TIMEDOUT, &adapter->work_flags)) {
   1520		mwifiex_dbg(adapter, ERROR,
   1521			    "Ignore scan. Card removed or firmware in bad state\n");
   1522		return -EFAULT;
   1523	}
   1524
   1525	spin_lock_bh(&adapter->mwifiex_cmd_lock);
   1526	adapter->scan_processing = true;
   1527	spin_unlock_bh(&adapter->mwifiex_cmd_lock);
   1528
   1529	scan_cfg_out = kzalloc(sizeof(union mwifiex_scan_cmd_config_tlv),
   1530			       GFP_KERNEL);
   1531	if (!scan_cfg_out) {
   1532		ret = -ENOMEM;
   1533		goto done;
   1534	}
   1535
   1536	scan_chan_list = kcalloc(MWIFIEX_USER_SCAN_CHAN_MAX,
   1537				 sizeof(struct mwifiex_chan_scan_param_set),
   1538				 GFP_KERNEL);
   1539	if (!scan_chan_list) {
   1540		kfree(scan_cfg_out);
   1541		ret = -ENOMEM;
   1542		goto done;
   1543	}
   1544
   1545	mwifiex_config_scan(priv, user_scan_in, &scan_cfg_out->config,
   1546			    &chan_list_out, scan_chan_list, &max_chan_per_scan,
   1547			    &filtered_scan, &scan_current_chan_only);
   1548
   1549	ret = mwifiex_scan_channel_list(priv, max_chan_per_scan, filtered_scan,
   1550					&scan_cfg_out->config, chan_list_out,
   1551					scan_chan_list);
   1552
   1553	/* Get scan command from scan_pending_q and put to cmd_pending_q */
   1554	if (!ret) {
   1555		spin_lock_bh(&adapter->scan_pending_q_lock);
   1556		if (!list_empty(&adapter->scan_pending_q)) {
   1557			cmd_node = list_first_entry(&adapter->scan_pending_q,
   1558						    struct cmd_ctrl_node, list);
   1559			list_del(&cmd_node->list);
   1560			spin_unlock_bh(&adapter->scan_pending_q_lock);
   1561			mwifiex_insert_cmd_to_pending_q(adapter, cmd_node);
   1562			queue_work(adapter->workqueue, &adapter->main_work);
   1563
   1564			/* Perform internal scan synchronously */
   1565			if (!priv->scan_request) {
   1566				mwifiex_dbg(adapter, INFO,
   1567					    "wait internal scan\n");
   1568				mwifiex_wait_queue_complete(adapter, cmd_node);
   1569			}
   1570		} else {
   1571			spin_unlock_bh(&adapter->scan_pending_q_lock);
   1572		}
   1573	}
   1574
   1575	kfree(scan_cfg_out);
   1576	kfree(scan_chan_list);
   1577done:
   1578	if (ret) {
   1579		spin_lock_bh(&adapter->mwifiex_cmd_lock);
   1580		adapter->scan_processing = false;
   1581		spin_unlock_bh(&adapter->mwifiex_cmd_lock);
   1582	}
   1583	return ret;
   1584}
   1585
   1586/*
   1587 * This function prepares a scan command to be sent to the firmware.
   1588 *
   1589 * This uses the scan command configuration sent to the command processing
   1590 * module in command preparation stage to configure a scan command structure
   1591 * to send to firmware.
   1592 *
   1593 * The fixed fields specifying the BSS type and BSSID filters as well as a
   1594 * variable number/length of TLVs are sent in the command to firmware.
   1595 *
   1596 * Preparation also includes -
   1597 *      - Setting command ID, and proper size
   1598 *      - Ensuring correct endian-ness
   1599 */
   1600int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
   1601			    struct mwifiex_scan_cmd_config *scan_cfg)
   1602{
   1603	struct host_cmd_ds_802_11_scan *scan_cmd = &cmd->params.scan;
   1604
   1605	/* Set fixed field variables in scan command */
   1606	scan_cmd->bss_mode = scan_cfg->bss_mode;
   1607	memcpy(scan_cmd->bssid, scan_cfg->specific_bssid,
   1608	       sizeof(scan_cmd->bssid));
   1609	memcpy(scan_cmd->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len);
   1610
   1611	cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN);
   1612
   1613	/* Size is equal to the sizeof(fixed portions) + the TLV len + header */
   1614	cmd->size = cpu_to_le16((u16) (sizeof(scan_cmd->bss_mode)
   1615					  + sizeof(scan_cmd->bssid)
   1616					  + scan_cfg->tlv_buf_len + S_DS_GEN));
   1617
   1618	return 0;
   1619}
   1620
   1621/*
   1622 * This function checks compatibility of requested network with current
   1623 * driver settings.
   1624 */
   1625int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
   1626					struct mwifiex_bssdescriptor *bss_desc)
   1627{
   1628	int ret = -1;
   1629
   1630	if (!bss_desc)
   1631		return -1;
   1632
   1633	if ((mwifiex_get_cfp(priv, (u8) bss_desc->bss_band,
   1634			     (u16) bss_desc->channel, 0))) {
   1635		switch (priv->bss_mode) {
   1636		case NL80211_IFTYPE_STATION:
   1637		case NL80211_IFTYPE_ADHOC:
   1638			ret = mwifiex_is_network_compatible(priv, bss_desc,
   1639							    priv->bss_mode);
   1640			if (ret)
   1641				mwifiex_dbg(priv->adapter, ERROR,
   1642					    "Incompatible network settings\n");
   1643			break;
   1644		default:
   1645			ret = 0;
   1646		}
   1647	}
   1648
   1649	return ret;
   1650}
   1651
   1652/* This function checks if SSID string contains all zeroes or length is zero */
   1653static bool mwifiex_is_hidden_ssid(struct cfg80211_ssid *ssid)
   1654{
   1655	int idx;
   1656
   1657	for (idx = 0; idx < ssid->ssid_len; idx++) {
   1658		if (ssid->ssid[idx])
   1659			return false;
   1660	}
   1661
   1662	return true;
   1663}
   1664
   1665/* This function checks if any hidden SSID found in passive scan channels
   1666 * and save those channels for specific SSID active scan
   1667 */
   1668static int mwifiex_save_hidden_ssid_channels(struct mwifiex_private *priv,
   1669					     struct cfg80211_bss *bss)
   1670{
   1671	struct mwifiex_bssdescriptor *bss_desc;
   1672	int ret;
   1673	int chid;
   1674
   1675	/* Allocate and fill new bss descriptor */
   1676	bss_desc = kzalloc(sizeof(*bss_desc), GFP_KERNEL);
   1677	if (!bss_desc)
   1678		return -ENOMEM;
   1679
   1680	ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc);
   1681	if (ret)
   1682		goto done;
   1683
   1684	if (mwifiex_is_hidden_ssid(&bss_desc->ssid)) {
   1685		mwifiex_dbg(priv->adapter, INFO, "found hidden SSID\n");
   1686		for (chid = 0 ; chid < MWIFIEX_USER_SCAN_CHAN_MAX; chid++) {
   1687			if (priv->hidden_chan[chid].chan_number ==
   1688			    bss->channel->hw_value)
   1689				break;
   1690
   1691			if (!priv->hidden_chan[chid].chan_number) {
   1692				priv->hidden_chan[chid].chan_number =
   1693					bss->channel->hw_value;
   1694				priv->hidden_chan[chid].radio_type =
   1695					bss->channel->band;
   1696				priv->hidden_chan[chid].scan_type =
   1697					MWIFIEX_SCAN_TYPE_ACTIVE;
   1698				break;
   1699			}
   1700		}
   1701	}
   1702
   1703done:
   1704	/* beacon_ie buffer was allocated in function
   1705	 * mwifiex_fill_new_bss_desc(). Free it now.
   1706	 */
   1707	kfree(bss_desc->beacon_buf);
   1708	kfree(bss_desc);
   1709	return 0;
   1710}
   1711
   1712static int mwifiex_update_curr_bss_params(struct mwifiex_private *priv,
   1713					  struct cfg80211_bss *bss)
   1714{
   1715	struct mwifiex_bssdescriptor *bss_desc;
   1716	int ret;
   1717
   1718	/* Allocate and fill new bss descriptor */
   1719	bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor), GFP_KERNEL);
   1720	if (!bss_desc)
   1721		return -ENOMEM;
   1722
   1723	ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc);
   1724	if (ret)
   1725		goto done;
   1726
   1727	ret = mwifiex_check_network_compatibility(priv, bss_desc);
   1728	if (ret)
   1729		goto done;
   1730
   1731	spin_lock_bh(&priv->curr_bcn_buf_lock);
   1732	/* Make a copy of current BSSID descriptor */
   1733	memcpy(&priv->curr_bss_params.bss_descriptor, bss_desc,
   1734	       sizeof(priv->curr_bss_params.bss_descriptor));
   1735
   1736	/* The contents of beacon_ie will be copied to its own buffer
   1737	 * in mwifiex_save_curr_bcn()
   1738	 */
   1739	mwifiex_save_curr_bcn(priv);
   1740	spin_unlock_bh(&priv->curr_bcn_buf_lock);
   1741
   1742done:
   1743	/* beacon_ie buffer was allocated in function
   1744	 * mwifiex_fill_new_bss_desc(). Free it now.
   1745	 */
   1746	kfree(bss_desc->beacon_buf);
   1747	kfree(bss_desc);
   1748	return 0;
   1749}
   1750
   1751static int
   1752mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info,
   1753				  u32 *bytes_left, u64 fw_tsf, u8 *radio_type,
   1754				  bool ext_scan, s32 rssi_val)
   1755{
   1756	struct mwifiex_adapter *adapter = priv->adapter;
   1757	struct mwifiex_chan_freq_power *cfp;
   1758	struct cfg80211_bss *bss;
   1759	u8 bssid[ETH_ALEN];
   1760	s32 rssi;
   1761	const u8 *ie_buf;
   1762	size_t ie_len;
   1763	u16 channel = 0;
   1764	u16 beacon_size = 0;
   1765	u32 curr_bcn_bytes;
   1766	u32 freq;
   1767	u16 beacon_period;
   1768	u16 cap_info_bitmap;
   1769	u8 *current_ptr;
   1770	u64 timestamp;
   1771	struct mwifiex_fixed_bcn_param *bcn_param;
   1772	struct mwifiex_bss_priv *bss_priv;
   1773
   1774	if (*bytes_left >= sizeof(beacon_size)) {
   1775		/* Extract & convert beacon size from command buffer */
   1776		beacon_size = get_unaligned_le16((*bss_info));
   1777		*bytes_left -= sizeof(beacon_size);
   1778		*bss_info += sizeof(beacon_size);
   1779	}
   1780
   1781	if (!beacon_size || beacon_size > *bytes_left) {
   1782		*bss_info += *bytes_left;
   1783		*bytes_left = 0;
   1784		return -EFAULT;
   1785	}
   1786
   1787	/* Initialize the current working beacon pointer for this BSS
   1788	 * iteration
   1789	 */
   1790	current_ptr = *bss_info;
   1791
   1792	/* Advance the return beacon pointer past the current beacon */
   1793	*bss_info += beacon_size;
   1794	*bytes_left -= beacon_size;
   1795
   1796	curr_bcn_bytes = beacon_size;
   1797
   1798	/* First 5 fields are bssid, RSSI(for legacy scan only),
   1799	 * time stamp, beacon interval, and capability information
   1800	 */
   1801	if (curr_bcn_bytes < ETH_ALEN + sizeof(u8) +
   1802	    sizeof(struct mwifiex_fixed_bcn_param)) {
   1803		mwifiex_dbg(adapter, ERROR,
   1804			    "InterpretIE: not enough bytes left\n");
   1805		return -EFAULT;
   1806	}
   1807
   1808	memcpy(bssid, current_ptr, ETH_ALEN);
   1809	current_ptr += ETH_ALEN;
   1810	curr_bcn_bytes -= ETH_ALEN;
   1811
   1812	if (!ext_scan) {
   1813		rssi = (s32) *current_ptr;
   1814		rssi = (-rssi) * 100;		/* Convert dBm to mBm */
   1815		current_ptr += sizeof(u8);
   1816		curr_bcn_bytes -= sizeof(u8);
   1817		mwifiex_dbg(adapter, INFO,
   1818			    "info: InterpretIE: RSSI=%d\n", rssi);
   1819	} else {
   1820		rssi = rssi_val;
   1821	}
   1822
   1823	bcn_param = (struct mwifiex_fixed_bcn_param *)current_ptr;
   1824	current_ptr += sizeof(*bcn_param);
   1825	curr_bcn_bytes -= sizeof(*bcn_param);
   1826
   1827	timestamp = le64_to_cpu(bcn_param->timestamp);
   1828	beacon_period = le16_to_cpu(bcn_param->beacon_period);
   1829
   1830	cap_info_bitmap = le16_to_cpu(bcn_param->cap_info_bitmap);
   1831	mwifiex_dbg(adapter, INFO,
   1832		    "info: InterpretIE: capabilities=0x%X\n",
   1833		    cap_info_bitmap);
   1834
   1835	/* Rest of the current buffer are IE's */
   1836	ie_buf = current_ptr;
   1837	ie_len = curr_bcn_bytes;
   1838	mwifiex_dbg(adapter, INFO,
   1839		    "info: InterpretIE: IELength for this AP = %d\n",
   1840		    curr_bcn_bytes);
   1841
   1842	while (curr_bcn_bytes >= sizeof(struct ieee_types_header)) {
   1843		u8 element_id, element_len;
   1844
   1845		element_id = *current_ptr;
   1846		element_len = *(current_ptr + 1);
   1847		if (curr_bcn_bytes < element_len +
   1848				sizeof(struct ieee_types_header)) {
   1849			mwifiex_dbg(adapter, ERROR,
   1850				    "%s: bytes left < IE length\n", __func__);
   1851			return -EFAULT;
   1852		}
   1853		if (element_id == WLAN_EID_DS_PARAMS) {
   1854			channel = *(current_ptr +
   1855				    sizeof(struct ieee_types_header));
   1856			break;
   1857		}
   1858
   1859		current_ptr += element_len + sizeof(struct ieee_types_header);
   1860		curr_bcn_bytes -= element_len +
   1861					sizeof(struct ieee_types_header);
   1862	}
   1863
   1864	if (channel) {
   1865		struct ieee80211_channel *chan;
   1866		u8 band;
   1867
   1868		/* Skip entry if on csa closed channel */
   1869		if (channel == priv->csa_chan) {
   1870			mwifiex_dbg(adapter, WARN,
   1871				    "Dropping entry on csa closed channel\n");
   1872			return 0;
   1873		}
   1874
   1875		band = BAND_G;
   1876		if (radio_type)
   1877			band = mwifiex_radio_type_to_band(*radio_type &
   1878							  (BIT(0) | BIT(1)));
   1879
   1880		cfp = mwifiex_get_cfp(priv, band, channel, 0);
   1881
   1882		freq = cfp ? cfp->freq : 0;
   1883
   1884		chan = ieee80211_get_channel(priv->wdev.wiphy, freq);
   1885
   1886		if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
   1887			bss = cfg80211_inform_bss(priv->wdev.wiphy,
   1888					    chan, CFG80211_BSS_FTYPE_UNKNOWN,
   1889					    bssid, timestamp,
   1890					    cap_info_bitmap, beacon_period,
   1891					    ie_buf, ie_len, rssi, GFP_ATOMIC);
   1892			if (bss) {
   1893				bss_priv = (struct mwifiex_bss_priv *)bss->priv;
   1894				bss_priv->band = band;
   1895				bss_priv->fw_tsf = fw_tsf;
   1896				if (priv->media_connected &&
   1897				    !memcmp(bssid, priv->curr_bss_params.
   1898					    bss_descriptor.mac_address,
   1899					    ETH_ALEN))
   1900					mwifiex_update_curr_bss_params(priv,
   1901								       bss);
   1902
   1903				if ((chan->flags & IEEE80211_CHAN_RADAR) ||
   1904				    (chan->flags & IEEE80211_CHAN_NO_IR)) {
   1905					mwifiex_dbg(adapter, INFO,
   1906						    "radar or passive channel %d\n",
   1907						    channel);
   1908					mwifiex_save_hidden_ssid_channels(priv,
   1909									  bss);
   1910				}
   1911
   1912				cfg80211_put_bss(priv->wdev.wiphy, bss);
   1913			}
   1914		}
   1915	} else {
   1916		mwifiex_dbg(adapter, WARN, "missing BSS channel IE\n");
   1917	}
   1918
   1919	return 0;
   1920}
   1921
   1922static void mwifiex_complete_scan(struct mwifiex_private *priv)
   1923{
   1924	struct mwifiex_adapter *adapter = priv->adapter;
   1925
   1926	adapter->survey_idx = 0;
   1927	if (adapter->curr_cmd->wait_q_enabled) {
   1928		adapter->cmd_wait_q.status = 0;
   1929		if (!priv->scan_request) {
   1930			mwifiex_dbg(adapter, INFO,
   1931				    "complete internal scan\n");
   1932			mwifiex_complete_cmd(adapter, adapter->curr_cmd);
   1933		}
   1934	}
   1935}
   1936
   1937/* This function checks if any hidden SSID found in passive scan channels
   1938 * and do specific SSID active scan for those channels
   1939 */
   1940static int
   1941mwifiex_active_scan_req_for_passive_chan(struct mwifiex_private *priv)
   1942{
   1943	int ret;
   1944	struct mwifiex_adapter *adapter = priv->adapter;
   1945	u8 id = 0;
   1946	struct mwifiex_user_scan_cfg  *user_scan_cfg;
   1947
   1948	if (adapter->active_scan_triggered || !priv->scan_request ||
   1949	    priv->scan_aborting) {
   1950		adapter->active_scan_triggered = false;
   1951		return 0;
   1952	}
   1953
   1954	if (!priv->hidden_chan[0].chan_number) {
   1955		mwifiex_dbg(adapter, INFO, "No BSS with hidden SSID found on DFS channels\n");
   1956		return 0;
   1957	}
   1958	user_scan_cfg = kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL);
   1959
   1960	if (!user_scan_cfg)
   1961		return -ENOMEM;
   1962
   1963	for (id = 0; id < MWIFIEX_USER_SCAN_CHAN_MAX; id++) {
   1964		if (!priv->hidden_chan[id].chan_number)
   1965			break;
   1966		memcpy(&user_scan_cfg->chan_list[id],
   1967		       &priv->hidden_chan[id],
   1968		       sizeof(struct mwifiex_user_scan_chan));
   1969	}
   1970
   1971	adapter->active_scan_triggered = true;
   1972	if (priv->scan_request->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)
   1973		ether_addr_copy(user_scan_cfg->random_mac,
   1974				priv->scan_request->mac_addr);
   1975	user_scan_cfg->num_ssids = priv->scan_request->n_ssids;
   1976	user_scan_cfg->ssid_list = priv->scan_request->ssids;
   1977
   1978	ret = mwifiex_scan_networks(priv, user_scan_cfg);
   1979	kfree(user_scan_cfg);
   1980
   1981	memset(&priv->hidden_chan, 0, sizeof(priv->hidden_chan));
   1982
   1983	if (ret) {
   1984		dev_err(priv->adapter->dev, "scan failed: %d\n", ret);
   1985		return ret;
   1986	}
   1987
   1988	return 0;
   1989}
   1990static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
   1991{
   1992	struct mwifiex_adapter *adapter = priv->adapter;
   1993	struct cmd_ctrl_node *cmd_node;
   1994
   1995	spin_lock_bh(&adapter->scan_pending_q_lock);
   1996	if (list_empty(&adapter->scan_pending_q)) {
   1997		spin_unlock_bh(&adapter->scan_pending_q_lock);
   1998
   1999		spin_lock_bh(&adapter->mwifiex_cmd_lock);
   2000		adapter->scan_processing = false;
   2001		spin_unlock_bh(&adapter->mwifiex_cmd_lock);
   2002
   2003		mwifiex_active_scan_req_for_passive_chan(priv);
   2004
   2005		if (!adapter->ext_scan)
   2006			mwifiex_complete_scan(priv);
   2007
   2008		if (priv->scan_request) {
   2009			struct cfg80211_scan_info info = {
   2010				.aborted = false,
   2011			};
   2012
   2013			mwifiex_dbg(adapter, INFO,
   2014				    "info: notifying scan done\n");
   2015			cfg80211_scan_done(priv->scan_request, &info);
   2016			priv->scan_request = NULL;
   2017			priv->scan_aborting = false;
   2018		} else {
   2019			priv->scan_aborting = false;
   2020			mwifiex_dbg(adapter, INFO,
   2021				    "info: scan already aborted\n");
   2022		}
   2023	} else if ((priv->scan_aborting && !priv->scan_request) ||
   2024		   priv->scan_block) {
   2025		spin_unlock_bh(&adapter->scan_pending_q_lock);
   2026
   2027		mwifiex_cancel_pending_scan_cmd(adapter);
   2028
   2029		spin_lock_bh(&adapter->mwifiex_cmd_lock);
   2030		adapter->scan_processing = false;
   2031		spin_unlock_bh(&adapter->mwifiex_cmd_lock);
   2032
   2033		if (!adapter->active_scan_triggered) {
   2034			if (priv->scan_request) {
   2035				struct cfg80211_scan_info info = {
   2036					.aborted = true,
   2037				};
   2038
   2039				mwifiex_dbg(adapter, INFO,
   2040					    "info: aborting scan\n");
   2041				cfg80211_scan_done(priv->scan_request, &info);
   2042				priv->scan_request = NULL;
   2043				priv->scan_aborting = false;
   2044			} else {
   2045				priv->scan_aborting = false;
   2046				mwifiex_dbg(adapter, INFO,
   2047					    "info: scan already aborted\n");
   2048			}
   2049		}
   2050	} else {
   2051		/* Get scan command from scan_pending_q and put to
   2052		 * cmd_pending_q
   2053		 */
   2054		cmd_node = list_first_entry(&adapter->scan_pending_q,
   2055					    struct cmd_ctrl_node, list);
   2056		list_del(&cmd_node->list);
   2057		spin_unlock_bh(&adapter->scan_pending_q_lock);
   2058		mwifiex_insert_cmd_to_pending_q(adapter, cmd_node);
   2059	}
   2060
   2061	return;
   2062}
   2063
   2064void mwifiex_cancel_scan(struct mwifiex_adapter *adapter)
   2065{
   2066	struct mwifiex_private *priv;
   2067	int i;
   2068
   2069	mwifiex_cancel_pending_scan_cmd(adapter);
   2070
   2071	if (adapter->scan_processing) {
   2072		spin_lock_bh(&adapter->mwifiex_cmd_lock);
   2073		adapter->scan_processing = false;
   2074		spin_unlock_bh(&adapter->mwifiex_cmd_lock);
   2075		for (i = 0; i < adapter->priv_num; i++) {
   2076			priv = adapter->priv[i];
   2077			if (!priv)
   2078				continue;
   2079			if (priv->scan_request) {
   2080				struct cfg80211_scan_info info = {
   2081					.aborted = true,
   2082				};
   2083
   2084				mwifiex_dbg(adapter, INFO,
   2085					    "info: aborting scan\n");
   2086				cfg80211_scan_done(priv->scan_request, &info);
   2087				priv->scan_request = NULL;
   2088				priv->scan_aborting = false;
   2089			}
   2090		}
   2091	}
   2092}
   2093
   2094/*
   2095 * This function handles the command response of scan.
   2096 *
   2097 * The response buffer for the scan command has the following
   2098 * memory layout:
   2099 *
   2100 *      .-------------------------------------------------------------.
   2101 *      |  Header (4 * sizeof(t_u16)):  Standard command response hdr |
   2102 *      .-------------------------------------------------------------.
   2103 *      |  BufSize (t_u16) : sizeof the BSS Description data          |
   2104 *      .-------------------------------------------------------------.
   2105 *      |  NumOfSet (t_u8) : Number of BSS Descs returned             |
   2106 *      .-------------------------------------------------------------.
   2107 *      |  BSSDescription data (variable, size given in BufSize)      |
   2108 *      .-------------------------------------------------------------.
   2109 *      |  TLV data (variable, size calculated using Header->Size,    |
   2110 *      |            BufSize and sizeof the fixed fields above)       |
   2111 *      .-------------------------------------------------------------.
   2112 */
   2113int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
   2114			    struct host_cmd_ds_command *resp)
   2115{
   2116	int ret = 0;
   2117	struct mwifiex_adapter *adapter = priv->adapter;
   2118	struct host_cmd_ds_802_11_scan_rsp *scan_rsp;
   2119	struct mwifiex_ie_types_data *tlv_data;
   2120	struct mwifiex_ie_types_tsf_timestamp *tsf_tlv;
   2121	u8 *bss_info;
   2122	u32 scan_resp_size;
   2123	u32 bytes_left;
   2124	u32 idx;
   2125	u32 tlv_buf_size;
   2126	struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv;
   2127	struct chan_band_param_set *chan_band;
   2128	u8 is_bgscan_resp;
   2129	__le64 fw_tsf = 0;
   2130	u8 *radio_type;
   2131	struct cfg80211_wowlan_nd_match *pmatch;
   2132	struct cfg80211_sched_scan_request *nd_config = NULL;
   2133
   2134	is_bgscan_resp = (le16_to_cpu(resp->command)
   2135			  == HostCmd_CMD_802_11_BG_SCAN_QUERY);
   2136	if (is_bgscan_resp)
   2137		scan_rsp = &resp->params.bg_scan_query_resp.scan_resp;
   2138	else
   2139		scan_rsp = &resp->params.scan_resp;
   2140
   2141
   2142	if (scan_rsp->number_of_sets > MWIFIEX_MAX_AP) {
   2143		mwifiex_dbg(adapter, ERROR,
   2144			    "SCAN_RESP: too many AP returned (%d)\n",
   2145			    scan_rsp->number_of_sets);
   2146		ret = -1;
   2147		goto check_next_scan;
   2148	}
   2149
   2150	/* Check csa channel expiry before parsing scan response */
   2151	mwifiex_11h_get_csa_closed_channel(priv);
   2152
   2153	bytes_left = le16_to_cpu(scan_rsp->bss_descript_size);
   2154	mwifiex_dbg(adapter, INFO,
   2155		    "info: SCAN_RESP: bss_descript_size %d\n",
   2156		    bytes_left);
   2157
   2158	scan_resp_size = le16_to_cpu(resp->size);
   2159
   2160	mwifiex_dbg(adapter, INFO,
   2161		    "info: SCAN_RESP: returned %d APs before parsing\n",
   2162		    scan_rsp->number_of_sets);
   2163
   2164	bss_info = scan_rsp->bss_desc_and_tlv_buffer;
   2165
   2166	/*
   2167	 * The size of the TLV buffer is equal to the entire command response
   2168	 *   size (scan_resp_size) minus the fixed fields (sizeof()'s), the
   2169	 *   BSS Descriptions (bss_descript_size as bytesLef) and the command
   2170	 *   response header (S_DS_GEN)
   2171	 */
   2172	tlv_buf_size = scan_resp_size - (bytes_left
   2173					 + sizeof(scan_rsp->bss_descript_size)
   2174					 + sizeof(scan_rsp->number_of_sets)
   2175					 + S_DS_GEN);
   2176
   2177	tlv_data = (struct mwifiex_ie_types_data *) (scan_rsp->
   2178						 bss_desc_and_tlv_buffer +
   2179						 bytes_left);
   2180
   2181	/* Search the TLV buffer space in the scan response for any valid
   2182	   TLVs */
   2183	mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size,
   2184					     TLV_TYPE_TSFTIMESTAMP,
   2185					     (struct mwifiex_ie_types_data **)
   2186					     &tsf_tlv);
   2187
   2188	/* Search the TLV buffer space in the scan response for any valid
   2189	   TLVs */
   2190	mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size,
   2191					     TLV_TYPE_CHANNELBANDLIST,
   2192					     (struct mwifiex_ie_types_data **)
   2193					     &chan_band_tlv);
   2194
   2195#ifdef CONFIG_PM
   2196	if (priv->wdev.wiphy->wowlan_config)
   2197		nd_config = priv->wdev.wiphy->wowlan_config->nd_config;
   2198#endif
   2199
   2200	if (nd_config) {
   2201		adapter->nd_info =
   2202			kzalloc(sizeof(struct cfg80211_wowlan_nd_match) +
   2203				sizeof(struct cfg80211_wowlan_nd_match *) *
   2204				scan_rsp->number_of_sets, GFP_ATOMIC);
   2205
   2206		if (adapter->nd_info)
   2207			adapter->nd_info->n_matches = scan_rsp->number_of_sets;
   2208	}
   2209
   2210	for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) {
   2211		/*
   2212		 * If the TSF TLV was appended to the scan results, save this
   2213		 * entry's TSF value in the fw_tsf field. It is the firmware's
   2214		 * TSF value at the time the beacon or probe response was
   2215		 * received.
   2216		 */
   2217		if (tsf_tlv)
   2218			memcpy(&fw_tsf, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE],
   2219			       sizeof(fw_tsf));
   2220
   2221		if (chan_band_tlv) {
   2222			chan_band = &chan_band_tlv->chan_band_param[idx];
   2223			radio_type = &chan_band->radio_type;
   2224		} else {
   2225			radio_type = NULL;
   2226		}
   2227
   2228		if (chan_band_tlv && adapter->nd_info) {
   2229			adapter->nd_info->matches[idx] =
   2230				kzalloc(sizeof(*pmatch) + sizeof(u32),
   2231					GFP_ATOMIC);
   2232
   2233			pmatch = adapter->nd_info->matches[idx];
   2234
   2235			if (pmatch) {
   2236				pmatch->n_channels = 1;
   2237				pmatch->channels[0] = chan_band->chan_number;
   2238			}
   2239		}
   2240
   2241		ret = mwifiex_parse_single_response_buf(priv, &bss_info,
   2242							&bytes_left,
   2243							le64_to_cpu(fw_tsf),
   2244							radio_type, false, 0);
   2245		if (ret)
   2246			goto check_next_scan;
   2247	}
   2248
   2249check_next_scan:
   2250	mwifiex_check_next_scan_command(priv);
   2251	return ret;
   2252}
   2253
   2254/*
   2255 * This function prepares an extended scan command to be sent to the firmware
   2256 *
   2257 * This uses the scan command configuration sent to the command processing
   2258 * module in command preparation stage to configure a extended scan command
   2259 * structure to send to firmware.
   2260 */
   2261int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv,
   2262				struct host_cmd_ds_command *cmd,
   2263				void *data_buf)
   2264{
   2265	struct host_cmd_ds_802_11_scan_ext *ext_scan = &cmd->params.ext_scan;
   2266	struct mwifiex_scan_cmd_config *scan_cfg = data_buf;
   2267
   2268	memcpy(ext_scan->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len);
   2269
   2270	cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN_EXT);
   2271
   2272	/* Size is equal to the sizeof(fixed portions) + the TLV len + header */
   2273	cmd->size = cpu_to_le16((u16)(sizeof(ext_scan->reserved)
   2274				      + scan_cfg->tlv_buf_len + S_DS_GEN));
   2275
   2276	return 0;
   2277}
   2278
   2279/* This function prepares an background scan config command to be sent
   2280 * to the firmware
   2281 */
   2282int mwifiex_cmd_802_11_bg_scan_config(struct mwifiex_private *priv,
   2283				      struct host_cmd_ds_command *cmd,
   2284				      void *data_buf)
   2285{
   2286	struct host_cmd_ds_802_11_bg_scan_config *bgscan_config =
   2287					&cmd->params.bg_scan_config;
   2288	struct mwifiex_bg_scan_cfg *bgscan_cfg_in = data_buf;
   2289	u8 *tlv_pos = bgscan_config->tlv;
   2290	u8 num_probes;
   2291	u32 ssid_len, chan_idx, scan_type, scan_dur, chan_num;
   2292	int i;
   2293	struct mwifiex_ie_types_num_probes *num_probes_tlv;
   2294	struct mwifiex_ie_types_repeat_count *repeat_count_tlv;
   2295	struct mwifiex_ie_types_min_rssi_threshold *rssi_threshold_tlv;
   2296	struct mwifiex_ie_types_bgscan_start_later *start_later_tlv;
   2297	struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv;
   2298	struct mwifiex_ie_types_chan_list_param_set *chan_list_tlv;
   2299	struct mwifiex_chan_scan_param_set *temp_chan;
   2300
   2301	cmd->command = cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_CONFIG);
   2302	cmd->size = cpu_to_le16(sizeof(*bgscan_config) + S_DS_GEN);
   2303
   2304	bgscan_config->action = cpu_to_le16(bgscan_cfg_in->action);
   2305	bgscan_config->enable = bgscan_cfg_in->enable;
   2306	bgscan_config->bss_type = bgscan_cfg_in->bss_type;
   2307	bgscan_config->scan_interval =
   2308		cpu_to_le32(bgscan_cfg_in->scan_interval);
   2309	bgscan_config->report_condition =
   2310		cpu_to_le32(bgscan_cfg_in->report_condition);
   2311
   2312	/*  stop sched scan  */
   2313	if (!bgscan_config->enable)
   2314		return 0;
   2315
   2316	bgscan_config->chan_per_scan = bgscan_cfg_in->chan_per_scan;
   2317
   2318	num_probes = (bgscan_cfg_in->num_probes ? bgscan_cfg_in->
   2319		      num_probes : priv->adapter->scan_probes);
   2320
   2321	if (num_probes) {
   2322		num_probes_tlv = (struct mwifiex_ie_types_num_probes *)tlv_pos;
   2323		num_probes_tlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES);
   2324		num_probes_tlv->header.len =
   2325			cpu_to_le16(sizeof(num_probes_tlv->num_probes));
   2326		num_probes_tlv->num_probes = cpu_to_le16((u16)num_probes);
   2327
   2328		tlv_pos += sizeof(num_probes_tlv->header) +
   2329			le16_to_cpu(num_probes_tlv->header.len);
   2330	}
   2331
   2332	if (bgscan_cfg_in->repeat_count) {
   2333		repeat_count_tlv =
   2334			(struct mwifiex_ie_types_repeat_count *)tlv_pos;
   2335		repeat_count_tlv->header.type =
   2336			cpu_to_le16(TLV_TYPE_REPEAT_COUNT);
   2337		repeat_count_tlv->header.len =
   2338			cpu_to_le16(sizeof(repeat_count_tlv->repeat_count));
   2339		repeat_count_tlv->repeat_count =
   2340			cpu_to_le16(bgscan_cfg_in->repeat_count);
   2341
   2342		tlv_pos += sizeof(repeat_count_tlv->header) +
   2343			le16_to_cpu(repeat_count_tlv->header.len);
   2344	}
   2345
   2346	if (bgscan_cfg_in->rssi_threshold) {
   2347		rssi_threshold_tlv =
   2348			(struct mwifiex_ie_types_min_rssi_threshold *)tlv_pos;
   2349		rssi_threshold_tlv->header.type =
   2350			cpu_to_le16(TLV_TYPE_RSSI_LOW);
   2351		rssi_threshold_tlv->header.len =
   2352			cpu_to_le16(sizeof(rssi_threshold_tlv->rssi_threshold));
   2353		rssi_threshold_tlv->rssi_threshold =
   2354			cpu_to_le16(bgscan_cfg_in->rssi_threshold);
   2355
   2356		tlv_pos += sizeof(rssi_threshold_tlv->header) +
   2357			le16_to_cpu(rssi_threshold_tlv->header.len);
   2358	}
   2359
   2360	for (i = 0; i < bgscan_cfg_in->num_ssids; i++) {
   2361		ssid_len = bgscan_cfg_in->ssid_list[i].ssid.ssid_len;
   2362
   2363		wildcard_ssid_tlv =
   2364			(struct mwifiex_ie_types_wildcard_ssid_params *)tlv_pos;
   2365		wildcard_ssid_tlv->header.type =
   2366				cpu_to_le16(TLV_TYPE_WILDCARDSSID);
   2367		wildcard_ssid_tlv->header.len = cpu_to_le16(
   2368				(u16)(ssid_len + sizeof(wildcard_ssid_tlv->
   2369							 max_ssid_length)));
   2370
   2371		/* max_ssid_length = 0 tells firmware to perform
   2372		 * specific scan for the SSID filled, whereas
   2373		 * max_ssid_length = IEEE80211_MAX_SSID_LEN is for
   2374		 * wildcard scan.
   2375		 */
   2376		if (ssid_len)
   2377			wildcard_ssid_tlv->max_ssid_length = 0;
   2378		else
   2379			wildcard_ssid_tlv->max_ssid_length =
   2380						IEEE80211_MAX_SSID_LEN;
   2381
   2382		memcpy(wildcard_ssid_tlv->ssid,
   2383		       bgscan_cfg_in->ssid_list[i].ssid.ssid, ssid_len);
   2384
   2385		tlv_pos += (sizeof(wildcard_ssid_tlv->header)
   2386				+ le16_to_cpu(wildcard_ssid_tlv->header.len));
   2387	}
   2388
   2389	chan_list_tlv = (struct mwifiex_ie_types_chan_list_param_set *)tlv_pos;
   2390
   2391	if (bgscan_cfg_in->chan_list[0].chan_number) {
   2392		dev_dbg(priv->adapter->dev, "info: bgscan: Using supplied channel list\n");
   2393
   2394		chan_list_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST);
   2395
   2396		for (chan_idx = 0;
   2397		     chan_idx < MWIFIEX_BG_SCAN_CHAN_MAX &&
   2398		     bgscan_cfg_in->chan_list[chan_idx].chan_number;
   2399		     chan_idx++) {
   2400			temp_chan = chan_list_tlv->chan_scan_param + chan_idx;
   2401
   2402			/* Increment the TLV header length by size appended */
   2403			le16_unaligned_add_cpu(&chan_list_tlv->header.len,
   2404					       sizeof(
   2405					       chan_list_tlv->chan_scan_param));
   2406
   2407			temp_chan->chan_number =
   2408				bgscan_cfg_in->chan_list[chan_idx].chan_number;
   2409			temp_chan->radio_type =
   2410				bgscan_cfg_in->chan_list[chan_idx].radio_type;
   2411
   2412			scan_type =
   2413				bgscan_cfg_in->chan_list[chan_idx].scan_type;
   2414
   2415			if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE)
   2416				temp_chan->chan_scan_mode_bitmap
   2417					|= MWIFIEX_PASSIVE_SCAN;
   2418			else
   2419				temp_chan->chan_scan_mode_bitmap
   2420					&= ~MWIFIEX_PASSIVE_SCAN;
   2421
   2422			if (bgscan_cfg_in->chan_list[chan_idx].scan_time) {
   2423				scan_dur = (u16)bgscan_cfg_in->
   2424					chan_list[chan_idx].scan_time;
   2425			} else {
   2426				scan_dur = (scan_type ==
   2427					    MWIFIEX_SCAN_TYPE_PASSIVE) ?
   2428					    priv->adapter->passive_scan_time :
   2429					    priv->adapter->specific_scan_time;
   2430			}
   2431
   2432			temp_chan->min_scan_time = cpu_to_le16(scan_dur);
   2433			temp_chan->max_scan_time = cpu_to_le16(scan_dur);
   2434		}
   2435	} else {
   2436		dev_dbg(priv->adapter->dev,
   2437			"info: bgscan: Creating full region channel list\n");
   2438		chan_num =
   2439			mwifiex_bgscan_create_channel_list(priv, bgscan_cfg_in,
   2440							   chan_list_tlv->
   2441							   chan_scan_param);
   2442		le16_unaligned_add_cpu(&chan_list_tlv->header.len,
   2443				       chan_num *
   2444			     sizeof(chan_list_tlv->chan_scan_param[0]));
   2445	}
   2446
   2447	tlv_pos += (sizeof(chan_list_tlv->header)
   2448			+ le16_to_cpu(chan_list_tlv->header.len));
   2449
   2450	if (bgscan_cfg_in->start_later) {
   2451		start_later_tlv =
   2452			(struct mwifiex_ie_types_bgscan_start_later *)tlv_pos;
   2453		start_later_tlv->header.type =
   2454			cpu_to_le16(TLV_TYPE_BGSCAN_START_LATER);
   2455		start_later_tlv->header.len =
   2456			cpu_to_le16(sizeof(start_later_tlv->start_later));
   2457		start_later_tlv->start_later =
   2458			cpu_to_le16(bgscan_cfg_in->start_later);
   2459
   2460		tlv_pos += sizeof(start_later_tlv->header) +
   2461			le16_to_cpu(start_later_tlv->header.len);
   2462	}
   2463
   2464	/* Append vendor specific IE TLV */
   2465	mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_BGSCAN, &tlv_pos);
   2466
   2467	le16_unaligned_add_cpu(&cmd->size, tlv_pos - bgscan_config->tlv);
   2468
   2469	return 0;
   2470}
   2471
   2472int mwifiex_stop_bg_scan(struct mwifiex_private *priv)
   2473{
   2474	struct mwifiex_bg_scan_cfg *bgscan_cfg;
   2475
   2476	if (!priv->sched_scanning) {
   2477		dev_dbg(priv->adapter->dev, "bgscan already stopped!\n");
   2478		return 0;
   2479	}
   2480
   2481	bgscan_cfg = kzalloc(sizeof(*bgscan_cfg), GFP_KERNEL);
   2482	if (!bgscan_cfg)
   2483		return -ENOMEM;
   2484
   2485	bgscan_cfg->bss_type = MWIFIEX_BSS_MODE_INFRA;
   2486	bgscan_cfg->action = MWIFIEX_BGSCAN_ACT_SET;
   2487	bgscan_cfg->enable = false;
   2488
   2489	if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_BG_SCAN_CONFIG,
   2490			     HostCmd_ACT_GEN_SET, 0, bgscan_cfg, true)) {
   2491		kfree(bgscan_cfg);
   2492		return -EFAULT;
   2493	}
   2494
   2495	kfree(bgscan_cfg);
   2496	priv->sched_scanning = false;
   2497
   2498	return 0;
   2499}
   2500
   2501static void
   2502mwifiex_update_chan_statistics(struct mwifiex_private *priv,
   2503			       struct mwifiex_ietypes_chanstats *tlv_stat)
   2504{
   2505	struct mwifiex_adapter *adapter = priv->adapter;
   2506	u8 i, num_chan;
   2507	struct mwifiex_fw_chan_stats *fw_chan_stats;
   2508	struct mwifiex_chan_stats chan_stats;
   2509
   2510	fw_chan_stats = (void *)((u8 *)tlv_stat +
   2511			      sizeof(struct mwifiex_ie_types_header));
   2512	num_chan = le16_to_cpu(tlv_stat->header.len) /
   2513					      sizeof(struct mwifiex_chan_stats);
   2514
   2515	for (i = 0 ; i < num_chan; i++) {
   2516		if (adapter->survey_idx >= adapter->num_in_chan_stats) {
   2517			mwifiex_dbg(adapter, WARN,
   2518				    "FW reported too many channel results (max %d)\n",
   2519				    adapter->num_in_chan_stats);
   2520			return;
   2521		}
   2522		chan_stats.chan_num = fw_chan_stats->chan_num;
   2523		chan_stats.bandcfg = fw_chan_stats->bandcfg;
   2524		chan_stats.flags = fw_chan_stats->flags;
   2525		chan_stats.noise = fw_chan_stats->noise;
   2526		chan_stats.total_bss = le16_to_cpu(fw_chan_stats->total_bss);
   2527		chan_stats.cca_scan_dur =
   2528				       le16_to_cpu(fw_chan_stats->cca_scan_dur);
   2529		chan_stats.cca_busy_dur =
   2530				       le16_to_cpu(fw_chan_stats->cca_busy_dur);
   2531		mwifiex_dbg(adapter, INFO,
   2532			    "chan=%d, noise=%d, total_network=%d scan_duration=%d, busy_duration=%d\n",
   2533			    chan_stats.chan_num,
   2534			    chan_stats.noise,
   2535			    chan_stats.total_bss,
   2536			    chan_stats.cca_scan_dur,
   2537			    chan_stats.cca_busy_dur);
   2538		memcpy(&adapter->chan_stats[adapter->survey_idx++], &chan_stats,
   2539		       sizeof(struct mwifiex_chan_stats));
   2540		fw_chan_stats++;
   2541	}
   2542}
   2543
   2544/* This function handles the command response of extended scan */
   2545int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv,
   2546				struct host_cmd_ds_command *resp)
   2547{
   2548	struct mwifiex_adapter *adapter = priv->adapter;
   2549	struct host_cmd_ds_802_11_scan_ext *ext_scan_resp;
   2550	struct mwifiex_ie_types_header *tlv;
   2551	struct mwifiex_ietypes_chanstats *tlv_stat;
   2552	u16 buf_left, type, len;
   2553
   2554	struct host_cmd_ds_command *cmd_ptr;
   2555	struct cmd_ctrl_node *cmd_node;
   2556	bool complete_scan = false;
   2557
   2558	mwifiex_dbg(adapter, INFO, "info: EXT scan returns successfully\n");
   2559
   2560	ext_scan_resp = &resp->params.ext_scan;
   2561
   2562	tlv = (void *)ext_scan_resp->tlv_buffer;
   2563	buf_left = le16_to_cpu(resp->size) - (sizeof(*ext_scan_resp) + S_DS_GEN
   2564					      - 1);
   2565
   2566	while (buf_left >= sizeof(struct mwifiex_ie_types_header)) {
   2567		type = le16_to_cpu(tlv->type);
   2568		len = le16_to_cpu(tlv->len);
   2569
   2570		if (buf_left < (sizeof(struct mwifiex_ie_types_header) + len)) {
   2571			mwifiex_dbg(adapter, ERROR,
   2572				    "error processing scan response TLVs");
   2573			break;
   2574		}
   2575
   2576		switch (type) {
   2577		case TLV_TYPE_CHANNEL_STATS:
   2578			tlv_stat = (void *)tlv;
   2579			mwifiex_update_chan_statistics(priv, tlv_stat);
   2580			break;
   2581		default:
   2582			break;
   2583		}
   2584
   2585		buf_left -= len + sizeof(struct mwifiex_ie_types_header);
   2586		tlv = (void *)((u8 *)tlv + len +
   2587			       sizeof(struct mwifiex_ie_types_header));
   2588	}
   2589
   2590	spin_lock_bh(&adapter->cmd_pending_q_lock);
   2591	spin_lock_bh(&adapter->scan_pending_q_lock);
   2592	if (list_empty(&adapter->scan_pending_q)) {
   2593		complete_scan = true;
   2594		list_for_each_entry(cmd_node, &adapter->cmd_pending_q, list) {
   2595			cmd_ptr = (void *)cmd_node->cmd_skb->data;
   2596			if (le16_to_cpu(cmd_ptr->command) ==
   2597			    HostCmd_CMD_802_11_SCAN_EXT) {
   2598				mwifiex_dbg(adapter, INFO,
   2599					    "Scan pending in command pending list");
   2600				complete_scan = false;
   2601				break;
   2602			}
   2603		}
   2604	}
   2605	spin_unlock_bh(&adapter->scan_pending_q_lock);
   2606	spin_unlock_bh(&adapter->cmd_pending_q_lock);
   2607
   2608	if (complete_scan)
   2609		mwifiex_complete_scan(priv);
   2610
   2611	return 0;
   2612}
   2613
   2614/* This function This function handles the event extended scan report. It
   2615 * parses extended scan results and informs to cfg80211 stack.
   2616 */
   2617int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv,
   2618					 void *buf)
   2619{
   2620	int ret = 0;
   2621	struct mwifiex_adapter *adapter = priv->adapter;
   2622	u8 *bss_info;
   2623	u32 bytes_left, bytes_left_for_tlv, idx;
   2624	u16 type, len;
   2625	struct mwifiex_ie_types_data *tlv;
   2626	struct mwifiex_ie_types_bss_scan_rsp *scan_rsp_tlv;
   2627	struct mwifiex_ie_types_bss_scan_info *scan_info_tlv;
   2628	u8 *radio_type;
   2629	u64 fw_tsf = 0;
   2630	s32 rssi = 0;
   2631	struct mwifiex_event_scan_result *event_scan = buf;
   2632	u8 num_of_set = event_scan->num_of_set;
   2633	u8 *scan_resp = buf + sizeof(struct mwifiex_event_scan_result);
   2634	u16 scan_resp_size = le16_to_cpu(event_scan->buf_size);
   2635
   2636	if (num_of_set > MWIFIEX_MAX_AP) {
   2637		mwifiex_dbg(adapter, ERROR,
   2638			    "EXT_SCAN: Invalid number of AP returned (%d)!!\n",
   2639			    num_of_set);
   2640		ret = -1;
   2641		goto check_next_scan;
   2642	}
   2643
   2644	bytes_left = scan_resp_size;
   2645	mwifiex_dbg(adapter, INFO,
   2646		    "EXT_SCAN: size %d, returned %d APs...",
   2647		    scan_resp_size, num_of_set);
   2648	mwifiex_dbg_dump(adapter, CMD_D, "EXT_SCAN buffer:", buf,
   2649			 scan_resp_size +
   2650			 sizeof(struct mwifiex_event_scan_result));
   2651
   2652	tlv = (struct mwifiex_ie_types_data *)scan_resp;
   2653
   2654	for (idx = 0; idx < num_of_set && bytes_left; idx++) {
   2655		type = le16_to_cpu(tlv->header.type);
   2656		len = le16_to_cpu(tlv->header.len);
   2657		if (bytes_left < sizeof(struct mwifiex_ie_types_header) + len) {
   2658			mwifiex_dbg(adapter, ERROR,
   2659				    "EXT_SCAN: Error bytes left < TLV length\n");
   2660			break;
   2661		}
   2662		scan_rsp_tlv = NULL;
   2663		scan_info_tlv = NULL;
   2664		bytes_left_for_tlv = bytes_left;
   2665
   2666		/* BSS response TLV with beacon or probe response buffer
   2667		 * at the initial position of each descriptor
   2668		 */
   2669		if (type != TLV_TYPE_BSS_SCAN_RSP)
   2670			break;
   2671
   2672		bss_info = (u8 *)tlv;
   2673		scan_rsp_tlv = (struct mwifiex_ie_types_bss_scan_rsp *)tlv;
   2674		tlv = (struct mwifiex_ie_types_data *)(tlv->data + len);
   2675		bytes_left_for_tlv -=
   2676				(len + sizeof(struct mwifiex_ie_types_header));
   2677
   2678		while (bytes_left_for_tlv >=
   2679		       sizeof(struct mwifiex_ie_types_header) &&
   2680		       le16_to_cpu(tlv->header.type) != TLV_TYPE_BSS_SCAN_RSP) {
   2681			type = le16_to_cpu(tlv->header.type);
   2682			len = le16_to_cpu(tlv->header.len);
   2683			if (bytes_left_for_tlv <
   2684			    sizeof(struct mwifiex_ie_types_header) + len) {
   2685				mwifiex_dbg(adapter, ERROR,
   2686					    "EXT_SCAN: Error in processing TLV,\t"
   2687					    "bytes left < TLV length\n");
   2688				scan_rsp_tlv = NULL;
   2689				bytes_left_for_tlv = 0;
   2690				continue;
   2691			}
   2692			switch (type) {
   2693			case TLV_TYPE_BSS_SCAN_INFO:
   2694				scan_info_tlv =
   2695				  (struct mwifiex_ie_types_bss_scan_info *)tlv;
   2696				if (len !=
   2697				 sizeof(struct mwifiex_ie_types_bss_scan_info) -
   2698				 sizeof(struct mwifiex_ie_types_header)) {
   2699					bytes_left_for_tlv = 0;
   2700					continue;
   2701				}
   2702				break;
   2703			default:
   2704				break;
   2705			}
   2706			tlv = (struct mwifiex_ie_types_data *)(tlv->data + len);
   2707			bytes_left -=
   2708				(len + sizeof(struct mwifiex_ie_types_header));
   2709			bytes_left_for_tlv -=
   2710				(len + sizeof(struct mwifiex_ie_types_header));
   2711		}
   2712
   2713		if (!scan_rsp_tlv)
   2714			break;
   2715
   2716		/* Advance pointer to the beacon buffer length and
   2717		 * update the bytes count so that the function
   2718		 * wlan_interpret_bss_desc_with_ie() can handle the
   2719		 * scan buffer withut any change
   2720		 */
   2721		bss_info += sizeof(u16);
   2722		bytes_left -= sizeof(u16);
   2723
   2724		if (scan_info_tlv) {
   2725			rssi = (s32)(s16)(le16_to_cpu(scan_info_tlv->rssi));
   2726			rssi *= 100;           /* Convert dBm to mBm */
   2727			mwifiex_dbg(adapter, INFO,
   2728				    "info: InterpretIE: RSSI=%d\n", rssi);
   2729			fw_tsf = le64_to_cpu(scan_info_tlv->tsf);
   2730			radio_type = &scan_info_tlv->radio_type;
   2731		} else {
   2732			radio_type = NULL;
   2733		}
   2734		ret = mwifiex_parse_single_response_buf(priv, &bss_info,
   2735							&bytes_left, fw_tsf,
   2736							radio_type, true, rssi);
   2737		if (ret)
   2738			goto check_next_scan;
   2739	}
   2740
   2741check_next_scan:
   2742	if (!event_scan->more_event)
   2743		mwifiex_check_next_scan_command(priv);
   2744
   2745	return ret;
   2746}
   2747
   2748/*
   2749 * This function prepares command for background scan query.
   2750 *
   2751 * Preparation includes -
   2752 *      - Setting command ID and proper size
   2753 *      - Setting background scan flush parameter
   2754 *      - Ensuring correct endian-ness
   2755 */
   2756int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd)
   2757{
   2758	struct host_cmd_ds_802_11_bg_scan_query *bg_query =
   2759		&cmd->params.bg_scan_query;
   2760
   2761	cmd->command = cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_QUERY);
   2762	cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_bg_scan_query)
   2763				+ S_DS_GEN);
   2764
   2765	bg_query->flush = 1;
   2766
   2767	return 0;
   2768}
   2769
   2770/*
   2771 * This function inserts scan command node to the scan pending queue.
   2772 */
   2773void
   2774mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
   2775		       struct cmd_ctrl_node *cmd_node)
   2776{
   2777	struct mwifiex_adapter *adapter = priv->adapter;
   2778
   2779	cmd_node->wait_q_enabled = true;
   2780	cmd_node->condition = &adapter->scan_wait_q_woken;
   2781	spin_lock_bh(&adapter->scan_pending_q_lock);
   2782	list_add_tail(&cmd_node->list, &adapter->scan_pending_q);
   2783	spin_unlock_bh(&adapter->scan_pending_q_lock);
   2784}
   2785
   2786/*
   2787 * This function sends a scan command for all available channels to the
   2788 * firmware, filtered on a specific SSID.
   2789 */
   2790static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
   2791				      struct cfg80211_ssid *req_ssid)
   2792{
   2793	struct mwifiex_adapter *adapter = priv->adapter;
   2794	int ret;
   2795	struct mwifiex_user_scan_cfg *scan_cfg;
   2796
   2797	if (adapter->scan_processing) {
   2798		mwifiex_dbg(adapter, WARN,
   2799			    "cmd: Scan already in process...\n");
   2800		return -EBUSY;
   2801	}
   2802
   2803	if (priv->scan_block) {
   2804		mwifiex_dbg(adapter, WARN,
   2805			    "cmd: Scan is blocked during association...\n");
   2806		return -EBUSY;
   2807	}
   2808
   2809	scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL);
   2810	if (!scan_cfg)
   2811		return -ENOMEM;
   2812
   2813	scan_cfg->ssid_list = req_ssid;
   2814	scan_cfg->num_ssids = 1;
   2815
   2816	ret = mwifiex_scan_networks(priv, scan_cfg);
   2817
   2818	kfree(scan_cfg);
   2819	return ret;
   2820}
   2821
   2822/*
   2823 * Sends IOCTL request to start a scan.
   2824 *
   2825 * This function allocates the IOCTL request buffer, fills it
   2826 * with requisite parameters and calls the IOCTL handler.
   2827 *
   2828 * Scan command can be issued for both normal scan and specific SSID
   2829 * scan, depending upon whether an SSID is provided or not.
   2830 */
   2831int mwifiex_request_scan(struct mwifiex_private *priv,
   2832			 struct cfg80211_ssid *req_ssid)
   2833{
   2834	int ret;
   2835
   2836	if (mutex_lock_interruptible(&priv->async_mutex)) {
   2837		mwifiex_dbg(priv->adapter, ERROR,
   2838			    "%s: acquire semaphore fail\n",
   2839			    __func__);
   2840		return -1;
   2841	}
   2842
   2843	priv->adapter->scan_wait_q_woken = false;
   2844
   2845	if (req_ssid && req_ssid->ssid_len != 0)
   2846		/* Specific SSID scan */
   2847		ret = mwifiex_scan_specific_ssid(priv, req_ssid);
   2848	else
   2849		/* Normal scan */
   2850		ret = mwifiex_scan_networks(priv, NULL);
   2851
   2852	mutex_unlock(&priv->async_mutex);
   2853
   2854	return ret;
   2855}
   2856
   2857/*
   2858 * This function appends the vendor specific IE TLV to a buffer.
   2859 */
   2860int
   2861mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv,
   2862			    u16 vsie_mask, u8 **buffer)
   2863{
   2864	int id, ret_len = 0;
   2865	struct mwifiex_ie_types_vendor_param_set *vs_param_set;
   2866
   2867	if (!buffer)
   2868		return 0;
   2869	if (!(*buffer))
   2870		return 0;
   2871
   2872	/*
   2873	 * Traverse through the saved vendor specific IE array and append
   2874	 * the selected(scan/assoc/adhoc) IE as TLV to the command
   2875	 */
   2876	for (id = 0; id < MWIFIEX_MAX_VSIE_NUM; id++) {
   2877		if (priv->vs_ie[id].mask & vsie_mask) {
   2878			vs_param_set =
   2879				(struct mwifiex_ie_types_vendor_param_set *)
   2880				*buffer;
   2881			vs_param_set->header.type =
   2882				cpu_to_le16(TLV_TYPE_PASSTHROUGH);
   2883			vs_param_set->header.len =
   2884				cpu_to_le16((((u16) priv->vs_ie[id].ie[1])
   2885				& 0x00FF) + 2);
   2886			if (le16_to_cpu(vs_param_set->header.len) >
   2887				MWIFIEX_MAX_VSIE_LEN) {
   2888				mwifiex_dbg(priv->adapter, ERROR,
   2889					    "Invalid param length!\n");
   2890				break;
   2891			}
   2892
   2893			memcpy(vs_param_set->ie, priv->vs_ie[id].ie,
   2894			       le16_to_cpu(vs_param_set->header.len));
   2895			*buffer += le16_to_cpu(vs_param_set->header.len) +
   2896				   sizeof(struct mwifiex_ie_types_header);
   2897			ret_len += le16_to_cpu(vs_param_set->header.len) +
   2898				   sizeof(struct mwifiex_ie_types_header);
   2899		}
   2900	}
   2901	return ret_len;
   2902}
   2903
   2904/*
   2905 * This function saves a beacon buffer of the current BSS descriptor.
   2906 *
   2907 * The current beacon buffer is saved so that it can be restored in the
   2908 * following cases that makes the beacon buffer not to contain the current
   2909 * ssid's beacon buffer.
   2910 *      - The current ssid was not found somehow in the last scan.
   2911 *      - The current ssid was the last entry of the scan table and overloaded.
   2912 */
   2913void
   2914mwifiex_save_curr_bcn(struct mwifiex_private *priv)
   2915{
   2916	struct mwifiex_bssdescriptor *curr_bss =
   2917		&priv->curr_bss_params.bss_descriptor;
   2918
   2919	if (!curr_bss->beacon_buf_size)
   2920		return;
   2921
   2922	/* allocate beacon buffer at 1st time; or if it's size has changed */
   2923	if (!priv->curr_bcn_buf ||
   2924	    priv->curr_bcn_size != curr_bss->beacon_buf_size) {
   2925		priv->curr_bcn_size = curr_bss->beacon_buf_size;
   2926
   2927		kfree(priv->curr_bcn_buf);
   2928		priv->curr_bcn_buf = kmalloc(curr_bss->beacon_buf_size,
   2929					     GFP_ATOMIC);
   2930		if (!priv->curr_bcn_buf)
   2931			return;
   2932	}
   2933
   2934	memcpy(priv->curr_bcn_buf, curr_bss->beacon_buf,
   2935	       curr_bss->beacon_buf_size);
   2936	mwifiex_dbg(priv->adapter, INFO,
   2937		    "info: current beacon saved %d\n",
   2938		    priv->curr_bcn_size);
   2939
   2940	curr_bss->beacon_buf = priv->curr_bcn_buf;
   2941
   2942	/* adjust the pointers in the current BSS descriptor */
   2943	if (curr_bss->bcn_wpa_ie)
   2944		curr_bss->bcn_wpa_ie =
   2945			(struct ieee_types_vendor_specific *)
   2946			(curr_bss->beacon_buf +
   2947			 curr_bss->wpa_offset);
   2948
   2949	if (curr_bss->bcn_rsn_ie)
   2950		curr_bss->bcn_rsn_ie = (struct ieee_types_generic *)
   2951			(curr_bss->beacon_buf +
   2952			 curr_bss->rsn_offset);
   2953
   2954	if (curr_bss->bcn_ht_cap)
   2955		curr_bss->bcn_ht_cap = (struct ieee80211_ht_cap *)
   2956			(curr_bss->beacon_buf +
   2957			 curr_bss->ht_cap_offset);
   2958
   2959	if (curr_bss->bcn_ht_oper)
   2960		curr_bss->bcn_ht_oper = (struct ieee80211_ht_operation *)
   2961			(curr_bss->beacon_buf +
   2962			 curr_bss->ht_info_offset);
   2963
   2964	if (curr_bss->bcn_vht_cap)
   2965		curr_bss->bcn_vht_cap = (void *)(curr_bss->beacon_buf +
   2966						 curr_bss->vht_cap_offset);
   2967
   2968	if (curr_bss->bcn_vht_oper)
   2969		curr_bss->bcn_vht_oper = (void *)(curr_bss->beacon_buf +
   2970						  curr_bss->vht_info_offset);
   2971
   2972	if (curr_bss->bcn_bss_co_2040)
   2973		curr_bss->bcn_bss_co_2040 =
   2974			(curr_bss->beacon_buf + curr_bss->bss_co_2040_offset);
   2975
   2976	if (curr_bss->bcn_ext_cap)
   2977		curr_bss->bcn_ext_cap = curr_bss->beacon_buf +
   2978			curr_bss->ext_cap_offset;
   2979
   2980	if (curr_bss->oper_mode)
   2981		curr_bss->oper_mode = (void *)(curr_bss->beacon_buf +
   2982					       curr_bss->oper_mode_offset);
   2983}
   2984
   2985/*
   2986 * This function frees the current BSS descriptor beacon buffer.
   2987 */
   2988void
   2989mwifiex_free_curr_bcn(struct mwifiex_private *priv)
   2990{
   2991	kfree(priv->curr_bcn_buf);
   2992	priv->curr_bcn_buf = NULL;
   2993}