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