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