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