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