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