xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/nxp/mlan/mlan_scan.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /** @file mlan_scan.c
2  *
3  *  @brief Functions implementing wlan scan IOCTL and firmware command APIs
4  *
5  *  IOCTL handlers as well as command preparation and response routines
6  *  for sending scan commands to the firmware.
7  *
8  *
9  *  Copyright 2008-2022 NXP
10  *
11  *  This software file (the File) is distributed by NXP
12  *  under the terms of the GNU General Public License Version 2, June 1991
13  *  (the License).  You may use, redistribute and/or modify the File in
14  *  accordance with the terms and conditions of the License, a copy of which
15  *  is available by writing to the Free Software Foundation, Inc.,
16  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the
17  *  worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt.
18  *
19  *  THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE
20  *  IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE
21  *  ARE EXPRESSLY DISCLAIMED.  The License provides additional details about
22  *  this warranty disclaimer.
23  *
24  */
25 
26 /******************************************************
27 Change log:
28     10/28/2008: initial version
29 ******************************************************/
30 
31 #include "mlan.h"
32 #include "mlan_join.h"
33 #include "mlan_util.h"
34 #include "mlan_fw.h"
35 #include "mlan_main.h"
36 #include "mlan_11n.h"
37 #include "mlan_11ac.h"
38 #include "mlan_11ax.h"
39 #include "mlan_11h.h"
40 #ifdef DRV_EMBEDDED_SUPPLICANT
41 #include "authenticator_api.h"
42 #endif
43 /********************************************************
44 			Local Constants
45 ********************************************************/
46 /** minimum scan time for passive to active scan */
47 #define MIN_PASSIVE_TO_ACTIVE_SCAN_TIME 150
48 
49 #define MRVDRV_MAX_CHANNELS_PER_SCAN 38
50 /** The maximum number of channels the firmware can scan per command */
51 #define MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN 4
52 
53 /**
54  * Number of channels to scan per firmware scan command issuance.
55  *
56  * Number restricted to prevent hitting the limit on the amount of scan data
57  * returned in a single firmware scan command.
58  */
59 #define MRVDRV_CHANNELS_PER_SCAN_CMD 4
60 
61 /** Memory needed to store a max sized Channel List TLV for a firmware scan */
62 #define CHAN_TLV_MAX_SIZE                                                      \
63 	(sizeof(MrvlIEtypesHeader_t) +                                         \
64 	 (MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN * sizeof(ChanScanParamSet_t)))
65 
66 /** Memory needed to store supported rate */
67 #define RATE_TLV_MAX_SIZE                                                      \
68 	(sizeof(MrvlIEtypes_RatesParamSet_t) + HOSTCMD_SUPPORTED_RATES)
69 
70 /** Memory needed to store a max number/size WildCard
71  *  SSID TLV for a firmware scan */
72 #define WILDCARD_SSID_TLV_MAX_SIZE                                             \
73 	(MRVDRV_MAX_SSID_LIST_LENGTH *                                         \
74 	 (sizeof(MrvlIEtypes_WildCardSsIdParamSet_t) +                         \
75 	  MRVDRV_MAX_SSID_LENGTH))
76 
77 /** Memory needed to store a max number/size BSSID TLV for a firmware scan */
78 #define BSSID_LIST_TLV_MAX_SIZE                                                \
79 	(sizeof(MrvlIEtypesHeader_t) +                                         \
80 	 (MRVDRV_MAX_BSSID_LIST * MLAN_MAC_ADDR_LENGTH))
81 
82 /** WPS TLV MAX size is MAX IE size plus 2 bytes for
83  *  t_u16 MRVL TLV extension */
84 #define WPS_TLV_MAX_SIZE (sizeof(IEEEtypes_VendorSpecific_t) + 2)
85 /** Maximum memory needed for a wlan_scan_cmd_config
86  *  with all TLVs at max */
87 #define MAX_SCAN_CFG_ALLOC                                                     \
88 	(sizeof(wlan_scan_cmd_config) + sizeof(MrvlIEtypes_NumProbes_t) +      \
89 	 sizeof(MrvlIETypes_HTCap_t) + CHAN_TLV_MAX_SIZE + RATE_TLV_MAX_SIZE + \
90 	 WILDCARD_SSID_TLV_MAX_SIZE + BSSID_LIST_TLV_MAX_SIZE +                \
91 	 WPS_TLV_MAX_SIZE)
92 
93 /********************************************************
94 			Local Variables
95 ********************************************************/
96 
97 /**
98  * Interally used to send a configured scan cmd between
99  * driver routines
100  */
101 typedef union {
102 	/** Scan configuration (variable length) */
103 	wlan_scan_cmd_config config;
104 	/** Max allocated block */
105 	t_u8 config_alloc_buf[MAX_SCAN_CFG_ALLOC];
106 } wlan_scan_cmd_config_tlv;
107 
108 /********************************************************
109 			Global Variables
110 ********************************************************/
111 
112 /********************************************************
113 			Local Functions
114 ********************************************************/
115 /** Cipher suite definition */
116 enum cipher_suite {
117 	CIPHER_SUITE_WEP40,
118 	CIPHER_SUITE_TKIP,
119 	CIPHER_SUITE_CCMP,
120 	CIPHER_SUITE_WEP104,
121 	CIPHER_SUITE_GCMP,
122 	CIPHER_SUITE_GCMP_256,
123 	CIPHER_SUITE_CCMP_256,
124 	CIPHER_SUITE_MAX
125 };
126 
127 static t_u8 wpa_ouis[CIPHER_SUITE_MAX][4] = {
128 	{0x00, 0x50, 0xf2, 0x01}, /* WEP40 */
129 	{0x00, 0x50, 0xf2, 0x02}, /* TKIP */
130 	{0x00, 0x50, 0xf2, 0x04}, /* AES */
131 	{0x00, 0x50, 0xf2, 0x05}, /* WEP104 */
132 };
133 
134 static t_u8 rsn_oui[CIPHER_SUITE_MAX][4] = {
135 	{0x00, 0x0f, 0xac, 0x01}, /* WEP40 */
136 	{0x00, 0x0f, 0xac, 0x02}, /* TKIP */
137 	{0x00, 0x0f, 0xac, 0x04}, /* AES */
138 	{0x00, 0x0f, 0xac, 0x05}, /* WEP104 */
139 	{0x00, 0x0f, 0xac, 0x08}, /* GCMP */
140 	{0x00, 0x0f, 0xac, 0x09}, /* GCMP-256 */
141 	{0x00, 0x0f, 0xac, 0x0a}, /* CCMP-256 */
142 };
143 
144 /**
145  *  @brief Convert radio type scan parameter to a band config used in join cmd
146  *
147  *  @param radio_type Scan parameter indicating the radio used for a channel
148  *                    in a scan command.
149  *
150  *  @return          Band type conversion of scanBand used in join/assoc cmds
151  *
152  */
radio_type_to_band(t_u8 radio_type)153 t_u16 radio_type_to_band(t_u8 radio_type)
154 {
155 	t_u16 ret_band;
156 
157 	switch (radio_type) {
158 	case BAND_5GHZ:
159 		ret_band = BAND_A;
160 		break;
161 	case BAND_2GHZ:
162 	default:
163 		ret_band = BAND_G;
164 		break;
165 	}
166 
167 	return ret_band;
168 }
169 
170 /**
171  *  @brief This function will update the channel statistics from scan result
172  *
173  *  @param pmpriv           A pointer to mlan_private structure
174  *  @param pchanstats_tlv   A pointer to MrvlIEtypes_ChannelStats_t tlv
175  *
176  *  @return                NA
177  */
178 static void
wlan_update_chan_statistics(mlan_private * pmpriv,MrvlIEtypes_ChannelStats_t * pchanstats_tlv)179 wlan_update_chan_statistics(mlan_private *pmpriv,
180 			    MrvlIEtypes_ChannelStats_t *pchanstats_tlv)
181 {
182 	mlan_adapter *pmadapter = pmpriv->adapter;
183 	t_u8 i;
184 	chan_statistics_t *pchan_stats =
185 		(chan_statistics_t *)((t_u8 *)pchanstats_tlv +
186 				      sizeof(MrvlIEtypesHeader_t));
187 	t_u8 num_chan = wlan_le16_to_cpu(pchanstats_tlv->header.len) /
188 			sizeof(chan_statistics_t);
189 
190 	ENTER();
191 
192 	for (i = 0; i < num_chan; i++) {
193 		if (pmadapter->idx_chan_stats >= pmadapter->num_in_chan_stats) {
194 			PRINTM(MERROR,
195 			       "Over flow: idx_chan_stats=%d, num_in_chan_stats=%d\n",
196 			       pmadapter->idx_chan_stats,
197 			       pmadapter->num_in_chan_stats);
198 			break;
199 		}
200 		pchan_stats->total_networks =
201 			wlan_le16_to_cpu(pchan_stats->total_networks);
202 		pchan_stats->cca_scan_duration =
203 			wlan_le16_to_cpu(pchan_stats->cca_scan_duration);
204 		pchan_stats->cca_busy_duration =
205 			wlan_le16_to_cpu(pchan_stats->cca_busy_duration);
206 		PRINTM(MCMND,
207 		       "chan=%d, noise=%d, total_network=%d scan_duration=%d, busy_duration=%d\n",
208 		       pchan_stats->chan_num, pchan_stats->noise,
209 		       pchan_stats->total_networks,
210 		       pchan_stats->cca_scan_duration,
211 		       pchan_stats->cca_busy_duration);
212 		memcpy_ext(pmadapter,
213 			   (chan_statistics_t *)&pmadapter
214 				   ->pchan_stats[pmadapter->idx_chan_stats],
215 			   pchan_stats, sizeof(chan_statistics_t),
216 			   sizeof(chan_statistics_t));
217 		pmadapter->idx_chan_stats++;
218 		pchan_stats++;
219 	}
220 	LEAVE();
221 	return;
222 }
223 
224 /**
225  *  @brief This function will parse a given IE for a given OUI
226  *
227  *  Parse a given WPA/RSN IE to find if it has a given oui in PTK,
228  *  if no OUI found for PTK it returns 0.
229  *
230  *  @param pbss_desc       A pointer to current BSS descriptor
231  *  @return                0 on failure to find OUI, 1 on success.
232  */
search_oui_in_ie(mlan_adapter * pmadapter,IEBody * ie_body,t_u8 * oui)233 static t_u8 search_oui_in_ie(mlan_adapter *pmadapter, IEBody *ie_body,
234 			     t_u8 *oui)
235 {
236 	t_u8 count;
237 
238 	count = ie_body->PtkCnt[0];
239 
240 	ENTER();
241 	/* There could be multiple OUIs for PTK hence
242 	 * 1) Take the length.
243 	 * 2) Check all the OUIs for AES.
244 	 * 3) If one of them is AES then pass success.
245 	 */
246 	while (count) {
247 		if (!memcmp(pmadapter, ie_body->PtkBody, oui,
248 			    sizeof(ie_body->PtkBody))) {
249 			LEAVE();
250 			return MLAN_OUI_PRESENT;
251 		}
252 
253 		--count;
254 		if (count) {
255 			ie_body = (IEBody *)((t_u8 *)ie_body +
256 					     sizeof(ie_body->PtkBody));
257 		}
258 	}
259 
260 	PRINTM(MINFO, "The OUI %x:%x:%x:%x is not found in PTK\n", oui[0],
261 	       oui[1], oui[2], oui[3]);
262 	LEAVE();
263 	return MLAN_OUI_NOT_PRESENT;
264 }
265 
266 /**
267  *  @brief This function will pass the correct ie and oui to search_oui_in_ie
268  *
269  *  Check the pbss_desc for appropriate IE and then check if RSN IE has AES
270  *  OUI in it. If RSN IE does not have AES in PTK then return 0;
271  *
272  *  @param pbss_desc       A pointer to current BSS descriptor
273  *  @return                0 on failure to find AES OUI, 1 on success.
274  */
is_rsn_oui_present(mlan_adapter * pmadapter,BSSDescriptor_t * pbss_desc,t_u32 cipher_suite)275 static t_u8 is_rsn_oui_present(mlan_adapter *pmadapter,
276 			       BSSDescriptor_t *pbss_desc, t_u32 cipher_suite)
277 {
278 	t_u8 *oui = MNULL;
279 	IEBody *ie_body = MNULL;
280 	t_u8 ret = MLAN_OUI_NOT_PRESENT;
281 
282 	ENTER();
283 	if (pbss_desc->prsn_ie &&
284 	    (pbss_desc->prsn_ie->ieee_hdr.element_id == RSN_IE) &&
285 	    (pbss_desc->prsn_ie->ieee_hdr.len > RSN_GTK_OUI_OFFSET)) {
286 		ie_body = (IEBody *)(((t_u8 *)pbss_desc->prsn_ie->data) +
287 				     RSN_GTK_OUI_OFFSET);
288 		oui = &rsn_oui[cipher_suite][0];
289 		ret = search_oui_in_ie(pmadapter, ie_body, oui);
290 		if (ret) {
291 			LEAVE();
292 			return ret;
293 		}
294 	}
295 	LEAVE();
296 	return ret;
297 }
298 
299 /**
300  *  @brief This function will pass the correct ie and oui to search_oui_in_ie
301  *
302  *  Check the wpa_ie for appropriate IE and then check if RSN IE has AES
303  *  OUI in it. If RSN IE does not have AES in PTK then return 0;
304  *
305  *  @param pmadapter       A pointer to mlan adapter.
306  *  @return                0 on failure to find AES OUI, 1 on success.
307  */
is_rsn_oui_present_in_wpa_ie(mlan_private * pmpriv,t_u32 cipher_suite)308 static t_u8 is_rsn_oui_present_in_wpa_ie(mlan_private *pmpriv,
309 					 t_u32 cipher_suite)
310 {
311 	mlan_adapter *pmadapter = pmpriv->adapter;
312 	t_u8 *oui = MNULL;
313 	IEBody *ie_body = MNULL;
314 	IEEEtypes_Generic_t *prsn_ie = MNULL;
315 	t_u8 ret = MLAN_OUI_NOT_PRESENT;
316 
317 	ENTER();
318 	prsn_ie = (IEEEtypes_Generic_t *)pmpriv->wpa_ie;
319 
320 	if (prsn_ie && (prsn_ie->ieee_hdr.element_id == RSN_IE) &&
321 	    (prsn_ie->ieee_hdr.len > RSN_GTK_OUI_OFFSET)) {
322 		ie_body = (IEBody *)(prsn_ie->data + RSN_GTK_OUI_OFFSET);
323 		oui = &rsn_oui[cipher_suite][0];
324 		ret = search_oui_in_ie(pmadapter, ie_body, oui);
325 		if (ret) {
326 			LEAVE();
327 			return ret;
328 		}
329 	}
330 
331 	LEAVE();
332 	return ret;
333 }
334 
335 /**
336  *  @brief This function will pass the correct ie and oui to search_oui_in_ie
337  *
338  *  Check the pbss_desc for appropriate IE and then check if WPA IE has AES
339  *  OUI in it. If WPA IE does not have AES in PTK then return 0;
340  *
341  *  @param pbss_desc       A pointer to current BSS descriptor
342  *  @return                0 on failure to find AES OUI, 1 on success.
343  */
is_wpa_oui_present(mlan_adapter * pmadapter,BSSDescriptor_t * pbss_desc,t_u32 cipher_suite)344 static t_u8 is_wpa_oui_present(mlan_adapter *pmadapter,
345 			       BSSDescriptor_t *pbss_desc, t_u32 cipher_suite)
346 {
347 	t_u8 *oui = MNULL;
348 	IEBody *ie_body = MNULL;
349 	t_u8 ret = MLAN_OUI_NOT_PRESENT;
350 
351 	ENTER();
352 	if (((pbss_desc->pwpa_ie) &&
353 	     ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id == WPA_IE))) {
354 		ie_body = (IEBody *)pbss_desc->pwpa_ie->data;
355 		oui = &wpa_ouis[cipher_suite][0];
356 		ret = search_oui_in_ie(pmadapter, ie_body, oui);
357 		if (ret) {
358 			LEAVE();
359 			return ret;
360 		}
361 	}
362 	LEAVE();
363 	return ret;
364 }
365 
366 /**
367  *  @brief compare config band and a band from the scan result,
368  *  which is defined by functiion radio_type_to_band(t_u8 radio_type) above
369  *
370  *  @param cfg_band:  band configured
371  *         scan_band: band from scan result
372  *
373  *  @return  matched: non-zero. unmatched: 0
374  *
375  */
wlan_is_band_compatible(t_u8 cfg_band,t_u8 scan_band)376 static t_u8 wlan_is_band_compatible(t_u8 cfg_band, t_u8 scan_band)
377 {
378 	t_u16 band;
379 	switch (scan_band) {
380 	case BAND_A:
381 		band = BAND_A | BAND_AN | BAND_AAC;
382 		break;
383 	case BAND_G:
384 	default:
385 		band = BAND_B | BAND_G | BAND_GN | BAND_GAC;
386 	}
387 	return cfg_band & band;
388 }
389 
390 /**
391  *  @brief This function finds the best SSID in the Scan List
392  *
393  *  Search the scan table for the best SSID that also matches the current
394  *   adapter network preference (infrastructure or adhoc)
395  *
396  *  @param pmpriv       A pointer to mlan_private structure
397  *  @return             index in BSSID list
398  */
wlan_find_best_network_in_list(mlan_private * pmpriv)399 static t_s32 wlan_find_best_network_in_list(mlan_private *pmpriv)
400 {
401 	mlan_adapter *pmadapter = pmpriv->adapter;
402 	t_u32 mode = pmpriv->bss_mode;
403 	t_s32 best_net = -1;
404 	t_s32 best_rssi = 0;
405 	t_u32 i;
406 
407 	ENTER();
408 
409 	PRINTM(MINFO, "Num of BSSIDs = %d\n", pmadapter->num_in_scan_table);
410 
411 	for (i = 0; i < pmadapter->num_in_scan_table; i++) {
412 		switch (mode) {
413 		case MLAN_BSS_MODE_INFRA:
414 		case MLAN_BSS_MODE_IBSS:
415 			if (wlan_is_network_compatible(pmpriv, i, mode) >= 0) {
416 				if (SCAN_RSSI(pmadapter->pscan_table[i].rssi) >
417 				    best_rssi) {
418 					best_rssi = SCAN_RSSI(
419 						pmadapter->pscan_table[i].rssi);
420 					best_net = i;
421 				}
422 			}
423 			break;
424 		case MLAN_BSS_MODE_AUTO:
425 		default:
426 			if (SCAN_RSSI(pmadapter->pscan_table[i].rssi) >
427 			    best_rssi) {
428 				best_rssi = SCAN_RSSI(
429 					pmadapter->pscan_table[i].rssi);
430 				best_net = i;
431 			}
432 			break;
433 		}
434 	}
435 
436 	LEAVE();
437 	return best_net;
438 }
439 
440 /**
441  *  @brief Create a channel list for the driver to scan based on region info
442  *
443  *  Use the driver region/band information to construct a comprehensive list
444  *    of channels to scan.  This routine is used for any scan that is not
445  *    provided a specific channel list to scan.
446  *
447  *  @param pmpriv           A pointer to mlan_private structure
448  *  @param puser_scan_in    MNULL or pointer to scan configuration parameters
449  *  @param pscan_chan_list  Output parameter: Resulting channel list to scan
450  *  @param filtered_scan    Flag indicating whether or not a BSSID or SSID
451  * filter is being sent in the command to firmware.  Used to increase the number
452  * of channels sent in a scan command and to disable the firmware channel scan
453  *                          filter.
454  *
455  *  @return                 num of channel
456  */
wlan_scan_create_channel_list(mlan_private * pmpriv,const wlan_user_scan_cfg * puser_scan_in,ChanScanParamSet_t * pscan_chan_list,t_u8 filtered_scan)457 static t_u8 wlan_scan_create_channel_list(
458 	mlan_private *pmpriv, const wlan_user_scan_cfg *puser_scan_in,
459 	ChanScanParamSet_t *pscan_chan_list, t_u8 filtered_scan)
460 {
461 	mlan_adapter *pmadapter = pmpriv->adapter;
462 	region_chan_t *pscan_region;
463 	chan_freq_power_t *cfp;
464 	t_u32 region_idx;
465 	t_u32 chan_idx = 0;
466 	t_u32 next_chan;
467 	t_u8 scan_type;
468 	t_u8 radio_type;
469 	t_u16 band;
470 	t_u16 scan_dur = 0;
471 
472 	ENTER();
473 
474 	for (region_idx = 0; region_idx < NELEMENTS(pmadapter->region_channel);
475 	     region_idx++) {
476 		if (wlan_11d_is_enabled(pmpriv) &&
477 		    pmpriv->media_connected != MTRUE) {
478 			/* Scan all the supported chan for the first scan */
479 			if (!pmadapter->universal_channel[region_idx].valid)
480 				continue;
481 			pscan_region =
482 				&pmadapter->universal_channel[region_idx];
483 		} else {
484 			if (!pmadapter->region_channel[region_idx].valid)
485 				continue;
486 			pscan_region = &pmadapter->region_channel[region_idx];
487 		}
488 
489 		if (puser_scan_in && !puser_scan_in->chan_list[0].chan_number &&
490 		    puser_scan_in->chan_list[0].radio_type & BAND_SPECIFIED) {
491 			radio_type = puser_scan_in->chan_list[0].radio_type &
492 				     ~BAND_SPECIFIED;
493 			if (!radio_type && (pscan_region->band != BAND_B) &&
494 			    (pscan_region->band != BAND_G))
495 				continue;
496 			if (radio_type && (pscan_region->band != BAND_A))
497 				continue;
498 		}
499 		PRINTM(MCMD_D,
500 		       "create_channel_list: region=%d band=%d num_cfp=%d\n",
501 		       pscan_region->region, pscan_region->band,
502 		       pscan_region->num_cfp);
503 		if ((puser_scan_in &&
504 		     (puser_scan_in->bss_mode == MLAN_SCAN_MODE_IBSS)) ||
505 		    pmpriv->bss_mode == MLAN_BSS_MODE_IBSS)
506 			band = pmadapter->adhoc_start_band;
507 		else
508 			band = pmpriv->config_bands;
509 		if (!wlan_is_band_compatible(band, pscan_region->band))
510 			continue;
511 		for (next_chan = 0; next_chan < pscan_region->num_cfp;
512 		     next_chan++) {
513 			/* Set the default scan type to the user specified type,
514 			 * will later be changed to passive on a per channel
515 			 * basis if restricted by regulatory requirements (11d
516 			 * or 11h)
517 			 */
518 			scan_type = pmadapter->scan_type;
519 			cfp = pscan_region->pcfp + next_chan;
520 			if (cfp->dynamic.flags & NXP_CHANNEL_DISABLED)
521 				continue;
522 
523 			if (wlan_is_chan_passive(pmpriv, pscan_region->band,
524 						 (t_u8)cfp->channel)) {
525 				/* do not send probe requests on this channel */
526 				scan_type = MLAN_SCAN_TYPE_PASSIVE;
527 			}
528 			switch (pscan_region->band) {
529 			case BAND_A:
530 				pscan_chan_list[chan_idx].bandcfg.chanBand =
531 					BAND_5GHZ;
532 				/* Passive scan on DFS channels */
533 				if (wlan_11h_radar_detect_required(
534 					    pmpriv, (t_u8)cfp->channel) &&
535 				    scan_type == MLAN_SCAN_TYPE_PASSIVE)
536 					scan_type =
537 						MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE;
538 				break;
539 			case BAND_B:
540 			case BAND_G:
541 				if (wlan_bg_scan_type_is_passive(
542 					    pmpriv, (t_u8)cfp->channel)) {
543 					scan_type = MLAN_SCAN_TYPE_PASSIVE;
544 				}
545 				pscan_chan_list[chan_idx].bandcfg.chanBand =
546 					BAND_2GHZ;
547 				break;
548 			default:
549 				pscan_chan_list[chan_idx].bandcfg.chanBand =
550 					BAND_2GHZ;
551 				break;
552 			}
553 
554 			if (puser_scan_in &&
555 			    puser_scan_in->chan_list[0].scan_time) {
556 				scan_dur = (t_u16)puser_scan_in->chan_list[0]
557 						   .scan_time;
558 			} else if (scan_type == MLAN_SCAN_TYPE_PASSIVE ||
559 				   scan_type ==
560 					   MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE) {
561 				scan_dur = pmadapter->passive_scan_time;
562 			} else if (filtered_scan) {
563 				scan_dur = pmadapter->specific_scan_time;
564 			} else {
565 				scan_dur = pmadapter->active_scan_time;
566 			}
567 			if (scan_type == MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE &&
568 			    pmadapter->passive_to_active_scan ==
569 				    MLAN_PASS_TO_ACT_SCAN_EN) {
570 				scan_dur = MAX(scan_dur,
571 					       MIN_PASSIVE_TO_ACTIVE_SCAN_TIME);
572 				pscan_chan_list[chan_idx]
573 					.chan_scan_mode.passive_to_active_scan =
574 					MTRUE;
575 			}
576 
577 			pscan_chan_list[chan_idx].max_scan_time =
578 				wlan_cpu_to_le16(scan_dur);
579 
580 			if (scan_type == MLAN_SCAN_TYPE_PASSIVE ||
581 			    scan_type == MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE) {
582 				pscan_chan_list[chan_idx]
583 					.chan_scan_mode.passive_scan = MTRUE;
584 				pscan_chan_list[chan_idx]
585 					.chan_scan_mode.hidden_ssid_report =
586 					MTRUE;
587 			} else {
588 				pscan_chan_list[chan_idx]
589 					.chan_scan_mode.passive_scan = MFALSE;
590 			}
591 
592 			pscan_chan_list[chan_idx].chan_number =
593 				(t_u8)cfp->channel;
594 			PRINTM(MCMD_D,
595 			       "chan=%d, mode=%d, passive_to_active=%d\n",
596 			       pscan_chan_list[chan_idx].chan_number,
597 			       pscan_chan_list[chan_idx]
598 				       .chan_scan_mode.passive_scan,
599 			       pscan_chan_list[chan_idx]
600 				       .chan_scan_mode.passive_to_active_scan);
601 			chan_idx++;
602 		}
603 	}
604 
605 	LEAVE();
606 	return chan_idx;
607 }
608 
609 /**
610  *  @brief Add WPS IE to probe request frame
611  *
612  *  @param pmpriv             A pointer to mlan_private structure
613  *  @param pptlv_out          A pointer to TLV to fill in
614  *
615  *  @return                   N/A
616  */
wlan_add_wps_probe_request_ie(mlan_private * pmpriv,t_u8 ** pptlv_out)617 static void wlan_add_wps_probe_request_ie(mlan_private *pmpriv,
618 					  t_u8 **pptlv_out)
619 {
620 	MrvlIEtypesHeader_t *tlv;
621 
622 	ENTER();
623 
624 	if (pmpriv->wps.wps_ie.vend_hdr.len) {
625 		tlv = (MrvlIEtypesHeader_t *)*pptlv_out;
626 		tlv->type = wlan_cpu_to_le16(VENDOR_SPECIFIC_221);
627 		tlv->len = wlan_cpu_to_le16(pmpriv->wps.wps_ie.vend_hdr.len);
628 		*pptlv_out += sizeof(MrvlIEtypesHeader_t);
629 		memcpy_ext(pmpriv->adapter, *pptlv_out,
630 			   pmpriv->wps.wps_ie.vend_hdr.oui,
631 			   pmpriv->wps.wps_ie.vend_hdr.len,
632 			   pmpriv->wps.wps_ie.vend_hdr.len);
633 		*pptlv_out += (pmpriv->wps.wps_ie.vend_hdr.len +
634 			       sizeof(MrvlIEtypesHeader_t));
635 	}
636 	LEAVE();
637 }
638 
639 /**
640  *  @brief Construct and send multiple scan config commands to the firmware
641  *
642  *  Previous routines have created a wlan_scan_cmd_config with any requested
643  *   TLVs.  This function splits the channel TLV into max_chan_per_scan lists
644  *   and sends the portion of the channel TLV along with the other TLVs
645  *   to the wlan_cmd routines for execution in the firmware.
646  *
647  *  @param pmpriv             A pointer to mlan_private structure
648  *  @param pioctl_buf         A pointer to MLAN IOCTL Request buffer
649  *  @param max_chan_per_scan  Maximum number channels to be included in each
650  *                            scan command sent to firmware
651  *  @param filtered_scan      Flag indicating whether or not a BSSID or SSID
652  *                            filter is being used for the firmware command
653  *                            scan command sent to firmware
654  *  @param pscan_cfg_out      Scan configuration used for this scan.
655  *  @param pchan_tlv_out      Pointer in the pscan_cfg_out where the channel TLV
656  *                            should start.  This is past any other TLVs that
657  *                            must be sent down in each firmware command.
658  *  @param pscan_chan_list    List of channels to scan in max_chan_per_scan
659  * segments
660  *
661  *  @return                   MLAN_STATUS_SUCCESS or error return otherwise
662  */
663 static mlan_status
wlan_scan_channel_list(mlan_private * pmpriv,t_void * pioctl_buf,t_u32 max_chan_per_scan,t_u8 filtered_scan,wlan_scan_cmd_config * pscan_cfg_out,MrvlIEtypes_ChanListParamSet_t * pchan_tlv_out,ChanScanParamSet_t * pscan_chan_list)664 wlan_scan_channel_list(mlan_private *pmpriv, t_void *pioctl_buf,
665 		       t_u32 max_chan_per_scan, t_u8 filtered_scan,
666 		       wlan_scan_cmd_config *pscan_cfg_out,
667 		       MrvlIEtypes_ChanListParamSet_t *pchan_tlv_out,
668 		       ChanScanParamSet_t *pscan_chan_list)
669 {
670 	mlan_status ret = MLAN_STATUS_SUCCESS;
671 	mlan_adapter *pmadapter = pmpriv->adapter;
672 	ChanScanParamSet_t *ptmp_chan_list;
673 	ChanScanParamSet_t *pstart_chan;
674 	pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
675 	t_u8 *pchan_tlv_out_temp = MNULL;
676 	t_u8 *ptlv_temp = MNULL;
677 	t_bool foundJPch14 = MFALSE;
678 	t_u16 tlv_buf_len = 0;
679 	t_u32 tlv_idx;
680 	t_u32 total_scan_time;
681 	t_u32 done_early;
682 	t_u32 cmd_no;
683 	t_u32 first_chan = 1;
684 	t_u8 *ptlv_pos;
685 	MrvlIETypes_HTCap_t *pht_cap;
686 
687 	MrvlIETypes_VHTCap_t *pvht_cap;
688 	MrvlIEtypes_Extension_t *phe_cap;
689 	t_u16 len = 0;
690 	t_u8 radio_type = 0;
691 
692 	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
693 
694 	ENTER();
695 
696 	if (!pscan_cfg_out || !pchan_tlv_out || !pscan_chan_list) {
697 		PRINTM(MINFO, "Scan: Null detect: %p, %p, %p\n", pscan_cfg_out,
698 		       pchan_tlv_out, pscan_chan_list);
699 		if (pioctl_req)
700 			pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
701 		LEAVE();
702 		return MLAN_STATUS_FAILURE;
703 	}
704 	if (!pscan_chan_list->chan_number) {
705 		PRINTM(MERROR, "Scan: No channel configured\n");
706 		if (pioctl_req)
707 			pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
708 		LEAVE();
709 		return MLAN_STATUS_FAILURE;
710 	}
711 
712 	/* check expiry before preparing scan list - may affect blacklist */
713 	wlan_11h_get_csa_closed_channel(pmpriv);
714 
715 	pchan_tlv_out->header.type = wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
716 
717 	/* Set the temp channel struct pointer to the start of the desired list
718 	 */
719 	ptmp_chan_list = pscan_chan_list;
720 
721 	/*
722 	 * Loop through the desired channel list, sending a new firmware scan
723 	 * commands for each max_chan_per_scan channels (or for 1,6,11
724 	 * individually if configured accordingly)
725 	 */
726 	while (ptmp_chan_list->chan_number) {
727 		tlv_idx = 0;
728 		total_scan_time = 0;
729 		pchan_tlv_out->header.len = 0;
730 		pstart_chan = ptmp_chan_list;
731 		done_early = MFALSE;
732 
733 		/*
734 		 * Construct the Channel TLV for the scan command.  Continue to
735 		 * insert channel TLVs until:
736 		 *   - the tlv_idx hits the maximum configured per scan command
737 		 *   - the next channel to insert is 0 (end of desired
738 		 *     channel list)
739 		 *   - done_early is set (controlling individual
740 		 *     scanning of 1,6,11)
741 		 */
742 		while (tlv_idx < max_chan_per_scan &&
743 		       ptmp_chan_list->chan_number && !done_early) {
744 			if (wlan_is_chan_blacklisted(
745 				    pmpriv,
746 				    radio_type_to_band(
747 					    ptmp_chan_list->bandcfg.chanBand),
748 				    ptmp_chan_list->chan_number) ||
749 			    wlan_is_chan_disabled(
750 				    pmpriv,
751 				    radio_type_to_band(
752 					    ptmp_chan_list->bandcfg.chanBand),
753 				    ptmp_chan_list->chan_number)) {
754 				PRINTM(MCMND, "Block scan chan = %d\n",
755 				       ptmp_chan_list->chan_number);
756 				ptmp_chan_list++;
757 				continue;
758 			}
759 
760 			if (first_chan) {
761 				ptmp_chan_list->chan_scan_mode.first_chan =
762 					MTRUE;
763 				first_chan = 0;
764 			}
765 			radio_type = ptmp_chan_list->bandcfg.chanBand;
766 			PRINTM(MCMD_D,
767 			       "Scan: Chan(%3d), bandcfg(%x), Mode(%d,%d), Dur(%d)\n",
768 			       ptmp_chan_list->chan_number,
769 			       ptmp_chan_list->bandcfg,
770 			       ptmp_chan_list->chan_scan_mode.passive_scan,
771 			       ptmp_chan_list->chan_scan_mode.disable_chan_filt,
772 			       wlan_le16_to_cpu(ptmp_chan_list->max_scan_time));
773 
774 			if (foundJPch14 == MTRUE) {
775 				foundJPch14 = MFALSE;
776 				/* Restore the TLV buffer */
777 				pchan_tlv_out =
778 					(MrvlIEtypes_ChanListParamSet_t *)
779 						pchan_tlv_out_temp;
780 				pchan_tlv_out->header.type =
781 					wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
782 				pchan_tlv_out->header.len = 0;
783 				if (ptlv_temp) {
784 					memcpy_ext(pmadapter,
785 						   pscan_cfg_out->tlv_buf,
786 						   ptlv_temp, tlv_buf_len,
787 						   tlv_buf_len);
788 					pcb->moal_mfree(pmadapter->pmoal_handle,
789 							ptlv_temp);
790 					ptlv_temp = MNULL;
791 				}
792 			}
793 
794 			/* Special Case: For Japan, Scan on CH14 for 11G rates
795 			   is not allowed
796 			    Hence Rates TLV needs to be updated to support only
797 			   11B rates */
798 			if ((pmadapter->region_code == COUNTRY_CODE_JP_40 ||
799 			     pmadapter->region_code == COUNTRY_CODE_JP_FF) &&
800 			    (ptmp_chan_list->chan_number == 14) &&
801 			    (pmadapter->ext_scan_type != EXT_SCAN_ENHANCE)) {
802 				t_u8 *ptlv_pos = pscan_cfg_out->tlv_buf;
803 				t_u16 old_ratetlv_len, new_ratetlv_len;
804 				MrvlIEtypesHeader_t *header;
805 				MrvlIEtypes_RatesParamSet_t *prates_tlv;
806 
807 				/* Preserve the current TLV buffer */
808 				ret = pcb->moal_malloc(
809 					pmadapter->pmoal_handle,
810 					MAX_SCAN_CFG_ALLOC - CHAN_TLV_MAX_SIZE,
811 					MLAN_MEM_DEF | MOAL_MEM_FLAG_ATOMIC,
812 					(t_u8 **)&ptlv_temp);
813 				if (ret != MLAN_STATUS_SUCCESS || !ptlv_temp) {
814 					PRINTM(MERROR,
815 					       "Memory allocation for pscan_cfg_out failed!\n");
816 					if (pioctl_req)
817 						pioctl_req->status_code =
818 							MLAN_ERROR_NO_MEM;
819 					LEAVE();
820 					return MLAN_STATUS_FAILURE;
821 				}
822 				pchan_tlv_out_temp = (t_u8 *)pchan_tlv_out;
823 				tlv_buf_len = (t_u32)(pchan_tlv_out_temp -
824 						      pscan_cfg_out->tlv_buf);
825 				memcpy_ext(pmadapter, ptlv_temp, ptlv_pos,
826 					   tlv_buf_len,
827 					   MAX_SCAN_CFG_ALLOC -
828 						   CHAN_TLV_MAX_SIZE);
829 
830 				/* Search for Rates TLV */
831 				while ((!foundJPch14) &&
832 				       (ptlv_pos < pchan_tlv_out_temp)) {
833 					header =
834 						(MrvlIEtypesHeader_t *)ptlv_pos;
835 					if (header->type ==
836 					    wlan_cpu_to_le16(TLV_TYPE_RATES))
837 						foundJPch14 = MTRUE;
838 					else
839 						ptlv_pos +=
840 							(sizeof(MrvlIEtypesHeader_t) +
841 							 wlan_le16_to_cpu(
842 								 header->len));
843 				}
844 
845 				if (foundJPch14) {
846 					/* Update the TLV buffer with *new*
847 					 * Rates TLV and rearrange remaining TLV
848 					 * buffer*/
849 					prates_tlv =
850 						(MrvlIEtypes_RatesParamSet_t *)
851 							ptlv_pos;
852 					old_ratetlv_len =
853 						sizeof(MrvlIEtypesHeader_t) +
854 						wlan_le16_to_cpu(
855 							prates_tlv->header.len);
856 
857 					prates_tlv->header.len = wlan_copy_rates(
858 						prates_tlv->rates, 0,
859 						SupportedRates_B,
860 						sizeof(SupportedRates_B));
861 					new_ratetlv_len =
862 						sizeof(MrvlIEtypesHeader_t) +
863 						prates_tlv->header.len;
864 					prates_tlv->header.len =
865 						wlan_cpu_to_le16(
866 							prates_tlv->header.len);
867 
868 					memmove(pmadapter,
869 						ptlv_pos + new_ratetlv_len,
870 						ptlv_pos + old_ratetlv_len,
871 						(t_u32)(pchan_tlv_out_temp -
872 							(ptlv_pos +
873 							 old_ratetlv_len)));
874 					pchan_tlv_out =
875 						(MrvlIEtypes_ChanListParamSet_t
876 							 *)(pchan_tlv_out_temp -
877 							    (old_ratetlv_len -
878 							     new_ratetlv_len));
879 					pchan_tlv_out->header.type =
880 						wlan_cpu_to_le16(
881 							TLV_TYPE_CHANLIST);
882 					pchan_tlv_out->header.len = 0;
883 				}
884 			}
885 
886 			/* Copy the current channel TLV to the command being
887 			 * prepared */
888 			memcpy_ext(pmadapter,
889 				   pchan_tlv_out->chan_scan_param + tlv_idx,
890 				   ptmp_chan_list,
891 				   sizeof(pchan_tlv_out->chan_scan_param),
892 				   sizeof(pchan_tlv_out->chan_scan_param));
893 
894 			/* Increment the TLV header length by the size appended
895 			 */
896 			pchan_tlv_out->header.len +=
897 				sizeof(pchan_tlv_out->chan_scan_param);
898 
899 			/*
900 			 * The tlv buffer length is set to the number of
901 			 * bytes of the between the channel tlv pointer
902 			 * and the start of the tlv buffer.  This
903 			 * compensates for any TLVs that were appended
904 			 * before the channel list.
905 			 */
906 			pscan_cfg_out->tlv_buf_len = (t_u32)(
907 				(t_u8 *)pchan_tlv_out - pscan_cfg_out->tlv_buf);
908 
909 			/* Add the size of the channel tlv header and the data
910 			 * length */
911 			pscan_cfg_out->tlv_buf_len +=
912 				(sizeof(pchan_tlv_out->header) +
913 				 pchan_tlv_out->header.len);
914 
915 			/* Increment the index to the channel tlv we are
916 			 * constructing */
917 			tlv_idx++;
918 
919 			/* Count the total scan time per command */
920 			total_scan_time +=
921 				wlan_le16_to_cpu(ptmp_chan_list->max_scan_time);
922 
923 			done_early = MFALSE;
924 
925 			/*
926 			 * Stop the loop if the *current* channel is in the
927 			 * 1,6,11 set and we are not filtering on a BSSID or
928 			 * SSID.
929 			 */
930 			if (!filtered_scan &&
931 			    (ptmp_chan_list->chan_number == 1 ||
932 			     ptmp_chan_list->chan_number == 6 ||
933 			     ptmp_chan_list->chan_number == 11)) {
934 				done_early = MTRUE;
935 			}
936 
937 			/*
938 			 * Stop the loop if the *current* channel is 14
939 			 * and region code is Japan (0x40 or 0xFF)
940 			 */
941 			if ((pmadapter->region_code == COUNTRY_CODE_JP_40 ||
942 			     pmadapter->region_code == COUNTRY_CODE_JP_FF) &&
943 			    (ptmp_chan_list->chan_number == 14)) {
944 				done_early = MTRUE;
945 			}
946 
947 			/* Increment the tmp pointer to the next channel to be
948 			 * scanned */
949 			ptmp_chan_list++;
950 
951 			/*
952 			 * Stop the loop if the *next* channel is in the 1,6,11
953 			 * set. This will cause it to be the only channel
954 			 * scanned on the next interation
955 			 */
956 			if (!filtered_scan &&
957 			    (ptmp_chan_list->chan_number == 1 ||
958 			     ptmp_chan_list->chan_number == 6 ||
959 			     ptmp_chan_list->chan_number == 11)) {
960 				done_early = MTRUE;
961 			}
962 
963 			/*
964 			 * Stop the loop if the *next* channel is 14
965 			 * and region code is Japan (0x40 or 0xFF)
966 			 */
967 			if ((pmadapter->region_code == COUNTRY_CODE_JP_40 ||
968 			     pmadapter->region_code == COUNTRY_CODE_JP_FF) &&
969 			    (ptmp_chan_list->chan_number == 14)) {
970 				done_early = MTRUE;
971 			}
972 			if (pmadapter->ext_scan && pmadapter->ext_scan_enh &&
973 			    pmadapter->ext_scan_type == EXT_SCAN_ENHANCE)
974 				done_early = MFALSE;
975 		}
976 
977 		/* The total scan time should be less than scan command timeout
978 		 * value */
979 		if (!total_scan_time ||
980 		    total_scan_time > MRVDRV_MAX_TOTAL_SCAN_TIME) {
981 			PRINTM(MMSG,
982 			       "Total scan time %d ms is invalid, limit (%d ms), scan skipped\n",
983 			       total_scan_time, MRVDRV_MAX_TOTAL_SCAN_TIME);
984 			if (pioctl_req)
985 				pioctl_req->status_code =
986 					MLAN_ERROR_CMD_SCAN_FAIL;
987 			ret = MLAN_STATUS_FAILURE;
988 			break;
989 		}
990 		ptlv_pos = (t_u8 *)pchan_tlv_out + pchan_tlv_out->header.len +
991 			   sizeof(MrvlIEtypesHeader_t);
992 
993 		pchan_tlv_out->header.len =
994 			wlan_cpu_to_le16(pchan_tlv_out->header.len);
995 
996 		if (ISSUPP_11NENABLED(pmpriv->adapter->fw_cap_info) &&
997 		    (pmpriv->config_bands & BAND_GN ||
998 		     pmpriv->config_bands & BAND_AN)) {
999 			pht_cap = (MrvlIETypes_HTCap_t *)ptlv_pos;
1000 			memset(pmadapter, pht_cap, 0,
1001 			       sizeof(MrvlIETypes_HTCap_t));
1002 			pht_cap->header.type = wlan_cpu_to_le16(HT_CAPABILITY);
1003 			pht_cap->header.len = sizeof(HTCap_t);
1004 			wlan_fill_ht_cap_tlv(pmpriv, pht_cap,
1005 					     pmpriv->config_bands, MTRUE);
1006 			HEXDUMP("SCAN: HT_CAPABILITIES IE", (t_u8 *)pht_cap,
1007 				sizeof(MrvlIETypes_HTCap_t));
1008 			ptlv_pos += sizeof(MrvlIETypes_HTCap_t);
1009 			pht_cap->header.len =
1010 				wlan_cpu_to_le16(pht_cap->header.len);
1011 		}
1012 
1013 		if (ISSUPP_11ACENABLED(pmpriv->adapter->fw_cap_info) &&
1014 		    (pmpriv->config_bands & BAND_AAC)) {
1015 			pvht_cap = (MrvlIETypes_VHTCap_t *)ptlv_pos;
1016 			memset(pmadapter, pvht_cap, 0,
1017 			       sizeof(MrvlIETypes_VHTCap_t));
1018 			pvht_cap->header.type =
1019 				wlan_cpu_to_le16(VHT_CAPABILITY);
1020 			pvht_cap->header.len = sizeof(VHT_capa_t);
1021 			wlan_fill_vht_cap_tlv(pmpriv, pvht_cap,
1022 					      pmpriv->config_bands, MFALSE,
1023 					      MFALSE);
1024 			HEXDUMP("SCAN: VHT_CAPABILITIES IE", (t_u8 *)pvht_cap,
1025 				sizeof(MrvlIETypes_VHTCap_t));
1026 			ptlv_pos += sizeof(MrvlIETypes_VHTCap_t);
1027 			pvht_cap->header.len =
1028 				wlan_cpu_to_le16(pvht_cap->header.len);
1029 		}
1030 
1031 		if (IS_FW_SUPPORT_11AX(pmadapter) &&
1032 		    ((pmpriv->config_bands & BAND_GAX) ||
1033 		     (pmpriv->config_bands & BAND_AAX))) {
1034 			phe_cap = (MrvlIEtypes_Extension_t *)ptlv_pos;
1035 			len = wlan_fill_he_cap_tlv(pmpriv, pmpriv->config_bands,
1036 						   phe_cap, MFALSE);
1037 			HEXDUMP("SCAN: HE_CAPABILITIES IE", (t_u8 *)phe_cap,
1038 				len);
1039 			ptlv_pos += len;
1040 		}
1041 
1042 		pscan_cfg_out->tlv_buf_len =
1043 			(t_u32)((t_u8 *)ptlv_pos - pscan_cfg_out->tlv_buf);
1044 
1045 		pmadapter->pscan_channels = pstart_chan;
1046 
1047 		/* Send the scan command to the firmware with the specified cfg
1048 		 */
1049 		if (pmadapter->ext_scan
1050 #ifdef USB8801
1051 		    && !IS_USB8801(pmadapter->card_type)
1052 #endif
1053 		)
1054 			cmd_no = HostCmd_CMD_802_11_SCAN_EXT;
1055 		else
1056 			cmd_no = HostCmd_CMD_802_11_SCAN;
1057 		ret = wlan_prepare_cmd(pmpriv, cmd_no, HostCmd_ACT_GEN_SET, 0,
1058 				       MNULL, pscan_cfg_out);
1059 		if (ret)
1060 			break;
1061 	}
1062 
1063 	LEAVE();
1064 
1065 	if (ptlv_temp)
1066 		pcb->moal_mfree(pmadapter->pmoal_handle, ptlv_temp);
1067 
1068 	if (ret)
1069 		return MLAN_STATUS_FAILURE;
1070 
1071 	return MLAN_STATUS_SUCCESS;
1072 }
1073 
1074 /**
1075  *  @brief Construct a wlan_scan_cmd_config structure to use in scan commands
1076  *
1077  *  Application layer or other functions can invoke wlan_scan_networks
1078  *    with a scan configuration supplied in a wlan_ioctl_user_scan_cfg struct.
1079  *    This structure is used as the basis of one or many wlan_scan_cmd_config
1080  *    commands that are sent to the command processing module and sent to
1081  *    firmware.
1082  *
1083  *  Create a wlan_scan_cmd_config based on the following user supplied
1084  *    parameters (if present):
1085  *             - SSID filter
1086  *             - BSSID filter
1087  *             - Number of Probes to be sent
1088  *             - Channel list
1089  *
1090  *  If the SSID or BSSID filter is not present, disable/clear the filter.
1091  *  If the number of probes is not set, use the adapter default setting
1092  *  Qualify the channel
1093  *
1094  *  @param pmpriv              A pointer to mlan_private structure
1095  *  @param puser_scan_in       MNULL or pointer to scan config parameters
1096  *  @param pscan_cfg_out       Output parameter: Resulting scan configuration
1097  *  @param ppchan_list_out     Output parameter: Pointer to the start of the
1098  *                             channel TLV portion of the output scan config
1099  *  @param pscan_chan_list     Output parameter: Pointer to the resulting
1100  *                             channel list to scan
1101  *  @param pmax_chan_per_scan  Output parameter: Number of channels to scan for
1102  *                             each issuance of the firmware scan command
1103  *  @param pfiltered_scan      Output parameter: Flag indicating whether or not
1104  *                             a BSSID or SSID filter is being sent in the
1105  *                             command to firmware. Used to increase the number
1106  *                             of channels sent in a scan command and to
1107  *                             disable the firmware channel scan filter.
1108  *  @param pscan_current_only  Output parameter: Flag indicating whether or not
1109  *                             we are only scanning our current active channel
1110  *
1111  *  @return                 MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1112  */
wlan_scan_setup_scan_config(mlan_private * pmpriv,wlan_user_scan_cfg * puser_scan_in,wlan_scan_cmd_config * pscan_cfg_out,MrvlIEtypes_ChanListParamSet_t ** ppchan_list_out,ChanScanParamSet_t * pscan_chan_list,t_u8 * pmax_chan_per_scan,t_u8 * pfiltered_scan,t_u8 * pscan_current_only)1113 static mlan_status wlan_scan_setup_scan_config(
1114 	mlan_private *pmpriv, wlan_user_scan_cfg *puser_scan_in,
1115 	wlan_scan_cmd_config *pscan_cfg_out,
1116 	MrvlIEtypes_ChanListParamSet_t **ppchan_list_out,
1117 	ChanScanParamSet_t *pscan_chan_list, t_u8 *pmax_chan_per_scan,
1118 	t_u8 *pfiltered_scan, t_u8 *pscan_current_only)
1119 {
1120 	mlan_adapter *pmadapter = pmpriv->adapter;
1121 	mlan_status ret = MLAN_STATUS_SUCCESS;
1122 	MrvlIEtypes_NumProbes_t *pnum_probes_tlv;
1123 	MrvlIEtypes_WildCardSsIdParamSet_t *pwildcard_ssid_tlv;
1124 	MrvlIEtypes_RatesParamSet_t *prates_tlv;
1125 	MrvlIEtypes_Bssid_List_t *pbssid_tlv;
1126 
1127 	const t_u8 zero_mac[MLAN_MAC_ADDR_LENGTH] = {0, 0, 0, 0, 0, 0};
1128 	t_u8 *ptlv_pos;
1129 	t_u32 num_probes;
1130 	t_u32 ssid_len;
1131 	t_u32 chan_idx;
1132 	t_u32 chan_list_idx = 0;
1133 	t_u32 scan_type;
1134 	t_u16 scan_dur;
1135 	t_u8 channel;
1136 	t_u8 radio_type;
1137 	t_u32 ssid_idx;
1138 	t_u8 ssid_filter;
1139 	WLAN_802_11_RATES rates;
1140 	t_u32 rates_size;
1141 	MrvlIEtypes_ScanChanGap_t *pscan_gap_tlv;
1142 	MrvlIEtypes_BssMode_t *pbss_mode;
1143 	t_u8 num_of_channel = 0;
1144 
1145 	ENTER();
1146 
1147 	/* The tlv_buf_len is calculated for each scan command.  The TLVs added
1148 	 *   in this routine will be preserved since the routine that sends
1149 	 *   the command will append channelTLVs at *ppchan_list_out.  The
1150 	 *   difference between the *ppchan_list_out and the tlv_buf start will
1151 	 * be used to calculate the size of anything we add in this routine.
1152 	 */
1153 	pscan_cfg_out->tlv_buf_len = 0;
1154 
1155 	/* Running tlv pointer.  Assigned to ppchan_list_out at end of function
1156 	 *  so later routines know where channels can be added to the command
1157 	 * buf
1158 	 */
1159 	ptlv_pos = pscan_cfg_out->tlv_buf;
1160 
1161 	/* Initialize the scan as un-filtered; the flag is later set to
1162 	 *   TRUE below if a SSID or BSSID filter is sent in the command
1163 	 */
1164 	*pfiltered_scan = MFALSE;
1165 
1166 	/* Initialize the scan as not being only on the current channel.  If
1167 	 *   the channel list is customized, only contains one channel, and
1168 	 *   is the active channel, this is set true and data flow is not
1169 	 * halted.
1170 	 */
1171 	*pscan_current_only = MFALSE;
1172 
1173 	if (puser_scan_in) {
1174 		ssid_filter = MFALSE;
1175 
1176 		/* Set the bss type scan filter, use Adapter setting if unset */
1177 		pscan_cfg_out->bss_mode =
1178 			(puser_scan_in->bss_mode ?
1179 				 (t_u8)puser_scan_in->bss_mode :
1180 				 (t_u8)pmadapter->scan_mode);
1181 
1182 		/* Set the number of probes to send, use Adapter setting if
1183 		 * unset */
1184 		num_probes =
1185 			(puser_scan_in->num_probes ? puser_scan_in->num_probes :
1186 						     pmadapter->scan_probes);
1187 		/*
1188 		 * Set the BSSID filter to the incoming configuration,
1189 		 *  if non-zero.  If not set, it will remain disabled
1190 		 * (all zeros).
1191 		 */
1192 		memcpy_ext(pmadapter, pscan_cfg_out->specific_bssid,
1193 			   puser_scan_in->specific_bssid,
1194 			   sizeof(pscan_cfg_out->specific_bssid),
1195 			   sizeof(pscan_cfg_out->specific_bssid));
1196 
1197 		if (pmadapter->ext_scan) {
1198 			if (puser_scan_in->bssid_num) {
1199 				pbssid_tlv =
1200 					(MrvlIEtypes_Bssid_List_t *)ptlv_pos;
1201 				pbssid_tlv->header.type = TLV_TYPE_BSSID;
1202 				pbssid_tlv->header.len = wlan_cpu_to_le16(
1203 					MLAN_MAC_ADDR_LENGTH *
1204 					puser_scan_in->bssid_num);
1205 				memcpy_ext(pmadapter, pbssid_tlv->bssid,
1206 					   puser_scan_in->bssid_list,
1207 					   MLAN_MAC_ADDR_LENGTH *
1208 						   puser_scan_in->bssid_num,
1209 					   MLAN_MAC_ADDR_LENGTH *
1210 						   puser_scan_in->bssid_num);
1211 				ptlv_pos += sizeof(MrvlIEtypesHeader_t) +
1212 					    MLAN_MAC_ADDR_LENGTH *
1213 						    puser_scan_in->bssid_num;
1214 				DBG_HEXDUMP(
1215 					MCMD_D, "scan bssid filter", pbssid_tlv,
1216 					sizeof(MrvlIEtypesHeader_t) +
1217 						MLAN_MAC_ADDR_LENGTH *
1218 							puser_scan_in
1219 								->bssid_num);
1220 			} else if (memcmp(pmadapter,
1221 					  pscan_cfg_out->specific_bssid,
1222 					  &zero_mac, sizeof(zero_mac))) {
1223 				pbssid_tlv =
1224 					(MrvlIEtypes_Bssid_List_t *)ptlv_pos;
1225 				pbssid_tlv->header.type = TLV_TYPE_BSSID;
1226 				pbssid_tlv->header.len =
1227 					wlan_cpu_to_le16(MLAN_MAC_ADDR_LENGTH);
1228 				memcpy_ext(pmadapter, pbssid_tlv->bssid,
1229 					   puser_scan_in->specific_bssid,
1230 					   MLAN_MAC_ADDR_LENGTH,
1231 					   MLAN_MAC_ADDR_LENGTH);
1232 				ptlv_pos += sizeof(MrvlIEtypes_Bssid_List_t);
1233 			}
1234 		}
1235 
1236 		for (ssid_idx = 0;
1237 		     ((ssid_idx < NELEMENTS(puser_scan_in->ssid_list)) &&
1238 		      (*puser_scan_in->ssid_list[ssid_idx].ssid ||
1239 		       puser_scan_in->ssid_list[ssid_idx].max_len));
1240 		     ssid_idx++) {
1241 			ssid_len = wlan_strlen(
1242 				(char *)puser_scan_in->ssid_list[ssid_idx].ssid);
1243 
1244 			pwildcard_ssid_tlv =
1245 				(MrvlIEtypes_WildCardSsIdParamSet_t *)ptlv_pos;
1246 			pwildcard_ssid_tlv->header.type =
1247 				wlan_cpu_to_le16(TLV_TYPE_WILDCARDSSID);
1248 			pwildcard_ssid_tlv->header.len = (t_u16)(
1249 				ssid_len +
1250 				sizeof(pwildcard_ssid_tlv->max_ssid_length));
1251 			pwildcard_ssid_tlv->max_ssid_length =
1252 				puser_scan_in->ssid_list[ssid_idx].max_len;
1253 
1254 			memcpy_ext(pmadapter, pwildcard_ssid_tlv->ssid,
1255 				   puser_scan_in->ssid_list[ssid_idx].ssid,
1256 				   ssid_len, MLAN_MAX_SSID_LENGTH);
1257 
1258 			ptlv_pos += (sizeof(pwildcard_ssid_tlv->header) +
1259 				     pwildcard_ssid_tlv->header.len);
1260 
1261 			pwildcard_ssid_tlv->header.len = wlan_cpu_to_le16(
1262 				pwildcard_ssid_tlv->header.len);
1263 
1264 			PRINTM(MINFO, "Scan: ssid_list[%d]: %s, %d\n", ssid_idx,
1265 			       pwildcard_ssid_tlv->ssid,
1266 			       pwildcard_ssid_tlv->max_ssid_length);
1267 
1268 			if (ssid_len) {
1269 				ssid_filter = MTRUE;
1270 				if (!puser_scan_in->ssid_list[ssid_idx].max_len) {
1271 					PRINTM(MCMND, "user scan: %s\n",
1272 					       pwildcard_ssid_tlv->ssid);
1273 					puser_scan_in->ssid_filter = MTRUE;
1274 				}
1275 			}
1276 		}
1277 
1278 		/*
1279 		 *  The default number of channels sent in the command is low to
1280 		 *  ensure the response buffer from the firmware does not
1281 		 *  truncate scan results.  That is not an issue with an SSID or
1282 		 *  BSSID filter applied to the scan results in the firmware.
1283 		 */
1284 		if ((ssid_idx && ssid_filter) ||
1285 		    memcmp(pmadapter, pscan_cfg_out->specific_bssid, &zero_mac,
1286 			   sizeof(zero_mac))) {
1287 			*pfiltered_scan = MTRUE;
1288 		}
1289 
1290 	} else {
1291 		pscan_cfg_out->bss_mode = (t_u8)pmadapter->scan_mode;
1292 		num_probes = pmadapter->scan_probes;
1293 	}
1294 
1295 	/*
1296 	 *  If a specific BSSID or SSID is used, the number of channels in
1297 	 *  the scan command will be increased to the absolute maximum.
1298 	 */
1299 	if (*pfiltered_scan)
1300 		*pmax_chan_per_scan = MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN;
1301 	else
1302 		*pmax_chan_per_scan = MRVDRV_CHANNELS_PER_SCAN_CMD;
1303 
1304 	if (puser_scan_in) {
1305 		if (puser_scan_in->scan_chan_gap) {
1306 			*pmax_chan_per_scan =
1307 				MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN;
1308 			PRINTM(MCMND, "Scan: channel gap = 0x%x\n",
1309 			       puser_scan_in->scan_chan_gap);
1310 			pscan_gap_tlv = (MrvlIEtypes_ScanChanGap_t *)ptlv_pos;
1311 			pscan_gap_tlv->header.type =
1312 				wlan_cpu_to_le16(TLV_TYPE_SCAN_CHANNEL_GAP);
1313 			pscan_gap_tlv->header.len = sizeof(pscan_gap_tlv->gap);
1314 			pscan_gap_tlv->gap = wlan_cpu_to_le16(
1315 				(t_u16)puser_scan_in->scan_chan_gap);
1316 			ptlv_pos += sizeof(pscan_gap_tlv->header) +
1317 				    pscan_gap_tlv->header.len;
1318 			pscan_gap_tlv->header.len =
1319 				wlan_cpu_to_le16(pscan_gap_tlv->header.len);
1320 		}
1321 	} else if (pmadapter->scan_chan_gap) {
1322 		*pmax_chan_per_scan = MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN;
1323 		PRINTM(MCMND, "Scan: channel gap = 0x%x\n",
1324 		       pmadapter->scan_chan_gap);
1325 		pscan_gap_tlv = (MrvlIEtypes_ScanChanGap_t *)ptlv_pos;
1326 		pscan_gap_tlv->header.type =
1327 			wlan_cpu_to_le16(TLV_TYPE_SCAN_CHANNEL_GAP);
1328 		pscan_gap_tlv->header.len = sizeof(pscan_gap_tlv->gap);
1329 		pscan_gap_tlv->gap =
1330 			wlan_cpu_to_le16((t_u16)pmadapter->scan_chan_gap);
1331 		ptlv_pos += sizeof(pscan_gap_tlv->header) +
1332 			    pscan_gap_tlv->header.len;
1333 	}
1334 	if (pmadapter->ext_scan) {
1335 		pbss_mode = (MrvlIEtypes_BssMode_t *)ptlv_pos;
1336 		pbss_mode->header.type = wlan_cpu_to_le16(TLV_TYPE_BSS_MODE);
1337 		pbss_mode->header.len = sizeof(pbss_mode->bss_mode);
1338 		pbss_mode->bss_mode = pscan_cfg_out->bss_mode;
1339 		ptlv_pos += sizeof(pbss_mode->header) + pbss_mode->header.len;
1340 		pbss_mode->header.len = wlan_cpu_to_le16(pbss_mode->header.len);
1341 		if (pmadapter->ext_scan_enh) {
1342 			if (puser_scan_in) {
1343 				if (puser_scan_in->ext_scan_type ==
1344 				    EXT_SCAN_ENHANCE)
1345 					pmadapter->ext_scan_type =
1346 						EXT_SCAN_ENHANCE;
1347 				else
1348 					pmadapter->ext_scan_type =
1349 						EXT_SCAN_DEFAULT;
1350 			} else if (pmadapter->ext_scan == EXT_SCAN_TYPE_ENH)
1351 				pmadapter->ext_scan_type = EXT_SCAN_ENHANCE;
1352 			else
1353 				pmadapter->ext_scan_type = EXT_SCAN_DEFAULT;
1354 			if (pmadapter->ext_scan_type == EXT_SCAN_ENHANCE)
1355 				*pmax_chan_per_scan =
1356 					MRVDRV_MAX_CHANNELS_PER_SCAN;
1357 		}
1358 	}
1359 	/* If the input config or adapter has the number of Probes set, add tlv
1360 	 */
1361 	if (num_probes) {
1362 		PRINTM(MINFO, "Scan: num_probes = %d\n", num_probes);
1363 
1364 		pnum_probes_tlv = (MrvlIEtypes_NumProbes_t *)ptlv_pos;
1365 		pnum_probes_tlv->header.type =
1366 			wlan_cpu_to_le16(TLV_TYPE_NUMPROBES);
1367 		pnum_probes_tlv->header.len =
1368 			sizeof(pnum_probes_tlv->num_probes);
1369 		pnum_probes_tlv->num_probes =
1370 			wlan_cpu_to_le16((t_u16)num_probes);
1371 
1372 		ptlv_pos += sizeof(pnum_probes_tlv->header) +
1373 			    pnum_probes_tlv->header.len;
1374 
1375 		pnum_probes_tlv->header.len =
1376 			wlan_cpu_to_le16(pnum_probes_tlv->header.len);
1377 	}
1378 
1379 	/* Append rates tlv */
1380 	memset(pmadapter, rates, 0, sizeof(rates));
1381 
1382 	rates_size = wlan_get_supported_rates(
1383 		pmpriv, pmpriv->bss_mode,
1384 		(pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) ?
1385 			pmpriv->config_bands :
1386 			pmadapter->adhoc_start_band,
1387 		rates);
1388 
1389 	prates_tlv = (MrvlIEtypes_RatesParamSet_t *)ptlv_pos;
1390 	prates_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_RATES);
1391 	prates_tlv->header.len = wlan_cpu_to_le16((t_u16)rates_size);
1392 	memcpy_ext(pmadapter, prates_tlv->rates, rates, rates_size, rates_size);
1393 	ptlv_pos += sizeof(prates_tlv->header) + rates_size;
1394 
1395 	PRINTM(MINFO, "SCAN_CMD: Rates size = %d\n", rates_size);
1396 
1397 	if (wlan_is_ext_capa_support(pmpriv))
1398 		wlan_add_ext_capa_info_ie(pmpriv, MNULL, &ptlv_pos);
1399 	if (pmpriv->adapter->ecsa_enable) {
1400 		t_u8 bandwidth = BW_20MHZ;
1401 		t_u8 oper_class = 1;
1402 		t_u32 usr_dot_11n_dev_cap;
1403 		if (pmpriv->media_connected) {
1404 			if (pmpriv->config_bands & BAND_A)
1405 				usr_dot_11n_dev_cap =
1406 					pmpriv->usr_dot_11n_dev_cap_a;
1407 			else
1408 				usr_dot_11n_dev_cap =
1409 					pmpriv->usr_dot_11n_dev_cap_bg;
1410 			if (usr_dot_11n_dev_cap & MBIT(17)) {
1411 				bandwidth = BW_40MHZ;
1412 				if (ISSUPP_11ACENABLED(
1413 					    pmadapter->fw_cap_info) &&
1414 				    (pmpriv->config_bands & BAND_AAC))
1415 					bandwidth = BW_80MHZ;
1416 			}
1417 			wlan_get_curr_oper_class(
1418 				pmpriv,
1419 				pmpriv->curr_bss_params.bss_descriptor.channel,
1420 				bandwidth, &oper_class);
1421 		}
1422 		wlan_add_supported_oper_class_ie(pmpriv, &ptlv_pos, oper_class);
1423 	}
1424 	wlan_add_wps_probe_request_ie(pmpriv, &ptlv_pos);
1425 
1426 	if (puser_scan_in && puser_scan_in->proberesp_only) {
1427 		MrvlIEtypes_OnlyProberesp_t *proberesp_only =
1428 			(MrvlIEtypes_OnlyProberesp_t *)ptlv_pos;
1429 		memset(pmadapter, proberesp_only, 0,
1430 		       sizeof(MrvlIEtypes_OnlyProberesp_t));
1431 		proberesp_only->header.type =
1432 			wlan_cpu_to_le16(TLV_TYPE_ONLYPROBERESP);
1433 		proberesp_only->header.len = wlan_cpu_to_le16(sizeof(t_u8));
1434 		proberesp_only->proberesp_only = puser_scan_in->proberesp_only;
1435 		ptlv_pos += sizeof(MrvlIEtypes_OnlyProberesp_t);
1436 	}
1437 
1438 	if (puser_scan_in && memcmp(pmadapter, puser_scan_in->random_mac,
1439 				    zero_mac, MLAN_MAC_ADDR_LENGTH)) {
1440 		MrvlIEtypes_MacAddr_t *randomMacParam =
1441 			(MrvlIEtypes_MacAddr_t *)ptlv_pos;
1442 		memset(pmadapter, randomMacParam, 0,
1443 		       sizeof(MrvlIEtypes_MacAddr_t));
1444 		randomMacParam->header.type =
1445 			wlan_cpu_to_le16(TLV_TYPE_RANDOM_MAC);
1446 		randomMacParam->header.len =
1447 			wlan_cpu_to_le16(MLAN_MAC_ADDR_LENGTH);
1448 		memcpy_ext(pmadapter, randomMacParam->mac,
1449 			   puser_scan_in->random_mac, MLAN_MAC_ADDR_LENGTH,
1450 			   MLAN_MAC_ADDR_LENGTH);
1451 		ptlv_pos += sizeof(MrvlIEtypes_MacAddr_t);
1452 	}
1453 	/*
1454 	 * Set the output for the channel TLV to the address in the tlv buffer
1455 	 *   past any TLVs that were added in this function (SSID, num_probes).
1456 	 *   Channel TLVs will be added past this for each scan command,
1457 	 *   preserving the TLVs that were previously added.
1458 	 */
1459 	*ppchan_list_out = (MrvlIEtypes_ChanListParamSet_t *)ptlv_pos;
1460 
1461 	if (puser_scan_in && puser_scan_in->chan_list[0].chan_number) {
1462 		PRINTM(MINFO, "Scan: Using supplied channel list\n");
1463 
1464 		for (chan_idx = 0;
1465 		     chan_idx < WLAN_USER_SCAN_CHAN_MAX &&
1466 		     puser_scan_in->chan_list[chan_idx].chan_number;
1467 		     chan_idx++) {
1468 			radio_type =
1469 				puser_scan_in->chan_list[chan_idx].radio_type;
1470 			/*Ignore 5G/2G channels if radio_type do not match
1471 			 * band*/
1472 			if (!wlan_is_band_compatible(
1473 				    pmpriv->config_bands,
1474 				    radio_type_to_band(radio_type)))
1475 				continue;
1476 			(pscan_chan_list + chan_list_idx)->bandcfg.chanBand =
1477 				radio_type;
1478 
1479 			channel =
1480 				puser_scan_in->chan_list[chan_idx].chan_number;
1481 			(pscan_chan_list + chan_list_idx)->chan_number =
1482 				channel;
1483 
1484 			scan_type =
1485 				puser_scan_in->chan_list[chan_idx].scan_type;
1486 			if (scan_type == MLAN_SCAN_TYPE_UNCHANGED)
1487 				scan_type = pmadapter->scan_type;
1488 
1489 			if (radio_type == BAND_5GHZ) {
1490 				if (pmadapter->fw_bands & BAND_A)
1491 					PRINTM(MINFO,
1492 					       "UserScan request for A Band channel %d!!\n",
1493 					       channel);
1494 				else {
1495 					PRINTM(MERROR,
1496 					       "Scan in A band is not allowed!!\n");
1497 					ret = MLAN_STATUS_FAILURE;
1498 					LEAVE();
1499 					return ret;
1500 				}
1501 			}
1502 			if (!puser_scan_in->scan_cfg_only) {
1503 				if (wlan_is_chan_passive(
1504 					    pmpriv,
1505 					    radio_type_to_band(radio_type),
1506 					    channel)) {
1507 					/* do not send probe requests on this
1508 					 * channel */
1509 					scan_type = MLAN_SCAN_TYPE_PASSIVE;
1510 				}
1511 			}
1512 			/* Prevent active scanning on a radar controlled channel
1513 			 */
1514 			if (radio_type == BAND_5GHZ &&
1515 			    scan_type == MLAN_SCAN_TYPE_PASSIVE) {
1516 				if (pmadapter->active_scan_triggered == MFALSE)
1517 					if (wlan_11h_radar_detect_required(
1518 						    pmpriv, channel)) {
1519 						scan_type =
1520 							MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE;
1521 					}
1522 			}
1523 			if (radio_type == BAND_2GHZ &&
1524 			    !puser_scan_in->scan_cfg_only &&
1525 			    scan_type != MLAN_SCAN_TYPE_PASSIVE) {
1526 				if (pmadapter->active_scan_triggered == MFALSE)
1527 					if (wlan_bg_scan_type_is_passive(
1528 						    pmpriv, channel)) {
1529 						scan_type =
1530 							MLAN_SCAN_TYPE_PASSIVE;
1531 					}
1532 			}
1533 			if (scan_type == MLAN_SCAN_TYPE_PASSIVE ||
1534 			    scan_type == MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE) {
1535 				(pscan_chan_list + chan_list_idx)
1536 					->chan_scan_mode.passive_scan = MTRUE;
1537 				(pscan_chan_list + chan_list_idx)
1538 					->chan_scan_mode.hidden_ssid_report =
1539 					MTRUE;
1540 			} else {
1541 				(pscan_chan_list + chan_list_idx)
1542 					->chan_scan_mode.passive_scan = MFALSE;
1543 			}
1544 
1545 			if (puser_scan_in->chan_list[chan_idx].scan_time) {
1546 				scan_dur = (t_u16)puser_scan_in
1547 						   ->chan_list[chan_idx]
1548 						   .scan_time;
1549 			} else {
1550 				if (scan_type == MLAN_SCAN_TYPE_PASSIVE ||
1551 				    scan_type ==
1552 					    MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE) {
1553 					scan_dur = pmadapter->passive_scan_time;
1554 				} else if (*pfiltered_scan) {
1555 					scan_dur =
1556 						pmadapter->specific_scan_time;
1557 				} else {
1558 					scan_dur = pmadapter->active_scan_time;
1559 				}
1560 			}
1561 
1562 			if (pmadapter->coex_scan &&
1563 			    pmadapter->coex_min_scan_time &&
1564 			    (pmadapter->coex_min_scan_time > scan_dur))
1565 				scan_dur = pmadapter->coex_min_scan_time;
1566 			if (scan_type == MLAN_SCAN_TYPE_PASSIVE_TO_ACTIVE &&
1567 			    pmadapter->passive_to_active_scan ==
1568 				    MLAN_PASS_TO_ACT_SCAN_EN) {
1569 				(pscan_chan_list + chan_list_idx)
1570 					->chan_scan_mode.passive_to_active_scan =
1571 					MTRUE;
1572 				scan_dur = MAX(MIN_PASSIVE_TO_ACTIVE_SCAN_TIME,
1573 					       scan_dur);
1574 			}
1575 			PRINTM(MINFO,
1576 			       "chan=%d, mode=%d, passive_to_active=%d\n",
1577 			       (pscan_chan_list + chan_list_idx)->chan_number,
1578 			       (pscan_chan_list + chan_list_idx)
1579 				       ->chan_scan_mode.passive_scan,
1580 			       (pscan_chan_list + chan_list_idx)
1581 				       ->chan_scan_mode.passive_to_active_scan);
1582 
1583 			(pscan_chan_list + chan_list_idx)->min_scan_time =
1584 				wlan_cpu_to_le16(scan_dur);
1585 			(pscan_chan_list + chan_list_idx)->max_scan_time =
1586 				wlan_cpu_to_le16(scan_dur);
1587 			chan_list_idx++;
1588 		}
1589 
1590 		/* Check if we are only scanning the current channel */
1591 		if ((chan_idx == 1) &&
1592 		    (puser_scan_in->chan_list[0].chan_number ==
1593 		     pmpriv->curr_bss_params.bss_descriptor.channel)) {
1594 			*pscan_current_only = MTRUE;
1595 			PRINTM(MINFO, "Scan: Scanning current channel only\n");
1596 		}
1597 
1598 	} else {
1599 		num_of_channel =
1600 			wlan_scan_create_channel_list(pmpriv, puser_scan_in,
1601 						      pscan_chan_list,
1602 						      *pfiltered_scan);
1603 		PRINTM(MCMND, "Scan: Creating full region channel list %d\n",
1604 		       num_of_channel);
1605 	}
1606 
1607 	LEAVE();
1608 	return ret;
1609 }
1610 
1611 /**
1612  *  @brief Inspect the scan response buffer for pointers to expected TLVs
1613  *
1614  *  TLVs can be included at the end of the scan response BSS information.
1615  *    Parse the data in the buffer for pointers to TLVs that can potentially
1616  *    be passed back in the response
1617  *
1618  *  @param pmadapter        Pointer to the mlan_adapter structure
1619  *  @param ptlv             Pointer to the start of the TLV buffer to parse
1620  *  @param tlv_buf_size     Size of the TLV buffer
1621  *  @param req_tlv_type     Request TLV's type
1622  *  @param pptlv            Output parameter: Pointer to the request TLV if
1623  * found
1624  *
1625  *  @return                 N/A
1626  */
wlan_ret_802_11_scan_get_tlv_ptrs(pmlan_adapter pmadapter,MrvlIEtypes_Data_t * ptlv,t_u32 tlv_buf_size,t_u32 req_tlv_type,MrvlIEtypes_Data_t ** pptlv)1627 static t_void wlan_ret_802_11_scan_get_tlv_ptrs(pmlan_adapter pmadapter,
1628 						MrvlIEtypes_Data_t *ptlv,
1629 						t_u32 tlv_buf_size,
1630 						t_u32 req_tlv_type,
1631 						MrvlIEtypes_Data_t **pptlv)
1632 {
1633 	MrvlIEtypes_Data_t *pcurrent_tlv;
1634 	t_u32 tlv_buf_left;
1635 	t_u32 tlv_type;
1636 	t_u32 tlv_len;
1637 
1638 	ENTER();
1639 
1640 	pcurrent_tlv = ptlv;
1641 	tlv_buf_left = tlv_buf_size;
1642 	*pptlv = MNULL;
1643 
1644 	PRINTM(MINFO, "SCAN_RESP: tlv_buf_size = %d\n", tlv_buf_size);
1645 
1646 	while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
1647 		tlv_type = wlan_le16_to_cpu(pcurrent_tlv->header.type);
1648 		tlv_len = wlan_le16_to_cpu(pcurrent_tlv->header.len);
1649 
1650 		if (sizeof(ptlv->header) + tlv_len > tlv_buf_left) {
1651 			PRINTM(MERROR, "SCAN_RESP: TLV buffer corrupt\n");
1652 			break;
1653 		}
1654 
1655 		if (req_tlv_type == tlv_type) {
1656 			switch (tlv_type) {
1657 			case TLV_TYPE_TSFTIMESTAMP:
1658 				PRINTM(MINFO,
1659 				       "SCAN_RESP: TSF Timestamp TLV, len = %d\n",
1660 				       tlv_len);
1661 				*pptlv = (MrvlIEtypes_Data_t *)pcurrent_tlv;
1662 				break;
1663 			case TLV_TYPE_CHANNELBANDLIST:
1664 				PRINTM(MINFO,
1665 				       "SCAN_RESP: CHANNEL BAND LIST TLV, len = %d\n",
1666 				       tlv_len);
1667 				*pptlv = (MrvlIEtypes_Data_t *)pcurrent_tlv;
1668 				break;
1669 			case TLV_TYPE_CHANNEL_STATS:
1670 				PRINTM(MINFO,
1671 				       "SCAN_RESP: CHANNEL STATS TLV, len = %d\n",
1672 				       tlv_len);
1673 				*pptlv = (MrvlIEtypes_Data_t *)pcurrent_tlv;
1674 				break;
1675 			default:
1676 				PRINTM(MERROR,
1677 				       "SCAN_RESP: Unhandled TLV = %d\n",
1678 				       tlv_type);
1679 				/* Give up, this seems corrupted */
1680 				LEAVE();
1681 				return;
1682 			}
1683 		}
1684 
1685 		if (*pptlv) {
1686 			/* HEXDUMP("SCAN_RESP: TLV Buf", (t_u8 *)*pptlv+4,
1687 			 * tlv_len); */
1688 			break;
1689 		}
1690 
1691 		tlv_buf_left -= (sizeof(ptlv->header) + tlv_len);
1692 		pcurrent_tlv =
1693 			(MrvlIEtypes_Data_t *)(pcurrent_tlv->data + tlv_len);
1694 
1695 	} /* while */
1696 
1697 	LEAVE();
1698 }
1699 
1700 /**
1701  *  @brief Interpret a BSS scan response returned from the firmware
1702  *
1703  *  Parse the various fixed fields and IEs passed back for a BSS probe
1704  *   response or beacon from the scan command.  Record information as needed
1705  *   in the scan table BSSDescriptor_t for that entry.
1706  *
1707  *  @param pmadapter    A pointer to mlan_adapter structure
1708  *  @param pbss_entry   Output parameter: Pointer to the BSS Entry
1709  *  @param pbeacon_info Pointer to the Beacon information
1710  *  @param bytes_left   Number of bytes left to parse
1711  *  @param ext_scan     extended scan
1712  *
1713  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
1714  */
wlan_interpret_bss_desc_with_ie(pmlan_adapter pmadapter,BSSDescriptor_t * pbss_entry,t_u8 ** pbeacon_info,t_u32 * bytes_left,t_u8 ext_scan)1715 static mlan_status wlan_interpret_bss_desc_with_ie(pmlan_adapter pmadapter,
1716 						   BSSDescriptor_t *pbss_entry,
1717 						   t_u8 **pbeacon_info,
1718 						   t_u32 *bytes_left,
1719 						   t_u8 ext_scan)
1720 {
1721 	mlan_status ret = MLAN_STATUS_SUCCESS;
1722 	IEEEtypes_ElementId_e element_id;
1723 	IEEEtypes_FhParamSet_t *pfh_param_set;
1724 	IEEEtypes_DsParamSet_t *pds_param_set;
1725 	IEEEtypes_CfParamSet_t *pcf_param_set;
1726 	IEEEtypes_IbssParamSet_t *pibss_param_set;
1727 	IEEEtypes_CapInfo_t *pcap_info;
1728 	WLAN_802_11_FIXED_IEs fixed_ie;
1729 	t_u8 *pcurrent_ptr;
1730 	t_u8 *prate;
1731 	t_u8 element_len;
1732 	t_u16 total_ie_len;
1733 	t_u8 bytes_to_copy;
1734 	t_u8 rate_size;
1735 	t_u16 beacon_size;
1736 	t_u8 found_data_rate_ie;
1737 	t_u32 bytes_left_for_current_beacon;
1738 	IEEEtypes_ERPInfo_t *perp_info;
1739 
1740 	IEEEtypes_VendorSpecific_t *pvendor_ie;
1741 	const t_u8 wpa_oui[4] = {0x00, 0x50, 0xf2, 0x01};
1742 	const t_u8 wmm_oui[4] = {0x00, 0x50, 0xf2, 0x02};
1743 	const t_u8 osen_oui[] = {0x50, 0x6f, 0x9a, 0x12};
1744 
1745 	IEEEtypes_CountryInfoSet_t *pcountry_info;
1746 	IEEEtypes_Extension_t *pext_tlv;
1747 
1748 	ENTER();
1749 
1750 	found_data_rate_ie = MFALSE;
1751 	rate_size = 0;
1752 	beacon_size = 0;
1753 
1754 	if (*bytes_left >= sizeof(beacon_size)) {
1755 		/* Extract & convert beacon size from the command buffer */
1756 		memcpy_ext(pmadapter, &beacon_size, *pbeacon_info,
1757 			   sizeof(beacon_size), sizeof(beacon_size));
1758 		beacon_size = wlan_le16_to_cpu(beacon_size);
1759 		*bytes_left -= sizeof(beacon_size);
1760 		*pbeacon_info += sizeof(beacon_size);
1761 	}
1762 
1763 	if (!beacon_size || beacon_size > *bytes_left) {
1764 		*pbeacon_info += *bytes_left;
1765 		*bytes_left = 0;
1766 
1767 		LEAVE();
1768 		return MLAN_STATUS_FAILURE;
1769 	}
1770 
1771 	/* Initialize the current working beacon pointer for this BSS iteration
1772 	 */
1773 	pcurrent_ptr = *pbeacon_info;
1774 
1775 	/* Advance the return beacon pointer past the current beacon */
1776 	*pbeacon_info += beacon_size;
1777 	*bytes_left -= beacon_size;
1778 
1779 	bytes_left_for_current_beacon = beacon_size;
1780 
1781 	if (bytes_left_for_current_beacon <
1782 	    (MLAN_MAC_ADDR_LENGTH + sizeof(t_u8) +
1783 	     sizeof(WLAN_802_11_FIXED_IEs))) {
1784 		PRINTM(MERROR, "InterpretIE: Not enough bytes left\n");
1785 		LEAVE();
1786 		return MLAN_STATUS_FAILURE;
1787 	}
1788 
1789 	memcpy_ext(pmadapter, pbss_entry->mac_address, pcurrent_ptr,
1790 		   MLAN_MAC_ADDR_LENGTH, MLAN_MAC_ADDR_LENGTH);
1791 	PRINTM(MINFO, "InterpretIE: AP MAC Addr-" MACSTR "\n",
1792 	       MAC2STR(pbss_entry->mac_address));
1793 
1794 	pcurrent_ptr += MLAN_MAC_ADDR_LENGTH;
1795 	bytes_left_for_current_beacon -= MLAN_MAC_ADDR_LENGTH;
1796 
1797 	/*
1798 	 * Next 4 fields are RSSI (for legacy scan only), time stamp,
1799 	 *   beacon interval, and capability information
1800 	 */
1801 	if (!ext_scan) {
1802 		/* RSSI is 1 byte long */
1803 		pbss_entry->rssi = (t_s32)(*pcurrent_ptr);
1804 		PRINTM(MINFO, "InterpretIE: RSSI=%02X\n", *pcurrent_ptr);
1805 		pcurrent_ptr += 1;
1806 		bytes_left_for_current_beacon -= 1;
1807 	}
1808 
1809 	/*
1810 	 *  The RSSI is not part of the beacon/probe response.  After we have
1811 	 *    advanced pcurrent_ptr past the RSSI field, save the remaining
1812 	 *    data for use at the application layer
1813 	 */
1814 	pbss_entry->pbeacon_buf = pcurrent_ptr;
1815 	pbss_entry->beacon_buf_size = bytes_left_for_current_beacon;
1816 
1817 	/* Time stamp is 8 bytes long */
1818 	memcpy_ext(pmadapter, fixed_ie.time_stamp, pcurrent_ptr, 8,
1819 		   sizeof(fixed_ie.time_stamp));
1820 	memcpy_ext(pmadapter, pbss_entry->time_stamp, pcurrent_ptr, 8,
1821 		   sizeof(pbss_entry->time_stamp));
1822 	pcurrent_ptr += 8;
1823 	bytes_left_for_current_beacon -= 8;
1824 
1825 	/* Beacon interval is 2 bytes long */
1826 	memcpy_ext(pmadapter, &fixed_ie.beacon_interval, pcurrent_ptr, 2,
1827 		   sizeof(fixed_ie.beacon_interval));
1828 	pbss_entry->beacon_period = wlan_le16_to_cpu(fixed_ie.beacon_interval);
1829 	pcurrent_ptr += 2;
1830 	bytes_left_for_current_beacon -= 2;
1831 
1832 	/* Capability information is 2 bytes long */
1833 	memcpy_ext(pmadapter, &fixed_ie.capabilities, pcurrent_ptr, 2,
1834 		   sizeof(fixed_ie.capabilities));
1835 	PRINTM(MINFO, "InterpretIE: fixed_ie.capabilities=0x%X\n",
1836 	       fixed_ie.capabilities);
1837 	fixed_ie.capabilities = wlan_le16_to_cpu(fixed_ie.capabilities);
1838 	pcap_info = (IEEEtypes_CapInfo_t *)&fixed_ie.capabilities;
1839 	memcpy_ext(pmadapter, &pbss_entry->cap_info, pcap_info,
1840 		   sizeof(IEEEtypes_CapInfo_t), sizeof(IEEEtypes_CapInfo_t));
1841 	pcurrent_ptr += 2;
1842 	bytes_left_for_current_beacon -= 2;
1843 
1844 	/* Rest of the current buffer are IE's */
1845 	PRINTM(MINFO, "InterpretIE: IELength for this AP = %d\n",
1846 	       bytes_left_for_current_beacon);
1847 
1848 	HEXDUMP("InterpretIE: IE info", (t_u8 *)pcurrent_ptr,
1849 		bytes_left_for_current_beacon);
1850 
1851 	if (pcap_info->privacy) {
1852 		PRINTM(MINFO, "InterpretIE: AP WEP enabled\n");
1853 		pbss_entry->privacy = Wlan802_11PrivFilter8021xWEP;
1854 	} else {
1855 		pbss_entry->privacy = Wlan802_11PrivFilterAcceptAll;
1856 	}
1857 
1858 	if (pcap_info->ibss == 1)
1859 		pbss_entry->bss_mode = MLAN_BSS_MODE_IBSS;
1860 	else
1861 		pbss_entry->bss_mode = MLAN_BSS_MODE_INFRA;
1862 
1863 	if (pcap_info->spectrum_mgmt == 1) {
1864 		PRINTM(MINFO, "InterpretIE: 11h- Spectrum Management "
1865 			      "capability bit found\n");
1866 		pbss_entry->wlan_11h_bss_info.sensed_11h = 1;
1867 	}
1868 
1869 	/* Process variable IE */
1870 	while (bytes_left_for_current_beacon >= 2) {
1871 		element_id = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
1872 		element_len = *((t_u8 *)pcurrent_ptr + 1);
1873 		total_ie_len = element_len + sizeof(IEEEtypes_Header_t);
1874 
1875 		if (bytes_left_for_current_beacon < total_ie_len) {
1876 			PRINTM(MERROR, "InterpretIE: Error in processing IE, "
1877 				       "bytes left < IE length\n");
1878 			bytes_left_for_current_beacon = 0;
1879 			ret = MLAN_STATUS_FAILURE;
1880 			continue;
1881 		}
1882 
1883 		switch (element_id) {
1884 		case SSID:
1885 			if (element_len > MRVDRV_MAX_SSID_LENGTH) {
1886 				bytes_left_for_current_beacon = 0;
1887 				ret = MLAN_STATUS_FAILURE;
1888 				continue;
1889 			}
1890 			if (!pbss_entry->ssid.ssid_len) {
1891 				pbss_entry->ssid.ssid_len = element_len;
1892 				memcpy_ext(pmadapter, pbss_entry->ssid.ssid,
1893 					   (pcurrent_ptr + 2), element_len,
1894 					   sizeof(pbss_entry->ssid.ssid));
1895 			}
1896 			PRINTM(MINFO, "InterpretIE: ssid: %-32s\n",
1897 			       pbss_entry->ssid.ssid);
1898 			break;
1899 
1900 		case SUPPORTED_RATES:
1901 			if (element_len > WLAN_SUPPORTED_RATES) {
1902 				bytes_left_for_current_beacon = 0;
1903 				ret = MLAN_STATUS_FAILURE;
1904 				continue;
1905 			}
1906 			memcpy_ext(pmadapter, pbss_entry->data_rates,
1907 				   pcurrent_ptr + 2, element_len,
1908 				   sizeof(pbss_entry->data_rates));
1909 			memcpy_ext(pmadapter, pbss_entry->supported_rates,
1910 				   pcurrent_ptr + 2, element_len,
1911 				   sizeof(pbss_entry->supported_rates));
1912 			HEXDUMP("InterpretIE: SupportedRates:",
1913 				pbss_entry->supported_rates, element_len);
1914 			rate_size = element_len;
1915 			found_data_rate_ie = MTRUE;
1916 			break;
1917 
1918 		case FH_PARAM_SET:
1919 			pfh_param_set = (IEEEtypes_FhParamSet_t *)pcurrent_ptr;
1920 			pbss_entry->network_type_use = Wlan802_11FH;
1921 			memcpy_ext(pmadapter,
1922 				   &pbss_entry->phy_param_set.fh_param_set,
1923 				   pfh_param_set, total_ie_len,
1924 				   sizeof(IEEEtypes_FhParamSet_t));
1925 			pbss_entry->phy_param_set.fh_param_set.len = MIN(
1926 				element_len, (sizeof(IEEEtypes_FhParamSet_t) -
1927 					      sizeof(IEEEtypes_Header_t)));
1928 			pbss_entry->phy_param_set.fh_param_set.dwell_time =
1929 				wlan_le16_to_cpu(
1930 					pbss_entry->phy_param_set.fh_param_set
1931 						.dwell_time);
1932 			break;
1933 
1934 		case DS_PARAM_SET:
1935 			pds_param_set = (IEEEtypes_DsParamSet_t *)pcurrent_ptr;
1936 
1937 			pbss_entry->network_type_use = Wlan802_11DS;
1938 			pbss_entry->channel = pds_param_set->current_chan;
1939 
1940 			memcpy_ext(pmadapter,
1941 				   &pbss_entry->phy_param_set.ds_param_set,
1942 				   pds_param_set, total_ie_len,
1943 				   sizeof(IEEEtypes_DsParamSet_t));
1944 			pbss_entry->phy_param_set.ds_param_set.len = MIN(
1945 				element_len, (sizeof(IEEEtypes_DsParamSet_t) -
1946 					      sizeof(IEEEtypes_Header_t)));
1947 			break;
1948 
1949 		case CF_PARAM_SET:
1950 			pcf_param_set = (IEEEtypes_CfParamSet_t *)pcurrent_ptr;
1951 			memcpy_ext(pmadapter,
1952 				   &pbss_entry->ss_param_set.cf_param_set,
1953 				   pcf_param_set, total_ie_len,
1954 				   sizeof(IEEEtypes_CfParamSet_t));
1955 			pbss_entry->ss_param_set.cf_param_set.len = MIN(
1956 				element_len, (sizeof(IEEEtypes_CfParamSet_t) -
1957 					      sizeof(IEEEtypes_Header_t)));
1958 			break;
1959 
1960 		case IBSS_PARAM_SET:
1961 			pibss_param_set =
1962 				(IEEEtypes_IbssParamSet_t *)pcurrent_ptr;
1963 			pbss_entry->atim_window =
1964 				wlan_le16_to_cpu(pibss_param_set->atim_window);
1965 			memcpy_ext(pmadapter,
1966 				   &pbss_entry->ss_param_set.ibss_param_set,
1967 				   pibss_param_set, total_ie_len,
1968 				   sizeof(IEEEtypes_IbssParamSet_t));
1969 			pbss_entry->ss_param_set.ibss_param_set.len = MIN(
1970 				element_len, (sizeof(IEEEtypes_IbssParamSet_t) -
1971 					      sizeof(IEEEtypes_Header_t)));
1972 			break;
1973 
1974 		/* Handle Country Info IE */
1975 		case COUNTRY_INFO:
1976 			pcountry_info =
1977 				(IEEEtypes_CountryInfoSet_t *)pcurrent_ptr;
1978 
1979 			if (pcountry_info->len <
1980 				    sizeof(pcountry_info->country_code) ||
1981 			    (unsigned)(pcountry_info->len + 2) >
1982 				    sizeof(IEEEtypes_CountryInfoFullSet_t)) {
1983 				PRINTM(MERROR,
1984 				       "InterpretIE: 11D- Err "
1985 				       "country_info len =%d min=%d max=%d\n",
1986 				       pcountry_info->len,
1987 				       sizeof(pcountry_info->country_code),
1988 				       sizeof(IEEEtypes_CountryInfoFullSet_t));
1989 				LEAVE();
1990 				return MLAN_STATUS_FAILURE;
1991 			}
1992 
1993 			memcpy_ext(pmadapter, &pbss_entry->country_info,
1994 				   pcountry_info, pcountry_info->len + 2,
1995 				   sizeof(pbss_entry->country_info));
1996 			HEXDUMP("InterpretIE: 11D- country_info:",
1997 				(t_u8 *)pcountry_info,
1998 				(t_u32)(pcountry_info->len + 2));
1999 			break;
2000 
2001 		case ERP_INFO:
2002 			perp_info = (IEEEtypes_ERPInfo_t *)pcurrent_ptr;
2003 			pbss_entry->erp_flags = perp_info->erp_flags;
2004 			break;
2005 
2006 		case POWER_CONSTRAINT:
2007 		case POWER_CAPABILITY:
2008 		case TPC_REPORT:
2009 		case CHANNEL_SWITCH_ANN:
2010 		case QUIET:
2011 		case IBSS_DFS:
2012 		case SUPPORTED_CHANNELS:
2013 		case TPC_REQUEST:
2014 			wlan_11h_process_bss_elem(
2015 				pmadapter, &pbss_entry->wlan_11h_bss_info,
2016 				pcurrent_ptr);
2017 			break;
2018 		case EXTENDED_SUPPORTED_RATES:
2019 			/*
2020 			 * Only process extended supported rate
2021 			 * if data rate is already found.
2022 			 * Data rate IE should come before
2023 			 * extended supported rate IE
2024 			 */
2025 			if (found_data_rate_ie) {
2026 				if ((element_len + rate_size) >
2027 				    WLAN_SUPPORTED_RATES) {
2028 					bytes_to_copy = (WLAN_SUPPORTED_RATES -
2029 							 rate_size);
2030 				} else {
2031 					bytes_to_copy = element_len;
2032 				}
2033 
2034 				prate = (t_u8 *)pbss_entry->data_rates;
2035 				prate += rate_size;
2036 				memcpy_ext(pmadapter, prate, pcurrent_ptr + 2,
2037 					   bytes_to_copy, bytes_to_copy);
2038 
2039 				prate = (t_u8 *)pbss_entry->supported_rates;
2040 				prate += rate_size;
2041 				memcpy_ext(pmadapter, prate, pcurrent_ptr + 2,
2042 					   bytes_to_copy, bytes_to_copy);
2043 			}
2044 			HEXDUMP("InterpretIE: ExtSupportedRates:",
2045 				pbss_entry->supported_rates,
2046 				element_len + rate_size);
2047 			break;
2048 
2049 		case VENDOR_SPECIFIC_221:
2050 			pvendor_ie = (IEEEtypes_VendorSpecific_t *)pcurrent_ptr;
2051 
2052 			if (!memcmp(pmadapter, pvendor_ie->vend_hdr.oui,
2053 				    wpa_oui, sizeof(wpa_oui))) {
2054 				pbss_entry->pwpa_ie =
2055 					(IEEEtypes_VendorSpecific_t *)
2056 						pcurrent_ptr;
2057 				pbss_entry->wpa_offset = (t_u16)(
2058 					pcurrent_ptr - pbss_entry->pbeacon_buf);
2059 				HEXDUMP("InterpretIE: Resp WPA_IE",
2060 					(t_u8 *)pbss_entry->pwpa_ie,
2061 					((*(pbss_entry->pwpa_ie)).vend_hdr.len +
2062 					 sizeof(IEEEtypes_Header_t)));
2063 			} else if (!memcmp(pmadapter, pvendor_ie->vend_hdr.oui,
2064 					   wmm_oui, sizeof(wmm_oui))) {
2065 				if (total_ie_len ==
2066 					    sizeof(IEEEtypes_WmmParameter_t) ||
2067 				    total_ie_len ==
2068 					    sizeof(IEEEtypes_WmmInfo_t)) {
2069 					/*
2070 					 * Only accept and copy the WMM IE if
2071 					 * it matches the size expected for the
2072 					 * WMM Info IE or the WMM Parameter IE.
2073 					 */
2074 					memcpy_ext(pmadapter,
2075 						   (t_u8 *)&pbss_entry->wmm_ie,
2076 						   pcurrent_ptr, total_ie_len,
2077 						   sizeof(pbss_entry->wmm_ie));
2078 					HEXDUMP("InterpretIE: Resp WMM_IE",
2079 						(t_u8 *)&pbss_entry->wmm_ie,
2080 						total_ie_len);
2081 				}
2082 			} else if (!memcmp(pmadapter, pvendor_ie->vend_hdr.oui,
2083 					   osen_oui, sizeof(osen_oui))) {
2084 				pbss_entry->posen_ie =
2085 					(IEEEtypes_Generic_t *)pcurrent_ptr;
2086 				pbss_entry->osen_offset = (t_u16)(
2087 					pcurrent_ptr - pbss_entry->pbeacon_buf);
2088 				HEXDUMP("InterpretIE: Resp OSEN_IE",
2089 					(t_u8 *)pbss_entry->posen_ie,
2090 					(*(pbss_entry->posen_ie)).ieee_hdr.len +
2091 						sizeof(IEEEtypes_Header_t));
2092 			}
2093 			break;
2094 		case RSN_IE:
2095 			pbss_entry->prsn_ie =
2096 				(IEEEtypes_Generic_t *)pcurrent_ptr;
2097 			pbss_entry->rsn_offset =
2098 				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2099 			HEXDUMP("InterpretIE: Resp RSN_IE",
2100 				(t_u8 *)pbss_entry->prsn_ie,
2101 				(*(pbss_entry->prsn_ie)).ieee_hdr.len +
2102 					sizeof(IEEEtypes_Header_t));
2103 			break;
2104 		case RSNX_IE:
2105 			pbss_entry->prsnx_ie =
2106 				(IEEEtypes_Generic_t *)pcurrent_ptr;
2107 			pbss_entry->rsnx_offset =
2108 				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2109 			HEXDUMP("InterpretIE: Resp RSNX_IE",
2110 				(t_u8 *)pbss_entry->prsnx_ie,
2111 				(*(pbss_entry->prsnx_ie)).ieee_hdr.len +
2112 					sizeof(IEEEtypes_Header_t));
2113 			break;
2114 		case WAPI_IE:
2115 			pbss_entry->pwapi_ie =
2116 				(IEEEtypes_Generic_t *)pcurrent_ptr;
2117 			pbss_entry->wapi_offset =
2118 				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2119 			HEXDUMP("InterpretIE: Resp WAPI_IE",
2120 				(t_u8 *)pbss_entry->pwapi_ie,
2121 				(*(pbss_entry->pwapi_ie)).ieee_hdr.len +
2122 					sizeof(IEEEtypes_Header_t));
2123 			break;
2124 		case MULTI_BSSID:
2125 			if (IS_FW_SUPPORT_MULTIBSSID(pmadapter)) {
2126 				pbss_entry->multi_bssid_ap = MULTI_BSSID_AP;
2127 				HEXDUMP("InterpretIE: Multi BSSID IE",
2128 					(t_u8 *)pcurrent_ptr, total_ie_len);
2129 			}
2130 			break;
2131 		case HT_CAPABILITY:
2132 			pbss_entry->pht_cap = (IEEEtypes_HTCap_t *)pcurrent_ptr;
2133 			pbss_entry->ht_cap_offset =
2134 				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2135 			HEXDUMP("InterpretIE: Resp HTCAP_IE",
2136 				(t_u8 *)pbss_entry->pht_cap,
2137 				(*(pbss_entry->pht_cap)).ieee_hdr.len +
2138 					sizeof(IEEEtypes_Header_t));
2139 			break;
2140 		case HT_OPERATION:
2141 			pbss_entry->pht_info =
2142 				(IEEEtypes_HTInfo_t *)pcurrent_ptr;
2143 			pbss_entry->ht_info_offset =
2144 				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2145 			HEXDUMP("InterpretIE: Resp HTINFO_IE",
2146 				(t_u8 *)pbss_entry->pht_info,
2147 				(*(pbss_entry->pht_info)).ieee_hdr.len +
2148 					sizeof(IEEEtypes_Header_t));
2149 			break;
2150 		case BSSCO_2040:
2151 			pbss_entry->pbss_co_2040 =
2152 				(IEEEtypes_2040BSSCo_t *)pcurrent_ptr;
2153 			pbss_entry->bss_co_2040_offset =
2154 				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2155 			HEXDUMP("InterpretIE: Resp 2040BSSCOEXISTANCE_IE",
2156 				(t_u8 *)pbss_entry->pbss_co_2040,
2157 				(*(pbss_entry->pbss_co_2040)).ieee_hdr.len +
2158 					sizeof(IEEEtypes_Header_t));
2159 			break;
2160 		case EXT_CAPABILITY:
2161 			pbss_entry->pext_cap =
2162 				(IEEEtypes_ExtCap_t *)pcurrent_ptr;
2163 			pbss_entry->ext_cap_offset =
2164 				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2165 			HEXDUMP("InterpretIE: Resp EXTCAP_IE",
2166 				(t_u8 *)pbss_entry->pext_cap,
2167 				(*(pbss_entry->pext_cap)).ieee_hdr.len +
2168 					sizeof(IEEEtypes_Header_t));
2169 			break;
2170 		case OVERLAPBSSSCANPARAM:
2171 			pbss_entry->poverlap_bss_scan_param =
2172 				(IEEEtypes_OverlapBSSScanParam_t *)pcurrent_ptr;
2173 			pbss_entry->overlap_bss_offset =
2174 				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2175 			HEXDUMP("InterpretIE: Resp OBSS_IE",
2176 				(t_u8 *)pbss_entry->poverlap_bss_scan_param,
2177 				(*(pbss_entry->poverlap_bss_scan_param))
2178 						.ieee_hdr.len +
2179 					sizeof(IEEEtypes_Header_t));
2180 			break;
2181 		case VHT_CAPABILITY:
2182 			pbss_entry->pvht_cap =
2183 				(IEEEtypes_VHTCap_t *)pcurrent_ptr;
2184 			pbss_entry->vht_cap_offset =
2185 				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2186 			HEXDUMP("InterpretIE: Resp VHTCAP_IE",
2187 				(t_u8 *)pbss_entry->pvht_cap,
2188 				(*(pbss_entry->pvht_cap)).ieee_hdr.len +
2189 					sizeof(IEEEtypes_Header_t));
2190 			break;
2191 		case VHT_OPERATION:
2192 			pbss_entry->pvht_oprat =
2193 				(IEEEtypes_VHTOprat_t *)pcurrent_ptr;
2194 			pbss_entry->vht_oprat_offset =
2195 				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2196 			HEXDUMP("InterpretIE: Resp VHTOPER_IE",
2197 				(t_u8 *)pbss_entry->pvht_oprat,
2198 				(*(pbss_entry->pvht_oprat)).ieee_hdr.len +
2199 					sizeof(IEEEtypes_Header_t));
2200 			break;
2201 		case EXT_BSS_LOAD:
2202 			pbss_entry->pext_bssload =
2203 				(IEEEtypes_ExtBSSload_t *)pcurrent_ptr;
2204 			pbss_entry->ext_bssload_offset =
2205 				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2206 			HEXDUMP("InterpretIE: Resp EXTBSSLOAD_IE",
2207 				(t_u8 *)pbss_entry->pext_bssload,
2208 				(*(pbss_entry->pext_bssload)).ieee_hdr.len +
2209 					sizeof(IEEEtypes_Header_t));
2210 			break;
2211 		case VHT_TX_POWER_ENV:
2212 			pbss_entry->pvht_txpower =
2213 				(IEEEtypes_VHTtxpower_t *)pcurrent_ptr;
2214 			pbss_entry->vht_txpower_offset =
2215 				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2216 			HEXDUMP("InterpretIE: Resp TXPOW_IE",
2217 				(t_u8 *)pbss_entry->pvht_txpower,
2218 				(*(pbss_entry->pvht_txpower)).ieee_hdr.len +
2219 					sizeof(IEEEtypes_Header_t));
2220 			break;
2221 		case EXT_POWER_CONSTR:
2222 			pbss_entry->pext_pwer =
2223 				(IEEEtypes_ExtPwerCons_t *)pcurrent_ptr;
2224 			pbss_entry->ext_pwer_offset =
2225 				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2226 			HEXDUMP("InterpretIE: Resp EXTPOW_IE",
2227 				(t_u8 *)pbss_entry->pext_pwer,
2228 				(*(pbss_entry->pext_pwer)).ieee_hdr.len +
2229 					sizeof(IEEEtypes_Header_t));
2230 			break;
2231 		case QUIET_CHAN:
2232 			pbss_entry->pquiet_chan =
2233 				(IEEEtypes_QuietChan_t *)pcurrent_ptr;
2234 			pbss_entry->quiet_chan_offset =
2235 				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2236 			HEXDUMP("InterpretIE: Resp QUIETCHAN_IE",
2237 				(t_u8 *)pbss_entry->pquiet_chan,
2238 				(*(pbss_entry->pquiet_chan)).ieee_hdr.len +
2239 					sizeof(IEEEtypes_Header_t));
2240 			break;
2241 		case BW_CHANNEL_SWITCH:
2242 			/* RANDYTODO */
2243 			break;
2244 		case AID_INFO:
2245 			break;
2246 		case OPER_MODE_NTF:
2247 			pbss_entry->poper_mode =
2248 				(IEEEtypes_OperModeNtf_t *)pcurrent_ptr;
2249 			pbss_entry->oper_mode_offset =
2250 				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2251 			HEXDUMP("InterpretIE: Resp OPERMODENTF_IE",
2252 				(t_u8 *)pbss_entry->poper_mode,
2253 				(*(pbss_entry->poper_mode)).ieee_hdr.len +
2254 					sizeof(IEEEtypes_Header_t));
2255 			break;
2256 		case EXTENSION:
2257 			pext_tlv = (IEEEtypes_Extension_t *)pcurrent_ptr;
2258 			switch (pext_tlv->ext_id) {
2259 			case HE_CAPABILITY:
2260 				pbss_entry->phe_cap =
2261 					(IEEEtypes_HECap_t *)pcurrent_ptr;
2262 				pbss_entry->he_cap_offset = (t_u16)(
2263 					pcurrent_ptr - pbss_entry->pbeacon_buf);
2264 				break;
2265 			case HE_OPERATION:
2266 				pbss_entry->phe_oprat = pext_tlv;
2267 				pbss_entry->he_oprat_offset = (t_u16)(
2268 					pcurrent_ptr - pbss_entry->pbeacon_buf);
2269 				break;
2270 			default:
2271 				break;
2272 			}
2273 			break;
2274 		case MOBILITY_DOMAIN:
2275 			PRINTM(MCMND, "Mobility Domain IE received in Scan\n");
2276 			pbss_entry->pmd_ie =
2277 				(IEEEtypes_MobilityDomain_t *)pcurrent_ptr;
2278 			pbss_entry->md_offset =
2279 				(t_u16)(pcurrent_ptr - pbss_entry->pbeacon_buf);
2280 			HEXDUMP("InterpretIE: Resp Mobility Domain IE",
2281 				(t_u8 *)pbss_entry->pmd_ie,
2282 				(*(pbss_entry->pmd_ie)).ieee_hdr.len +
2283 					sizeof(IEEEtypes_Header_t));
2284 			break;
2285 		default:
2286 			break;
2287 		}
2288 
2289 		pcurrent_ptr += element_len + 2;
2290 
2291 		/* Need to account for IE ID and IE Len */
2292 		bytes_left_for_current_beacon -= (element_len + 2);
2293 
2294 	} /* while (bytes_left_for_current_beacon > 2) */
2295 
2296 	LEAVE();
2297 	return ret;
2298 }
2299 
2300 /**
2301  *  @brief Adjust ie's position in BSSDescriptor_t
2302  *
2303  *  @param pmpriv       A pointer to mlan_private structure
2304  *  @param pbss_entry   A pointer to BSSDescriptor_t structure
2305  *
2306  *  @return           N/A
2307  */
wlan_adjust_ie_in_bss_entry(mlan_private * pmpriv,BSSDescriptor_t * pbss_entry)2308 static t_void wlan_adjust_ie_in_bss_entry(mlan_private *pmpriv,
2309 					  BSSDescriptor_t *pbss_entry)
2310 {
2311 	ENTER();
2312 	if (pbss_entry->pbeacon_buf) {
2313 		if (pbss_entry->pwpa_ie) {
2314 			pbss_entry->pwpa_ie =
2315 				(IEEEtypes_VendorSpecific_t
2316 					 *)(pbss_entry->pbeacon_buf +
2317 					    pbss_entry->wpa_offset);
2318 		}
2319 		if (pbss_entry->prsn_ie) {
2320 			pbss_entry->prsn_ie =
2321 				(IEEEtypes_Generic_t *)(pbss_entry->pbeacon_buf +
2322 							pbss_entry->rsn_offset);
2323 		}
2324 		if (pbss_entry->pwapi_ie) {
2325 			pbss_entry->pwapi_ie =
2326 				(IEEEtypes_Generic_t *)(pbss_entry->pbeacon_buf +
2327 							pbss_entry->wapi_offset);
2328 		}
2329 
2330 		if (pbss_entry->posen_ie) {
2331 			pbss_entry->posen_ie =
2332 				(IEEEtypes_Generic_t *)(pbss_entry->pbeacon_buf +
2333 							pbss_entry->osen_offset);
2334 		}
2335 		if (pbss_entry->pmd_ie) {
2336 			pbss_entry->pmd_ie =
2337 				(IEEEtypes_MobilityDomain_t
2338 					 *)(pbss_entry->pbeacon_buf +
2339 					    pbss_entry->md_offset);
2340 		}
2341 		if (pbss_entry->pht_cap) {
2342 			pbss_entry->pht_cap =
2343 				(IEEEtypes_HTCap_t *)(pbss_entry->pbeacon_buf +
2344 						      pbss_entry->ht_cap_offset);
2345 		}
2346 		if (pbss_entry->pht_info) {
2347 			pbss_entry->pht_info =
2348 				(IEEEtypes_HTInfo_t
2349 					 *)(pbss_entry->pbeacon_buf +
2350 					    pbss_entry->ht_info_offset);
2351 		}
2352 		if (pbss_entry->pbss_co_2040) {
2353 			pbss_entry->pbss_co_2040 =
2354 				(IEEEtypes_2040BSSCo_t
2355 					 *)(pbss_entry->pbeacon_buf +
2356 					    pbss_entry->bss_co_2040_offset);
2357 		}
2358 		if (pbss_entry->pext_cap) {
2359 			pbss_entry->pext_cap =
2360 				(IEEEtypes_ExtCap_t
2361 					 *)(pbss_entry->pbeacon_buf +
2362 					    pbss_entry->ext_cap_offset);
2363 		}
2364 		if (pbss_entry->poverlap_bss_scan_param) {
2365 			pbss_entry->poverlap_bss_scan_param =
2366 				(IEEEtypes_OverlapBSSScanParam_t
2367 					 *)(pbss_entry->pbeacon_buf +
2368 					    pbss_entry->overlap_bss_offset);
2369 		}
2370 		if (pbss_entry->pvht_cap) {
2371 			pbss_entry->pvht_cap =
2372 				(IEEEtypes_VHTCap_t
2373 					 *)(pbss_entry->pbeacon_buf +
2374 					    pbss_entry->vht_cap_offset);
2375 		}
2376 		if (pbss_entry->pvht_oprat) {
2377 			pbss_entry->pvht_oprat =
2378 				(IEEEtypes_VHTOprat_t
2379 					 *)(pbss_entry->pbeacon_buf +
2380 					    pbss_entry->vht_oprat_offset);
2381 		}
2382 		if (pbss_entry->pvht_txpower) {
2383 			pbss_entry->pvht_txpower =
2384 				(IEEEtypes_VHTtxpower_t
2385 					 *)(pbss_entry->pbeacon_buf +
2386 					    pbss_entry->vht_txpower_offset);
2387 		}
2388 		if (pbss_entry->pext_pwer) {
2389 			pbss_entry->pext_pwer =
2390 				(IEEEtypes_ExtPwerCons_t
2391 					 *)(pbss_entry->pbeacon_buf +
2392 					    pbss_entry->ext_pwer_offset);
2393 		}
2394 		if (pbss_entry->pext_bssload) {
2395 			pbss_entry->pext_bssload =
2396 				(IEEEtypes_ExtBSSload_t
2397 					 *)(pbss_entry->pbeacon_buf +
2398 					    pbss_entry->ext_bssload_offset);
2399 		}
2400 		if (pbss_entry->pquiet_chan) {
2401 			pbss_entry->pquiet_chan =
2402 				(IEEEtypes_QuietChan_t
2403 					 *)(pbss_entry->pbeacon_buf +
2404 					    pbss_entry->quiet_chan_offset);
2405 		}
2406 		if (pbss_entry->poper_mode) {
2407 			pbss_entry->poper_mode =
2408 				(IEEEtypes_OperModeNtf_t
2409 					 *)(pbss_entry->pbeacon_buf +
2410 					    pbss_entry->oper_mode_offset);
2411 		}
2412 		if (pbss_entry->phe_cap) {
2413 			pbss_entry->phe_cap =
2414 				(IEEEtypes_HECap_t *)(pbss_entry->pbeacon_buf +
2415 						      pbss_entry->he_cap_offset);
2416 		}
2417 
2418 		if (pbss_entry->phe_oprat) {
2419 			pbss_entry->phe_oprat =
2420 				(IEEEtypes_Extension_t
2421 					 *)(pbss_entry->pbeacon_buf +
2422 					    pbss_entry->he_oprat_offset);
2423 		}
2424 		if (pbss_entry->prsnx_ie) {
2425 			pbss_entry->prsnx_ie =
2426 				(IEEEtypes_Generic_t *)(pbss_entry->pbeacon_buf +
2427 							pbss_entry->rsnx_offset);
2428 		}
2429 	} else {
2430 		pbss_entry->pwpa_ie = MNULL;
2431 		pbss_entry->wpa_offset = 0;
2432 		pbss_entry->prsn_ie = MNULL;
2433 		pbss_entry->rsn_offset = 0;
2434 		pbss_entry->pwapi_ie = MNULL;
2435 		pbss_entry->wapi_offset = 0;
2436 
2437 		pbss_entry->posen_ie = MNULL;
2438 		pbss_entry->osen_offset = 0;
2439 		pbss_entry->pmd_ie = MNULL;
2440 		pbss_entry->md_offset = 0;
2441 		pbss_entry->pht_cap = MNULL;
2442 		pbss_entry->ht_cap_offset = 0;
2443 		pbss_entry->pht_info = MNULL;
2444 		pbss_entry->ht_info_offset = 0;
2445 		pbss_entry->pbss_co_2040 = MNULL;
2446 		pbss_entry->bss_co_2040_offset = 0;
2447 		pbss_entry->pext_cap = MNULL;
2448 		pbss_entry->ext_cap_offset = 0;
2449 		pbss_entry->poverlap_bss_scan_param = MNULL;
2450 		pbss_entry->overlap_bss_offset = 0;
2451 	}
2452 	LEAVE();
2453 	return;
2454 }
2455 
2456 /**
2457  *  @brief Store a beacon or probe response for a BSS returned in the scan
2458  *
2459  *  Store a new scan response or an update for a previous scan response.  New
2460  *    entries need to verify that they do not exceed the total amount of
2461  *    memory allocated for the table.
2462 
2463  *  Replacement entries need to take into consideration the amount of space
2464  *    currently allocated for the beacon/probe response and adjust the entry
2465  *    as needed.
2466  *
2467  *  A small amount of extra pad (SCAN_BEACON_ENTRY_PAD) is generally reserved
2468  *    for an entry in case it is a beacon since a probe response for the
2469  *    network will by larger per the standard.  This helps to reduce the
2470  *    amount of memory copying to fit a new probe response into an entry
2471  *    already occupied by a network's previously stored beacon.
2472  *
2473  *  @param pmpriv       A pointer to mlan_private structure
2474  *  @param beacon_idx   Index in the scan table to store this entry; may be
2475  *                      replacing an older duplicate entry for this BSS
2476  *  @param num_of_ent   Number of entries currently in the table
2477  *  @param pnew_beacon  Pointer to the new beacon/probe response to save
2478  *
2479  *  @return           N/A
2480  */
wlan_ret_802_11_scan_store_beacon(mlan_private * pmpriv,t_u32 beacon_idx,t_u32 num_of_ent,BSSDescriptor_t * pnew_beacon)2481 static t_void wlan_ret_802_11_scan_store_beacon(mlan_private *pmpriv,
2482 						t_u32 beacon_idx,
2483 						t_u32 num_of_ent,
2484 						BSSDescriptor_t *pnew_beacon)
2485 {
2486 	mlan_adapter *pmadapter = pmpriv->adapter;
2487 	t_u8 *pbcn_store;
2488 	t_u32 new_bcn_size;
2489 	t_u32 old_bcn_size;
2490 	t_u32 bcn_space;
2491 	t_u32 adj_idx;
2492 	mlan_status ret = MLAN_STATUS_SUCCESS;
2493 	t_u8 *tmp_buf;
2494 	t_u32 bcn_size = 0;
2495 	t_u32 bcn_offset = 0;
2496 
2497 	ENTER();
2498 
2499 	if (pmadapter->pscan_table[beacon_idx].pbeacon_buf) {
2500 		new_bcn_size = pnew_beacon->beacon_buf_size;
2501 		old_bcn_size =
2502 			pmadapter->pscan_table[beacon_idx].beacon_buf_size;
2503 		bcn_space =
2504 			pmadapter->pscan_table[beacon_idx].beacon_buf_size_max;
2505 		pbcn_store = pmadapter->pscan_table[beacon_idx].pbeacon_buf;
2506 
2507 		/* Set the max to be the same as current entry unless changed
2508 		 * below */
2509 		pnew_beacon->beacon_buf_size_max = bcn_space;
2510 
2511 		if (new_bcn_size == old_bcn_size) {
2512 			/*
2513 			 * Beacon is the same size as the previous entry.
2514 			 *   Replace the previous contents with the scan result
2515 			 */
2516 			memcpy_ext(pmadapter, pbcn_store,
2517 				   pnew_beacon->pbeacon_buf,
2518 				   pnew_beacon->beacon_buf_size,
2519 				   pnew_beacon->beacon_buf_size);
2520 
2521 		} else if (new_bcn_size <= bcn_space) {
2522 			/*
2523 			 * New beacon size will fit in the amount of space
2524 			 *   we have previously allocated for it
2525 			 */
2526 
2527 			/* Copy the new beacon buffer entry over the old one */
2528 			memcpy_ext(pmadapter, pbcn_store,
2529 				   pnew_beacon->pbeacon_buf, new_bcn_size,
2530 				   new_bcn_size);
2531 
2532 			/*
2533 			 *  If the old beacon size was less than the
2534 			 *  maximum we had allotted for the entry, and
2535 			 *  the new entry is even smaller, reset the
2536 			 *  max size to the old beacon entry and compress
2537 			 *  the storage space (leaving a new pad space of
2538 			 *  (old_bcn_size - new_bcn_size).
2539 			 */
2540 			if (old_bcn_size < bcn_space &&
2541 			    new_bcn_size <= old_bcn_size) {
2542 				/*
2543 				 * Old Beacon size is smaller than the
2544 				 * allotted storage size. Shrink the
2545 				 * allotted storage space.
2546 				 */
2547 				PRINTM(MINFO,
2548 				       "AppControl: Smaller Duplicate Beacon (%d), "
2549 				       "old = %d, new = %d, space = %d, left = %d\n",
2550 				       beacon_idx, old_bcn_size, new_bcn_size,
2551 				       bcn_space,
2552 				       (pmadapter->bcn_buf_size -
2553 					(pmadapter->pbcn_buf_end -
2554 					 pmadapter->bcn_buf)));
2555 
2556 				/*
2557 				 * memmove (since the memory overlaps) the data
2558 				 * after the beacon we just stored to the end
2559 				 * of the current beacon.  This cleans up any
2560 				 * unused space the old larger beacon was using
2561 				 * in the buffer
2562 				 */
2563 				memmove(pmadapter,
2564 					(void *)((t_ptr)pbcn_store +
2565 						 (t_ptr)old_bcn_size),
2566 					(void *)((t_ptr)pbcn_store +
2567 						 (t_ptr)bcn_space),
2568 					(t_u32)((t_ptr)pmadapter->pbcn_buf_end -
2569 						((t_ptr)pbcn_store +
2570 						 (t_ptr)bcn_space)));
2571 
2572 				/*
2573 				 * Decrement the end pointer by the difference
2574 				 * between the old larger size and the new
2575 				 * smaller size since we are using less space
2576 				 * due to the new beacon being smaller
2577 				 */
2578 				pmadapter->pbcn_buf_end -=
2579 					(bcn_space - old_bcn_size);
2580 
2581 				/*
2582 				 * Set the maximum storage size to the old
2583 				 * beacon size
2584 				 */
2585 				pnew_beacon->beacon_buf_size_max = old_bcn_size;
2586 
2587 				/* Adjust beacon buffer pointers that are past
2588 				 * the current */
2589 				for (adj_idx = 0; adj_idx < num_of_ent;
2590 				     adj_idx++) {
2591 					if (pmadapter->pscan_table[adj_idx]
2592 						    .pbeacon_buf > pbcn_store) {
2593 						pmadapter->pscan_table[adj_idx]
2594 							.pbeacon_buf -=
2595 							(bcn_space -
2596 							 old_bcn_size);
2597 						wlan_adjust_ie_in_bss_entry(
2598 							pmpriv,
2599 							&pmadapter->pscan_table
2600 								 [adj_idx]);
2601 					}
2602 				}
2603 			}
2604 		} else if (pmadapter->pbcn_buf_end +
2605 				   (new_bcn_size - bcn_space) <
2606 			   (pmadapter->bcn_buf + pmadapter->bcn_buf_size)) {
2607 			/*
2608 			 * Beacon is larger than space previously allocated
2609 			 * (bcn_space) and there is enough space left in the
2610 			 * beaconBuffer to store the additional data
2611 			 */
2612 			PRINTM(MINFO,
2613 			       "AppControl: Larger Duplicate Beacon (%d), "
2614 			       "old = %d, new = %d, space = %d, left = %d\n",
2615 			       beacon_idx, old_bcn_size, new_bcn_size,
2616 			       bcn_space,
2617 			       (pmadapter->bcn_buf_size -
2618 				(pmadapter->pbcn_buf_end - pmadapter->bcn_buf)));
2619 
2620 			/*
2621 			 * memmove (since the memory overlaps) the data
2622 			 *  after the beacon we just stored to the end of
2623 			 *  the current beacon.  This moves the data for
2624 			 *  the beacons after this further in memory to
2625 			 *  make space for the new larger beacon we are
2626 			 *  about to copy in.
2627 			 */
2628 			memmove(pmadapter,
2629 				(void *)((t_ptr)pbcn_store +
2630 					 (t_ptr)new_bcn_size),
2631 				(void *)((t_ptr)pbcn_store + (t_ptr)bcn_space),
2632 				(t_u32)((t_ptr)pmadapter->pbcn_buf_end -
2633 					((t_ptr)pbcn_store + (t_ptr)bcn_space)));
2634 
2635 			/* Copy the new beacon buffer entry over the old one */
2636 			memcpy_ext(pmadapter, pbcn_store,
2637 				   pnew_beacon->pbeacon_buf, new_bcn_size,
2638 				   new_bcn_size);
2639 
2640 			/*
2641 			 * Move the beacon end pointer by the amount of new
2642 			 * beacon data we are adding
2643 			 */
2644 			pmadapter->pbcn_buf_end += (new_bcn_size - bcn_space);
2645 
2646 			/*
2647 			 * This entry is bigger than the allotted max space
2648 			 *  previously reserved.  Increase the max space to
2649 			 *  be equal to the new beacon size
2650 			 */
2651 			pnew_beacon->beacon_buf_size_max = new_bcn_size;
2652 
2653 			/* Adjust beacon buffer pointers that are past the
2654 			 * current */
2655 			for (adj_idx = 0; adj_idx < num_of_ent; adj_idx++) {
2656 				if (pmadapter->pscan_table[adj_idx].pbeacon_buf >
2657 				    pbcn_store) {
2658 					pmadapter->pscan_table[adj_idx]
2659 						.pbeacon_buf +=
2660 						(new_bcn_size - bcn_space);
2661 					wlan_adjust_ie_in_bss_entry(
2662 						pmpriv,
2663 						&pmadapter->pscan_table[adj_idx]);
2664 				}
2665 			}
2666 		} else {
2667 			/*
2668 			 * Beacon is larger than the previously allocated
2669 			 * space, but there is not enough free space to
2670 			 * store the additional data
2671 			 */
2672 			PRINTM(MERROR,
2673 			       "AppControl: Failed: Larger Duplicate Beacon (%d),"
2674 			       " old = %d, new = %d, space = %d, left = %d\n",
2675 			       beacon_idx, old_bcn_size, new_bcn_size,
2676 			       bcn_space,
2677 			       (pmadapter->bcn_buf_size -
2678 				(pmadapter->pbcn_buf_end - pmadapter->bcn_buf)));
2679 
2680 			/* Storage failure, keep old beacon intact */
2681 			pnew_beacon->beacon_buf_size = old_bcn_size;
2682 			if (pnew_beacon->pwpa_ie)
2683 				pnew_beacon->wpa_offset =
2684 					pmadapter->pscan_table[beacon_idx]
2685 						.wpa_offset;
2686 			if (pnew_beacon->prsn_ie)
2687 				pnew_beacon->rsn_offset =
2688 					pmadapter->pscan_table[beacon_idx]
2689 						.rsn_offset;
2690 			if (pnew_beacon->pwapi_ie)
2691 				pnew_beacon->wapi_offset =
2692 					pmadapter->pscan_table[beacon_idx]
2693 						.wapi_offset;
2694 
2695 			if (pnew_beacon->posen_ie)
2696 				pnew_beacon->osen_offset =
2697 					pmadapter->pscan_table[beacon_idx]
2698 						.osen_offset;
2699 			if (pnew_beacon->pmd_ie)
2700 				pnew_beacon->md_offset =
2701 					pmadapter->pscan_table[beacon_idx]
2702 						.md_offset;
2703 			if (pnew_beacon->pht_cap)
2704 				pnew_beacon->ht_cap_offset =
2705 					pmadapter->pscan_table[beacon_idx]
2706 						.ht_cap_offset;
2707 			if (pnew_beacon->pht_info)
2708 				pnew_beacon->ht_info_offset =
2709 					pmadapter->pscan_table[beacon_idx]
2710 						.ht_info_offset;
2711 			if (pnew_beacon->pbss_co_2040)
2712 				pnew_beacon->bss_co_2040_offset =
2713 					pmadapter->pscan_table[beacon_idx]
2714 						.bss_co_2040_offset;
2715 			if (pnew_beacon->pext_cap)
2716 				pnew_beacon->ext_cap_offset =
2717 					pmadapter->pscan_table[beacon_idx]
2718 						.ext_cap_offset;
2719 			if (pnew_beacon->poverlap_bss_scan_param)
2720 				pnew_beacon->overlap_bss_offset =
2721 					pmadapter->pscan_table[beacon_idx]
2722 						.overlap_bss_offset;
2723 			if (pnew_beacon->pvht_cap)
2724 				pnew_beacon->vht_cap_offset =
2725 					pmadapter->pscan_table[beacon_idx]
2726 						.vht_cap_offset;
2727 			if (pnew_beacon->pvht_oprat)
2728 				pnew_beacon->vht_oprat_offset =
2729 					pmadapter->pscan_table[beacon_idx]
2730 						.vht_oprat_offset;
2731 			if (pnew_beacon->pvht_txpower)
2732 				pnew_beacon->vht_txpower_offset =
2733 					pmadapter->pscan_table[beacon_idx]
2734 						.vht_txpower_offset;
2735 			if (pnew_beacon->pext_pwer)
2736 				pnew_beacon->ext_pwer_offset =
2737 					pmadapter->pscan_table[beacon_idx]
2738 						.ext_pwer_offset;
2739 			if (pnew_beacon->pext_bssload)
2740 				pnew_beacon->ext_bssload_offset =
2741 					pmadapter->pscan_table[beacon_idx]
2742 						.ext_bssload_offset;
2743 			if (pnew_beacon->pquiet_chan)
2744 				pnew_beacon->quiet_chan_offset =
2745 					pmadapter->pscan_table[beacon_idx]
2746 						.quiet_chan_offset;
2747 			if (pnew_beacon->poper_mode)
2748 				pnew_beacon->oper_mode_offset =
2749 					pmadapter->pscan_table[beacon_idx]
2750 						.oper_mode_offset;
2751 			if (pnew_beacon->phe_cap)
2752 				pnew_beacon->he_cap_offset =
2753 					pmadapter->pscan_table[beacon_idx]
2754 						.he_cap_offset;
2755 			if (pnew_beacon->phe_oprat)
2756 				pnew_beacon->he_oprat_offset =
2757 					pmadapter->pscan_table[beacon_idx]
2758 						.he_oprat_offset;
2759 			if (pnew_beacon->prsnx_ie)
2760 				pnew_beacon->rsnx_offset =
2761 					pmadapter->pscan_table[beacon_idx]
2762 						.rsnx_offset;
2763 		}
2764 		/* Point the new entry to its permanent storage space */
2765 		pnew_beacon->pbeacon_buf = pbcn_store;
2766 		wlan_adjust_ie_in_bss_entry(pmpriv, pnew_beacon);
2767 	} else {
2768 		if ((pmadapter->pbcn_buf_end + pnew_beacon->beacon_buf_size +
2769 			     SCAN_BEACON_ENTRY_PAD >
2770 		     (pmadapter->bcn_buf + pmadapter->bcn_buf_size)) &&
2771 		    (pmadapter->bcn_buf_size < MAX_SCAN_BEACON_BUFFER)) {
2772 			/* no space for this entry, realloc bcn buffer */
2773 			if (pmadapter->callbacks.moal_vmalloc &&
2774 			    pmadapter->callbacks.moal_vfree)
2775 				ret = pmadapter->callbacks.moal_vmalloc(
2776 					pmadapter->pmoal_handle,
2777 					pmadapter->bcn_buf_size +
2778 						DEFAULT_SCAN_BEACON_BUFFER,
2779 					(t_u8 **)&tmp_buf);
2780 			else
2781 				ret = pmadapter->callbacks.moal_malloc(
2782 					pmadapter->pmoal_handle,
2783 					pmadapter->bcn_buf_size +
2784 						DEFAULT_SCAN_BEACON_BUFFER,
2785 					MLAN_MEM_DEF, (t_u8 **)&tmp_buf);
2786 
2787 			if ((ret == MLAN_STATUS_SUCCESS) && (tmp_buf)) {
2788 				PRINTM(MCMND,
2789 				       "Realloc Beacon buffer, old size=%d, new_size=%d\n",
2790 				       pmadapter->bcn_buf_size,
2791 				       pmadapter->bcn_buf_size +
2792 					       DEFAULT_SCAN_BEACON_BUFFER);
2793 				bcn_size = pmadapter->pbcn_buf_end -
2794 					   pmadapter->bcn_buf;
2795 				memcpy_ext(pmadapter, tmp_buf,
2796 					   pmadapter->bcn_buf, bcn_size,
2797 					   bcn_size);
2798 				/* Adjust beacon buffer pointers that are past
2799 				 * the current */
2800 				for (adj_idx = 0; adj_idx < num_of_ent;
2801 				     adj_idx++) {
2802 					bcn_offset =
2803 						pmadapter->pscan_table[adj_idx]
2804 							.pbeacon_buf -
2805 						pmadapter->bcn_buf;
2806 					pmadapter->pscan_table[adj_idx]
2807 						.pbeacon_buf =
2808 						tmp_buf + bcn_offset;
2809 					wlan_adjust_ie_in_bss_entry(
2810 						pmpriv,
2811 						&pmadapter->pscan_table[adj_idx]);
2812 				}
2813 				pmadapter->pbcn_buf_end = tmp_buf + bcn_size;
2814 				if (pmadapter->callbacks.moal_vmalloc &&
2815 				    pmadapter->callbacks.moal_vfree)
2816 					pmadapter->callbacks.moal_vfree(
2817 						pmadapter->pmoal_handle,
2818 						(t_u8 *)pmadapter->bcn_buf);
2819 				else
2820 					pmadapter->callbacks.moal_mfree(
2821 						pmadapter->pmoal_handle,
2822 						(t_u8 *)pmadapter->bcn_buf);
2823 				pmadapter->bcn_buf = tmp_buf;
2824 				pmadapter->bcn_buf_size +=
2825 					DEFAULT_SCAN_BEACON_BUFFER;
2826 			}
2827 		}
2828 		/*
2829 		 * No existing beacon data exists for this entry, check to see
2830 		 *   if we can fit it in the remaining space
2831 		 */
2832 		if (pmadapter->pbcn_buf_end + pnew_beacon->beacon_buf_size +
2833 			    SCAN_BEACON_ENTRY_PAD <
2834 		    (pmadapter->bcn_buf + pmadapter->bcn_buf_size)) {
2835 			/*
2836 			 * Copy the beacon buffer data from the local entry
2837 			 * to the adapter dev struct buffer space used to
2838 			 * store the raw beacon data for each entry in the
2839 			 * scan table
2840 			 */
2841 			memcpy_ext(pmadapter, pmadapter->pbcn_buf_end,
2842 				   pnew_beacon->pbeacon_buf,
2843 				   pnew_beacon->beacon_buf_size,
2844 				   pnew_beacon->beacon_buf_size);
2845 
2846 			/*
2847 			 * Update the beacon ptr to point to the table
2848 			 * save area
2849 			 */
2850 			pnew_beacon->pbeacon_buf = pmadapter->pbcn_buf_end;
2851 			pnew_beacon->beacon_buf_size_max =
2852 				(pnew_beacon->beacon_buf_size +
2853 				 SCAN_BEACON_ENTRY_PAD);
2854 			wlan_adjust_ie_in_bss_entry(pmpriv, pnew_beacon);
2855 
2856 			/* Increment the end pointer by the size reserved */
2857 			pmadapter->pbcn_buf_end +=
2858 				pnew_beacon->beacon_buf_size_max;
2859 
2860 			PRINTM(MINFO,
2861 			       "AppControl: Beacon[%02d] sz=%03d,"
2862 			       " used = %04d, left = %04d\n",
2863 			       beacon_idx, pnew_beacon->beacon_buf_size,
2864 			       (pmadapter->pbcn_buf_end - pmadapter->bcn_buf),
2865 			       (pmadapter->bcn_buf_size -
2866 				(pmadapter->pbcn_buf_end - pmadapter->bcn_buf)));
2867 		} else {
2868 			/*
2869 			 * No space for new beacon
2870 			 */
2871 			PRINTM(MCMND,
2872 			       "AppControl: No space beacon (%d): " MACSTR
2873 			       "; sz=%03d, left=%03d\n",
2874 			       beacon_idx, MAC2STR(pnew_beacon->mac_address),
2875 			       pnew_beacon->beacon_buf_size,
2876 			       (pmadapter->bcn_buf_size -
2877 				(pmadapter->pbcn_buf_end - pmadapter->bcn_buf)));
2878 
2879 			/*
2880 			 * Storage failure; clear storage records
2881 			 * for this bcn
2882 			 */
2883 			pnew_beacon->pbeacon_buf = MNULL;
2884 			pnew_beacon->beacon_buf_size = 0;
2885 			pnew_beacon->beacon_buf_size_max = 0;
2886 			wlan_adjust_ie_in_bss_entry(pmpriv, pnew_beacon);
2887 		}
2888 	}
2889 
2890 	LEAVE();
2891 }
2892 
2893 /**
2894  *  @brief update beacon buffer of the current bss descriptor
2895  *
2896  *  @param pmpriv       A pointer to mlan_private structure
2897  *
2898  *  @return             MLAN_STATUS_SUCCESS, otherwise failure
2899  */
wlan_update_curr_bcn(mlan_private * pmpriv)2900 static mlan_status wlan_update_curr_bcn(mlan_private *pmpriv)
2901 {
2902 	BSSDescriptor_t *pcurr_bss = &pmpriv->curr_bss_params.bss_descriptor;
2903 	mlan_status ret = MLAN_STATUS_SUCCESS;
2904 
2905 	ENTER();
2906 
2907 	if (pmpriv->pcurr_bcn_buf && pmpriv->curr_bcn_size) {
2908 		pcurr_bss->pbeacon_buf = pmpriv->pcurr_bcn_buf;
2909 		pcurr_bss->beacon_buf_size = pmpriv->curr_bcn_size;
2910 		pcurr_bss->beacon_buf_size_max = pmpriv->curr_bcn_size;
2911 
2912 		/* adjust the pointers in the current bss descriptor */
2913 		if (pcurr_bss->pwpa_ie) {
2914 			pcurr_bss->pwpa_ie =
2915 				(IEEEtypes_VendorSpecific_t
2916 					 *)(pcurr_bss->pbeacon_buf +
2917 					    pcurr_bss->wpa_offset);
2918 		}
2919 		if (pcurr_bss->prsn_ie) {
2920 			pcurr_bss->prsn_ie =
2921 				(IEEEtypes_Generic_t *)(pcurr_bss->pbeacon_buf +
2922 							pcurr_bss->rsn_offset);
2923 		}
2924 		if (pcurr_bss->pmd_ie) {
2925 			pcurr_bss->pmd_ie = (IEEEtypes_MobilityDomain_t
2926 						     *)(pcurr_bss->pbeacon_buf +
2927 							pcurr_bss->md_offset);
2928 		}
2929 		if (pcurr_bss->pht_cap) {
2930 			pcurr_bss->pht_cap =
2931 				(IEEEtypes_HTCap_t *)(pcurr_bss->pbeacon_buf +
2932 						      pcurr_bss->ht_cap_offset);
2933 		}
2934 
2935 		if (pcurr_bss->pht_info) {
2936 			pcurr_bss->pht_info =
2937 				(IEEEtypes_HTInfo_t
2938 					 *)(pcurr_bss->pbeacon_buf +
2939 					    pcurr_bss->ht_info_offset);
2940 		}
2941 
2942 		if (pcurr_bss->pbss_co_2040) {
2943 			pcurr_bss->pbss_co_2040 =
2944 				(IEEEtypes_2040BSSCo_t
2945 					 *)(pcurr_bss->pbeacon_buf +
2946 					    pcurr_bss->bss_co_2040_offset);
2947 		}
2948 
2949 		if (pcurr_bss->pext_cap) {
2950 			pcurr_bss->pext_cap =
2951 				(IEEEtypes_ExtCap_t
2952 					 *)(pcurr_bss->pbeacon_buf +
2953 					    pcurr_bss->ext_cap_offset);
2954 		}
2955 
2956 		if (pcurr_bss->poverlap_bss_scan_param) {
2957 			pcurr_bss->poverlap_bss_scan_param =
2958 				(IEEEtypes_OverlapBSSScanParam_t
2959 					 *)(pcurr_bss->pbeacon_buf +
2960 					    pcurr_bss->overlap_bss_offset);
2961 		}
2962 
2963 		if (pcurr_bss->pvht_cap) {
2964 			pcurr_bss->pvht_cap =
2965 				(IEEEtypes_VHTCap_t
2966 					 *)(pcurr_bss->pbeacon_buf +
2967 					    pcurr_bss->vht_cap_offset);
2968 		}
2969 
2970 		if (pcurr_bss->pvht_oprat) {
2971 			pcurr_bss->pvht_oprat =
2972 				(IEEEtypes_VHTOprat_t
2973 					 *)(pcurr_bss->pbeacon_buf +
2974 					    pcurr_bss->vht_oprat_offset);
2975 		}
2976 
2977 		if (pcurr_bss->pvht_txpower) {
2978 			pcurr_bss->pvht_txpower =
2979 				(IEEEtypes_VHTtxpower_t
2980 					 *)(pcurr_bss->pbeacon_buf +
2981 					    pcurr_bss->vht_txpower_offset);
2982 		}
2983 
2984 		if (pcurr_bss->pext_pwer) {
2985 			pcurr_bss->pext_pwer =
2986 				(IEEEtypes_ExtPwerCons_t
2987 					 *)(pcurr_bss->pbeacon_buf +
2988 					    pcurr_bss->ext_pwer_offset);
2989 		}
2990 
2991 		if (pcurr_bss->pext_bssload) {
2992 			pcurr_bss->pext_bssload =
2993 				(IEEEtypes_ExtBSSload_t
2994 					 *)(pcurr_bss->pbeacon_buf +
2995 					    pcurr_bss->ext_bssload_offset);
2996 		}
2997 
2998 		if (pcurr_bss->pquiet_chan) {
2999 			pcurr_bss->pquiet_chan =
3000 				(IEEEtypes_QuietChan_t
3001 					 *)(pcurr_bss->pbeacon_buf +
3002 					    pcurr_bss->quiet_chan_offset);
3003 		}
3004 
3005 		if (pcurr_bss->poper_mode) {
3006 			pcurr_bss->poper_mode =
3007 				(IEEEtypes_OperModeNtf_t
3008 					 *)(pcurr_bss->pbeacon_buf +
3009 					    pcurr_bss->oper_mode_offset);
3010 		}
3011 		if (pcurr_bss->phe_cap) {
3012 			pcurr_bss->phe_cap =
3013 				(IEEEtypes_HECap_t *)(pcurr_bss->pbeacon_buf +
3014 						      pcurr_bss->he_cap_offset);
3015 		}
3016 
3017 		if (pcurr_bss->phe_oprat) {
3018 			pcurr_bss->phe_oprat =
3019 				(IEEEtypes_Extension_t
3020 					 *)(pcurr_bss->pbeacon_buf +
3021 					    pcurr_bss->he_oprat_offset);
3022 		}
3023 		if (pcurr_bss->prsnx_ie) {
3024 			pcurr_bss->prsnx_ie =
3025 				(IEEEtypes_Generic_t *)(pcurr_bss->pbeacon_buf +
3026 							pcurr_bss->rsnx_offset);
3027 		}
3028 
3029 		PRINTM(MINFO, "current beacon restored %d\n",
3030 		       pmpriv->curr_bcn_size);
3031 	} else {
3032 		PRINTM(MERROR, "curr_bcn_buf not saved\n");
3033 		ret = MLAN_STATUS_FAILURE;
3034 	}
3035 
3036 	LEAVE();
3037 	return ret;
3038 }
3039 
3040 /**
3041  *  @brief get the chan load from chan stats.
3042  *
3043  *  @param pmadapter    A pointer to mlan_adapter structure
3044  *  @param channel      channel  *
3045  *
3046  *  @return             channel load
3047  */
wlan_get_chan_load(mlan_adapter * pmadapter,t_u8 channel)3048 static t_u16 wlan_get_chan_load(mlan_adapter *pmadapter, t_u8 channel)
3049 {
3050 	t_u16 chan_load = 0;
3051 	int i;
3052 	for (i = 0; i < (int)pmadapter->num_in_chan_stats; i++) {
3053 		if ((pmadapter->pchan_stats[i].chan_num == channel) &&
3054 		    pmadapter->pchan_stats[i].cca_scan_duration) {
3055 			chan_load =
3056 				(pmadapter->pchan_stats[i].cca_busy_duration *
3057 				 100) /
3058 				pmadapter->pchan_stats[i].cca_scan_duration;
3059 			break;
3060 		}
3061 	}
3062 	return chan_load;
3063 }
3064 
3065 /**
3066  *  @brief get the chan min/max rssi
3067  *
3068  *  @param pmadapter    A pointer to mlan_adapter structure
3069  *  @param channel      channel  *
3070  *  @param min_flag     flag to get min rssi
3071  *  @return             rssi
3072  */
wlan_get_chan_rssi(mlan_adapter * pmadapter,t_u8 channel,t_u8 min_flag)3073 static t_u8 wlan_get_chan_rssi(mlan_adapter *pmadapter, t_u8 channel,
3074 			       t_u8 min_flag)
3075 {
3076 	t_u8 rssi = 0;
3077 	int i;
3078 	for (i = 0; i < (int)pmadapter->num_in_scan_table; i++) {
3079 		if (pmadapter->pscan_table[i].channel == channel) {
3080 			if (rssi == 0)
3081 				rssi = (t_s32)pmadapter->pscan_table[i].rssi;
3082 			else {
3083 				if (min_flag)
3084 					rssi = MIN(
3085 						rssi,
3086 						pmadapter->pscan_table[i].rssi);
3087 				else
3088 					rssi = MAX(
3089 						rssi,
3090 						pmadapter->pscan_table[i].rssi);
3091 			}
3092 		}
3093 	}
3094 	return rssi;
3095 }
3096 
3097 /**
3098  *  @brief update the min/max rssi for channel statistics.
3099  *
3100  *  @param pmadapter    A pointer to mlan_adapter structure
3101  *	@return             N/A
3102  */
wlan_update_chan_rssi(mlan_adapter * pmadapter)3103 static t_void wlan_update_chan_rssi(mlan_adapter *pmadapter)
3104 {
3105 	int i;
3106 	t_s8 min_rssi = 0;
3107 	t_s8 max_rssi = 0;
3108 	t_s8 rss = 0;
3109 	for (i = 0; i < (int)pmadapter->num_in_chan_stats; i++) {
3110 		if (pmadapter->pchan_stats[i].chan_num &&
3111 		    pmadapter->pchan_stats[i].cca_scan_duration) {
3112 			min_rssi = -wlan_get_chan_rssi(
3113 				pmadapter, pmadapter->pchan_stats[i].chan_num,
3114 				MFALSE);
3115 			max_rssi = -wlan_get_chan_rssi(
3116 				pmadapter, pmadapter->pchan_stats[i].chan_num,
3117 				MTRUE);
3118 			rss = min_rssi - pmadapter->pchan_stats[i].noise;
3119 			// rss should always > 0, FW need fix the wrong
3120 			// rssi/noise in scantable
3121 			if (rss > 0)
3122 				pmadapter->pchan_stats[i].min_rss = rss;
3123 			else
3124 				pmadapter->pchan_stats[i].min_rss = 0;
3125 
3126 			rss = max_rssi - pmadapter->pchan_stats[i].noise;
3127 			if (rss > 0)
3128 				pmadapter->pchan_stats[i].max_rss = rss;
3129 			else
3130 				pmadapter->pchan_stats[i].max_rss = 0;
3131 			PRINTM(MCMND,
3132 			       "chan=%d, min_rssi=%d, max_rssi=%d noise=%d min_rss=%d, max_rss=%d\n",
3133 			       pmadapter->pchan_stats[i].chan_num, min_rssi,
3134 			       max_rssi, pmadapter->pchan_stats[i].noise,
3135 			       pmadapter->pchan_stats[i].min_rss,
3136 			       pmadapter->pchan_stats[i].max_rss);
3137 		}
3138 	}
3139 	return;
3140 }
3141 
3142 /**
3143  *  @brief Post process the scan table after a new scan command has completed
3144  *
3145  *  Inspect each entry of the scan table and try to find an entry that
3146  *    matches our current associated/joined network from the scan.  If
3147  *    one is found, update the stored copy of the BSSDescriptor for our
3148  *    current network.
3149  *
3150  *  Debug dump the current scan table contents if compiled accordingly.
3151  *
3152  *  @param pmpriv       A pointer to mlan_private structure
3153  *
3154  *  @return             N/A
3155  */
wlan_scan_process_results(mlan_private * pmpriv)3156 static t_void wlan_scan_process_results(mlan_private *pmpriv)
3157 {
3158 	mlan_adapter *pmadapter = pmpriv->adapter;
3159 	t_s32 j;
3160 	t_u32 i;
3161 	mlan_status ret = MLAN_STATUS_SUCCESS;
3162 	BSSDescriptor_t *bss_new_entry = MNULL;
3163 	pmlan_callbacks pcb = &pmadapter->callbacks;
3164 
3165 	ENTER();
3166 
3167 	if (pmpriv->media_connected == MTRUE) {
3168 		j = wlan_find_bssid_in_list(
3169 			pmpriv,
3170 			pmpriv->curr_bss_params.bss_descriptor.mac_address,
3171 			pmpriv->bss_mode);
3172 
3173 		if (j >= 0) {
3174 			memcpy_ext(pmadapter, &pmadapter->pscan_table[j].ssid,
3175 				   &pmpriv->curr_bss_params.bss_descriptor.ssid,
3176 				   sizeof(mlan_802_11_ssid),
3177 				   sizeof(mlan_802_11_ssid));
3178 			pmadapter->callbacks.moal_spin_lock(
3179 				pmadapter->pmoal_handle,
3180 				pmpriv->curr_bcn_buf_lock);
3181 			pmpriv->curr_bss_params.bss_descriptor.pwpa_ie = MNULL;
3182 			pmpriv->curr_bss_params.bss_descriptor.wpa_offset = 0;
3183 			pmpriv->curr_bss_params.bss_descriptor.prsn_ie = MNULL;
3184 			pmpriv->curr_bss_params.bss_descriptor.rsn_offset = 0;
3185 			pmpriv->curr_bss_params.bss_descriptor.pwapi_ie = MNULL;
3186 			pmpriv->curr_bss_params.bss_descriptor.wapi_offset = 0;
3187 
3188 			pmpriv->curr_bss_params.bss_descriptor.posen_ie = MNULL;
3189 			pmpriv->curr_bss_params.bss_descriptor.osen_offset = 0;
3190 			pmpriv->curr_bss_params.bss_descriptor.pmd_ie = MNULL;
3191 			pmpriv->curr_bss_params.bss_descriptor.md_offset = 0;
3192 			pmpriv->curr_bss_params.bss_descriptor.pht_cap = MNULL;
3193 			pmpriv->curr_bss_params.bss_descriptor.ht_cap_offset =
3194 				0;
3195 			pmpriv->curr_bss_params.bss_descriptor.pht_info = MNULL;
3196 			pmpriv->curr_bss_params.bss_descriptor.ht_info_offset =
3197 				0;
3198 			pmpriv->curr_bss_params.bss_descriptor.pbss_co_2040 =
3199 				MNULL;
3200 			pmpriv->curr_bss_params.bss_descriptor
3201 				.bss_co_2040_offset = 0;
3202 			pmpriv->curr_bss_params.bss_descriptor.pext_cap = MNULL;
3203 			pmpriv->curr_bss_params.bss_descriptor.ext_cap_offset =
3204 				0;
3205 			pmpriv->curr_bss_params.bss_descriptor
3206 				.poverlap_bss_scan_param = MNULL;
3207 			pmpriv->curr_bss_params.bss_descriptor
3208 				.overlap_bss_offset = 0;
3209 			pmpriv->curr_bss_params.bss_descriptor.pvht_cap = MNULL;
3210 			pmpriv->curr_bss_params.bss_descriptor.vht_cap_offset =
3211 				0;
3212 			pmpriv->curr_bss_params.bss_descriptor.pvht_oprat =
3213 				MNULL;
3214 			pmpriv->curr_bss_params.bss_descriptor.vht_oprat_offset =
3215 				0;
3216 			pmpriv->curr_bss_params.bss_descriptor.pvht_txpower =
3217 				MNULL;
3218 			pmpriv->curr_bss_params.bss_descriptor
3219 				.vht_txpower_offset = 0;
3220 			pmpriv->curr_bss_params.bss_descriptor.pext_pwer =
3221 				MNULL;
3222 			pmpriv->curr_bss_params.bss_descriptor.ext_pwer_offset =
3223 				0;
3224 			pmpriv->curr_bss_params.bss_descriptor.pext_bssload =
3225 				MNULL;
3226 			pmpriv->curr_bss_params.bss_descriptor
3227 				.ext_bssload_offset = 0;
3228 			pmpriv->curr_bss_params.bss_descriptor.pquiet_chan =
3229 				MNULL;
3230 			pmpriv->curr_bss_params.bss_descriptor
3231 				.quiet_chan_offset = 0;
3232 			pmpriv->curr_bss_params.bss_descriptor.poper_mode =
3233 				MNULL;
3234 			pmpriv->curr_bss_params.bss_descriptor.oper_mode_offset =
3235 				0;
3236 			pmpriv->curr_bss_params.bss_descriptor.phe_cap = MNULL;
3237 			pmpriv->curr_bss_params.bss_descriptor.he_cap_offset =
3238 				0;
3239 			pmpriv->curr_bss_params.bss_descriptor.phe_oprat =
3240 				MNULL;
3241 			pmpriv->curr_bss_params.bss_descriptor.he_oprat_offset =
3242 				0;
3243 			pmpriv->curr_bss_params.bss_descriptor.prsnx_ie = MNULL;
3244 			pmpriv->curr_bss_params.bss_descriptor.rsnx_offset = 0;
3245 			pmpriv->curr_bss_params.bss_descriptor.pbeacon_buf =
3246 				MNULL;
3247 			pmpriv->curr_bss_params.bss_descriptor.beacon_buf_size =
3248 				0;
3249 			pmpriv->curr_bss_params.bss_descriptor
3250 				.beacon_buf_size_max = 0;
3251 
3252 			PRINTM(MINFO,
3253 			       "Found current ssid/bssid in list @ index #%d\n",
3254 			       j);
3255 			/* Make a copy of current BSSID descriptor */
3256 			memcpy_ext(
3257 				pmadapter,
3258 				&pmpriv->curr_bss_params.bss_descriptor,
3259 				&pmadapter->pscan_table[j],
3260 				sizeof(pmpriv->curr_bss_params.bss_descriptor),
3261 				sizeof(pmpriv->curr_bss_params.bss_descriptor));
3262 
3263 			pmadapter->callbacks.moal_spin_unlock(
3264 				pmadapter->pmoal_handle,
3265 				pmpriv->curr_bcn_buf_lock);
3266 			wlan_save_curr_bcn(pmpriv);
3267 		} else {
3268 			// Apend to the end of scan table
3269 			if (pmpriv->pcurr_bcn_buf && pmpriv->curr_bcn_size) {
3270 				ret = pcb->moal_malloc(pmadapter->pmoal_handle,
3271 						       sizeof(BSSDescriptor_t),
3272 						       MLAN_MEM_DEF,
3273 						       (t_u8 **)&bss_new_entry);
3274 				if (ret == MLAN_STATUS_SUCCESS &&
3275 				    bss_new_entry) {
3276 					memcpy_ext(
3277 						pmadapter, bss_new_entry,
3278 						&pmpriv->curr_bss_params
3279 							 .bss_descriptor,
3280 						sizeof(pmpriv->curr_bss_params
3281 							       .bss_descriptor),
3282 						sizeof(BSSDescriptor_t));
3283 					if (pmadapter->num_in_scan_table <
3284 					    MRVDRV_MAX_BSSID_LIST)
3285 						pmadapter->num_in_scan_table++;
3286 					pmadapter
3287 						->pscan_table
3288 							[pmadapter->num_in_scan_table -
3289 							 1]
3290 						.pbeacon_buf = MNULL;
3291 					wlan_ret_802_11_scan_store_beacon(
3292 						pmpriv,
3293 						pmadapter->num_in_scan_table -
3294 							1,
3295 						pmadapter->num_in_scan_table,
3296 						bss_new_entry);
3297 					if (bss_new_entry->pbeacon_buf == MNULL)
3298 						pmadapter->num_in_scan_table--;
3299 					else
3300 						memcpy_ext(
3301 							pmadapter,
3302 							&pmadapter->pscan_table
3303 								 [pmadapter->num_in_scan_table -
3304 								  1],
3305 							bss_new_entry,
3306 							sizeof(BSSDescriptor_t),
3307 							sizeof(BSSDescriptor_t));
3308 					pcb->moal_mfree(pmadapter->pmoal_handle,
3309 							(t_u8 *)bss_new_entry);
3310 				}
3311 			}
3312 		}
3313 	}
3314 
3315 	for (i = 0; i < pmadapter->num_in_scan_table; i++) {
3316 		PRINTM(MINFO,
3317 		       "Scan:(%02d) " MACSTR ", "
3318 		       "RSSI[%03d], SSID[%s]\n",
3319 		       i, MAC2STR(pmadapter->pscan_table[i].mac_address),
3320 		       (t_s32)pmadapter->pscan_table[i].rssi,
3321 		       pmadapter->pscan_table[i].ssid.ssid);
3322 		pmadapter->pscan_table[i].chan_load = wlan_get_chan_load(
3323 			pmadapter, pmadapter->pscan_table[i].channel);
3324 	}
3325 	wlan_update_chan_rssi(pmadapter);
3326 
3327 	/*
3328 	 * Prepares domain info from scan table and downloads the
3329 	 *   domain info command to the FW.
3330 	 */
3331 	wlan_11d_prepare_dnld_domain_info_cmd(pmpriv);
3332 	PRINTM(MMSG, "wlan: SCAN COMPLETED: scanned AP count=%d\n",
3333 	       pmadapter->num_in_scan_table);
3334 	LEAVE();
3335 }
3336 
3337 /**
3338  *  @brief Delete a specific indexed entry from the scan table.
3339  *
3340  *  Delete the scan table entry indexed by table_idx.  Compact the remaining
3341  *    entries and adjust any buffering of beacon/probe response data
3342  *    if needed.
3343  *
3344  *  @param pmpriv       A pointer to mlan_private structure
3345  *  @param table_idx    Scan table entry index to delete from the table
3346  *
3347  *  @return             N/A
3348  *
3349  *  @pre                table_idx must be an index to a valid entry
3350  */
wlan_scan_delete_table_entry(mlan_private * pmpriv,t_s32 table_idx)3351 static t_void wlan_scan_delete_table_entry(mlan_private *pmpriv,
3352 					   t_s32 table_idx)
3353 {
3354 	mlan_adapter *pmadapter = pmpriv->adapter;
3355 	t_u32 del_idx;
3356 	t_u32 beacon_buf_adj;
3357 	t_u8 *pbeacon_buf;
3358 
3359 	ENTER();
3360 
3361 	/*
3362 	 * Shift the saved beacon buffer data for the scan table back over the
3363 	 *   entry being removed.  Update the end of buffer pointer.  Save the
3364 	 *   deleted buffer allocation size for pointer adjustments for entries
3365 	 *   compacted after the deleted index.
3366 	 */
3367 	beacon_buf_adj = pmadapter->pscan_table[table_idx].beacon_buf_size_max;
3368 
3369 	PRINTM(MINFO,
3370 	       "Scan: Delete Entry %d, beacon buffer removal = %d bytes\n",
3371 	       table_idx, beacon_buf_adj);
3372 
3373 	/* Check if the table entry had storage allocated for its beacon */
3374 	if (beacon_buf_adj) {
3375 		pbeacon_buf = pmadapter->pscan_table[table_idx].pbeacon_buf;
3376 
3377 		/*
3378 		 * Remove the entry's buffer space, decrement the table
3379 		 * end pointer by the amount we are removing
3380 		 */
3381 		pmadapter->pbcn_buf_end -= beacon_buf_adj;
3382 
3383 		PRINTM(MINFO,
3384 		       "Scan: Delete Entry %d, compact data: %p <- %p (sz = %d)\n",
3385 		       table_idx, pbeacon_buf, pbeacon_buf + beacon_buf_adj,
3386 		       pmadapter->pbcn_buf_end - pbeacon_buf);
3387 
3388 		/*
3389 		 * Compact data storage.  Copy all data after the deleted
3390 		 * entry's end address (pbeacon_buf + beacon_buf_adj) back to
3391 		 * the original start address (pbeacon_buf).
3392 		 *
3393 		 * Scan table entries affected by the move will have their entry
3394 		 *   pointer adjusted below.
3395 		 *
3396 		 * Use memmove since the dest/src memory regions overlap.
3397 		 */
3398 		memmove(pmadapter, pbeacon_buf,
3399 			(void *)((t_ptr)pbeacon_buf + (t_ptr)beacon_buf_adj),
3400 			(t_u32)((t_ptr)pmadapter->pbcn_buf_end -
3401 				(t_ptr)pbeacon_buf));
3402 	}
3403 
3404 	PRINTM(MINFO, "Scan: Delete Entry %d, num_in_scan_table = %d\n",
3405 	       table_idx, pmadapter->num_in_scan_table);
3406 
3407 	/*
3408 	 * Shift all of the entries after the table_idx back by one, compacting
3409 	 * the table and removing the requested entry
3410 	 */
3411 	for (del_idx = table_idx; (del_idx + 1) < pmadapter->num_in_scan_table;
3412 	     del_idx++) {
3413 		/* Copy the next entry over this one */
3414 		memcpy_ext(pmadapter, pmadapter->pscan_table + del_idx,
3415 			   pmadapter->pscan_table + del_idx + 1,
3416 			   sizeof(BSSDescriptor_t), sizeof(BSSDescriptor_t));
3417 
3418 		/*
3419 		 * Adjust this entry's pointer to its beacon buffer based on the
3420 		 *   removed/compacted entry from the deleted index.  Don't
3421 		 * decrement if the buffer pointer is MNULL (no data stored for
3422 		 * this entry).
3423 		 */
3424 		if (pmadapter->pscan_table[del_idx].pbeacon_buf) {
3425 			pmadapter->pscan_table[del_idx].pbeacon_buf -=
3426 				beacon_buf_adj;
3427 			if (pmadapter->pscan_table[del_idx].pwpa_ie) {
3428 				pmadapter->pscan_table[del_idx].pwpa_ie =
3429 					(IEEEtypes_VendorSpecific_t
3430 						 *)(pmadapter
3431 							    ->pscan_table[del_idx]
3432 							    .pbeacon_buf +
3433 						    pmadapter
3434 							    ->pscan_table[del_idx]
3435 							    .wpa_offset);
3436 			}
3437 			if (pmadapter->pscan_table[del_idx].prsn_ie) {
3438 				pmadapter->pscan_table[del_idx].prsn_ie =
3439 					(IEEEtypes_Generic_t
3440 						 *)(pmadapter
3441 							    ->pscan_table[del_idx]
3442 							    .pbeacon_buf +
3443 						    pmadapter
3444 							    ->pscan_table[del_idx]
3445 							    .rsn_offset);
3446 			}
3447 			if (pmadapter->pscan_table[del_idx].pwapi_ie) {
3448 				pmadapter->pscan_table[del_idx].pwapi_ie =
3449 					(IEEEtypes_Generic_t
3450 						 *)(pmadapter
3451 							    ->pscan_table[del_idx]
3452 							    .pbeacon_buf +
3453 						    pmadapter
3454 							    ->pscan_table[del_idx]
3455 							    .wapi_offset);
3456 			}
3457 
3458 			if (pmadapter->pscan_table[del_idx].posen_ie) {
3459 				pmadapter->pscan_table[del_idx].posen_ie =
3460 					(IEEEtypes_Generic_t
3461 						 *)(pmadapter
3462 							    ->pscan_table[del_idx]
3463 							    .pbeacon_buf +
3464 						    pmadapter
3465 							    ->pscan_table[del_idx]
3466 							    .osen_offset);
3467 			}
3468 			if (pmadapter->pscan_table[del_idx].pmd_ie) {
3469 				pmadapter->pscan_table[del_idx].pmd_ie =
3470 					(IEEEtypes_MobilityDomain_t
3471 						 *)(pmadapter
3472 							    ->pscan_table[del_idx]
3473 							    .pbeacon_buf +
3474 						    pmadapter
3475 							    ->pscan_table[del_idx]
3476 							    .md_offset);
3477 			}
3478 			if (pmadapter->pscan_table[del_idx].pht_cap) {
3479 				pmadapter->pscan_table[del_idx].pht_cap =
3480 					(IEEEtypes_HTCap_t
3481 						 *)(pmadapter
3482 							    ->pscan_table[del_idx]
3483 							    .pbeacon_buf +
3484 						    pmadapter
3485 							    ->pscan_table[del_idx]
3486 							    .ht_cap_offset);
3487 			}
3488 
3489 			if (pmadapter->pscan_table[del_idx].pht_info) {
3490 				pmadapter->pscan_table[del_idx].pht_info =
3491 					(IEEEtypes_HTInfo_t
3492 						 *)(pmadapter
3493 							    ->pscan_table[del_idx]
3494 							    .pbeacon_buf +
3495 						    pmadapter
3496 							    ->pscan_table[del_idx]
3497 							    .ht_info_offset);
3498 			}
3499 			if (pmadapter->pscan_table[del_idx].pbss_co_2040) {
3500 				pmadapter->pscan_table[del_idx].pbss_co_2040 =
3501 					(IEEEtypes_2040BSSCo_t
3502 						 *)(pmadapter
3503 							    ->pscan_table[del_idx]
3504 							    .pbeacon_buf +
3505 						    pmadapter
3506 							    ->pscan_table[del_idx]
3507 							    .bss_co_2040_offset);
3508 			}
3509 			if (pmadapter->pscan_table[del_idx].pext_cap) {
3510 				pmadapter->pscan_table[del_idx].pext_cap =
3511 					(IEEEtypes_ExtCap_t
3512 						 *)(pmadapter
3513 							    ->pscan_table[del_idx]
3514 							    .pbeacon_buf +
3515 						    pmadapter
3516 							    ->pscan_table[del_idx]
3517 							    .ext_cap_offset);
3518 			}
3519 			if (pmadapter->pscan_table[del_idx]
3520 				    .poverlap_bss_scan_param) {
3521 				pmadapter->pscan_table[del_idx]
3522 					.poverlap_bss_scan_param =
3523 					(IEEEtypes_OverlapBSSScanParam_t
3524 						 *)(pmadapter
3525 							    ->pscan_table[del_idx]
3526 							    .pbeacon_buf +
3527 						    pmadapter
3528 							    ->pscan_table[del_idx]
3529 							    .overlap_bss_offset);
3530 			}
3531 
3532 			if (pmadapter->pscan_table[del_idx].pvht_cap) {
3533 				pmadapter->pscan_table[del_idx].pvht_cap =
3534 					(IEEEtypes_VHTCap_t
3535 						 *)(pmadapter
3536 							    ->pscan_table[del_idx]
3537 							    .pbeacon_buf +
3538 						    pmadapter
3539 							    ->pscan_table[del_idx]
3540 							    .vht_cap_offset);
3541 			}
3542 
3543 			if (pmadapter->pscan_table[del_idx].pvht_oprat) {
3544 				pmadapter->pscan_table[del_idx].pvht_oprat =
3545 					(IEEEtypes_VHTOprat_t
3546 						 *)(pmadapter
3547 							    ->pscan_table[del_idx]
3548 							    .pbeacon_buf +
3549 						    pmadapter
3550 							    ->pscan_table[del_idx]
3551 							    .vht_oprat_offset);
3552 			}
3553 			if (pmadapter->pscan_table[del_idx].pvht_txpower) {
3554 				pmadapter->pscan_table[del_idx].pvht_txpower =
3555 					(IEEEtypes_VHTtxpower_t
3556 						 *)(pmadapter
3557 							    ->pscan_table[del_idx]
3558 							    .pbeacon_buf +
3559 						    pmadapter
3560 							    ->pscan_table[del_idx]
3561 							    .vht_txpower_offset);
3562 			}
3563 			if (pmadapter->pscan_table[del_idx].pext_pwer) {
3564 				pmadapter->pscan_table[del_idx].pext_pwer =
3565 					(IEEEtypes_ExtPwerCons_t
3566 						 *)(pmadapter
3567 							    ->pscan_table[del_idx]
3568 							    .pbeacon_buf +
3569 						    pmadapter
3570 							    ->pscan_table[del_idx]
3571 							    .ext_pwer_offset);
3572 			}
3573 			if (pmadapter->pscan_table[del_idx].pext_bssload) {
3574 				pmadapter->pscan_table[del_idx].pext_bssload =
3575 					(IEEEtypes_ExtBSSload_t
3576 						 *)(pmadapter
3577 							    ->pscan_table[del_idx]
3578 							    .pbeacon_buf +
3579 						    pmadapter
3580 							    ->pscan_table[del_idx]
3581 							    .ext_bssload_offset);
3582 			}
3583 			if (pmadapter->pscan_table[del_idx].pquiet_chan) {
3584 				pmadapter->pscan_table[del_idx].pquiet_chan =
3585 					(IEEEtypes_QuietChan_t
3586 						 *)(pmadapter
3587 							    ->pscan_table[del_idx]
3588 							    .pbeacon_buf +
3589 						    pmadapter
3590 							    ->pscan_table[del_idx]
3591 							    .quiet_chan_offset);
3592 			}
3593 			if (pmadapter->pscan_table[del_idx].poper_mode) {
3594 				pmadapter->pscan_table[del_idx].poper_mode =
3595 					(IEEEtypes_OperModeNtf_t
3596 						 *)(pmadapter
3597 							    ->pscan_table[del_idx]
3598 							    .pbeacon_buf +
3599 						    pmadapter
3600 							    ->pscan_table[del_idx]
3601 							    .oper_mode_offset);
3602 			}
3603 			if (pmadapter->pscan_table[del_idx].phe_cap) {
3604 				pmadapter->pscan_table[del_idx].phe_cap =
3605 					(IEEEtypes_HECap_t
3606 						 *)(pmadapter
3607 							    ->pscan_table[del_idx]
3608 							    .pbeacon_buf +
3609 						    pmadapter
3610 							    ->pscan_table[del_idx]
3611 							    .he_cap_offset);
3612 			}
3613 			if (pmadapter->pscan_table[del_idx].phe_oprat) {
3614 				pmadapter->pscan_table[del_idx].phe_oprat =
3615 					(IEEEtypes_Extension_t
3616 						 *)(pmadapter
3617 							    ->pscan_table[del_idx]
3618 							    .pbeacon_buf +
3619 						    pmadapter
3620 							    ->pscan_table[del_idx]
3621 							    .he_oprat_offset);
3622 			}
3623 		}
3624 	}
3625 
3626 	/* The last entry is invalid now that it has been deleted or moved back
3627 	 */
3628 	memset(pmadapter,
3629 	       pmadapter->pscan_table + pmadapter->num_in_scan_table - 1, 0x00,
3630 	       sizeof(BSSDescriptor_t));
3631 
3632 	pmadapter->num_in_scan_table--;
3633 
3634 	LEAVE();
3635 }
3636 
3637 /**
3638  *  @brief Delete all entry's age out
3639  *
3640  *  @param pmpriv       A pointer to mlan_private structure
3641  *
3642  *  @return             N/A
3643  */
wlan_scan_delete_ageout_entry(mlan_private * pmpriv)3644 static void wlan_scan_delete_ageout_entry(mlan_private *pmpriv)
3645 {
3646 	BSSDescriptor_t *pbss_entry;
3647 	mlan_adapter *pmadapter = pmpriv->adapter;
3648 	t_s32 table_idx = pmadapter->num_in_scan_table - 1;
3649 	t_u32 i = 0;
3650 	t_u32 age_in_secs = 0;
3651 	t_u32 age_ts_usec = 0;
3652 
3653 	ENTER();
3654 #define SCAN_RESULT_AGEOUT 10
3655 	pmadapter->callbacks.moal_get_system_time(pmadapter->pmoal_handle,
3656 						  &age_in_secs, &age_ts_usec);
3657 
3658 	for (i = 0; i < pmadapter->num_in_scan_table; i++) {
3659 		pbss_entry = &pmadapter->pscan_table[table_idx];
3660 		if (age_in_secs >
3661 		    (pbss_entry->age_in_secs + SCAN_RESULT_AGEOUT)) {
3662 			PRINTM(MCMND,
3663 			       "SCAN: ageout AP MAC Addr-" MACSTR
3664 			       " ssid: %-32s\n",
3665 			       MAC2STR(pbss_entry->mac_address),
3666 			       pbss_entry->ssid.ssid);
3667 			wlan_scan_delete_table_entry(pmpriv, table_idx);
3668 		}
3669 		table_idx--;
3670 	}
3671 	LEAVE();
3672 	return;
3673 }
3674 
3675 /**
3676  *  @brief Delete all occurrences of a given SSID from the scan table
3677  *
3678  *  Iterate through the scan table and delete all entries that match a given
3679  *    SSID.  Compact the remaining scan table entries.
3680  *
3681  *  @param pmpriv       A pointer to mlan_private structure
3682  *  @param pdel_ssid    Pointer to an SSID to be used in deleting all
3683  *                        matching SSIDs from the scan table
3684  *
3685  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
3686  */
3687 static mlan_status
wlan_scan_delete_ssid_table_entry(mlan_private * pmpriv,mlan_802_11_ssid * pdel_ssid)3688 wlan_scan_delete_ssid_table_entry(mlan_private *pmpriv,
3689 				  mlan_802_11_ssid *pdel_ssid)
3690 {
3691 	mlan_status ret = MLAN_STATUS_FAILURE;
3692 	t_s32 table_idx;
3693 
3694 	ENTER();
3695 
3696 	PRINTM(MINFO, "Scan: Delete Ssid Entry: %-32s\n", pdel_ssid->ssid);
3697 
3698 	/*
3699 	 * If the requested SSID is found in the table, delete it.  Then keep
3700 	 * searching the table for multiple entries for the SSID until no
3701 	 * more are found
3702 	 */
3703 	while ((table_idx = wlan_find_ssid_in_list(pmpriv, pdel_ssid, MNULL,
3704 						   MLAN_BSS_MODE_AUTO)) >= 0) {
3705 		PRINTM(MINFO, "Scan: Delete SSID Entry: Found Idx = %d\n",
3706 		       table_idx);
3707 		ret = MLAN_STATUS_SUCCESS;
3708 		wlan_scan_delete_table_entry(pmpriv, table_idx);
3709 	}
3710 
3711 	LEAVE();
3712 	return ret;
3713 }
3714 
3715 /********************************************************
3716 			Global Functions
3717 ********************************************************/
3718 
3719 /**
3720  *  @brief Check if a scanned network compatible with the driver settings
3721  *
3722  *   WEP     WPA     WPA2    ad-hoc  encrypt                      Network
3723  * enabled enabled  enabled   AES     mode   Privacy  WPA  WPA2  Compatible
3724  *    0       0        0       0      NONE      0      0    0   yes No security
3725  *    0       1        0       0       x        1x     1    x   yes WPA (disable
3726  * HT if no AES) 0       0        1       0       x        1x     x    1   yes
3727  * WPA2 (disable HT if no AES) 0       0        0       1      NONE      1 0 0
3728  * yes Ad-hoc AES 1       0        0       0      NONE      1      0    0   yes
3729  * Static WEP (disable HT) 0       0        0       0     !=NONE     1      0 0
3730  * yes Dynamic WEP
3731  *
3732  *  @param pmpriv  A pointer to mlan_private
3733  *  @param index   Index in scan table to check against current driver settings
3734  *  @param mode    Network mode: Infrastructure or IBSS
3735  *
3736  *  @return        Index in ScanTable, or negative value if error
3737  */
wlan_is_network_compatible(mlan_private * pmpriv,t_u32 index,t_u32 mode)3738 t_s32 wlan_is_network_compatible(mlan_private *pmpriv, t_u32 index, t_u32 mode)
3739 {
3740 	mlan_adapter *pmadapter = pmpriv->adapter;
3741 	BSSDescriptor_t *pbss_desc;
3742 
3743 	ENTER();
3744 
3745 	pbss_desc = &pmadapter->pscan_table[index];
3746 	/* Don't check for compatibility if roaming */
3747 	if ((pmpriv->media_connected == MTRUE) &&
3748 	    (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) &&
3749 	    (pbss_desc->bss_mode == MLAN_BSS_MODE_INFRA)) {
3750 		LEAVE();
3751 		return index;
3752 	}
3753 
3754 	pbss_desc->disable_11n = MFALSE;
3755 
3756 	/* if the HE CAP IE exists, HT CAP IE should exist too */
3757 	/* 2.4G AX AP, don't have VHT CAP */
3758 	if (pbss_desc->phe_cap && !pbss_desc->pht_cap) {
3759 		PRINTM(MINFO,
3760 		       "Disable 11n if VHT CAP/HT CAP IE is not found from the 11AX AP\n");
3761 		pbss_desc->disable_11n = MTRUE;
3762 	}
3763 
3764 	/* if the VHT CAP IE exists, the HT CAP IE should exist too */
3765 	if (pbss_desc->pvht_cap && !pbss_desc->pht_cap) {
3766 		PRINTM(MINFO,
3767 		       "Disable 11n if HT CAP IE is not found from the 11AC AP\n");
3768 		pbss_desc->disable_11n = MTRUE;
3769 	}
3770 
3771 	if (pbss_desc->wlan_11h_bss_info.chan_switch_ann.element_id ==
3772 	    CHANNEL_SWITCH_ANN) {
3773 		PRINTM(MINFO,
3774 		       "Don't connect to AP with CHANNEL_SWITCH_ANN IE.\n");
3775 		LEAVE();
3776 		return -1;
3777 	}
3778 
3779 	if (pmpriv->wps.session_enable == MTRUE) {
3780 		PRINTM(MINFO, "Return success directly in WPS period\n");
3781 		LEAVE();
3782 		return index;
3783 	}
3784 
3785 	if (pmpriv->sec_info.osen_enabled && pbss_desc->posen_ie &&
3786 	    ((*(pbss_desc->posen_ie)).ieee_hdr.element_id ==
3787 	     VENDOR_SPECIFIC_221)) {
3788 		/* Hotspot 2.0 OSEN AKM */
3789 		PRINTM(MMSG,
3790 		       "Return success directly in Hotspot OSEN: index=%d "
3791 		       "encryption_mode=%#x\n",
3792 		       index, pmpriv->sec_info.encryption_mode);
3793 		LEAVE();
3794 		return index;
3795 	}
3796 
3797 	if ((pbss_desc->bss_mode == mode) &&
3798 	    (pmpriv->sec_info.ewpa_enabled == MTRUE
3799 #ifdef DRV_EMBEDDED_SUPPLICANT
3800 	     || supplicantIsEnabled(pmpriv->psapriv)
3801 #endif
3802 		     )) {
3803 		if (((pbss_desc->pwpa_ie) &&
3804 		     ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id == WPA_IE)) ||
3805 		    ((pbss_desc->prsn_ie) &&
3806 		     ((*(pbss_desc->prsn_ie)).ieee_hdr.element_id == RSN_IE))) {
3807 			if (((pmpriv->adapter->config_bands & BAND_GN ||
3808 			      pmpriv->adapter->config_bands & BAND_AN) &&
3809 			     pbss_desc->pht_cap) &&
3810 			    (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) &&
3811 			    !is_wpa_oui_present(pmpriv->adapter, pbss_desc,
3812 						CIPHER_SUITE_CCMP) &&
3813 			    !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
3814 						CIPHER_SUITE_CCMP) &&
3815 			    !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
3816 						CIPHER_SUITE_GCMP) &&
3817 			    !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
3818 						CIPHER_SUITE_GCMP_256) &&
3819 			    !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
3820 						CIPHER_SUITE_CCMP_256)) {
3821 				if (is_wpa_oui_present(pmpriv->adapter,
3822 						       pbss_desc,
3823 						       CIPHER_SUITE_TKIP) ||
3824 				    is_rsn_oui_present(pmpriv->adapter,
3825 						       pbss_desc,
3826 						       CIPHER_SUITE_TKIP)) {
3827 					PRINTM(MINFO,
3828 					       "Disable 11n if AES is not supported by AP\n");
3829 					pbss_desc->disable_11n = MTRUE;
3830 				} else {
3831 					LEAVE();
3832 					return -1;
3833 				}
3834 			}
3835 			LEAVE();
3836 			return index;
3837 		} else {
3838 			PRINTM(MINFO,
3839 			       "ewpa_enabled: Ignore none WPA/WPA2 AP\n");
3840 			LEAVE();
3841 			return -1;
3842 		}
3843 	}
3844 
3845 	if (pmpriv->sec_info.wapi_enabled &&
3846 	    (pbss_desc->pwapi_ie &&
3847 	     ((*(pbss_desc->pwapi_ie)).ieee_hdr.element_id == WAPI_IE))) {
3848 		PRINTM(MINFO, "Return success for WAPI AP\n");
3849 		LEAVE();
3850 		return index;
3851 	}
3852 
3853 	if (pbss_desc->bss_mode == mode) {
3854 		if (pmpriv->sec_info.wep_status == Wlan802_11WEPDisabled &&
3855 		    !pmpriv->sec_info.wpa_enabled &&
3856 		    !pmpriv->sec_info.wpa2_enabled &&
3857 		    ((!pbss_desc->pwpa_ie) ||
3858 		     ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id != WPA_IE)) &&
3859 		    ((!pbss_desc->prsn_ie) ||
3860 		     ((*(pbss_desc->prsn_ie)).ieee_hdr.element_id != RSN_IE)) &&
3861 		    pmpriv->sec_info.encryption_mode ==
3862 			    MLAN_ENCRYPTION_MODE_NONE &&
3863 		    !pbss_desc->privacy) {
3864 			/* No security */
3865 			LEAVE();
3866 			return index;
3867 		} else if (pmpriv->sec_info.wep_status ==
3868 				   Wlan802_11WEPEnabled &&
3869 			   !pmpriv->sec_info.wpa_enabled &&
3870 			   !pmpriv->sec_info.wpa2_enabled &&
3871 			   pbss_desc->privacy) {
3872 			/* Static WEP enabled */
3873 			PRINTM(MINFO, "Disable 11n in WEP mode\n");
3874 			pbss_desc->disable_11n = MTRUE;
3875 			/* Reject the following cases: */
3876 			/*
3877 			 * case 1: RSN IE w/o WEP OUI and WPA IE w/o WEP OUI
3878 			 * case 2: RSN IE w/o WEP OUI and No WPA IE
3879 			 * case 3: WPA IE w/o WEP OUI and No RSN IE
3880 			 */
3881 			if (((pbss_desc->prsn_ie) &&
3882 			     ((*(pbss_desc->prsn_ie)).ieee_hdr.element_id ==
3883 			      RSN_IE)) ||
3884 			    ((pbss_desc->pwpa_ie) &&
3885 			     ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id ==
3886 			      WPA_IE))) {
3887 				if (!is_rsn_oui_present(pmpriv->adapter,
3888 							pbss_desc,
3889 							CIPHER_SUITE_WEP40) &&
3890 				    !is_rsn_oui_present(pmpriv->adapter,
3891 							pbss_desc,
3892 							CIPHER_SUITE_WEP104) &&
3893 				    !is_wpa_oui_present(pmpriv->adapter,
3894 							pbss_desc,
3895 							CIPHER_SUITE_WEP40) &&
3896 				    !is_wpa_oui_present(pmpriv->adapter,
3897 							pbss_desc,
3898 							CIPHER_SUITE_WEP104))
3899 					index = -1;
3900 			}
3901 
3902 			LEAVE();
3903 			return index;
3904 		} else if (pmpriv->sec_info.wep_status ==
3905 				   Wlan802_11WEPDisabled &&
3906 			   pmpriv->sec_info.wpa_enabled &&
3907 			   !pmpriv->sec_info.wpa2_enabled &&
3908 			   ((pbss_desc->pwpa_ie) &&
3909 			    ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id ==
3910 			     WPA_IE))
3911 			   /*
3912 			    * Privacy bit may NOT be set in some APs like
3913 			    * LinkSys WRT54G && pbss_desc->privacy
3914 			    */
3915 		) {
3916 			PRINTM(MINFO,
3917 			       "wlan_is_network_compatible() WPA: index=%d wpa_ie=%#x "
3918 			       "rsn_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode=%#x "
3919 			       "privacy=%#x\n",
3920 			       index,
3921 			       (pbss_desc->pwpa_ie) ?
3922 				       (*(pbss_desc->pwpa_ie))
3923 					       .vend_hdr.element_id :
3924 				       0,
3925 			       (pbss_desc->prsn_ie) ?
3926 				       (*(pbss_desc->prsn_ie))
3927 					       .ieee_hdr.element_id :
3928 				       0,
3929 			       (pmpriv->sec_info.wep_status ==
3930 				Wlan802_11WEPEnabled) ?
3931 				       "e" :
3932 				       "d",
3933 			       (pmpriv->sec_info.wpa_enabled) ? "e" : "d",
3934 			       (pmpriv->sec_info.wpa2_enabled) ? "e" : "d",
3935 			       pmpriv->sec_info.encryption_mode,
3936 			       pbss_desc->privacy);
3937 			if (((pmpriv->adapter->config_bands & BAND_GN ||
3938 			      pmpriv->adapter->config_bands & BAND_AN) &&
3939 			     pbss_desc->pht_cap) &&
3940 			    (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) &&
3941 			    !is_wpa_oui_present(pmpriv->adapter, pbss_desc,
3942 						CIPHER_SUITE_CCMP)) {
3943 				if (is_wpa_oui_present(pmpriv->adapter,
3944 						       pbss_desc,
3945 						       CIPHER_SUITE_TKIP)) {
3946 					PRINTM(MINFO,
3947 					       "Disable 11n if AES is not supported by AP\n");
3948 					pbss_desc->disable_11n = MTRUE;
3949 				} else {
3950 					LEAVE();
3951 					return -1;
3952 				}
3953 			}
3954 			LEAVE();
3955 			return index;
3956 		} else if (pmpriv->sec_info.wep_status ==
3957 				   Wlan802_11WEPDisabled &&
3958 			   !pmpriv->sec_info.wpa_enabled &&
3959 			   pmpriv->sec_info.wpa2_enabled &&
3960 			   ((pbss_desc->prsn_ie) &&
3961 			    ((*(pbss_desc->prsn_ie)).ieee_hdr.element_id ==
3962 			     RSN_IE))
3963 			   /*
3964 			    * Privacy bit may NOT be set in some APs like
3965 			    * LinkSys WRT54G && pbss_desc->privacy
3966 			    */
3967 		) {
3968 			/* WPA2 enabled */
3969 			PRINTM(MINFO,
3970 			       "wlan_is_network_compatible() WPA2: index=%d wpa_ie=%#x "
3971 			       "rsn_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode=%#x "
3972 			       "privacy=%#x\n",
3973 			       index,
3974 			       (pbss_desc->pwpa_ie) ?
3975 				       (*(pbss_desc->pwpa_ie))
3976 					       .vend_hdr.element_id :
3977 				       0,
3978 			       (pbss_desc->prsn_ie) ?
3979 				       (*(pbss_desc->prsn_ie))
3980 					       .ieee_hdr.element_id :
3981 				       0,
3982 			       (pmpriv->sec_info.wep_status ==
3983 				Wlan802_11WEPEnabled) ?
3984 				       "e" :
3985 				       "d",
3986 			       (pmpriv->sec_info.wpa_enabled) ? "e" : "d",
3987 			       (pmpriv->sec_info.wpa2_enabled) ? "e" : "d",
3988 			       pmpriv->sec_info.encryption_mode,
3989 			       pbss_desc->privacy);
3990 			if (((pmpriv->adapter->config_bands & BAND_GN ||
3991 			      pmpriv->adapter->config_bands & BAND_AN) &&
3992 			     pbss_desc->pht_cap) &&
3993 			    (pmpriv->bss_mode == MLAN_BSS_MODE_INFRA) &&
3994 			    !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
3995 						CIPHER_SUITE_CCMP) &&
3996 			    !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
3997 						CIPHER_SUITE_GCMP) &&
3998 			    !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
3999 						CIPHER_SUITE_GCMP_256) &&
4000 			    !is_rsn_oui_present(pmpriv->adapter, pbss_desc,
4001 						CIPHER_SUITE_CCMP_256)) {
4002 				if (is_rsn_oui_present(pmpriv->adapter,
4003 						       pbss_desc,
4004 						       CIPHER_SUITE_TKIP)) {
4005 					PRINTM(MINFO,
4006 					       "Disable 11n if AES is not supported by AP\n");
4007 					pbss_desc->disable_11n = MTRUE;
4008 				} else if (is_rsn_oui_present_in_wpa_ie(
4009 						   pmpriv, CIPHER_SUITE_CCMP) ||
4010 					   is_rsn_oui_present_in_wpa_ie(
4011 						   pmpriv, CIPHER_SUITE_GCMP) ||
4012 					   is_rsn_oui_present_in_wpa_ie(
4013 						   pmpriv,
4014 						   CIPHER_SUITE_GCMP_256) ||
4015 					   is_rsn_oui_present_in_wpa_ie(
4016 						   pmpriv,
4017 						   CIPHER_SUITE_CCMP_256)) {
4018 					LEAVE();
4019 					return index;
4020 				} else {
4021 					LEAVE();
4022 					return -1;
4023 				}
4024 			}
4025 			LEAVE();
4026 			return index;
4027 		} else if (pmpriv->sec_info.wep_status ==
4028 				   Wlan802_11WEPDisabled &&
4029 			   !pmpriv->sec_info.wpa_enabled &&
4030 			   !pmpriv->sec_info.wpa2_enabled &&
4031 			   ((!pbss_desc->pwpa_ie) ||
4032 			    ((*(pbss_desc->pwpa_ie)).vend_hdr.element_id !=
4033 			     WPA_IE)) &&
4034 			   ((!pbss_desc->prsn_ie) ||
4035 			    ((*(pbss_desc->prsn_ie)).ieee_hdr.element_id !=
4036 			     RSN_IE)) &&
4037 			   pmpriv->sec_info.encryption_mode !=
4038 				   MLAN_ENCRYPTION_MODE_NONE &&
4039 			   pbss_desc->privacy) {
4040 			/* Dynamic WEP enabled */
4041 			pbss_desc->disable_11n = MTRUE;
4042 			PRINTM(MINFO,
4043 			       "wlan_is_network_compatible() dynamic WEP: index=%d "
4044 			       "wpa_ie=%#x rsn_ie=%#x EncMode=%#x privacy=%#x\n",
4045 			       index,
4046 			       (pbss_desc->pwpa_ie) ?
4047 				       (*(pbss_desc->pwpa_ie))
4048 					       .vend_hdr.element_id :
4049 				       0,
4050 			       (pbss_desc->prsn_ie) ?
4051 				       (*(pbss_desc->prsn_ie))
4052 					       .ieee_hdr.element_id :
4053 				       0,
4054 			       pmpriv->sec_info.encryption_mode,
4055 			       pbss_desc->privacy);
4056 			LEAVE();
4057 			return index;
4058 		}
4059 		/* Security doesn't match */
4060 		PRINTM(MINFO,
4061 		       "wlan_is_network_compatible() FAILED: index=%d wpa_ie=%#x "
4062 		       "rsn_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode=%#x privacy=%#x\n",
4063 		       index,
4064 		       (pbss_desc->pwpa_ie) ?
4065 			       (*(pbss_desc->pwpa_ie)).vend_hdr.element_id :
4066 			       0,
4067 		       (pbss_desc->prsn_ie) ?
4068 			       (*(pbss_desc->prsn_ie)).ieee_hdr.element_id :
4069 			       0,
4070 		       (pmpriv->sec_info.wep_status == Wlan802_11WEPEnabled) ?
4071 			       "e" :
4072 			       "d",
4073 		       (pmpriv->sec_info.wpa_enabled) ? "e" : "d",
4074 		       (pmpriv->sec_info.wpa2_enabled) ? "e" : "d",
4075 		       pmpriv->sec_info.encryption_mode, pbss_desc->privacy);
4076 		LEAVE();
4077 		return -1;
4078 	}
4079 	/* Mode doesn't match */
4080 	LEAVE();
4081 	return -1;
4082 }
4083 
4084 /**
4085  *  @brief Internal function used to flush the scan list
4086  *
4087  *  @param pmadapter    A pointer to mlan_adapter structure
4088  *
4089  *  @return             MLAN_STATUS_SUCCESS
4090  */
wlan_flush_scan_table(pmlan_adapter pmadapter)4091 mlan_status wlan_flush_scan_table(pmlan_adapter pmadapter)
4092 {
4093 	t_u8 i = 0;
4094 	ENTER();
4095 
4096 	PRINTM(MINFO, "Flushing scan table\n");
4097 
4098 	memset(pmadapter, pmadapter->pscan_table, 0,
4099 	       (sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST));
4100 	pmadapter->num_in_scan_table = 0;
4101 
4102 	memset(pmadapter, pmadapter->bcn_buf, 0, pmadapter->bcn_buf_size);
4103 	pmadapter->pbcn_buf_end = pmadapter->bcn_buf;
4104 
4105 	for (i = 0; i < pmadapter->num_in_chan_stats; i++)
4106 		pmadapter->pchan_stats[i].cca_scan_duration = 0;
4107 	pmadapter->idx_chan_stats = 0;
4108 
4109 	LEAVE();
4110 	return MLAN_STATUS_SUCCESS;
4111 }
4112 
4113 /**
4114  *  @brief Internal function used to start a scan based on an input config
4115  *
4116  *  Use the input user scan configuration information when provided in
4117  *    order to send the appropriate scan commands to firmware to populate or
4118  *    update the internal driver scan table
4119  *
4120  *  @param pmpriv          A pointer to mlan_private structure
4121  *  @param pioctl_buf      A pointer to MLAN IOCTL Request buffer
4122  *  @param puser_scan_in   Pointer to the input configuration for the requested
4123  *                         scan.
4124  *
4125  *  @return              MLAN_STATUS_SUCCESS or < 0 if error
4126  */
wlan_scan_networks(mlan_private * pmpriv,t_void * pioctl_buf,wlan_user_scan_cfg * puser_scan_in)4127 mlan_status wlan_scan_networks(mlan_private *pmpriv, t_void *pioctl_buf,
4128 			       wlan_user_scan_cfg *puser_scan_in)
4129 {
4130 	mlan_status ret = MLAN_STATUS_SUCCESS;
4131 	mlan_adapter *pmadapter = pmpriv->adapter;
4132 	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
4133 	cmd_ctrl_node *pcmd_node = MNULL;
4134 	pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
4135 
4136 	wlan_scan_cmd_config_tlv *pscan_cfg_out = MNULL;
4137 	MrvlIEtypes_ChanListParamSet_t *pchan_list_out;
4138 	t_u32 buf_size;
4139 	ChanScanParamSet_t *pscan_chan_list;
4140 
4141 	t_u8 keep_previous_scan;
4142 	t_u8 filtered_scan;
4143 	t_u8 scan_current_chan_only;
4144 	t_u8 max_chan_per_scan;
4145 	t_u8 i;
4146 
4147 	ENTER();
4148 
4149 	ret = pcb->moal_malloc(pmadapter->pmoal_handle,
4150 			       sizeof(wlan_scan_cmd_config_tlv),
4151 			       MLAN_MEM_DEF | MLAN_MEM_FLAG_ATOMIC,
4152 			       (t_u8 **)&pscan_cfg_out);
4153 	if (ret != MLAN_STATUS_SUCCESS || !pscan_cfg_out) {
4154 		PRINTM(MERROR, "Memory allocation for pscan_cfg_out failed!\n");
4155 		if (pioctl_req)
4156 			pioctl_req->status_code = MLAN_ERROR_NO_MEM;
4157 		LEAVE();
4158 		return MLAN_STATUS_FAILURE;
4159 	}
4160 
4161 	buf_size = sizeof(ChanScanParamSet_t) * WLAN_USER_SCAN_CHAN_MAX;
4162 	ret = pcb->moal_malloc(pmadapter->pmoal_handle, buf_size,
4163 			       MLAN_MEM_DEF | MLAN_MEM_FLAG_ATOMIC,
4164 			       (t_u8 **)&pscan_chan_list);
4165 	if (ret != MLAN_STATUS_SUCCESS || !pscan_chan_list) {
4166 		PRINTM(MERROR, "Failed to allocate scan_chan_list\n");
4167 		if (pscan_cfg_out)
4168 			pcb->moal_mfree(pmadapter->pmoal_handle,
4169 					(t_u8 *)pscan_cfg_out);
4170 		if (pioctl_req)
4171 			pioctl_req->status_code = MLAN_ERROR_NO_MEM;
4172 		LEAVE();
4173 		return MLAN_STATUS_FAILURE;
4174 	}
4175 
4176 	memset(pmadapter, pscan_chan_list, 0x00, buf_size);
4177 	memset(pmadapter, pscan_cfg_out, 0x00,
4178 	       sizeof(wlan_scan_cmd_config_tlv));
4179 
4180 	keep_previous_scan = MFALSE;
4181 
4182 	ret = wlan_scan_setup_scan_config(pmpriv, puser_scan_in,
4183 					  &pscan_cfg_out->config,
4184 					  &pchan_list_out, pscan_chan_list,
4185 					  &max_chan_per_scan, &filtered_scan,
4186 					  &scan_current_chan_only);
4187 	if (ret != MLAN_STATUS_SUCCESS) {
4188 		PRINTM(MERROR, "Failed to setup scan config\n");
4189 		if (pscan_cfg_out)
4190 			pcb->moal_mfree(pmadapter->pmoal_handle,
4191 					(t_u8 *)pscan_cfg_out);
4192 		if (pscan_chan_list)
4193 			pcb->moal_mfree(pmadapter->pmoal_handle,
4194 					(t_u8 *)pscan_chan_list);
4195 		if (pioctl_req)
4196 			pioctl_req->status_code = MLAN_ERROR_INVALID_PARAMETER;
4197 		LEAVE();
4198 		return MLAN_STATUS_FAILURE;
4199 	}
4200 
4201 	if (puser_scan_in)
4202 		keep_previous_scan = puser_scan_in->keep_previous_scan;
4203 
4204 	if (keep_previous_scan == MFALSE) {
4205 		memset(pmadapter, pmadapter->pscan_table, 0x00,
4206 		       sizeof(BSSDescriptor_t) * MRVDRV_MAX_BSSID_LIST);
4207 		pmadapter->num_in_scan_table = 0;
4208 		pmadapter->pbcn_buf_end = pmadapter->bcn_buf;
4209 	} else {
4210 		wlan_scan_delete_ageout_entry(pmpriv);
4211 	}
4212 	for (i = 0; i < pmadapter->num_in_chan_stats; i++)
4213 		pmadapter->pchan_stats[i].cca_scan_duration = 0;
4214 	pmadapter->idx_chan_stats = 0;
4215 
4216 	ret = wlan_scan_channel_list(pmpriv, pioctl_buf, max_chan_per_scan,
4217 				     filtered_scan, &pscan_cfg_out->config,
4218 				     pchan_list_out, pscan_chan_list);
4219 
4220 	/* Get scan command from scan_pending_q and put to cmd_pending_q */
4221 	if (ret == MLAN_STATUS_SUCCESS) {
4222 		wlan_request_cmd_lock(pmadapter);
4223 		if (util_peek_list(pmadapter->pmoal_handle,
4224 				   &pmadapter->scan_pending_q, MNULL, MNULL)) {
4225 			pcmd_node = (cmd_ctrl_node *)util_dequeue_list(
4226 				pmadapter->pmoal_handle,
4227 				&pmadapter->scan_pending_q, MNULL, MNULL);
4228 			pmadapter->pscan_ioctl_req = pioctl_req;
4229 			pmadapter->scan_processing = MTRUE;
4230 			pmadapter->scan_state = SCAN_STATE_SCAN_START;
4231 			wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node,
4232 						     MTRUE);
4233 		}
4234 		wlan_release_cmd_lock(pmadapter);
4235 	}
4236 	if (pscan_cfg_out)
4237 		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)pscan_cfg_out);
4238 
4239 	if (pscan_chan_list)
4240 		pcb->moal_mfree(pmadapter->pmoal_handle,
4241 				(t_u8 *)pscan_chan_list);
4242 
4243 	LEAVE();
4244 	return ret;
4245 }
4246 
4247 /**
4248  *  @brief Prepare a scan command to be sent to the firmware
4249  *
4250  *  Use the wlan_scan_cmd_config sent to the command processing module in
4251  *   the wlan_prepare_cmd to configure a HostCmd_DS_802_11_SCAN command
4252  *   struct to send to firmware.
4253  *
4254  *  The fixed fields specifying the BSS type and BSSID filters as well as a
4255  *   variable number/length of TLVs are sent in the command to firmware.
4256  *
4257  *  @param pmpriv     A pointer to mlan_private structure
4258  *  @param pcmd       A pointer to HostCmd_DS_COMMAND structure to be sent to
4259  *                    firmware with the HostCmd_DS_801_11_SCAN structure
4260  *  @param pdata_buf  Void pointer cast of a wlan_scan_cmd_config struct used
4261  *                    to set the fields/TLVs for the command sent to firmware
4262  *
4263  *  @return           MLAN_STATUS_SUCCESS
4264  */
wlan_cmd_802_11_scan(mlan_private * pmpriv,HostCmd_DS_COMMAND * pcmd,t_void * pdata_buf)4265 mlan_status wlan_cmd_802_11_scan(mlan_private *pmpriv, HostCmd_DS_COMMAND *pcmd,
4266 				 t_void *pdata_buf)
4267 {
4268 	HostCmd_DS_802_11_SCAN *pscan_cmd = &pcmd->params.scan;
4269 	wlan_scan_cmd_config *pscan_cfg;
4270 
4271 	ENTER();
4272 
4273 	pscan_cfg = (wlan_scan_cmd_config *)pdata_buf;
4274 
4275 	/* Set fixed field variables in scan command */
4276 	pscan_cmd->bss_mode = pscan_cfg->bss_mode;
4277 	memcpy_ext(pmpriv->adapter, pscan_cmd->bssid, pscan_cfg->specific_bssid,
4278 		   sizeof(pscan_cmd->bssid), sizeof(pscan_cmd->bssid));
4279 	memcpy_ext(pmpriv->adapter, pscan_cmd->tlv_buffer, pscan_cfg->tlv_buf,
4280 		   pscan_cfg->tlv_buf_len, pscan_cfg->tlv_buf_len);
4281 
4282 	pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SCAN);
4283 
4284 	/* Size is equal to the sizeof(fixed portions) + the TLV len + header */
4285 	pcmd->size = (t_u16)wlan_cpu_to_le16(
4286 		(t_u16)(sizeof(pscan_cmd->bss_mode) + sizeof(pscan_cmd->bssid) +
4287 			pscan_cfg->tlv_buf_len + S_DS_GEN));
4288 
4289 	LEAVE();
4290 	return MLAN_STATUS_SUCCESS;
4291 }
4292 
4293 /**
4294  *  @brief  Check if any hidden SSID found in passive scan channels
4295  *          and do specific SSID active scan for those channels
4296  *
4297  *  @param pmpriv       A pointer to mlan_private structure
4298  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
4299  *
4300  *  @return             MTRUE/MFALSE
4301  */
4302 
wlan_active_scan_req_for_passive_chan(mlan_private * pmpriv,mlan_ioctl_req * pioctl_buf)4303 static t_bool wlan_active_scan_req_for_passive_chan(mlan_private *pmpriv,
4304 						    mlan_ioctl_req *pioctl_buf)
4305 {
4306 	t_bool ret = MFALSE;
4307 	mlan_adapter *pmadapter = pmpriv->adapter;
4308 	t_bool scan_reqd = MFALSE;
4309 	t_bool chan_listed = MFALSE;
4310 	t_u8 id = 0;
4311 	t_u32 bss_idx, i;
4312 	t_u8 null_ssid[MLAN_MAX_SSID_LENGTH] = {0};
4313 	mlan_callbacks *pcb = (mlan_callbacks *)&pmpriv->adapter->callbacks;
4314 	wlan_user_scan_cfg *user_scan_cfg;
4315 	mlan_ds_scan *pscan = (mlan_ds_scan *)pioctl_buf->pbuf;
4316 	mlan_scan_req *pscan_req = MNULL;
4317 	wlan_user_scan_cfg *puser_scan_in = MNULL;
4318 
4319 	ENTER();
4320 
4321 	if (pscan->sub_command == MLAN_OID_SCAN_USER_CONFIG) {
4322 		puser_scan_in = (wlan_user_scan_cfg *)
4323 					pscan->param.user_scan.scan_cfg_buf;
4324 		if (!puser_scan_in->ssid_filter)
4325 			goto done;
4326 	}
4327 
4328 	if (pmadapter->active_scan_triggered) {
4329 		pmadapter->active_scan_triggered = MFALSE;
4330 		goto done;
4331 	}
4332 
4333 	if ((pcb->moal_malloc(pmadapter->pmoal_handle,
4334 			      sizeof(wlan_user_scan_cfg), MLAN_MEM_DEF,
4335 			      (t_u8 **)&user_scan_cfg) !=
4336 	     MLAN_STATUS_SUCCESS) ||
4337 	    !user_scan_cfg) {
4338 		PRINTM(MERROR, "Memory allocation for user_scan_cfg failed\n");
4339 		goto done;
4340 	}
4341 	memset(pmadapter, user_scan_cfg, 0, sizeof(wlan_user_scan_cfg));
4342 	for (bss_idx = 0; bss_idx < pmadapter->num_in_scan_table; bss_idx++) {
4343 		scan_reqd = MFALSE;
4344 		if (!memcmp(pmadapter,
4345 			    pmadapter->pscan_table[bss_idx].ssid.ssid,
4346 			    null_ssid,
4347 			    pmadapter->pscan_table[bss_idx].ssid.ssid_len)) {
4348 			if (puser_scan_in &&
4349 			    puser_scan_in->chan_list[0].chan_number) {
4350 				for (i = 0;
4351 				     i < WLAN_USER_SCAN_CHAN_MAX &&
4352 				     puser_scan_in->chan_list[i].chan_number;
4353 				     i++) {
4354 					if (puser_scan_in->chan_list[i]
4355 						    .chan_number ==
4356 					    pmadapter->pscan_table[bss_idx]
4357 						    .channel) {
4358 						if (puser_scan_in->chan_list[i]
4359 							    .scan_type ==
4360 						    MLAN_SCAN_TYPE_PASSIVE)
4361 							scan_reqd = MTRUE;
4362 						break;
4363 					}
4364 				}
4365 			} else if (pmadapter->scan_type ==
4366 				   MLAN_SCAN_TYPE_PASSIVE) {
4367 				scan_reqd = MTRUE;
4368 			} else {
4369 				if ((pmadapter->pscan_table[bss_idx].bss_band &
4370 				     BAND_A) &&
4371 				    wlan_11h_radar_detect_required(
4372 					    pmpriv,
4373 					    pmadapter->pscan_table[bss_idx]
4374 						    .channel))
4375 					scan_reqd = MTRUE;
4376 				if (pmadapter->pscan_table[bss_idx].bss_band &
4377 					    (BAND_B | BAND_G) &&
4378 				    wlan_bg_scan_type_is_passive(
4379 					    pmpriv,
4380 					    pmadapter->pscan_table[bss_idx]
4381 						    .channel))
4382 					scan_reqd = MTRUE;
4383 			}
4384 
4385 			if (scan_reqd) {
4386 				chan_listed = MFALSE;
4387 				for (i = 0; i < id; i++) {
4388 					if ((user_scan_cfg->chan_list[i]
4389 						     .chan_number ==
4390 					     pmadapter->pscan_table[bss_idx]
4391 						     .channel) &&
4392 					    (user_scan_cfg->chan_list[i]
4393 						     .radio_type &
4394 					     pmadapter->pscan_table[bss_idx]
4395 						     .bss_band)) {
4396 						chan_listed = MTRUE;
4397 						break;
4398 					}
4399 				}
4400 				if (chan_listed == MTRUE)
4401 					continue;
4402 				user_scan_cfg->chan_list[id].chan_number =
4403 					pmadapter->pscan_table[bss_idx].channel;
4404 				if (pmadapter->pscan_table[bss_idx].bss_band &
4405 				    (BAND_B | BAND_G))
4406 					user_scan_cfg->chan_list[id].radio_type =
4407 						BAND_2GHZ;
4408 				if (pmadapter->pscan_table[bss_idx].bss_band &
4409 				    BAND_A)
4410 					user_scan_cfg->chan_list[id].radio_type =
4411 						BAND_5GHZ;
4412 				user_scan_cfg->chan_list[id].scan_type =
4413 					MLAN_SCAN_TYPE_ACTIVE;
4414 				id++;
4415 			}
4416 		}
4417 	}
4418 	if (id) {
4419 		pmadapter->active_scan_triggered = MTRUE;
4420 		if (pscan->sub_command == MLAN_OID_SCAN_USER_CONFIG) {
4421 			memcpy_ext(pmpriv->adapter, user_scan_cfg->ssid_list,
4422 				   puser_scan_in->ssid_list,
4423 				   sizeof(user_scan_cfg->ssid_list),
4424 				   sizeof(user_scan_cfg->ssid_list));
4425 		} else {
4426 			pscan_req = &pscan->param.scan_req;
4427 			memcpy_ext(pmpriv->adapter,
4428 				   user_scan_cfg->ssid_list[0].ssid,
4429 				   pscan_req->scan_ssid.ssid,
4430 				   pscan_req->scan_ssid.ssid_len,
4431 				   MLAN_MAX_SSID_LENGTH);
4432 		}
4433 		user_scan_cfg->keep_previous_scan = MTRUE;
4434 		if (MLAN_STATUS_SUCCESS !=
4435 		    wlan_scan_networks(pmpriv, pioctl_buf, user_scan_cfg)) {
4436 			goto done;
4437 		}
4438 		ret = MTRUE;
4439 	}
4440 	if (user_scan_cfg)
4441 		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)user_scan_cfg);
4442 
4443 done:
4444 	LEAVE();
4445 	return ret;
4446 }
4447 
4448 /**
4449  *  @brief This function handles the command response of scan
4450  *
4451  *   The response buffer for the scan command has the following
4452  *      memory layout:
4453  *
4454  *     .-------------------------------------------------------------.
4455  *     |  Header (4 * sizeof(t_u16)):  Standard command response hdr |
4456  *     .-------------------------------------------------------------.
4457  *     |  BufSize (t_u16) : sizeof the BSS Description data          |
4458  *     .-------------------------------------------------------------.
4459  *     |  NumOfSet (t_u8) : Number of BSS Descs returned             |
4460  *     .-------------------------------------------------------------.
4461  *     |  BSSDescription data (variable, size given in BufSize)      |
4462  *     .-------------------------------------------------------------.
4463  *     |  TLV data (variable, size calculated using Header->Size,    |
4464  *     |            BufSize and sizeof the fixed fields above)       |
4465  *     .-------------------------------------------------------------.
4466  *
4467  *  @param pmpriv       A pointer to mlan_private structure
4468  *  @param resp         A pointer to HostCmd_DS_COMMAND
4469  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
4470  *
4471  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4472  */
wlan_ret_802_11_scan(mlan_private * pmpriv,HostCmd_DS_COMMAND * resp,t_void * pioctl_buf)4473 mlan_status wlan_ret_802_11_scan(mlan_private *pmpriv, HostCmd_DS_COMMAND *resp,
4474 				 t_void *pioctl_buf)
4475 {
4476 	mlan_status ret = MLAN_STATUS_SUCCESS;
4477 	mlan_adapter *pmadapter = pmpriv->adapter;
4478 	mlan_callbacks *pcb = MNULL;
4479 	cmd_ctrl_node *pcmd_node = MNULL;
4480 	HostCmd_DS_802_11_SCAN_RSP *pscan_rsp = MNULL;
4481 	BSSDescriptor_t *bss_new_entry = MNULL;
4482 	MrvlIEtypes_Data_t *ptlv;
4483 	MrvlIEtypes_TsfTimestamp_t *ptsf_tlv = MNULL;
4484 	MrvlIEtypes_ChannelStats_t *pchanstats_tlv = MNULL;
4485 	t_u8 *pbss_info;
4486 	t_u32 scan_resp_size;
4487 	t_u32 bytes_left;
4488 	t_u32 num_in_table;
4489 	t_u32 bss_idx;
4490 	t_u32 idx;
4491 	t_u32 tlv_buf_size;
4492 	t_u64 tsf_val;
4493 	chan_freq_power_t *cfp;
4494 	MrvlIEtypes_ChanBandListParamSet_t *pchan_band_tlv = MNULL;
4495 	ChanBandParamSet_t *pchan_band;
4496 	t_u16 band;
4497 	t_u8 is_bgscan_resp;
4498 	t_u32 age_ts_usec;
4499 	t_u8 null_ssid[MLAN_MAX_SSID_LENGTH] = {0};
4500 	t_u32 status_code = 0;
4501 	pmlan_ioctl_req pscan_ioctl_req = MNULL;
4502 
4503 	ENTER();
4504 	pcb = (pmlan_callbacks)&pmadapter->callbacks;
4505 
4506 	is_bgscan_resp = (resp->command == HostCmd_CMD_802_11_BG_SCAN_QUERY);
4507 	if (is_bgscan_resp)
4508 		pscan_rsp = &resp->params.bg_scan_query_resp.scan_resp;
4509 	else
4510 		pscan_rsp = &resp->params.scan_resp;
4511 
4512 	if (pscan_rsp->number_of_sets > MRVDRV_MAX_BSSID_LIST) {
4513 		PRINTM(MERROR,
4514 		       "SCAN_RESP: Invalid number of AP returned (%d)!!\n",
4515 		       pscan_rsp->number_of_sets);
4516 		status_code = MLAN_ERROR_CMD_SCAN_FAIL;
4517 		ret = MLAN_STATUS_FAILURE;
4518 		goto done;
4519 	}
4520 
4521 	bytes_left = wlan_le16_to_cpu(pscan_rsp->bss_descript_size);
4522 	PRINTM(MINFO, "SCAN_RESP: bss_descript_size %d\n", bytes_left);
4523 
4524 	scan_resp_size = resp->size;
4525 
4526 	PRINTM(MINFO, "SCAN_RESP: returned %d APs before parsing\n",
4527 	       pscan_rsp->number_of_sets);
4528 
4529 	/* Update the age_in_second */
4530 	pmadapter->callbacks.moal_get_system_time(
4531 		pmadapter->pmoal_handle, &pmadapter->age_in_secs, &age_ts_usec);
4532 
4533 	num_in_table = pmadapter->num_in_scan_table;
4534 	pbss_info = pscan_rsp->bss_desc_and_tlv_buffer;
4535 
4536 	/*
4537 	 * The size of the TLV buffer is equal to the entire command response
4538 	 *   size (scan_resp_size) minus the fixed fields (sizeof()'s), the
4539 	 *   BSS Descriptions (bss_descript_size as bytesLef) and the command
4540 	 *   response header (S_DS_GEN)
4541 	 */
4542 	tlv_buf_size = scan_resp_size -
4543 		       (bytes_left + sizeof(pscan_rsp->bss_descript_size) +
4544 			sizeof(pscan_rsp->number_of_sets) + S_DS_GEN);
4545 	if (is_bgscan_resp)
4546 		tlv_buf_size -= sizeof(
4547 			resp->params.bg_scan_query_resp.report_condition);
4548 
4549 	ptlv = (MrvlIEtypes_Data_t *)(pscan_rsp->bss_desc_and_tlv_buffer +
4550 				      bytes_left);
4551 
4552 	/*
4553 	 * Search the TLV buffer space in the scan response
4554 	 * for any valid TLVs
4555 	 */
4556 	wlan_ret_802_11_scan_get_tlv_ptrs(pmadapter, ptlv, tlv_buf_size,
4557 					  TLV_TYPE_TSFTIMESTAMP,
4558 					  (MrvlIEtypes_Data_t **)&ptsf_tlv);
4559 
4560 	/*
4561 	 * Search the TLV buffer space in the scan response
4562 	 * for any valid TLVs
4563 	 */
4564 	wlan_ret_802_11_scan_get_tlv_ptrs(
4565 		pmadapter, ptlv, tlv_buf_size, TLV_TYPE_CHANNELBANDLIST,
4566 		(MrvlIEtypes_Data_t **)&pchan_band_tlv);
4567 	wlan_ret_802_11_scan_get_tlv_ptrs(
4568 		pmadapter, ptlv, tlv_buf_size, TLV_TYPE_CHANNEL_STATS,
4569 		(MrvlIEtypes_Data_t **)&pchanstats_tlv);
4570 
4571 	if (pchanstats_tlv)
4572 		wlan_update_chan_statistics(pmpriv, pchanstats_tlv);
4573 
4574 	/*
4575 	 * Process each scan response returned (pscan_rsp->number_of_sets).
4576 	 * Save the information in the bss_new_entry and then insert into
4577 	 * the driver scan table either as an update to an existing entry
4578 	 * or as an addition at the end of the table
4579 	 */
4580 	ret = pcb->moal_malloc(pmadapter->pmoal_handle, sizeof(BSSDescriptor_t),
4581 			       MLAN_MEM_DEF, (t_u8 **)&bss_new_entry);
4582 
4583 	if (ret != MLAN_STATUS_SUCCESS || !bss_new_entry) {
4584 		PRINTM(MERROR, "Memory allocation for bss_new_entry failed!\n");
4585 		status_code = MLAN_ERROR_NO_MEM;
4586 		ret = MLAN_STATUS_FAILURE;
4587 		goto done;
4588 	}
4589 
4590 	for (idx = 0; idx < pscan_rsp->number_of_sets && bytes_left; idx++) {
4591 		/* Zero out the bss_new_entry we are about to store info in */
4592 		memset(pmadapter, bss_new_entry, 0x00, sizeof(BSSDescriptor_t));
4593 
4594 		/* Process the data fields and IEs returned for this BSS */
4595 		if (wlan_interpret_bss_desc_with_ie(
4596 			    pmadapter, bss_new_entry, &pbss_info, &bytes_left,
4597 			    MFALSE) == MLAN_STATUS_SUCCESS) {
4598 			PRINTM(MINFO, "SCAN_RESP: BSSID = " MACSTR "\n",
4599 			       MAC2STR(bss_new_entry->mac_address));
4600 
4601 			band = BAND_G;
4602 			if (pchan_band_tlv) {
4603 				pchan_band =
4604 					&pchan_band_tlv->chan_band_param[idx];
4605 				band = radio_type_to_band(
4606 					pchan_band->bandcfg.chanBand);
4607 				if (!bss_new_entry->channel)
4608 					bss_new_entry->channel =
4609 						pchan_band->chan_number;
4610 			}
4611 			/*
4612 			 * Save the band designation for this entry
4613 			 * for use in join
4614 			 */
4615 			bss_new_entry->bss_band = band;
4616 			bss_new_entry->age_in_secs = pmadapter->age_in_secs;
4617 			cfp = wlan_find_cfp_by_band_and_channel(
4618 				pmadapter, bss_new_entry->bss_band,
4619 				(t_u16)bss_new_entry->channel);
4620 			if (cfp)
4621 				bss_new_entry->freq = cfp->freq;
4622 			else
4623 				bss_new_entry->freq = 0;
4624 
4625 			/* Skip entry if on blacklisted channel */
4626 			if (cfp && cfp->dynamic.blacklist) {
4627 				PRINTM(MINFO,
4628 				       "SCAN_RESP: dropping entry on blacklist channel.\n");
4629 				continue;
4630 			}
4631 
4632 			/*
4633 			 * Search the scan table for the same bssid
4634 			 */
4635 			for (bss_idx = 0; bss_idx < num_in_table; bss_idx++) {
4636 				if (!memcmp(pmadapter,
4637 					    bss_new_entry->mac_address,
4638 					    pmadapter->pscan_table[bss_idx]
4639 						    .mac_address,
4640 					    sizeof(bss_new_entry->mac_address))) {
4641 					/*
4642 					 * If the SSID matches as well, it is a
4643 					 * duplicate of this entry.  Keep the
4644 					 * bss_idx set to this entry so we
4645 					 * replace the old contents in the table
4646 					 */
4647 					if ((bss_new_entry->ssid.ssid_len ==
4648 					     pmadapter->pscan_table[bss_idx]
4649 						     .ssid.ssid_len) &&
4650 					    (!memcmp(
4651 						    pmadapter,
4652 						    bss_new_entry->ssid.ssid,
4653 						    pmadapter
4654 							    ->pscan_table[bss_idx]
4655 							    .ssid.ssid,
4656 						    bss_new_entry->ssid
4657 							    .ssid_len))) {
4658 						PRINTM(MINFO,
4659 						       "SCAN_RESP: Duplicate of index: %d\n",
4660 						       bss_idx);
4661 
4662 						break;
4663 					}
4664 					/*
4665 					 * If the SSID is NULL for same BSSID
4666 					 * keep the bss_idx set to this entry
4667 					 * so we replace the old contents in
4668 					 * the table
4669 					 */
4670 					if (!memcmp(pmadapter,
4671 						    pmadapter
4672 							    ->pscan_table[bss_idx]
4673 							    .ssid.ssid,
4674 						    null_ssid,
4675 						    pmadapter
4676 							    ->pscan_table[bss_idx]
4677 							    .ssid.ssid_len)) {
4678 						PRINTM(MINFO,
4679 						       "SCAN_RESP: Duplicate of index: %d\n",
4680 						       bss_idx);
4681 						break;
4682 					}
4683 				}
4684 			}
4685 			/*
4686 			 * If the bss_idx is equal to the number of entries
4687 			 * in the table, the new entry was not a duplicate;
4688 			 * append it to the scan table
4689 			 */
4690 			if (bss_idx == num_in_table) {
4691 				/*
4692 				 * Range check the bss_idx, keep it limited
4693 				 * to the last entry
4694 				 */
4695 				if (bss_idx == MRVDRV_MAX_BSSID_LIST)
4696 					bss_idx--;
4697 				else
4698 					num_in_table++;
4699 			} else {
4700 				if ((bss_new_entry->channel !=
4701 				     pmadapter->pscan_table[bss_idx].channel) &&
4702 				    (bss_new_entry->rssi >
4703 				     pmadapter->pscan_table[bss_idx].rssi)) {
4704 					PRINTM(MCMND,
4705 					       "skip update the duplicate entry with low rssi\n");
4706 					continue;
4707 				}
4708 			}
4709 			/*
4710 			 * Save the beacon/probe response returned for later
4711 			 * application retrieval. Duplicate beacon/probe
4712 			 * responses are updated if possible
4713 			 */
4714 			wlan_ret_802_11_scan_store_beacon(
4715 				pmpriv, bss_idx, num_in_table, bss_new_entry);
4716 			if (bss_new_entry->pbeacon_buf == MNULL) {
4717 				PRINTM(MCMND,
4718 				       "No space for beacon, drop this entry\n");
4719 				num_in_table--;
4720 				continue;
4721 			}
4722 			/*
4723 			 * If the TSF TLV was appended to the scan results, save
4724 			 * this entry's TSF value in the networkTSF field.  The
4725 			 * networkTSF is the firmware's TSF value at the time
4726 			 * the beacon or probe response was received.
4727 			 */
4728 			if (ptsf_tlv) {
4729 				memcpy_ext(
4730 					pmpriv->adapter, &tsf_val,
4731 					&ptsf_tlv->tsf_data[idx * TSF_DATA_SIZE],
4732 					sizeof(tsf_val), sizeof(tsf_val));
4733 				tsf_val = wlan_le64_to_cpu(tsf_val);
4734 				memcpy_ext(pmpriv->adapter,
4735 					   &bss_new_entry->network_tsf,
4736 					   &tsf_val,
4737 					   sizeof(bss_new_entry->network_tsf),
4738 					   sizeof(bss_new_entry->network_tsf));
4739 			}
4740 
4741 			/* Copy the locally created bss_new_entry to the scan
4742 			 * table */
4743 			memcpy_ext(pmadapter, &pmadapter->pscan_table[bss_idx],
4744 				   bss_new_entry,
4745 				   sizeof(pmadapter->pscan_table[bss_idx]),
4746 				   sizeof(pmadapter->pscan_table[bss_idx]));
4747 
4748 		} else {
4749 			/* Error parsing/interpreting the scan response, skipped
4750 			 */
4751 			PRINTM(MERROR,
4752 			       "SCAN_RESP: wlan_interpret_bss_desc_with_ie returned error\n");
4753 		}
4754 	}
4755 
4756 	PRINTM(MINFO, "SCAN_RESP: Scanned %2d APs, %d valid, %d total\n",
4757 	       pscan_rsp->number_of_sets,
4758 	       num_in_table - pmadapter->num_in_scan_table, num_in_table);
4759 
4760 	/* Update the total number of BSSIDs in the scan table */
4761 	pmadapter->num_in_scan_table = num_in_table;
4762 	if (is_bgscan_resp)
4763 		goto done;
4764 	wlan_request_cmd_lock(pmadapter);
4765 	if (!util_peek_list(pmadapter->pmoal_handle, &pmadapter->scan_pending_q,
4766 			    MNULL, MNULL)) {
4767 		wlan_release_cmd_lock(pmadapter);
4768 		if (pmadapter->pscan_ioctl_req) {
4769 			if (((mlan_ds_scan *)pmadapter->pscan_ioctl_req->pbuf)
4770 					    ->sub_command ==
4771 				    MLAN_OID_SCAN_SPECIFIC_SSID ||
4772 			    ((mlan_ds_scan *)pmadapter->pscan_ioctl_req->pbuf)
4773 					    ->sub_command ==
4774 				    MLAN_OID_SCAN_USER_CONFIG) {
4775 				if (wlan_active_scan_req_for_passive_chan(
4776 					    pmpriv,
4777 					    pmadapter->pscan_ioctl_req)) {
4778 					goto done;
4779 				}
4780 			}
4781 		}
4782 		/*
4783 		 * Process the resulting scan table:
4784 		 *   - Remove any bad ssids
4785 		 *   - Update our current BSS information from scan data
4786 		 */
4787 		wlan_scan_process_results(pmpriv);
4788 
4789 		wlan_request_cmd_lock(pmadapter);
4790 		pmadapter->scan_processing = MFALSE;
4791 		pscan_ioctl_req = pmadapter->pscan_ioctl_req;
4792 		pmadapter->pscan_ioctl_req = MNULL;
4793 		/* Need to indicate IOCTL complete */
4794 		if (pscan_ioctl_req) {
4795 			pscan_ioctl_req->status_code = MLAN_ERROR_NO_ERROR;
4796 			/* Indicate ioctl complete */
4797 			pcb->moal_ioctl_complete(
4798 				pmadapter->pmoal_handle,
4799 				(pmlan_ioctl_req)pscan_ioctl_req,
4800 				MLAN_STATUS_SUCCESS);
4801 		}
4802 		wlan_release_cmd_lock(pmadapter);
4803 		pmadapter->bgscan_reported = MFALSE;
4804 		wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_SCAN_REPORT, MNULL);
4805 	} else {
4806 		/* If firmware not ready, do not issue any more scan commands */
4807 		if (pmadapter->hw_status != WlanHardwareStatusReady) {
4808 			wlan_release_cmd_lock(pmadapter);
4809 			status_code = MLAN_ERROR_FW_NOT_READY;
4810 			ret = MLAN_STATUS_FAILURE;
4811 			goto done;
4812 		} else {
4813 			/* Get scan command from scan_pending_q and put to
4814 			 * cmd_pending_q */
4815 			pcmd_node = (cmd_ctrl_node *)util_dequeue_list(
4816 				pmadapter->pmoal_handle,
4817 				&pmadapter->scan_pending_q, MNULL, MNULL);
4818 			wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node,
4819 						     MTRUE);
4820 			wlan_release_cmd_lock(pmadapter);
4821 		}
4822 	}
4823 
4824 done:
4825 	if (bss_new_entry)
4826 		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)bss_new_entry);
4827 	if (ret) {
4828 		/* Flush all pending scan commands */
4829 		wlan_flush_scan_queue(pmadapter);
4830 		wlan_request_cmd_lock(pmadapter);
4831 		pmadapter->scan_processing = MFALSE;
4832 		pscan_ioctl_req = pmadapter->pscan_ioctl_req;
4833 		pmadapter->pscan_ioctl_req = MNULL;
4834 		if (pscan_ioctl_req) {
4835 			pscan_ioctl_req->status_code = status_code;
4836 			/* Indicate ioctl complete */
4837 			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
4838 						 pscan_ioctl_req,
4839 						 MLAN_STATUS_FAILURE);
4840 		}
4841 		wlan_release_cmd_lock(pmadapter);
4842 	}
4843 	LEAVE();
4844 	return ret;
4845 }
4846 
4847 /**
4848  *  @brief Get ext_scan state from ext_scan_type
4849  *
4850  *
4851  *  @param pcmd       A pointer to HostCmd_DS_COMMAND structure to be sent to
4852  *                    firmware with the HostCmd_DS_802_11_SCAN_EXT structure
4853  *
4854  *  @return
4855  * SCAN_STATE_EXT_SCAN_ENH/SCAN_STATE_EXT_SCAN_CANCEL/SCAN_STATE_EXT_SCAN_ENH
4856  */
wlan_get_ext_scan_state(HostCmd_DS_COMMAND * pcmd)4857 t_u8 wlan_get_ext_scan_state(HostCmd_DS_COMMAND *pcmd)
4858 {
4859 	HostCmd_DS_802_11_SCAN_EXT *pext_scan_cmd = &pcmd->params.ext_scan;
4860 	if (pext_scan_cmd->ext_scan_type == EXT_SCAN_ENHANCE)
4861 		return SCAN_STATE_EXT_SCAN_ENH;
4862 	if (pext_scan_cmd->ext_scan_type == EXT_SCAN_CANCEL)
4863 		return SCAN_STATE_EXT_SCAN_CANCEL;
4864 	return SCAN_STATE_EXT_SCAN;
4865 }
4866 
4867 /**
4868  *  @brief Prepare an extended scan command to be sent to the firmware
4869  *
4870  *  Use the wlan_scan_cmd_config sent to the command processing module in
4871  *   the wlan_prepare_cmd to configure a HostCmd_DS_802_11_SCAN_EXT command
4872  *   struct to send to firmware.
4873  *
4874  *  @param pmpriv     A pointer to mlan_private structure
4875  *  @param pcmd       A pointer to HostCmd_DS_COMMAND structure to be sent to
4876  *                    firmware with the HostCmd_DS_802_11_SCAN_EXT structure
4877  *  @param pdata_buf  Void pointer cast of a wlan_scan_cmd_config struct used
4878  *                    to set the fields/TLVs for the command sent to firmware
4879  *
4880  *  @return           MLAN_STATUS_SUCCESS
4881  */
wlan_cmd_802_11_scan_ext(mlan_private * pmpriv,HostCmd_DS_COMMAND * pcmd,t_void * pdata_buf)4882 mlan_status wlan_cmd_802_11_scan_ext(mlan_private *pmpriv,
4883 				     HostCmd_DS_COMMAND *pcmd,
4884 				     t_void *pdata_buf)
4885 {
4886 	HostCmd_DS_802_11_SCAN_EXT *pext_scan_cmd = &pcmd->params.ext_scan;
4887 	wlan_scan_cmd_config *pscan_cfg = MNULL;
4888 
4889 	ENTER();
4890 
4891 	pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_SCAN_EXT);
4892 
4893 	if (pmpriv->adapter->ext_scan_enh == MTRUE) {
4894 		if (pdata_buf) {
4895 			if (pmpriv->adapter->ext_scan_type == EXT_SCAN_ENHANCE)
4896 				pext_scan_cmd->ext_scan_type = EXT_SCAN_ENHANCE;
4897 			else
4898 				pext_scan_cmd->ext_scan_type = EXT_SCAN_DEFAULT;
4899 		} else {
4900 			pcmd->size = wlan_cpu_to_le16((t_u16)(
4901 				sizeof(pext_scan_cmd->ext_scan_type) +
4902 				(t_u16)(sizeof(pext_scan_cmd->reserved)) +
4903 				S_DS_GEN));
4904 			pext_scan_cmd->ext_scan_type = EXT_SCAN_CANCEL;
4905 			LEAVE();
4906 			return MLAN_STATUS_SUCCESS;
4907 		}
4908 	}
4909 	if (!pdata_buf) {
4910 		PRINTM(MERROR, "wlan_cmd_802_11_scan_ext: pdata_buf is null\n");
4911 		LEAVE();
4912 		return MLAN_STATUS_FAILURE;
4913 	}
4914 	pscan_cfg = (wlan_scan_cmd_config *)pdata_buf;
4915 
4916 	memcpy_ext(pmpriv->adapter, pext_scan_cmd->tlv_buffer,
4917 		   pscan_cfg->tlv_buf, pscan_cfg->tlv_buf_len,
4918 		   pscan_cfg->tlv_buf_len);
4919 
4920 	/* Size is equal to the sizeof(fixed portions) + the TLV len + header */
4921 	pcmd->size = wlan_cpu_to_le16(
4922 		(t_u16)(sizeof(pext_scan_cmd->ext_scan_type) +
4923 			(t_u16)sizeof(pext_scan_cmd->reserved) +
4924 			pscan_cfg->tlv_buf_len + S_DS_GEN));
4925 
4926 	LEAVE();
4927 	return MLAN_STATUS_SUCCESS;
4928 }
4929 
4930 /**
4931  *  @brief This function handles the command response of extended scan
4932  *
4933  *  @param pmpriv       A pointer to mlan_private structure
4934  *  @param resp         A pointer to HostCmd_DS_COMMAND
4935  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
4936  *
4937  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
4938  */
wlan_ret_802_11_scan_ext(mlan_private * pmpriv,HostCmd_DS_COMMAND * resp,t_void * pioctl_buf)4939 mlan_status wlan_ret_802_11_scan_ext(mlan_private *pmpriv,
4940 				     HostCmd_DS_COMMAND *resp,
4941 				     t_void *pioctl_buf)
4942 {
4943 	HostCmd_DS_802_11_SCAN_EXT *pext_scan_cmd = &(resp->params.ext_scan);
4944 	MrvlIEtypesHeader_t *tlv = MNULL;
4945 	MrvlIEtypes_ChannelStats_t *tlv_chanstats = MNULL;
4946 	t_u16 tlv_buf_left = 0;
4947 	t_u16 tlv_type = 0;
4948 	t_u16 tlv_len = 0;
4949 	t_u32 ext_scan_type;
4950 	mlan_callbacks *pcb = (mlan_callbacks *)&pmpriv->adapter->callbacks;
4951 	pmlan_ioctl_req pioctl_req = (pmlan_ioctl_req)pioctl_buf;
4952 	mlan_adapter *pmadapter = pmpriv->adapter;
4953 	ENTER();
4954 
4955 	PRINTM(MINFO, "EXT scan returns successfully\n");
4956 	pmadapter->scan_state |= wlan_get_ext_scan_state(resp);
4957 	ext_scan_type = pext_scan_cmd->ext_scan_type;
4958 	if (ext_scan_type == EXT_SCAN_CANCEL) {
4959 		PRINTM(MCMND, "Cancel scan command completed!\n");
4960 		wlan_request_cmd_lock(pmadapter);
4961 		pmadapter->scan_processing = MFALSE;
4962 		pmadapter->scan_state |= SCAN_STATE_SCAN_COMPLETE;
4963 		pmadapter->ext_scan_type = EXT_SCAN_DEFAULT;
4964 		wlan_release_cmd_lock(pmadapter);
4965 		/* Need to indicate IOCTL complete */
4966 		if (pioctl_req != MNULL) {
4967 			pioctl_req->status_code = MLAN_STATUS_SUCCESS;
4968 			/* Indicate ioctl complete */
4969 			pcb->moal_ioctl_complete(pmadapter->pmoal_handle,
4970 						 (pmlan_ioctl_req)pioctl_req,
4971 						 MLAN_STATUS_SUCCESS);
4972 		}
4973 		LEAVE();
4974 		return MLAN_STATUS_SUCCESS;
4975 	} else if (ext_scan_type == EXT_SCAN_ENHANCE) {
4976 		/* Setup the timer after scan command response */
4977 		pcb->moal_start_timer(pmpriv->adapter->pmoal_handle,
4978 				      pmpriv->adapter->pmlan_cmd_timer, MFALSE,
4979 				      MRVDRV_TIMER_10S * 2);
4980 		pmpriv->adapter->cmd_timer_is_set = MTRUE;
4981 		LEAVE();
4982 		return MLAN_STATUS_SUCCESS;
4983 	}
4984 	tlv = (MrvlIEtypesHeader_t *)pext_scan_cmd->tlv_buffer;
4985 	tlv_buf_left = resp->size -
4986 		       (sizeof(HostCmd_DS_802_11_SCAN_EXT) - 1 + S_DS_GEN);
4987 	while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
4988 		tlv_type = wlan_le16_to_cpu(tlv->type);
4989 		tlv_len = wlan_le16_to_cpu(tlv->len);
4990 		if (tlv_buf_left < (tlv_len + sizeof(MrvlIEtypesHeader_t))) {
4991 			PRINTM(MERROR, "Error processing scan gap TLV\n");
4992 			break;
4993 		}
4994 		switch (tlv_type) {
4995 		case TLV_TYPE_CHANNEL_STATS:
4996 			tlv_chanstats = (MrvlIEtypes_ChannelStats_t *)tlv;
4997 			wlan_update_chan_statistics(pmpriv, tlv_chanstats);
4998 			break;
4999 		default:
5000 			break;
5001 		}
5002 		tlv_buf_left -= tlv_len + sizeof(MrvlIEtypesHeader_t);
5003 		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
5004 					      sizeof(MrvlIEtypesHeader_t));
5005 	}
5006 	LEAVE();
5007 	return MLAN_STATUS_SUCCESS;
5008 }
5009 
5010 /**
5011  *  @brief This function add a new entry to scan_table
5012  *
5013  *  @param pmpriv           A pointer to mlan_private structure
5014  *  @param bss_new_entry    A pointer to the bss_new_entry
5015  *  @param num_in_tbl		number of scan entry in scan_table
5016  *
5017  *  @return             N/A
5018  */
wlan_add_new_entry_to_scan_table(mlan_private * pmpriv,BSSDescriptor_t * bss_new_entry,t_u32 * num_in_tbl)5019 static t_void wlan_add_new_entry_to_scan_table(mlan_private *pmpriv,
5020 					       BSSDescriptor_t *bss_new_entry,
5021 					       t_u32 *num_in_tbl)
5022 {
5023 	mlan_adapter *pmadapter = pmpriv->adapter;
5024 	t_u32 bss_idx;
5025 	t_u32 num_in_table = *num_in_tbl;
5026 	t_u8 null_ssid[MLAN_MAX_SSID_LENGTH] = {0};
5027 
5028 	/*
5029 	 * Search the scan table for the same bssid
5030 	 */
5031 	for (bss_idx = 0; bss_idx < num_in_table; bss_idx++) {
5032 		if (!memcmp(pmadapter, bss_new_entry->mac_address,
5033 			    pmadapter->pscan_table[bss_idx].mac_address,
5034 			    sizeof(bss_new_entry->mac_address))) {
5035 			/*
5036 			 * If the SSID matches as well, it is a
5037 			 * duplicate of this entry.  Keep the
5038 			 * bss_idx set to this entry so we
5039 			 * replace the old contents in the table
5040 			 */
5041 			if ((bss_new_entry->ssid.ssid_len ==
5042 			     pmadapter->pscan_table[bss_idx].ssid.ssid_len) &&
5043 			    (!memcmp(pmadapter, bss_new_entry->ssid.ssid,
5044 				     pmadapter->pscan_table[bss_idx].ssid.ssid,
5045 				     bss_new_entry->ssid.ssid_len))) {
5046 				PRINTM(MINFO,
5047 				       "EXT_SCAN: Duplicate of index: %d\n",
5048 				       bss_idx);
5049 				break;
5050 			}
5051 			/*
5052 			 * If the SSID is NULL for same BSSID
5053 			 * keep the bss_idx set to this entry
5054 			 * so we replace the old contents in
5055 			 * the table
5056 			 */
5057 			if (!memcmp(pmadapter,
5058 				    pmadapter->pscan_table[bss_idx].ssid.ssid,
5059 				    null_ssid,
5060 				    pmadapter->pscan_table[bss_idx]
5061 					    .ssid.ssid_len)) {
5062 				PRINTM(MINFO,
5063 				       "EXT_SCAN: Duplicate of index: %d\n",
5064 				       bss_idx);
5065 				break;
5066 			}
5067 		}
5068 	}
5069 	/* If the bss_idx is equal to the number of entries
5070 	 * in the table, the new entry was not a duplicate;
5071 	 * append it to the scan table
5072 	 */
5073 	if (bss_idx == num_in_table) {
5074 		/* Range check the bss_idx, keep it limited to the last entry */
5075 		if (bss_idx == MRVDRV_MAX_BSSID_LIST)
5076 			bss_idx--;
5077 		else
5078 			num_in_table++;
5079 	} else {
5080 		if ((bss_new_entry->channel !=
5081 		     pmadapter->pscan_table[bss_idx].channel) &&
5082 		    (bss_new_entry->rssi >
5083 		     pmadapter->pscan_table[bss_idx].rssi)) {
5084 			PRINTM(MCMND,
5085 			       "skip update the duplicate entry with low rssi\n");
5086 			return;
5087 		}
5088 	}
5089 	/*
5090 	 * Save the beacon/probe response returned for later
5091 	 * application retrieval. Duplicate beacon/probe
5092 	 * responses are updated if possible
5093 	 */
5094 	wlan_ret_802_11_scan_store_beacon(pmpriv, bss_idx, num_in_table,
5095 					  bss_new_entry);
5096 	if (bss_new_entry->pbeacon_buf == MNULL) {
5097 		PRINTM(MCMND, "No space for beacon, drop this entry\n");
5098 		num_in_table--;
5099 		goto done;
5100 	} else {
5101 		/* Copy the locally created bss_new_entry to the scan table */
5102 		memcpy_ext(pmadapter, &pmadapter->pscan_table[bss_idx],
5103 			   bss_new_entry,
5104 			   sizeof(pmadapter->pscan_table[bss_idx]),
5105 			   sizeof(pmadapter->pscan_table[bss_idx]));
5106 	}
5107 done:
5108 	*num_in_tbl = num_in_table;
5109 	return;
5110 }
5111 
5112 /** 8 bytes timestamp, 2 bytest interval, 2 bytes capability */
5113 #define BEACON_FIX_SIZE 12
5114 
5115 /**
5116  *  @brief This function realloc the beacon buffer and update ssid for new entry
5117  *
5118  *  @param pmadpater        A pointer to mlan_adapter structure
5119  *  @param pbss_entry       A pointer to the bss_entry which has multi-bssid IE
5120  *  @param pnew_entry       A pinter to new entry
5121  *  @param pssid            A pointer to ssid IE
5122  *
5123  *  @return                MLAN_STATUS_FAILURE/MLAN_STATUS_SUCCESS
5124  */
wlan_update_ssid_in_beacon_buf(mlan_adapter * pmadapter,BSSDescriptor_t * pbss_entry,BSSDescriptor_t * pnew_entry,IEEEtypes_Ssid_t * pssid,IEEEtypes_ExtCap_t * pnew_extcap,IEEEtypes_Generic_t * pnew_rsnx)5125 static mlan_status wlan_update_ssid_in_beacon_buf(
5126 	mlan_adapter *pmadapter, BSSDescriptor_t *pbss_entry,
5127 	BSSDescriptor_t *pnew_entry, IEEEtypes_Ssid_t *pssid,
5128 	IEEEtypes_ExtCap_t *pnew_extcap, IEEEtypes_Generic_t *pnew_rsnx)
5129 {
5130 	mlan_callbacks *pcb = (pmlan_callbacks)&pmadapter->callbacks;
5131 	t_u8 *pbeacon_buf = MNULL;
5132 	t_u32 beacon_buf_size = 0;
5133 	t_s8 offset = pnew_entry->ssid.ssid_len - pbss_entry->ssid.ssid_len;
5134 	IEEEtypes_ExtCap_t *pextcap;
5135 	mlan_status ret = MLAN_STATUS_FAILURE;
5136 	t_u32 rsnx_offset = 0;
5137 
5138 	if (pnew_entry->ssid.ssid_len >= pbss_entry->ssid.ssid_len)
5139 		beacon_buf_size =
5140 			pbss_entry->beacon_buf_size +
5141 			(pnew_entry->ssid.ssid_len - pbss_entry->ssid.ssid_len);
5142 	else
5143 		beacon_buf_size =
5144 			pbss_entry->beacon_buf_size -
5145 			(pbss_entry->ssid.ssid_len - pnew_entry->ssid.ssid_len);
5146 
5147 	rsnx_offset = beacon_buf_size;
5148 	if (pnew_rsnx)
5149 		beacon_buf_size +=
5150 			pnew_rsnx->ieee_hdr.len + sizeof(IEEEtypes_Header_t);
5151 
5152 	ret = pcb->moal_malloc(pmadapter->pmoal_handle, beacon_buf_size,
5153 			       MLAN_MEM_DEF, (t_u8 **)&pbeacon_buf);
5154 	if (ret != MLAN_STATUS_SUCCESS || !pbeacon_buf) {
5155 		PRINTM(MERROR,
5156 		       "Memory allocation for beacon buf for bss_new_entry\n");
5157 		goto done;
5158 	}
5159 	pnew_entry->beacon_buf_size = beacon_buf_size;
5160 	pnew_entry->pbeacon_buf = pbeacon_buf;
5161 	/** copy fixed IE */
5162 	memcpy_ext(pmadapter, pbeacon_buf, pbss_entry->pbeacon_buf,
5163 		   BEACON_FIX_SIZE, BEACON_FIX_SIZE);
5164 	/** copy new ssid ie */
5165 	memcpy_ext(pmadapter, pbeacon_buf + BEACON_FIX_SIZE, (t_u8 *)pssid,
5166 		   pssid->len + sizeof(IEEEtypes_Header_t),
5167 		   pssid->len + sizeof(IEEEtypes_Header_t));
5168 	/** copy left IE to new beacon buffer */
5169 	memcpy_ext(pmadapter,
5170 		   pbeacon_buf + BEACON_FIX_SIZE + pssid->len +
5171 			   sizeof(IEEEtypes_Header_t),
5172 		   pbss_entry->pbeacon_buf + BEACON_FIX_SIZE +
5173 			   pbss_entry->ssid.ssid_len +
5174 			   sizeof(IEEEtypes_Header_t),
5175 		   pbss_entry->beacon_buf_size - BEACON_FIX_SIZE -
5176 			   (pbss_entry->ssid.ssid_len +
5177 			    sizeof(IEEEtypes_Header_t)),
5178 		   pbss_entry->beacon_buf_size - BEACON_FIX_SIZE -
5179 			   (pbss_entry->ssid.ssid_len +
5180 			    sizeof(IEEEtypes_Header_t)));
5181 
5182 	/* adjust the ie pointer */
5183 	if (pnew_entry->pwpa_ie)
5184 		pnew_entry->wpa_offset += offset;
5185 	if (pnew_entry->prsn_ie)
5186 		pnew_entry->rsn_offset += offset;
5187 	if (pnew_entry->pwapi_ie)
5188 		pnew_entry->wapi_offset += offset;
5189 
5190 	if (pnew_entry->posen_ie)
5191 		pnew_entry->osen_offset += offset;
5192 	if (pnew_entry->pmd_ie)
5193 		pnew_entry->md_offset += offset;
5194 	if (pnew_entry->pht_cap)
5195 		pnew_entry->ht_cap_offset += offset;
5196 	if (pnew_entry->pht_info)
5197 		pnew_entry->ht_info_offset += offset;
5198 	if (pnew_entry->pbss_co_2040)
5199 		pnew_entry->bss_co_2040_offset += offset;
5200 	if (pnew_entry->pext_cap) {
5201 		pnew_entry->ext_cap_offset += offset;
5202 		if (pnew_extcap) {
5203 			pextcap = (IEEEtypes_ExtCap_t
5204 					   *)(pnew_entry->pbeacon_buf +
5205 					      pnew_entry->ext_cap_offset);
5206 			memcpy_ext(pmadapter,
5207 				   pbeacon_buf + pnew_entry->ext_cap_offset,
5208 				   (t_u8 *)pnew_extcap,
5209 				   pnew_extcap->ieee_hdr.len +
5210 					   sizeof(IEEEtypes_Header_t),
5211 				   pextcap->ieee_hdr.len +
5212 					   sizeof(IEEEtypes_Header_t));
5213 		}
5214 	}
5215 	if (pnew_entry->poverlap_bss_scan_param)
5216 		pnew_entry->overlap_bss_offset += offset;
5217 	if (pnew_entry->pvht_cap)
5218 		pnew_entry->vht_cap_offset += offset;
5219 	if (pnew_entry->pvht_oprat)
5220 		pnew_entry->vht_oprat_offset += offset;
5221 	if (pnew_entry->pvht_txpower)
5222 		pnew_entry->vht_txpower_offset += offset;
5223 	if (pnew_entry->pext_pwer)
5224 		pnew_entry->ext_pwer_offset += offset;
5225 	if (pnew_entry->pext_bssload)
5226 		pnew_entry->ext_bssload_offset += offset;
5227 	if (pnew_entry->pquiet_chan)
5228 		pnew_entry->quiet_chan_offset += offset;
5229 	if (pnew_entry->poper_mode)
5230 		pnew_entry->oper_mode_offset += offset;
5231 	if (pnew_entry->phe_cap)
5232 		pnew_entry->he_cap_offset += offset;
5233 	if (pnew_entry->phe_oprat)
5234 		pnew_entry->he_oprat_offset += offset;
5235 	if (pnew_rsnx)
5236 		memcpy_ext(
5237 			pmadapter, pbeacon_buf + rsnx_offset, (t_u8 *)pnew_rsnx,
5238 			pnew_rsnx->ieee_hdr.len + sizeof(IEEEtypes_Header_t),
5239 			pnew_rsnx->ieee_hdr.len + sizeof(IEEEtypes_Header_t));
5240 	DBG_HEXDUMP(MCMD_D, "MBSSID beacon buf", pbeacon_buf, beacon_buf_size);
5241 	ret = MLAN_STATUS_SUCCESS;
5242 done:
5243 	return ret;
5244 }
5245 
5246 /**
5247  *  @brief This function generate the bssid from bssid_idx
5248  *
5249  *  @param pmadpater        A pointer to mlan_adapter structure
5250  *  @param pbss_entry       A pointer to the bss_entry which has multi-bssid IE
5251  *  @param pnew_entry       A pinter to new entry
5252  *  @param bssid_index      bssid_index from BSSID_IDX IE
5253  *
5254  *  @return                N/A
5255  */
wlan_gen_multi_bssid_by_bssid_index(pmlan_adapter pmadapter,BSSDescriptor_t * pbss_entry,BSSDescriptor_t * pnew_entry,t_u8 bssid_index,t_u8 max_bssid_indicator)5256 static void wlan_gen_multi_bssid_by_bssid_index(pmlan_adapter pmadapter,
5257 						BSSDescriptor_t *pbss_entry,
5258 						BSSDescriptor_t *pnew_entry,
5259 						t_u8 bssid_index,
5260 						t_u8 max_bssid_indicator)
5261 {
5262 	t_u8 mask = 0xff;
5263 	t_u8 new_bssid[6];
5264 	t_u8 bssid_a;
5265 	t_u8 src_bssid[6];
5266 
5267 	memcpy_ext(pmadapter, (t_u8 *)src_bssid, pbss_entry->mac_address,
5268 		   sizeof(mlan_802_11_mac_addr), sizeof(src_bssid));
5269 	memcpy_ext(pmadapter, (t_u8 *)new_bssid,
5270 		   (t_u8 *)&pbss_entry->mac_address,
5271 		   sizeof(mlan_802_11_mac_addr), sizeof(new_bssid));
5272 
5273 	mask = (mask >> (8 - max_bssid_indicator));
5274 	bssid_a = src_bssid[5] & (~mask);
5275 	src_bssid[5] = (src_bssid[5] + bssid_index) & mask;
5276 	new_bssid[5] = bssid_a | src_bssid[5];
5277 
5278 	memcpy_ext(pmadapter, (t_u8 *)&pnew_entry->mac_address, new_bssid,
5279 		   sizeof(new_bssid), sizeof(mlan_802_11_mac_addr));
5280 	memcpy_ext(pmadapter, (t_u8 *)&pnew_entry->multi_bssid_ap_addr,
5281 		   (t_u8 *)&pbss_entry->mac_address,
5282 		   sizeof(mlan_802_11_mac_addr), sizeof(mlan_802_11_mac_addr));
5283 }
5284 
5285 /**
5286  *  @brief This function parse the non_trans_bssid_profile
5287  *
5288  *  @param pmadapter        A pointer to mlan_adapter structure
5289  *  @param pbss_entry       A pointer to BSSDescriptor_t which has multi-bssid
5290  * IE
5291  *  @param pbss_profile     A pointer to IEEEtypes_NonTransBSSIDprofile_t
5292  *  @param num_in_table     A pointer to buffer to save num of entry in scan
5293  * table.
5294  *  @param  max_bssid_indicator max bssid indicator
5295  *
5296  *  @return                 N/A
5297  */
wlan_parse_non_trans_bssid_profile(mlan_private * pmpriv,BSSDescriptor_t * pbss_entry,IEEEtypes_NonTransBSSIDProfile_t * pbss_profile,t_u32 * num_in_table,t_u8 max_bssid_indicator)5298 static t_void wlan_parse_non_trans_bssid_profile(
5299 	mlan_private *pmpriv, BSSDescriptor_t *pbss_entry,
5300 	IEEEtypes_NonTransBSSIDProfile_t *pbss_profile, t_u32 *num_in_table,
5301 	t_u8 max_bssid_indicator)
5302 {
5303 	mlan_adapter *pmadapter = pmpriv->adapter;
5304 	IEEEtypes_Header_t *pheader =
5305 		(IEEEtypes_Header_t *)pbss_profile->profile_data;
5306 	IEEEtypes_MultiBSSIDIndex_t *pbssid_index = MNULL;
5307 	IEEEtypes_Ssid_t *pssid = MNULL;
5308 	IEEEtypes_NotxBssCap_t *pcap =
5309 		(IEEEtypes_NotxBssCap_t *)pbss_profile->profile_data;
5310 	t_u8 *pos = pbss_profile->profile_data;
5311 	t_s8 left_len = pbss_profile->ieee_hdr.len;
5312 	t_u8 ret = MFALSE;
5313 	mlan_callbacks *pcb = (pmlan_callbacks)&pmadapter->callbacks;
5314 	BSSDescriptor_t *bss_new_entry = MNULL;
5315 	t_u8 *pbeacon_buf = MNULL;
5316 	IEEEtypes_ExtCap_t *pextcap = MNULL;
5317 	IEEEtypes_Generic_t *prsnx = MNULL;
5318 
5319 	ENTER();
5320 
5321 	/* The first element within the Nontransmitted
5322 	 * BSSID Profile is not the Nontransmitted
5323 	 * BSSID Capability element.
5324 	 */
5325 	if (pcap->element_id != NONTX_BSSID_CAP || pcap->len != 2) {
5326 		PRINTM(MERROR,
5327 		       "The first element within the Nontransmitted BSSID Profile is not the NontransmittedBSSID Capability element\n");
5328 		LEAVE();
5329 		return;
5330 	}
5331 
5332 	while (left_len >= 2) {
5333 		pheader = (IEEEtypes_Header_t *)pos;
5334 		if ((t_s8)(pheader->len + sizeof(IEEEtypes_Header_t)) >
5335 		    left_len) {
5336 			PRINTM(MMSG, "invalid IE length = %d left len %d\n",
5337 			       pheader->len, left_len);
5338 			break;
5339 		}
5340 		switch (pheader->element_id) {
5341 		case MBSSID_INDEX:
5342 			pbssid_index = (IEEEtypes_MultiBSSIDIndex_t *)pos;
5343 			if (pbssid_index->bssid_index == 0 ||
5344 			    pbssid_index->bssid_index > 46) {
5345 				PRINTM(MERROR,
5346 				       " No valid Multiple BSSID-Index element\n");
5347 				goto done;
5348 			}
5349 			PRINTM(MCMND, "MBSSID: Find mbssid_index=%d\n",
5350 			       pbssid_index->bssid_index);
5351 			ret = MTRUE;
5352 			break;
5353 		case EXT_CAPABILITY:
5354 			pextcap = (IEEEtypes_ExtCap_t *)pos;
5355 			DBG_HEXDUMP(MCMD_D, "MBSSID extcap", pos,
5356 				    pextcap->ieee_hdr.len +
5357 					    sizeof(IEEEtypes_Header_t));
5358 			break;
5359 		case RSNX_IE:
5360 			prsnx = (IEEEtypes_Generic_t *)pos;
5361 			DBG_HEXDUMP(MCMD_D, "MBSSID RSNX", pos,
5362 				    prsnx->ieee_hdr.len +
5363 					    sizeof(IEEEtypes_Header_t));
5364 			break;
5365 		case SSID:
5366 			pssid = (IEEEtypes_Ssid_t *)pos;
5367 			PRINTM(MCMND, "MBSSID: Find mbssid ssid=%s\n",
5368 			       pssid->ssid);
5369 			break;
5370 		default:
5371 			break;
5372 		}
5373 		left_len -= pheader->len + sizeof(IEEEtypes_Header_t);
5374 		pos += pheader->len + sizeof(IEEEtypes_Header_t);
5375 	}
5376 	if (ret == MTRUE) {
5377 		ret = pcb->moal_malloc(pmadapter->pmoal_handle,
5378 				       sizeof(BSSDescriptor_t), MLAN_MEM_DEF,
5379 				       (t_u8 **)&bss_new_entry);
5380 		if (ret != MLAN_STATUS_SUCCESS || !bss_new_entry) {
5381 			PRINTM(MERROR,
5382 			       "Memory allocation for bss_new_entry failed!\n");
5383 			goto done;
5384 		}
5385 		memcpy_ext(pmadapter, bss_new_entry, pbss_entry,
5386 			   sizeof(BSSDescriptor_t), sizeof(BSSDescriptor_t));
5387 		wlan_gen_multi_bssid_by_bssid_index(pmadapter, pbss_entry,
5388 						    bss_new_entry,
5389 						    pbssid_index->bssid_index,
5390 						    max_bssid_indicator);
5391 		if (pssid) {
5392 			memset(pmadapter, (t_u8 *)&bss_new_entry->ssid, 0,
5393 			       sizeof(mlan_802_11_ssid));
5394 			bss_new_entry->ssid.ssid_len = pssid->len;
5395 			memcpy_ext(pmadapter, bss_new_entry->ssid.ssid,
5396 				   pssid->ssid, pssid->len,
5397 				   MLAN_MAX_SSID_LENGTH);
5398 			if (MLAN_STATUS_SUCCESS !=
5399 			    wlan_update_ssid_in_beacon_buf(
5400 				    pmadapter, pbss_entry, bss_new_entry, pssid,
5401 				    pextcap, prsnx)) {
5402 				PRINTM(MERROR,
5403 				       "Fail to update MBSSID beacon buf\n");
5404 				pcb->moal_mfree(pmadapter->pmoal_handle,
5405 						(t_u8 *)bss_new_entry);
5406 				goto done;
5407 			}
5408 			pbeacon_buf = bss_new_entry->pbeacon_buf;
5409 		}
5410 		memcpy_ext(pmadapter, &bss_new_entry->cap_info, &pcap->cap,
5411 			   sizeof(IEEEtypes_CapInfo_t),
5412 			   sizeof(IEEEtypes_CapInfo_t));
5413 		bss_new_entry->multi_bssid_ap = MULTI_BSSID_SUB_AP;
5414 		wlan_add_new_entry_to_scan_table(pmpriv, bss_new_entry,
5415 						 num_in_table);
5416 		if (pssid && pbeacon_buf)
5417 			pcb->moal_mfree(pmadapter->pmoal_handle,
5418 					(t_u8 *)pbeacon_buf);
5419 		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)bss_new_entry);
5420 	}
5421 done:
5422 	LEAVE();
5423 	return;
5424 }
5425 
5426 /**
5427  *  @brief This function parse the multi_bssid IE from pbss_entry
5428  *
5429  *  @param pmpriv        A pointer to mlan_private structure
5430  *  @param pbss_entry       A pointer to BSSDescriptor_t which has multi-bssid
5431  * IE
5432  *  @param num_in_table     A pointer to buffer to save num of entry in scan
5433  * table.
5434  *
5435  *  @return                 number entry in scan table
5436  */
wlan_parse_multi_bssid_ie(mlan_private * pmpriv,BSSDescriptor_t * pbss_entry,IEEEtypes_MultiBSSID_t * pmulti_bssid,t_u32 * num_in_table)5437 static t_void wlan_parse_multi_bssid_ie(mlan_private *pmpriv,
5438 					BSSDescriptor_t *pbss_entry,
5439 					IEEEtypes_MultiBSSID_t *pmulti_bssid,
5440 					t_u32 *num_in_table)
5441 {
5442 	t_u32 bytes_left = 0;
5443 	t_u8 *pcurrent_ptr = MNULL;
5444 	IEEEtypes_NonTransBSSIDProfile_t *pbssid_profile = MNULL;
5445 
5446 	if (!pmulti_bssid)
5447 		return;
5448 	bytes_left = pmulti_bssid->ieee_hdr.len - 1;
5449 	pcurrent_ptr = pmulti_bssid->sub_elem_data;
5450 	while (bytes_left >= 2) {
5451 		pbssid_profile =
5452 			(IEEEtypes_NonTransBSSIDProfile_t *)pcurrent_ptr;
5453 		if (pbssid_profile->ieee_hdr.element_id !=
5454 		    NONTRANS_BSSID_PROFILE_SUBELEM_ID) {
5455 			PRINTM(MERROR, "Invalid multi-bssid IE\n");
5456 			break;
5457 		}
5458 		if (bytes_left < (t_u32)(pbssid_profile->ieee_hdr.len + 2)) {
5459 			PRINTM(MERROR, "Invalid multi-bssid IE\n");
5460 			break;
5461 		}
5462 		wlan_parse_non_trans_bssid_profile(
5463 			pmpriv, pbss_entry, pbssid_profile, num_in_table,
5464 			pmulti_bssid->max_bssid_indicator);
5465 		pcurrent_ptr += pbssid_profile->ieee_hdr.len + 2;
5466 		bytes_left -= pbssid_profile->ieee_hdr.len + 2;
5467 	}
5468 	return;
5469 }
5470 
5471 /**
5472  *  @brief This function search all the mbssid IE in the beacon buffer
5473  *
5474  *  @param pmpriv           A pointer to mlan_private structure
5475  *  @param pbss_entry       A pointer to BSSDescriptor_t which has multi-bssid
5476  * IE
5477  *  @param num_in_table     A pointer to buffer to save num of entry in scan
5478  * table.
5479  *
5480  *  @return                 N/A
5481  */
wlan_parse_multi_bssid_ap(mlan_private * pmpriv,BSSDescriptor_t * pbss_entry,t_u32 * num_in_table)5482 static void wlan_parse_multi_bssid_ap(mlan_private *pmpriv,
5483 				      BSSDescriptor_t *pbss_entry,
5484 				      t_u32 *num_in_table)
5485 {
5486 	IEEEtypes_ElementId_e element_id;
5487 	t_u8 element_len;
5488 	t_u16 total_ie_len;
5489 	t_u32 bytes_left = pbss_entry->beacon_buf_size - BEACON_FIX_SIZE;
5490 	t_u8 *pcurrent_ptr = pbss_entry->pbeacon_buf + BEACON_FIX_SIZE;
5491 	IEEEtypes_Ssid_t *pssid = (IEEEtypes_Ssid_t *)pcurrent_ptr;
5492 
5493 	if (pssid->element_id != SSID) {
5494 		PRINTM(MERROR,
5495 		       "Invalid beacon ie, ssid should be in the first element\n");
5496 		return;
5497 	}
5498 	/* Process variable IE */
5499 	while (bytes_left >= 2) {
5500 		element_id = (IEEEtypes_ElementId_e)(*((t_u8 *)pcurrent_ptr));
5501 		element_len = *((t_u8 *)pcurrent_ptr + 1);
5502 		total_ie_len = element_len + sizeof(IEEEtypes_Header_t);
5503 
5504 		if (bytes_left < total_ie_len) {
5505 			PRINTM(MERROR, "InterpretIE: Error in processing IE, "
5506 				       "bytes left < IE length\n");
5507 			bytes_left = 0;
5508 			continue;
5509 		}
5510 		if (element_id == MULTI_BSSID)
5511 			wlan_parse_multi_bssid_ie(
5512 				pmpriv, pbss_entry,
5513 				(IEEEtypes_MultiBSSID_t *)pcurrent_ptr,
5514 				num_in_table);
5515 		pcurrent_ptr += total_ie_len;
5516 		bytes_left -= total_ie_len;
5517 	}
5518 	return;
5519 }
5520 
5521 /**
5522  *  @brief This function parse and store the extended scan results
5523  *
5524  *  @param pmpriv           A pointer to mlan_private structure
5525  *  @param number_of_sets   Number of BSS
5526  *  @param pscan_resp       A pointer to scan response buffer
5527  *  @param scan_resp_size   Size of scan response buffer
5528  *
5529  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
5530  */
wlan_parse_ext_scan_result(mlan_private * pmpriv,t_u8 number_of_sets,t_u8 * pscan_resp,t_u16 scan_resp_size)5531 static mlan_status wlan_parse_ext_scan_result(mlan_private *pmpriv,
5532 					      t_u8 number_of_sets,
5533 					      t_u8 *pscan_resp,
5534 					      t_u16 scan_resp_size)
5535 {
5536 	mlan_status ret = MLAN_STATUS_SUCCESS;
5537 	mlan_adapter *pmadapter = pmpriv->adapter;
5538 	mlan_callbacks *pcb = MNULL;
5539 	BSSDescriptor_t *bss_new_entry = MNULL;
5540 	t_u8 *pbss_info;
5541 	t_u32 bytes_left;
5542 	t_u32 bytes_left_for_tlv;
5543 	t_u32 num_in_table;
5544 	t_u32 idx;
5545 	t_u64 tsf_val;
5546 	chan_freq_power_t *cfp;
5547 	t_u16 tlv_type, tlv_len;
5548 	MrvlIEtypes_Data_t *ptlv = MNULL;
5549 	MrvlIEtypes_Bss_Scan_Rsp_t *pscan_rsp_tlv = MNULL;
5550 	MrvlIEtypes_Bss_Scan_Info_t *pscan_info_tlv = MNULL;
5551 	t_u16 band;
5552 	t_u32 age_ts_usec;
5553 
5554 	ENTER();
5555 	pcb = (pmlan_callbacks)&pmadapter->callbacks;
5556 
5557 	if (number_of_sets > MRVDRV_MAX_BSSID_LIST) {
5558 		PRINTM(MERROR,
5559 		       "EXT_SCAN: Invalid number of AP returned (%d)!!\n",
5560 		       number_of_sets);
5561 		ret = MLAN_STATUS_FAILURE;
5562 		goto done;
5563 	}
5564 
5565 	bytes_left = scan_resp_size;
5566 	PRINTM(MINFO, "EXT_SCAN: bss_descript_size %d\n", scan_resp_size);
5567 	PRINTM(MINFO, "EXT_SCAN: returned %d APs before parsing\n",
5568 	       number_of_sets);
5569 	/* Update the age_in_second */
5570 	pmadapter->callbacks.moal_get_system_time(
5571 		pmadapter->pmoal_handle, &pmadapter->age_in_secs, &age_ts_usec);
5572 
5573 	num_in_table = pmadapter->num_in_scan_table;
5574 	ptlv = (MrvlIEtypes_Data_t *)pscan_resp;
5575 
5576 	/*
5577 	 *  Process each scan response returned number_of_sets. Save
5578 	 *    the information in the bss_new_entry and then insert into the
5579 	 *    driver scan table either as an update to an existing entry
5580 	 *    or as an addition at the end of the table
5581 	 */
5582 	ret = pcb->moal_malloc(pmadapter->pmoal_handle, sizeof(BSSDescriptor_t),
5583 			       MLAN_MEM_DEF, (t_u8 **)&bss_new_entry);
5584 
5585 	if (ret != MLAN_STATUS_SUCCESS || !bss_new_entry) {
5586 		PRINTM(MERROR, "Memory allocation for bss_new_entry failed!\n");
5587 		ret = MLAN_STATUS_FAILURE;
5588 		goto done;
5589 	}
5590 
5591 	for (idx = 0;
5592 	     idx < number_of_sets && bytes_left > sizeof(MrvlIEtypesHeader_t);
5593 	     idx++) {
5594 		tlv_type = wlan_le16_to_cpu(ptlv->header.type);
5595 		tlv_len = wlan_le16_to_cpu(ptlv->header.len);
5596 		if (bytes_left < sizeof(MrvlIEtypesHeader_t) + tlv_len) {
5597 			PRINTM(MERROR,
5598 			       "EXT_SCAN: Error bytes left < TLV length\n");
5599 			break;
5600 		}
5601 		pscan_rsp_tlv = MNULL;
5602 		pscan_info_tlv = MNULL;
5603 		bytes_left_for_tlv = bytes_left;
5604 		/*
5605 		 * BSS response TLV with beacon or probe response buffer
5606 		 * at the initial position of each descriptor
5607 		 */
5608 		if (tlv_type == TLV_TYPE_BSS_SCAN_RSP) {
5609 			pbss_info = (t_u8 *)ptlv;
5610 			pscan_rsp_tlv = (MrvlIEtypes_Bss_Scan_Rsp_t *)ptlv;
5611 			ptlv = (MrvlIEtypes_Data_t *)(ptlv->data + tlv_len);
5612 			bytes_left_for_tlv -=
5613 				(tlv_len + sizeof(MrvlIEtypesHeader_t));
5614 		} else
5615 			break;
5616 
5617 		/* Process variable TLV */
5618 		while (bytes_left_for_tlv >= sizeof(MrvlIEtypesHeader_t) &&
5619 		       wlan_le16_to_cpu(ptlv->header.type) !=
5620 			       TLV_TYPE_BSS_SCAN_RSP) {
5621 			tlv_type = wlan_le16_to_cpu(ptlv->header.type);
5622 			tlv_len = wlan_le16_to_cpu(ptlv->header.len);
5623 			if (bytes_left_for_tlv <
5624 			    sizeof(MrvlIEtypesHeader_t) + tlv_len) {
5625 				PRINTM(MERROR,
5626 				       "EXT_SCAN: Error in processing TLV, "
5627 				       "bytes left < TLV length\n");
5628 				pscan_rsp_tlv = MNULL;
5629 				bytes_left_for_tlv = 0;
5630 				continue;
5631 			}
5632 			switch (tlv_type) {
5633 			case TLV_TYPE_BSS_SCAN_INFO:
5634 				pscan_info_tlv =
5635 					(MrvlIEtypes_Bss_Scan_Info_t *)ptlv;
5636 				if (tlv_len !=
5637 				    sizeof(MrvlIEtypes_Bss_Scan_Info_t) -
5638 					    sizeof(MrvlIEtypesHeader_t)) {
5639 					bytes_left_for_tlv = 0;
5640 					continue;
5641 				}
5642 				break;
5643 			default:
5644 				break;
5645 			}
5646 			ptlv = (MrvlIEtypes_Data_t *)(ptlv->data + tlv_len);
5647 			bytes_left -= (tlv_len + sizeof(MrvlIEtypesHeader_t));
5648 			bytes_left_for_tlv -=
5649 				(tlv_len + sizeof(MrvlIEtypesHeader_t));
5650 		}
5651 		/* No BSS response TLV */
5652 		if (pscan_rsp_tlv == MNULL)
5653 			break;
5654 
5655 		/*
5656 		 * Advance pointer to the beacon buffer length and
5657 		 * update the bytes count so that the function
5658 		 * wlan_interpret_bss_desc_with_ie() can handle the
5659 		 * scan buffer withut any change
5660 		 */
5661 		pbss_info += sizeof(t_u16);
5662 		bytes_left -= sizeof(t_u16);
5663 
5664 		/* Zero out the bss_new_entry we are about to store info in */
5665 		memset(pmadapter, bss_new_entry, 0x00, sizeof(BSSDescriptor_t));
5666 
5667 		/* Process the data fields and IEs returned for this BSS */
5668 		if (wlan_interpret_bss_desc_with_ie(
5669 			    pmadapter, bss_new_entry, &pbss_info, &bytes_left,
5670 			    MTRUE) == MLAN_STATUS_SUCCESS) {
5671 			PRINTM(MINFO, "EXT_SCAN: BSSID = " MACSTR "\n",
5672 			       MAC2STR(bss_new_entry->mac_address));
5673 
5674 			band = BAND_G;
5675 			/*
5676 			 * If the BSS info TLV was appended to the scan results,
5677 			 * save this entry's TSF value in the networkTSF field.
5678 			 * The networkTSF is the firmware's TSF value at the
5679 			 * time the beacon or probe response was received.
5680 			 */
5681 			if (pscan_info_tlv) {
5682 				/* RSSI is 2 byte long */
5683 				bss_new_entry->rssi = -(t_s32)(
5684 					wlan_le16_to_cpu(pscan_info_tlv->rssi));
5685 				PRINTM(MINFO, "EXT_SCAN: RSSI=%d\n",
5686 				       bss_new_entry->rssi);
5687 				memcpy_ext(pmpriv->adapter, &tsf_val,
5688 					   &pscan_info_tlv->tsf,
5689 					   sizeof(tsf_val), sizeof(tsf_val));
5690 				tsf_val = wlan_le64_to_cpu(tsf_val);
5691 				memcpy_ext(pmpriv->adapter,
5692 					   &bss_new_entry->network_tsf,
5693 					   &tsf_val,
5694 					   sizeof(bss_new_entry->network_tsf),
5695 					   sizeof(bss_new_entry->network_tsf));
5696 				band = radio_type_to_band(
5697 					pscan_info_tlv->bandcfg.chanBand);
5698 				if (!bss_new_entry->channel)
5699 					bss_new_entry->channel =
5700 						pscan_info_tlv->channel;
5701 			}
5702 			/* Save the band designation for this entry for use in
5703 			 * join */
5704 			bss_new_entry->bss_band = band;
5705 			bss_new_entry->age_in_secs = pmadapter->age_in_secs;
5706 
5707 			cfp = wlan_find_cfp_by_band_and_channel(
5708 				pmadapter, bss_new_entry->bss_band,
5709 				(t_u16)bss_new_entry->channel);
5710 			if (cfp)
5711 				bss_new_entry->freq = cfp->freq;
5712 			else
5713 				bss_new_entry->freq = 0;
5714 
5715 			/* Skip entry if on blacklisted channel */
5716 			if (cfp && cfp->dynamic.blacklist) {
5717 				PRINTM(MINFO,
5718 				       "EXT_SCAN: dropping entry on blacklist channel.\n");
5719 				continue;
5720 			}
5721 			if (IS_FW_SUPPORT_MULTIBSSID(pmadapter)) {
5722 				if (bss_new_entry->multi_bssid_ap ==
5723 				    MULTI_BSSID_AP)
5724 					wlan_parse_multi_bssid_ap(
5725 						pmpriv, bss_new_entry,
5726 						&num_in_table);
5727 			}
5728 			wlan_add_new_entry_to_scan_table(pmpriv, bss_new_entry,
5729 							 &num_in_table);
5730 
5731 		} else {
5732 			/* Error parsing/interpreting the scan response, skipped
5733 			 */
5734 			PRINTM(MERROR,
5735 			       "EXT_SCAN: wlan_interpret_bss_desc_with_ie returned error\n");
5736 		}
5737 	}
5738 
5739 	PRINTM(MCMND, "EXT_SCAN: Scanned %2d APs, %d valid, %d total\n",
5740 	       number_of_sets, num_in_table - pmadapter->num_in_scan_table,
5741 	       num_in_table);
5742 
5743 	/* Update the total number of BSSIDs in the scan table */
5744 	pmadapter->num_in_scan_table = num_in_table;
5745 	/* Update the age_in_second */
5746 	pmadapter->callbacks.moal_get_system_time(
5747 		pmadapter->pmoal_handle, &pmadapter->age_in_secs, &age_ts_usec);
5748 
5749 done:
5750 	if (bss_new_entry)
5751 		pcb->moal_mfree(pmadapter->pmoal_handle, (t_u8 *)bss_new_entry);
5752 
5753 	LEAVE();
5754 	return ret;
5755 }
5756 
5757 /**
5758  *  @brief This function handles the event extended scan report
5759  *
5760  *  @param pmpriv       A pointer to mlan_private structure
5761  *  @param pmbuf        A pointer to mlan_buffer
5762  *
5763  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
5764  */
wlan_handle_event_ext_scan_report(mlan_private * pmpriv,mlan_buffer * pmbuf)5765 mlan_status wlan_handle_event_ext_scan_report(mlan_private *pmpriv,
5766 					      mlan_buffer *pmbuf)
5767 {
5768 	mlan_adapter *pmadapter = pmpriv->adapter;
5769 	mlan_callbacks *pcb = &pmadapter->callbacks;
5770 	mlan_ioctl_req *pioctl_req = MNULL;
5771 	cmd_ctrl_node *pcmd_node = MNULL;
5772 	mlan_status ret = MLAN_STATUS_SUCCESS;
5773 
5774 	mlan_event_scan_result *pevent_scan =
5775 		(pmlan_event_scan_result)(pmbuf->pbuf + pmbuf->data_offset);
5776 	t_u8 *ptlv = (pmbuf->pbuf + pmbuf->data_offset +
5777 		      sizeof(mlan_event_scan_result));
5778 	t_u16 tlv_buf_left = wlan_le16_to_cpu(pevent_scan->buf_size);
5779 
5780 	DBG_HEXDUMP(MCMD_D, "EVENT EXT_SCAN", pmbuf->pbuf + pmbuf->data_offset,
5781 		    pmbuf->data_len);
5782 
5783 	if (!pevent_scan->more_event)
5784 		pmadapter->scan_state |= SCAN_STATE_EXT_SCAN_RESULT |
5785 					 SCAN_STATE_LAST_EXT_SCAN_RESULT;
5786 	else
5787 		pmadapter->scan_state |= SCAN_STATE_EXT_SCAN_RESULT;
5788 
5789 	wlan_parse_ext_scan_result(pmpriv, pevent_scan->num_of_set, ptlv,
5790 				   tlv_buf_left);
5791 	if (!pevent_scan->more_event &&
5792 	    (pmadapter->ext_scan_type != EXT_SCAN_ENHANCE)) {
5793 		wlan_request_cmd_lock(pmadapter);
5794 		if (!util_peek_list(pmadapter->pmoal_handle,
5795 				    &pmadapter->scan_pending_q, MNULL, MNULL)) {
5796 			wlan_release_cmd_lock(pmadapter);
5797 			if (pmadapter->pscan_ioctl_req) {
5798 				if (((mlan_ds_scan *)
5799 					     pmadapter->pscan_ioctl_req->pbuf)
5800 						    ->sub_command ==
5801 					    MLAN_OID_SCAN_SPECIFIC_SSID ||
5802 				    ((mlan_ds_scan *)
5803 					     pmadapter->pscan_ioctl_req->pbuf)
5804 						    ->sub_command ==
5805 					    MLAN_OID_SCAN_USER_CONFIG) {
5806 					if (wlan_active_scan_req_for_passive_chan(
5807 						    pmpriv,
5808 						    pmadapter->pscan_ioctl_req)) {
5809 						LEAVE();
5810 						return ret;
5811 					}
5812 				}
5813 			}
5814 			/*
5815 			 * Process the resulting scan table:
5816 			 *   - Remove any bad ssids
5817 			 *   - Update our current BSS information from scan data
5818 			 */
5819 			wlan_scan_process_results(pmpriv);
5820 			wlan_request_cmd_lock(pmadapter);
5821 			pmadapter->scan_processing = MFALSE;
5822 			pmadapter->scan_state |= SCAN_STATE_SCAN_COMPLETE;
5823 			pioctl_req = pmadapter->pscan_ioctl_req;
5824 			pmadapter->pscan_ioctl_req = MNULL;
5825 			/* Need to indicate IOCTL complete */
5826 			if (pioctl_req != MNULL) {
5827 				pioctl_req->status_code = MLAN_ERROR_NO_ERROR;
5828 				/* Indicate ioctl complete */
5829 				pcb->moal_ioctl_complete(
5830 					pmadapter->pmoal_handle,
5831 					(pmlan_ioctl_req)pioctl_req,
5832 					MLAN_STATUS_SUCCESS);
5833 			}
5834 			wlan_release_cmd_lock(pmadapter);
5835 
5836 			pmadapter->bgscan_reported = MFALSE;
5837 			wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_SCAN_REPORT,
5838 					MNULL);
5839 		} else {
5840 			/* If firmware not ready, do not issue any more scan
5841 			 * commands */
5842 			if (pmadapter->hw_status != WlanHardwareStatusReady) {
5843 				wlan_release_cmd_lock(pmadapter);
5844 				/* Flush all pending scan commands */
5845 				wlan_flush_scan_queue(pmadapter);
5846 				wlan_request_cmd_lock(pmadapter);
5847 				pmadapter->scan_processing = MFALSE;
5848 				pmadapter->scan_state |=
5849 					SCAN_STATE_SCAN_COMPLETE;
5850 
5851 				pioctl_req = pmadapter->pscan_ioctl_req;
5852 				pmadapter->pscan_ioctl_req = MNULL;
5853 				/* Indicate IOCTL complete */
5854 				if (pioctl_req != MNULL) {
5855 					pioctl_req->status_code =
5856 						MLAN_ERROR_FW_NOT_READY;
5857 
5858 					/* Indicate ioctl complete */
5859 					pcb->moal_ioctl_complete(
5860 						pmadapter->pmoal_handle,
5861 						(pmlan_ioctl_req)pioctl_req,
5862 						MLAN_STATUS_FAILURE);
5863 				}
5864 				wlan_release_cmd_lock(pmadapter);
5865 			} else {
5866 				/* Get scan command from scan_pending_q and put
5867 				 * to cmd_pending_q */
5868 				pcmd_node = (cmd_ctrl_node *)util_dequeue_list(
5869 					pmadapter->pmoal_handle,
5870 					&pmadapter->scan_pending_q, MNULL,
5871 					MNULL);
5872 				wlan_insert_cmd_to_pending_q(pmadapter,
5873 							     pcmd_node, MTRUE);
5874 				wlan_release_cmd_lock(pmadapter);
5875 			}
5876 		}
5877 	}
5878 	LEAVE();
5879 	return ret;
5880 }
5881 
5882 /**
5883  *  @brief This function handles the event extended scan status
5884  *
5885  *  @param pmpriv       A pointer to mlan_private structure
5886  *  @param pmbuf        A pointer to mlan_buffer
5887  *
5888  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
5889  */
wlan_handle_event_ext_scan_status(mlan_private * pmpriv,mlan_buffer * pmbuf)5890 mlan_status wlan_handle_event_ext_scan_status(mlan_private *pmpriv,
5891 					      mlan_buffer *pmbuf)
5892 {
5893 	mlan_adapter *pmadapter = pmpriv->adapter;
5894 	mlan_status ret = MLAN_STATUS_SUCCESS;
5895 	mlan_event_scan_status *scan_event;
5896 	mlan_ioctl_req *pioctl_req;
5897 	mlan_callbacks *pcb = (mlan_callbacks *)&pmadapter->callbacks;
5898 	t_u16 tlv_buf_left, tlv_len, tlv_type;
5899 	MrvlIEtypesHeader_t *tlv;
5900 	MrvlIEtypes_ChannelStats_t *tlv_chan_stats;
5901 	t_u8 status;
5902 	cmd_ctrl_node *pcmd_node = MNULL;
5903 
5904 	ENTER();
5905 
5906 	if (pmbuf->data_len < sizeof(mlan_event_scan_status)) {
5907 		PRINTM(MERROR, "Wrong ext scan status event data length\n");
5908 		ret = MLAN_STATUS_FAILURE;
5909 		goto done;
5910 	}
5911 	pmadapter->scan_state |= SCAN_STATE_EXT_SCAN_STATUS;
5912 
5913 	scan_event =
5914 		(pmlan_event_scan_status)(pmbuf->pbuf + pmbuf->data_offset);
5915 	DBG_HEXDUMP(MCMD_D, "EVENT: Ext_Scan_Status", scan_event,
5916 		    pmbuf->data_len);
5917 	status = scan_event->scan_status;
5918 	PRINTM(MEVENT, "ext_scan_status: status %d (scan %s), buf_len %d\n",
5919 	       status, status ? "cancelled" : "success", scan_event->buf_len);
5920 
5921 	tlv = (MrvlIEtypesHeader_t *)scan_event->event_buf;
5922 	tlv_buf_left = pmbuf->data_len - sizeof(mlan_event_scan_status);
5923 	while (tlv_buf_left >= sizeof(MrvlIEtypesHeader_t)) {
5924 		tlv_type = wlan_le16_to_cpu(tlv->type);
5925 		tlv_len = wlan_le16_to_cpu(tlv->len);
5926 		if (tlv_buf_left < (tlv_len + sizeof(MrvlIEtypesHeader_t))) {
5927 			PRINTM(MERROR,
5928 			       "Error process scan gap tlv: length %d type 0x%x\n",
5929 			       tlv_len, tlv_type);
5930 			ret = MLAN_STATUS_FAILURE;
5931 			goto done;
5932 		}
5933 		switch (tlv_type) {
5934 		case TLV_TYPE_CHANNEL_STATS:
5935 			tlv_chan_stats = (MrvlIEtypes_ChannelStats_t *)tlv;
5936 			wlan_update_chan_statistics(pmpriv, tlv_chan_stats);
5937 			break;
5938 		default:
5939 			break;
5940 		}
5941 		tlv_buf_left -= tlv_len + sizeof(MrvlIEtypesHeader_t);
5942 		tlv = (MrvlIEtypesHeader_t *)((t_u8 *)tlv + tlv_len +
5943 					      sizeof(MrvlIEtypesHeader_t));
5944 	}
5945 
5946 done:
5947 	wlan_request_cmd_lock(pmadapter);
5948 	if (util_peek_list(pmadapter->pmoal_handle, &pmadapter->scan_pending_q,
5949 			   MNULL, MNULL)) {
5950 		/* If firmware not ready, do not issue any more scan
5951 		 * commands */
5952 		if (pmadapter->hw_status != WlanHardwareStatusReady) {
5953 			wlan_release_cmd_lock(pmadapter);
5954 			/* Flush all pending scan commands */
5955 			wlan_flush_scan_queue(pmadapter);
5956 			wlan_request_cmd_lock(pmadapter);
5957 			pmadapter->scan_processing = MFALSE;
5958 			pmadapter->scan_state |= SCAN_STATE_SCAN_COMPLETE;
5959 			pioctl_req = pmadapter->pscan_ioctl_req;
5960 			pmadapter->pscan_ioctl_req = MNULL;
5961 			/* Indicate IOCTL complete */
5962 			if (pioctl_req != MNULL) {
5963 				pioctl_req->status_code =
5964 					MLAN_ERROR_FW_NOT_READY;
5965 
5966 				/* Indicate ioctl complete */
5967 				pcb->moal_ioctl_complete(
5968 					pmadapter->pmoal_handle,
5969 					(pmlan_ioctl_req)pioctl_req,
5970 					MLAN_STATUS_FAILURE);
5971 			}
5972 			wlan_release_cmd_lock(pmadapter);
5973 		} else {
5974 			/* Get scan command from scan_pending_q and put
5975 			 * to cmd_pending_q */
5976 			pcmd_node = (cmd_ctrl_node *)util_dequeue_list(
5977 				pmadapter->pmoal_handle,
5978 				&pmadapter->scan_pending_q, MNULL, MNULL);
5979 			wlan_insert_cmd_to_pending_q(pmadapter, pcmd_node,
5980 						     MTRUE);
5981 			wlan_release_cmd_lock(pmadapter);
5982 		}
5983 		LEAVE();
5984 		return ret;
5985 	}
5986 	wlan_release_cmd_lock(pmadapter);
5987 
5988 	/* Now we got response from FW, cancel the command timer */
5989 	if (!pmadapter->curr_cmd && pmadapter->cmd_timer_is_set) {
5990 		/* Cancel command timeout timer */
5991 		pcb->moal_stop_timer(pmadapter->pmoal_handle,
5992 				     pmadapter->pmlan_cmd_timer);
5993 		/* Cancel command timeout timer */
5994 		pmadapter->cmd_timer_is_set = MFALSE;
5995 	}
5996 	if (pmadapter->pscan_ioctl_req) {
5997 		if (((mlan_ds_scan *)pmadapter->pscan_ioctl_req->pbuf)
5998 				    ->sub_command ==
5999 			    MLAN_OID_SCAN_SPECIFIC_SSID ||
6000 		    ((mlan_ds_scan *)pmadapter->pscan_ioctl_req->pbuf)
6001 				    ->sub_command ==
6002 			    MLAN_OID_SCAN_USER_CONFIG) {
6003 			if (wlan_active_scan_req_for_passive_chan(
6004 				    pmpriv, pmadapter->pscan_ioctl_req)) {
6005 				LEAVE();
6006 				return ret;
6007 			}
6008 		}
6009 	}
6010 	/*
6011 	 * Process the resulting scan table:
6012 	 *   - Remove any bad ssids
6013 	 *   - Update our current BSS information from scan data
6014 	 */
6015 	wlan_scan_process_results(pmpriv);
6016 	/** Complete scan ioctl */
6017 	wlan_request_cmd_lock(pmadapter);
6018 	pmadapter->scan_processing = MFALSE;
6019 	pmadapter->scan_state |= SCAN_STATE_SCAN_COMPLETE;
6020 	pioctl_req = pmadapter->pscan_ioctl_req;
6021 	pmadapter->pscan_ioctl_req = MNULL;
6022 	/* Need to indicate IOCTL complete */
6023 	if (pioctl_req != MNULL) {
6024 		pioctl_req->status_code = MLAN_ERROR_NO_ERROR;
6025 		/* Indicate ioctl complete */
6026 		pcb->moal_ioctl_complete(pmadapter->pmoal_handle, pioctl_req,
6027 					 MLAN_STATUS_SUCCESS);
6028 	}
6029 	wlan_release_cmd_lock(pmadapter);
6030 	wlan_move_cmd_to_cmd_pending_q(pmadapter);
6031 	pmadapter->bgscan_reported = MFALSE;
6032 	wlan_recv_event(pmpriv, MLAN_EVENT_ID_DRV_SCAN_REPORT, MNULL);
6033 	LEAVE();
6034 	return ret;
6035 }
6036 
6037 /**
6038  *  @brief This function prepares command of bg_scan_query.
6039  *
6040  *  @param pmpriv     A pointer to mlan_private structure
6041  *  @param pcmd       A pointer to HostCmd_DS_COMMAND structure
6042  *  @param pdata_buf  Void pointer cast of a wlan_scan_cmd_config struct used
6043  *                    to set the fields/TLVs for the command sent to firmware
6044  *
6045  *  @return           MLAN_STATUS_SUCCESS
6046  */
wlan_cmd_802_11_bg_scan_query(mlan_private * pmpriv,HostCmd_DS_COMMAND * pcmd,t_void * pdata_buf)6047 mlan_status wlan_cmd_802_11_bg_scan_query(mlan_private *pmpriv,
6048 					  HostCmd_DS_COMMAND *pcmd,
6049 					  t_void *pdata_buf)
6050 {
6051 	HostCmd_DS_802_11_BG_SCAN_QUERY *bg_query = &pcmd->params.bg_scan_query;
6052 
6053 	ENTER();
6054 
6055 	pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_QUERY);
6056 	pcmd->size = wlan_cpu_to_le16(sizeof(HostCmd_DS_802_11_BG_SCAN_QUERY) +
6057 				      S_DS_GEN);
6058 
6059 	bg_query->flush = MTRUE;
6060 
6061 	LEAVE();
6062 	return MLAN_STATUS_SUCCESS;
6063 }
6064 
6065 /**
6066  *  @brief Create a channel list for the driver to scan based on region info
6067  *
6068  *  Use the driver region/band information to construct a comprehensive list
6069  *    of channels to scan.  This routine is used for any scan that is not
6070  *    provided a specific channel list to scan.
6071  *
6072  *  @param pmpriv           A pointer to mlan_private structure
6073  *  @param pbg_scan_in      pointer to scan configuration parameters
6074  *  @param tlv_chan_list    A pointer to structure
6075  * MrvlIEtypes_ChanListParamSet_t
6076  *
6077  *  @return                 channel number
6078  */
6079 static t_u8
wlan_bgscan_create_channel_list(mlan_private * pmpriv,const wlan_bgscan_cfg * pbg_scan_in,MrvlIEtypes_ChanListParamSet_t * tlv_chan_list)6080 wlan_bgscan_create_channel_list(mlan_private *pmpriv,
6081 				const wlan_bgscan_cfg *pbg_scan_in,
6082 				MrvlIEtypes_ChanListParamSet_t *tlv_chan_list)
6083 {
6084 	mlan_adapter *pmadapter = pmpriv->adapter;
6085 	region_chan_t *pscan_region;
6086 	chan_freq_power_t *cfp;
6087 	t_u32 region_idx;
6088 	t_u32 chan_idx = 0;
6089 	t_u32 next_chan;
6090 	t_u8 scan_type;
6091 	t_u8 radio_type;
6092 	t_u16 band;
6093 
6094 	ENTER();
6095 
6096 	for (region_idx = 0; region_idx < NELEMENTS(pmadapter->region_channel);
6097 	     region_idx++) {
6098 		if (wlan_11d_is_enabled(pmpriv) &&
6099 		    pmpriv->media_connected != MTRUE) {
6100 			/* Scan all the supported chan for the first scan */
6101 			if (!pmadapter->universal_channel[region_idx].valid)
6102 				continue;
6103 			pscan_region =
6104 				&pmadapter->universal_channel[region_idx];
6105 		} else {
6106 			if (!pmadapter->region_channel[region_idx].valid)
6107 				continue;
6108 			pscan_region = &pmadapter->region_channel[region_idx];
6109 		}
6110 
6111 		if (pbg_scan_in && !pbg_scan_in->chan_list[0].chan_number &&
6112 		    pbg_scan_in->chan_list[0].radio_type & BAND_SPECIFIED) {
6113 			radio_type = pbg_scan_in->chan_list[0].radio_type &
6114 				     ~BAND_SPECIFIED;
6115 			if (!radio_type && (pscan_region->band != BAND_B) &&
6116 			    (pscan_region->band != BAND_G))
6117 				continue;
6118 			if (radio_type && (pscan_region->band != BAND_A))
6119 				continue;
6120 		}
6121 		if ((pbg_scan_in &&
6122 		     (pbg_scan_in->bss_type == MLAN_SCAN_MODE_IBSS)) ||
6123 		    pmpriv->bss_mode == MLAN_BSS_MODE_IBSS)
6124 			band = pmadapter->adhoc_start_band;
6125 		else
6126 			band = pmpriv->config_bands;
6127 		if (!wlan_is_band_compatible(band, pscan_region->band))
6128 			continue;
6129 		for (next_chan = 0; next_chan < pscan_region->num_cfp;
6130 		     next_chan++, chan_idx++) {
6131 			if (chan_idx >= WLAN_BG_SCAN_CHAN_MAX)
6132 				break;
6133 			/*
6134 			 * Set the default scan type to ACTIVE SCAN type, will
6135 			 * later be changed to passive on a per channel basis
6136 			 * if restricted by regulatory requirements (11d or 11h)
6137 			 */
6138 			scan_type = MLAN_SCAN_TYPE_ACTIVE;
6139 			cfp = pscan_region->pcfp + next_chan;
6140 
6141 			switch (pscan_region->band) {
6142 			case BAND_A:
6143 				tlv_chan_list->chan_scan_param[chan_idx]
6144 					.bandcfg.chanBand = BAND_5GHZ;
6145 				/* Passive scan on DFS channels */
6146 				if (wlan_11h_radar_detect_required(
6147 					    pmpriv, (t_u8)cfp->channel))
6148 					scan_type = MLAN_SCAN_TYPE_PASSIVE;
6149 				break;
6150 			case BAND_B:
6151 			case BAND_G:
6152 				if (wlan_bg_scan_type_is_passive(
6153 					    pmpriv, (t_u8)cfp->channel))
6154 					scan_type = MLAN_SCAN_TYPE_PASSIVE;
6155 				tlv_chan_list->chan_scan_param[chan_idx]
6156 					.bandcfg.chanBand = BAND_2GHZ;
6157 				break;
6158 			default:
6159 				tlv_chan_list->chan_scan_param[chan_idx]
6160 					.bandcfg.chanBand = BAND_2GHZ;
6161 				break;
6162 			}
6163 
6164 			if (pbg_scan_in &&
6165 			    pbg_scan_in->chan_list[0].scan_time) {
6166 				tlv_chan_list->chan_scan_param[chan_idx]
6167 					.max_scan_time = wlan_cpu_to_le16(
6168 					(t_u16)pbg_scan_in->chan_list[0]
6169 						.scan_time);
6170 				tlv_chan_list->chan_scan_param[chan_idx]
6171 					.min_scan_time = wlan_cpu_to_le16(
6172 					(t_u16)pbg_scan_in->chan_list[0]
6173 						.scan_time);
6174 			} else if (scan_type == MLAN_SCAN_TYPE_PASSIVE) {
6175 				tlv_chan_list->chan_scan_param[chan_idx]
6176 					.max_scan_time = wlan_cpu_to_le16(
6177 					pmadapter->passive_scan_time);
6178 				tlv_chan_list->chan_scan_param[chan_idx]
6179 					.min_scan_time = wlan_cpu_to_le16(
6180 					pmadapter->passive_scan_time);
6181 			} else {
6182 				tlv_chan_list->chan_scan_param[chan_idx]
6183 					.max_scan_time = wlan_cpu_to_le16(
6184 					pmadapter->specific_scan_time);
6185 				tlv_chan_list->chan_scan_param[chan_idx]
6186 					.min_scan_time = wlan_cpu_to_le16(
6187 					pmadapter->specific_scan_time);
6188 			}
6189 
6190 			if (scan_type == MLAN_SCAN_TYPE_PASSIVE) {
6191 				tlv_chan_list->chan_scan_param[chan_idx]
6192 					.chan_scan_mode.passive_scan = MTRUE;
6193 			} else {
6194 				tlv_chan_list->chan_scan_param[chan_idx]
6195 					.chan_scan_mode.passive_scan = MFALSE;
6196 			}
6197 
6198 			tlv_chan_list->chan_scan_param[chan_idx].chan_number =
6199 				(t_u8)cfp->channel;
6200 		}
6201 	}
6202 
6203 	LEAVE();
6204 	return chan_idx;
6205 }
6206 
6207 /**
6208  *  @brief This function prepares command of bg_scan_config
6209  *
6210  *  @param pmpriv     A pointer to mlan_private structure
6211  *  @param pcmd       A pointer to HostCmd_DS_COMMAND structure
6212  *  @param pdata_buf  Void pointer cast of a wlan_scan_cmd_config struct used
6213  *                    to set the fields/TLVs for the command sent to firmware
6214  *
6215  *  @return           MLAN_STATUS_SUCCESS
6216  */
wlan_cmd_bgscan_config(mlan_private * pmpriv,HostCmd_DS_COMMAND * pcmd,t_void * pdata_buf)6217 mlan_status wlan_cmd_bgscan_config(mlan_private *pmpriv,
6218 				   HostCmd_DS_COMMAND *pcmd, t_void *pdata_buf)
6219 {
6220 	mlan_adapter *pmadapter = pmpriv->adapter;
6221 	HostCmd_DS_802_11_BG_SCAN_CONFIG *bg_scan =
6222 		&pcmd->params.bg_scan_config;
6223 	wlan_bgscan_cfg *bg_scan_in = (wlan_bgscan_cfg *)pdata_buf;
6224 	t_u16 cmd_size = 0;
6225 	MrvlIEtypes_NumProbes_t *pnum_probes_tlv = MNULL;
6226 	MrvlIEtypes_BeaconLowRssiThreshold_t *rssi_tlv = MNULL;
6227 	MrvlIEtypes_BeaconLowSnrThreshold_t *snr_tlv = MNULL;
6228 	MrvlIEtypes_WildCardSsIdParamSet_t *pwildcard_ssid_tlv = MNULL;
6229 	MrvlIEtypes_ChanListParamSet_t *tlv_chan_list = MNULL;
6230 	MrvlIEtypes_StartLater_t *tlv_start_later = MNULL;
6231 	MrvlIEtypes_RepeatCount_t *tlv_repeat = MNULL;
6232 	MrvlIEtypes_EESParamSet_t *tlv_ees_cfg = MNULL;
6233 	MrvlIEtype_EESNetworkCfg_t *tlv_ees_net_cfg = MNULL;
6234 	MrvlIEtypes_Cipher_t *tlv_ees_cipher = MNULL;
6235 	MrvlIEtypes_SsIdParamSet_t *tlv_ssid = MNULL;
6236 	MrvlIETypes_HTCap_t *pht_cap = MNULL;
6237 	MrvlIETypes_VHTCap_t *pvht_cap = MNULL;
6238 	MrvlIEtypes_Extension_t *phe_cap = MNULL;
6239 	t_u16 len = 0;
6240 
6241 	t_u8 index;
6242 	t_u8 *tlv = MNULL;
6243 	t_u16 num_probes = 0;
6244 	t_u32 ssid_idx;
6245 	t_u32 ssid_len = 0;
6246 	t_u32 chan_idx;
6247 	t_u32 chan_num;
6248 	t_u8 radio_type;
6249 	t_u16 scan_dur;
6250 	t_u8 scan_type;
6251 	t_u16 band;
6252 	const t_u8 zero_mac[6] = {0, 0, 0, 0, 0, 0};
6253 
6254 	ENTER();
6255 
6256 	pcmd->command = wlan_cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_CONFIG);
6257 	bg_scan->action = wlan_cpu_to_le16(bg_scan_in->action);
6258 	bg_scan->enable = bg_scan_in->enable;
6259 	bg_scan->bss_type = bg_scan_in->bss_type;
6260 	cmd_size = sizeof(HostCmd_DS_802_11_BG_SCAN_CONFIG) + S_DS_GEN;
6261 	if (bg_scan_in->scan_interval)
6262 		bg_scan->scan_interval =
6263 			wlan_cpu_to_le32(bg_scan_in->scan_interval);
6264 	else
6265 		bg_scan->scan_interval =
6266 			wlan_cpu_to_le32(DEFAULT_BGSCAN_INTERVAL);
6267 	bg_scan->report_condition =
6268 		wlan_cpu_to_le32(bg_scan_in->report_condition);
6269 
6270 	if ((bg_scan_in->action == BG_SCAN_ACT_GET) ||
6271 	    (bg_scan_in->action == BG_SCAN_ACT_GET_PPS_UAPSD) ||
6272 	    (!bg_scan->enable))
6273 		goto done;
6274 
6275 	tlv = (t_u8 *)bg_scan + sizeof(HostCmd_DS_802_11_BG_SCAN_CONFIG);
6276 	num_probes = (bg_scan_in->num_probes ? bg_scan_in->num_probes :
6277 					       pmadapter->scan_probes);
6278 	if (num_probes) {
6279 		pnum_probes_tlv = (MrvlIEtypes_NumProbes_t *)tlv;
6280 		pnum_probes_tlv->header.type =
6281 			wlan_cpu_to_le16(TLV_TYPE_NUMPROBES);
6282 		pnum_probes_tlv->header.len =
6283 			wlan_cpu_to_le16(sizeof(pnum_probes_tlv->num_probes));
6284 		pnum_probes_tlv->num_probes =
6285 			wlan_cpu_to_le16((t_u16)num_probes);
6286 		tlv += sizeof(MrvlIEtypes_NumProbes_t);
6287 		cmd_size += sizeof(MrvlIEtypes_NumProbes_t);
6288 	}
6289 	if (bg_scan_in->rssi_threshold) {
6290 		rssi_tlv = (MrvlIEtypes_BeaconLowRssiThreshold_t *)tlv;
6291 		rssi_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_RSSI_LOW);
6292 		rssi_tlv->header.len = wlan_cpu_to_le16(
6293 			sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t) -
6294 			sizeof(MrvlIEtypesHeader_t));
6295 		rssi_tlv->value = bg_scan_in->rssi_threshold;
6296 		rssi_tlv->frequency = 0;
6297 		tlv += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t);
6298 		cmd_size += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t);
6299 	}
6300 	if (bg_scan_in->snr_threshold) {
6301 		snr_tlv = (MrvlIEtypes_BeaconLowSnrThreshold_t *)tlv;
6302 		snr_tlv->header.type = wlan_cpu_to_le16(TLV_TYPE_SNR_LOW);
6303 		snr_tlv->header.len = wlan_cpu_to_le16(
6304 			sizeof(MrvlIEtypes_BeaconLowSnrThreshold_t) -
6305 			sizeof(MrvlIEtypesHeader_t));
6306 		snr_tlv->value = bg_scan_in->snr_threshold;
6307 		snr_tlv->frequency = 0;
6308 		tlv += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t);
6309 		cmd_size += sizeof(MrvlIEtypes_BeaconLowRssiThreshold_t);
6310 	}
6311 	if (bg_scan_in->repeat_count) {
6312 		tlv_repeat = (MrvlIEtypes_RepeatCount_t *)tlv;
6313 		tlv_repeat->header.type =
6314 			wlan_cpu_to_le16(TLV_TYPE_REPEAT_COUNT);
6315 		tlv_repeat->header.len =
6316 			wlan_cpu_to_le16(sizeof(MrvlIEtypes_RepeatCount_t) -
6317 					 sizeof(MrvlIEtypesHeader_t));
6318 		tlv_repeat->repeat_count =
6319 			wlan_cpu_to_le16(bg_scan_in->repeat_count);
6320 		tlv += sizeof(MrvlIEtypes_RepeatCount_t);
6321 		cmd_size += sizeof(MrvlIEtypes_RepeatCount_t);
6322 	}
6323 	for (ssid_idx = 0; ((ssid_idx < NELEMENTS(bg_scan_in->ssid_list)) &&
6324 			    (*bg_scan_in->ssid_list[ssid_idx].ssid ||
6325 			     bg_scan_in->ssid_list[ssid_idx].max_len));
6326 	     ssid_idx++) {
6327 		ssid_len = wlan_strlen(
6328 			(char *)bg_scan_in->ssid_list[ssid_idx].ssid);
6329 		pwildcard_ssid_tlv = (MrvlIEtypes_WildCardSsIdParamSet_t *)tlv;
6330 		pwildcard_ssid_tlv->header.type =
6331 			wlan_cpu_to_le16(TLV_TYPE_WILDCARDSSID);
6332 		pwildcard_ssid_tlv->header.len = (t_u16)(
6333 			ssid_len + sizeof(pwildcard_ssid_tlv->max_ssid_length));
6334 		pwildcard_ssid_tlv->max_ssid_length =
6335 			bg_scan_in->ssid_list[ssid_idx].max_len;
6336 		memcpy_ext(pmadapter, pwildcard_ssid_tlv->ssid,
6337 			   bg_scan_in->ssid_list[ssid_idx].ssid, ssid_len,
6338 			   MLAN_MAX_SSID_LENGTH);
6339 		tlv += sizeof(pwildcard_ssid_tlv->header) +
6340 		       pwildcard_ssid_tlv->header.len;
6341 		cmd_size += sizeof(pwildcard_ssid_tlv->header) +
6342 			    pwildcard_ssid_tlv->header.len;
6343 		pwildcard_ssid_tlv->header.len =
6344 			wlan_cpu_to_le16(pwildcard_ssid_tlv->header.len);
6345 		PRINTM(MINFO, "Scan: ssid_list[%d]: %s, %d\n", ssid_idx,
6346 		       pwildcard_ssid_tlv->ssid,
6347 		       pwildcard_ssid_tlv->max_ssid_length);
6348 	}
6349 	if (bg_scan_in->chan_list[0].chan_number) {
6350 		tlv_chan_list = (MrvlIEtypes_ChanListParamSet_t *)tlv;
6351 		PRINTM(MINFO, "Scan: Using supplied channel list\n");
6352 		chan_num = 0;
6353 		for (chan_idx = 0; chan_idx < WLAN_BG_SCAN_CHAN_MAX &&
6354 				   bg_scan_in->chan_list[chan_idx].chan_number;
6355 		     chan_idx++) {
6356 			radio_type = bg_scan_in->chan_list[chan_idx].radio_type;
6357 			if (bg_scan_in->bss_type == MLAN_SCAN_MODE_IBSS ||
6358 			    pmpriv->bss_mode == MLAN_BSS_MODE_IBSS)
6359 				band = pmadapter->adhoc_start_band;
6360 			else
6361 				band = pmpriv->config_bands;
6362 			if (!wlan_is_band_compatible(
6363 				    band, radio_type_to_band(radio_type)))
6364 				continue;
6365 			scan_type = bg_scan_in->chan_list[chan_idx].scan_type;
6366 			/* Prevent active scanning on a radar controlled channel
6367 			 */
6368 			if (radio_type == BAND_5GHZ) {
6369 				if (wlan_11h_radar_detect_required(
6370 					    pmpriv,
6371 					    bg_scan_in->chan_list[chan_idx]
6372 						    .chan_number)) {
6373 					scan_type = MLAN_SCAN_TYPE_PASSIVE;
6374 				}
6375 			}
6376 			if (radio_type == BAND_2GHZ) {
6377 				if (wlan_bg_scan_type_is_passive(
6378 					    pmpriv,
6379 					    bg_scan_in->chan_list[chan_idx]
6380 						    .chan_number)) {
6381 					scan_type = MLAN_SCAN_TYPE_PASSIVE;
6382 				}
6383 			}
6384 			tlv_chan_list->chan_scan_param[chan_num].chan_number =
6385 				bg_scan_in->chan_list[chan_idx].chan_number;
6386 			tlv_chan_list->chan_scan_param[chan_num]
6387 				.bandcfg.chanBand =
6388 				bg_scan_in->chan_list[chan_idx].radio_type;
6389 
6390 			if (scan_type == MLAN_SCAN_TYPE_PASSIVE) {
6391 				tlv_chan_list->chan_scan_param[chan_num]
6392 					.chan_scan_mode.passive_scan = MTRUE;
6393 			} else {
6394 				tlv_chan_list->chan_scan_param[chan_num]
6395 					.chan_scan_mode.passive_scan = MFALSE;
6396 			}
6397 			if (bg_scan_in->chan_list[chan_idx].scan_time) {
6398 				scan_dur =
6399 					(t_u16)bg_scan_in->chan_list[chan_idx]
6400 						.scan_time;
6401 			} else {
6402 				if (scan_type == MLAN_SCAN_TYPE_PASSIVE) {
6403 					scan_dur = pmadapter->passive_scan_time;
6404 				} else {
6405 					scan_dur =
6406 						pmadapter->specific_scan_time;
6407 				}
6408 			}
6409 			tlv_chan_list->chan_scan_param[chan_num].min_scan_time =
6410 				wlan_cpu_to_le16(scan_dur);
6411 			tlv_chan_list->chan_scan_param[chan_num].max_scan_time =
6412 				wlan_cpu_to_le16(scan_dur);
6413 			chan_num++;
6414 		}
6415 		tlv_chan_list->header.type =
6416 			wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
6417 		tlv_chan_list->header.len =
6418 			wlan_cpu_to_le16(sizeof(ChanScanParamSet_t) * chan_num);
6419 		tlv += sizeof(MrvlIEtypesHeader_t) +
6420 		       sizeof(ChanScanParamSet_t) * chan_num;
6421 		cmd_size += sizeof(MrvlIEtypesHeader_t) +
6422 			    sizeof(ChanScanParamSet_t) * chan_num;
6423 	} else {
6424 		tlv_chan_list = (MrvlIEtypes_ChanListParamSet_t *)tlv;
6425 		chan_num = wlan_bgscan_create_channel_list(pmpriv, bg_scan_in,
6426 							   tlv_chan_list);
6427 		tlv_chan_list->header.type =
6428 			wlan_cpu_to_le16(TLV_TYPE_CHANLIST);
6429 		tlv_chan_list->header.len =
6430 			wlan_cpu_to_le16(sizeof(ChanScanParamSet_t) * chan_num);
6431 		tlv += sizeof(MrvlIEtypesHeader_t) +
6432 		       sizeof(ChanScanParamSet_t) * chan_num;
6433 		cmd_size += sizeof(MrvlIEtypesHeader_t) +
6434 			    sizeof(ChanScanParamSet_t) * chan_num;
6435 	}
6436 	if (bg_scan_in->chan_per_scan) {
6437 		bg_scan->chan_per_scan = bg_scan_in->chan_per_scan;
6438 	} else {
6439 		if (bg_scan_in->report_condition & BG_SCAN_WAIT_ALL_CHAN_DONE)
6440 			bg_scan->chan_per_scan = chan_num;
6441 		else
6442 			bg_scan->chan_per_scan =
6443 				MRVDRV_MAX_CHANNELS_PER_SPECIFIC_SCAN;
6444 	}
6445 	if (ISSUPP_11NENABLED(pmpriv->adapter->fw_cap_info) &&
6446 	    (pmpriv->config_bands & BAND_GN ||
6447 	     pmpriv->config_bands & BAND_AN)) {
6448 		pht_cap = (MrvlIETypes_HTCap_t *)tlv;
6449 		memset(pmadapter, pht_cap, 0, sizeof(MrvlIETypes_HTCap_t));
6450 		pht_cap->header.type = wlan_cpu_to_le16(HT_CAPABILITY);
6451 		pht_cap->header.len = sizeof(HTCap_t);
6452 		wlan_fill_ht_cap_tlv(pmpriv, pht_cap, pmpriv->config_bands,
6453 				     MTRUE);
6454 		DBG_HEXDUMP(MCMD_D, "BGSCAN: HT_CAPABILITIES IE",
6455 			    (t_u8 *)pht_cap, sizeof(MrvlIETypes_HTCap_t));
6456 		tlv += sizeof(MrvlIETypes_HTCap_t);
6457 		cmd_size += sizeof(MrvlIETypes_HTCap_t);
6458 		pht_cap->header.len = wlan_cpu_to_le16(pht_cap->header.len);
6459 	}
6460 	if (ISSUPP_11ACENABLED(pmpriv->adapter->fw_cap_info) &&
6461 	    (pmpriv->config_bands & BAND_AAC)) {
6462 		pvht_cap = (MrvlIETypes_VHTCap_t *)tlv;
6463 		memset(pmadapter, pvht_cap, 0, sizeof(MrvlIETypes_VHTCap_t));
6464 		pvht_cap->header.type = wlan_cpu_to_le16(VHT_CAPABILITY);
6465 		pvht_cap->header.len = sizeof(VHT_capa_t);
6466 		wlan_fill_vht_cap_tlv(pmpriv, pvht_cap, pmpriv->config_bands,
6467 				      MFALSE, MFALSE);
6468 		DBG_HEXDUMP(MCMD_D, "BGSCAN: VHT_CAPABILITIES IE",
6469 			    (t_u8 *)pvht_cap, sizeof(MrvlIETypes_VHTCap_t));
6470 		tlv += sizeof(MrvlIETypes_VHTCap_t);
6471 		cmd_size += sizeof(MrvlIETypes_VHTCap_t);
6472 		pvht_cap->header.len = wlan_cpu_to_le16(pvht_cap->header.len);
6473 	}
6474 
6475 	if (IS_FW_SUPPORT_11AX(pmadapter) &&
6476 	    ((pmpriv->config_bands & BAND_GAX) ||
6477 	     (pmpriv->config_bands & BAND_AAX))) {
6478 		phe_cap = (MrvlIEtypes_Extension_t *)tlv;
6479 		len = wlan_fill_he_cap_tlv(pmpriv, pmpriv->config_bands,
6480 					   phe_cap, MFALSE);
6481 		DBG_HEXDUMP(MCMD_D, "BGSCAN: HE_CAPABILITIES IE",
6482 			    (t_u8 *)phe_cap, len);
6483 		tlv += len;
6484 		cmd_size += len;
6485 	}
6486 	if (wlan_is_ext_capa_support(pmpriv)) {
6487 		wlan_add_ext_capa_info_ie(pmpriv, MNULL, &tlv);
6488 		cmd_size += sizeof(MrvlIETypes_ExtCap_t);
6489 	}
6490 	if (pmpriv->adapter->ecsa_enable) {
6491 		t_u8 bandwidth = BW_20MHZ;
6492 		t_u8 oper_class = 1;
6493 		t_u32 usr_dot_11n_dev_cap;
6494 		if (pmpriv->media_connected) {
6495 			if (pmpriv->config_bands & BAND_A)
6496 				usr_dot_11n_dev_cap =
6497 					pmpriv->usr_dot_11n_dev_cap_a;
6498 			else
6499 				usr_dot_11n_dev_cap =
6500 					pmpriv->usr_dot_11n_dev_cap_bg;
6501 			if (usr_dot_11n_dev_cap & MBIT(17)) {
6502 				bandwidth = BW_40MHZ;
6503 				if (ISSUPP_11ACENABLED(
6504 					    pmadapter->fw_cap_info) &&
6505 				    (pmpriv->config_bands & BAND_AAC))
6506 					bandwidth = BW_80MHZ;
6507 			}
6508 			wlan_get_curr_oper_class(
6509 				pmpriv,
6510 				pmpriv->curr_bss_params.bss_descriptor.channel,
6511 				bandwidth, &oper_class);
6512 		}
6513 		len = wlan_add_supported_oper_class_ie(pmpriv, &tlv,
6514 						       oper_class);
6515 		cmd_size += len;
6516 	}
6517 
6518 	tlv_start_later = (MrvlIEtypes_StartLater_t *)tlv;
6519 	tlv_start_later->header.type =
6520 		wlan_cpu_to_le16(TLV_TYPE_STARTBGSCANLATER);
6521 	tlv_start_later->header.len = wlan_cpu_to_le16(
6522 		sizeof(MrvlIEtypes_StartLater_t) - sizeof(MrvlIEtypesHeader_t));
6523 	tlv_start_later->value = wlan_cpu_to_le16(bg_scan_in->start_later);
6524 	tlv += sizeof(MrvlIEtypes_StartLater_t);
6525 	cmd_size += sizeof(MrvlIEtypes_StartLater_t);
6526 
6527 	if (bg_scan_in->config_ees) {
6528 		/* Fill EES configuration */
6529 		tlv_ees_cfg = (MrvlIEtypes_EESParamSet_t *)tlv;
6530 		tlv_ees_cfg->header.type = wlan_cpu_to_le16(TLV_TYPE_EES_CFG);
6531 		tlv_ees_cfg->header.len =
6532 			wlan_cpu_to_le16(sizeof(MrvlIEtypes_EESParamSet_t) -
6533 					 sizeof(MrvlIEtypesHeader_t));
6534 		tlv_ees_cfg->ees_mode = wlan_cpu_to_le16(bg_scan_in->ees_mode);
6535 		tlv_ees_cfg->report_cond =
6536 			wlan_cpu_to_le16(bg_scan_in->report_cond);
6537 		tlv_ees_cfg->high_period =
6538 			wlan_cpu_to_le16(bg_scan_in->high_period);
6539 		tlv_ees_cfg->high_period_count =
6540 			wlan_cpu_to_le16(bg_scan_in->high_period_count);
6541 		tlv_ees_cfg->mid_period =
6542 			wlan_cpu_to_le16(bg_scan_in->mid_period);
6543 		tlv_ees_cfg->mid_period_count =
6544 			wlan_cpu_to_le16(bg_scan_in->mid_period_count);
6545 		tlv_ees_cfg->low_period =
6546 			wlan_cpu_to_le16(bg_scan_in->low_period);
6547 		tlv_ees_cfg->low_period_count =
6548 			wlan_cpu_to_le16(bg_scan_in->low_period_count);
6549 		tlv += sizeof(MrvlIEtypes_EESParamSet_t);
6550 		cmd_size += sizeof(MrvlIEtypes_EESParamSet_t);
6551 
6552 		if (bg_scan_in->network_count) {
6553 			/* Fill EES network configuration */
6554 			tlv_ees_net_cfg = (MrvlIEtype_EESNetworkCfg_t *)tlv;
6555 			tlv_ees_net_cfg->header.type =
6556 				wlan_cpu_to_le16(TLV_TYPE_EES_NET_CFG);
6557 			tlv_ees_net_cfg->header.len = wlan_cpu_to_le16(
6558 				sizeof(MrvlIEtype_EESNetworkCfg_t) -
6559 				sizeof(MrvlIEtypesHeader_t));
6560 			tlv_ees_net_cfg->network_count =
6561 				bg_scan_in->network_count;
6562 			tlv_ees_net_cfg->max_conn_count =
6563 				bg_scan_in->max_conn_count;
6564 			tlv_ees_net_cfg->black_list_exp =
6565 				bg_scan_in->black_list_exp;
6566 			tlv += sizeof(MrvlIEtype_EESNetworkCfg_t);
6567 			cmd_size += sizeof(MrvlIEtype_EESNetworkCfg_t);
6568 			for (index = 0; index < bg_scan_in->network_count;
6569 			     index++) {
6570 				if (wlan_strlen((char *)bg_scan_in
6571 							->ees_ssid_cfg[index]
6572 							.ssid)) {
6573 					/* Fill SSID settings */
6574 					tlv_ssid =
6575 						(MrvlIEtypes_SsIdParamSet_t *)
6576 							tlv;
6577 					tlv_ssid->header.type =
6578 						wlan_cpu_to_le16(TLV_TYPE_SSID);
6579 					tlv_ssid->header.len = wlan_cpu_to_le16(
6580 						(t_u16)bg_scan_in
6581 							->ees_ssid_cfg[index]
6582 							.max_len);
6583 					memcpy_ext(
6584 						pmadapter, tlv_ssid->ssid,
6585 						bg_scan_in->ees_ssid_cfg[index]
6586 							.ssid,
6587 						bg_scan_in->ees_ssid_cfg[index]
6588 							.max_len,
6589 						MLAN_MAX_SSID_LENGTH);
6590 					tlv += sizeof(MrvlIEtypesHeader_t) +
6591 					       tlv_ssid->header.len;
6592 					cmd_size +=
6593 						sizeof(MrvlIEtypesHeader_t) +
6594 						tlv_ssid->header.len;
6595 				} else {
6596 					/* Fill Wildcard SSID settings */
6597 					pwildcard_ssid_tlv =
6598 						(MrvlIEtypes_WildCardSsIdParamSet_t
6599 							 *)tlv;
6600 					pwildcard_ssid_tlv->header.type =
6601 						wlan_cpu_to_le16(
6602 							TLV_TYPE_WILDCARDSSID);
6603 					pwildcard_ssid_tlv->header
6604 						.len = wlan_cpu_to_le16(
6605 						sizeof(MrvlIEtypes_WildCardSsIdParamSet_t) -
6606 						sizeof(MrvlIEtypesHeader_t));
6607 					pwildcard_ssid_tlv->max_ssid_length =
6608 						MLAN_MAX_SSID_LENGTH;
6609 					tlv += sizeof(MrvlIEtypesHeader_t) +
6610 					       sizeof(pwildcard_ssid_tlv
6611 							      ->max_ssid_length);
6612 					cmd_size +=
6613 						sizeof(MrvlIEtypesHeader_t) +
6614 						sizeof(pwildcard_ssid_tlv
6615 							       ->max_ssid_length);
6616 				}
6617 				/* Fill Cipher settings */
6618 				tlv_ees_cipher = (MrvlIEtypes_Cipher_t *)tlv;
6619 				tlv_ees_cipher->header.type =
6620 					wlan_cpu_to_le16(TLV_TYPE_CIPHER);
6621 				tlv_ees_cipher->header.len = wlan_cpu_to_le16(
6622 					sizeof(MrvlIEtypes_Cipher_t) -
6623 					sizeof(MrvlIEtypesHeader_t));
6624 				tlv_ees_cipher->pair_cipher =
6625 					bg_scan_in->ees_ssid_cfg[index]
6626 						.pair_cipher;
6627 				tlv_ees_cipher->group_cipher =
6628 					bg_scan_in->ees_ssid_cfg[index]
6629 						.group_cipher;
6630 				tlv += sizeof(MrvlIEtypes_Cipher_t);
6631 				cmd_size += sizeof(MrvlIEtypes_Cipher_t);
6632 			}
6633 		}
6634 	}
6635 
6636 	if (memcmp(pmadapter, bg_scan_in->random_mac, zero_mac,
6637 		   MLAN_MAC_ADDR_LENGTH)) {
6638 		MrvlIEtypes_MacAddr_t *randomMacParam =
6639 			(MrvlIEtypes_MacAddr_t *)tlv;
6640 		memset(pmadapter, randomMacParam, 0,
6641 		       sizeof(MrvlIEtypes_MacAddr_t));
6642 		randomMacParam->header.type =
6643 			wlan_cpu_to_le16(TLV_TYPE_RANDOM_MAC);
6644 		randomMacParam->header.len =
6645 			wlan_cpu_to_le16(MLAN_MAC_ADDR_LENGTH);
6646 		memcpy_ext(pmadapter, randomMacParam->mac,
6647 			   bg_scan_in->random_mac, MLAN_MAC_ADDR_LENGTH,
6648 			   MLAN_MAC_ADDR_LENGTH);
6649 		tlv += sizeof(MrvlIEtypes_MacAddr_t);
6650 		cmd_size += sizeof(MrvlIEtypes_MacAddr_t);
6651 	}
6652 done:
6653 	pcmd->size = wlan_cpu_to_le16(cmd_size);
6654 	LEAVE();
6655 	return MLAN_STATUS_SUCCESS;
6656 }
6657 
6658 /**
6659  *  @brief This function handles the command response of extended scan
6660  *
6661  *  @param pmpriv       A pointer to mlan_private structure
6662  *  @param resp         A pointer to HostCmd_DS_COMMAND
6663  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
6664  *
6665  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
6666  */
wlan_ret_bgscan_config(mlan_private * pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)6667 mlan_status wlan_ret_bgscan_config(mlan_private *pmpriv,
6668 				   HostCmd_DS_COMMAND *resp,
6669 				   mlan_ioctl_req *pioctl_buf)
6670 {
6671 	mlan_ds_scan *pscan = MNULL;
6672 	HostCmd_DS_802_11_BG_SCAN_CONFIG *bg_scan =
6673 		&resp->params.bg_scan_config;
6674 	wlan_bgscan_cfg *bg_scan_out = MNULL;
6675 
6676 	ENTER();
6677 	if (pioctl_buf) {
6678 		pscan = (mlan_ds_scan *)pioctl_buf->pbuf;
6679 		bg_scan_out =
6680 			(wlan_bgscan_cfg *)pscan->param.user_scan.scan_cfg_buf;
6681 		bg_scan_out->action = wlan_le16_to_cpu(bg_scan->action);
6682 		if ((bg_scan_out->action == BG_SCAN_ACT_GET) ||
6683 		    (bg_scan_out->action == BG_SCAN_ACT_GET_PPS_UAPSD)) {
6684 			bg_scan_out->enable = bg_scan->enable;
6685 			bg_scan_out->bss_type = bg_scan->bss_type;
6686 			bg_scan_out->chan_per_scan = bg_scan->chan_per_scan;
6687 			bg_scan_out->scan_interval =
6688 				wlan_le32_to_cpu(bg_scan->scan_interval);
6689 			bg_scan_out->report_condition =
6690 				wlan_le32_to_cpu(bg_scan->report_condition);
6691 			pioctl_buf->data_read_written =
6692 				sizeof(mlan_ds_scan) + MLAN_SUB_COMMAND_SIZE;
6693 		}
6694 	}
6695 	LEAVE();
6696 	return MLAN_STATUS_SUCCESS;
6697 }
6698 
6699 /**
6700  *  @brief This function handles the command response of bgscan_query
6701  *  @param pmpriv       A pointer to mlan_private structure
6702  *  @param resp         A pointer to HostCmd_DS_COMMAND
6703  *  @param pioctl_buf   A pointer to mlan_ioctl_req structure
6704  *
6705  *  @return             MLAN_STATUS_SUCCESS or MLAN_STATUS_FAILURE
6706  */
wlan_ret_802_11_bgscan_query(mlan_private * pmpriv,HostCmd_DS_COMMAND * resp,mlan_ioctl_req * pioctl_buf)6707 mlan_status wlan_ret_802_11_bgscan_query(mlan_private *pmpriv,
6708 					 HostCmd_DS_COMMAND *resp,
6709 					 mlan_ioctl_req *pioctl_buf)
6710 {
6711 	mlan_ds_scan *pscan = MNULL;
6712 	mlan_adapter *pmadapter = pmpriv->adapter;
6713 	t_u8 i;
6714 	ENTER();
6715 	for (i = 0; i < pmadapter->num_in_chan_stats; i++)
6716 		pmadapter->pchan_stats[i].cca_scan_duration = 0;
6717 	pmadapter->idx_chan_stats = 0;
6718 
6719 	wlan_ret_802_11_scan(pmpriv, resp, MNULL);
6720 	if (pioctl_buf) {
6721 		pscan = (mlan_ds_scan *)pioctl_buf->pbuf;
6722 		pscan->param.scan_resp.pscan_table =
6723 			(t_u8 *)pmadapter->pscan_table;
6724 		pscan->param.scan_resp.num_in_scan_table =
6725 			pmadapter->num_in_scan_table;
6726 		pscan->param.scan_resp.age_in_secs = pmadapter->age_in_secs;
6727 		pscan->param.scan_resp.pchan_stats =
6728 			(t_u8 *)pmadapter->pchan_stats;
6729 		pscan->param.scan_resp.num_in_chan_stats =
6730 			pmadapter->num_in_chan_stats;
6731 
6732 		pioctl_buf->data_read_written =
6733 			sizeof(mlan_scan_resp) + MLAN_SUB_COMMAND_SIZE;
6734 	}
6735 	LEAVE();
6736 	return MLAN_STATUS_SUCCESS;
6737 }
6738 
6739 /**
6740  *  @brief This function finds ssid in ssid list.
6741  *
6742  *  @param pmpriv       A pointer to mlan_private structure
6743  *  @param ssid         SSID to find in the list
6744  *  @param bssid        BSSID to qualify the SSID selection (if provided)
6745  *  @param mode         Network mode: Infrastructure or IBSS
6746  *
6747  *  @return             index in BSSID list or < 0 if error
6748  */
wlan_find_ssid_in_list(mlan_private * pmpriv,mlan_802_11_ssid * ssid,t_u8 * bssid,t_u32 mode)6749 t_s32 wlan_find_ssid_in_list(mlan_private *pmpriv, mlan_802_11_ssid *ssid,
6750 			     t_u8 *bssid, t_u32 mode)
6751 {
6752 	mlan_adapter *pmadapter = pmpriv->adapter;
6753 	t_s32 net = -1, j;
6754 	t_u8 best_rssi = 0;
6755 	t_u32 i;
6756 
6757 	ENTER();
6758 	PRINTM(MINFO, "Num of entries in scan table = %d\n",
6759 	       pmadapter->num_in_scan_table);
6760 
6761 	/*
6762 	 * Loop through the table until the maximum is reached or until a match
6763 	 *   is found based on the bssid field comparison
6764 	 */
6765 	for (i = 0;
6766 	     i < pmadapter->num_in_scan_table && (!bssid || (bssid && net < 0));
6767 	     i++) {
6768 		if (!wlan_ssid_cmp(pmadapter, &pmadapter->pscan_table[i].ssid,
6769 				   ssid) &&
6770 		    (!bssid ||
6771 		     !memcmp(pmadapter, pmadapter->pscan_table[i].mac_address,
6772 			     bssid, MLAN_MAC_ADDR_LENGTH))) {
6773 			if ((mode == MLAN_BSS_MODE_INFRA) &&
6774 			    !wlan_is_band_compatible(
6775 				    pmpriv->config_bands,
6776 				    pmadapter->pscan_table[i].bss_band))
6777 				continue;
6778 
6779 			switch (mode) {
6780 			case MLAN_BSS_MODE_INFRA:
6781 			case MLAN_BSS_MODE_IBSS:
6782 				j = wlan_is_network_compatible(pmpriv, i, mode);
6783 
6784 				if (j >= 0) {
6785 					if (SCAN_RSSI(pmadapter->pscan_table[i]
6786 							      .rssi) >
6787 					    best_rssi) {
6788 						best_rssi = SCAN_RSSI(
6789 							pmadapter
6790 								->pscan_table[i]
6791 								.rssi);
6792 						net = i;
6793 					}
6794 				} else {
6795 					if (net == -1)
6796 						net = j;
6797 				}
6798 				break;
6799 			case MLAN_BSS_MODE_AUTO:
6800 			default:
6801 				/*
6802 				 * Do not check compatibility if the mode
6803 				 * requested is Auto/Unknown.  Allows generic
6804 				 * find to work without verifying against the
6805 				 * Adapter security settings
6806 				 */
6807 				if (SCAN_RSSI(pmadapter->pscan_table[i].rssi) >
6808 				    best_rssi) {
6809 					best_rssi = SCAN_RSSI(
6810 						pmadapter->pscan_table[i].rssi);
6811 					net = i;
6812 				}
6813 				break;
6814 			}
6815 		}
6816 	}
6817 
6818 	LEAVE();
6819 	return net;
6820 }
6821 
6822 /**
6823  *  @brief This function finds a specific compatible BSSID in the scan list
6824  *
6825  *  @param pmpriv       A pointer to mlan_private structure
6826  *  @param bssid        BSSID to find in the scan list
6827  *  @param mode         Network mode: Infrastructure or IBSS
6828  *
6829  *  @return             index in BSSID list or < 0 if error
6830  */
wlan_find_bssid_in_list(mlan_private * pmpriv,t_u8 * bssid,t_u32 mode)6831 t_s32 wlan_find_bssid_in_list(mlan_private *pmpriv, t_u8 *bssid, t_u32 mode)
6832 {
6833 	mlan_adapter *pmadapter = pmpriv->adapter;
6834 	t_s32 net = -1;
6835 	t_u32 i;
6836 
6837 	ENTER();
6838 
6839 	if (!bssid) {
6840 		LEAVE();
6841 		return -1;
6842 	}
6843 
6844 	PRINTM(MINFO, "FindBSSID: Num of BSSIDs = %d\n",
6845 	       pmadapter->num_in_scan_table);
6846 
6847 	/*
6848 	 * Look through the scan table for a compatible match. The ret return
6849 	 *   variable will be equal to the index in the scan table (greater
6850 	 *   than zero) if the network is compatible.  The loop will continue
6851 	 *   past a matched bssid that is not compatible in case there is an
6852 	 *   AP with multiple SSIDs assigned to the same BSSID
6853 	 */
6854 	for (i = 0; net < 0 && i < pmadapter->num_in_scan_table; i++) {
6855 		if (!memcmp(pmadapter, pmadapter->pscan_table[i].mac_address,
6856 			    bssid, MLAN_MAC_ADDR_LENGTH)) {
6857 			if ((mode == MLAN_BSS_MODE_INFRA) &&
6858 			    !wlan_is_band_compatible(
6859 				    pmpriv->config_bands,
6860 				    pmadapter->pscan_table[i].bss_band))
6861 				continue;
6862 			switch (mode) {
6863 			case MLAN_BSS_MODE_INFRA:
6864 			case MLAN_BSS_MODE_IBSS:
6865 				net = wlan_is_network_compatible(pmpriv, i,
6866 								 mode);
6867 				break;
6868 			default:
6869 				net = i;
6870 				break;
6871 			}
6872 		}
6873 	}
6874 
6875 	LEAVE();
6876 	return net;
6877 }
6878 
6879 /**
6880  *  @brief Compare two SSIDs
6881  *
6882  *  @param pmadapter A pointer to mlan_adapter structure
6883  *  @param ssid1     A pointer to ssid to compare
6884  *  @param ssid2     A pointer to ssid to compare
6885  *
6886  *  @return         0--ssid is same, otherwise is different
6887  */
wlan_ssid_cmp(pmlan_adapter pmadapter,mlan_802_11_ssid * ssid1,mlan_802_11_ssid * ssid2)6888 t_s32 wlan_ssid_cmp(pmlan_adapter pmadapter, mlan_802_11_ssid *ssid1,
6889 		    mlan_802_11_ssid *ssid2)
6890 {
6891 	ENTER();
6892 
6893 	if (!ssid1 || !ssid2) {
6894 		LEAVE();
6895 		return -1;
6896 	}
6897 
6898 	if (ssid1->ssid_len != ssid2->ssid_len) {
6899 		LEAVE();
6900 		return -1;
6901 	}
6902 
6903 	LEAVE();
6904 	return memcmp(pmadapter, ssid1->ssid, ssid2->ssid, ssid1->ssid_len);
6905 }
6906 
6907 /**
6908  *  @brief Find the AP with specific ssid in the scan list
6909  *
6910  *  @param pmpriv               A pointer to mlan_private structure
6911  *  @param preq_ssid_bssid      A pointer to AP's ssid returned
6912  *
6913  *  @return                     MLAN_STATUS_SUCCESS--success, otherwise--fail
6914  */
wlan_find_best_network(mlan_private * pmpriv,mlan_ssid_bssid * preq_ssid_bssid)6915 mlan_status wlan_find_best_network(mlan_private *pmpriv,
6916 				   mlan_ssid_bssid *preq_ssid_bssid)
6917 {
6918 	mlan_adapter *pmadapter = pmpriv->adapter;
6919 	mlan_status ret = MLAN_STATUS_SUCCESS;
6920 	BSSDescriptor_t *preq_bss;
6921 	t_s32 i;
6922 
6923 	ENTER();
6924 
6925 	memset(pmadapter, preq_ssid_bssid, 0, sizeof(mlan_ssid_bssid));
6926 
6927 	i = wlan_find_best_network_in_list(pmpriv);
6928 
6929 	if (i >= 0) {
6930 		preq_bss = &pmadapter->pscan_table[i];
6931 		memcpy_ext(pmadapter, &preq_ssid_bssid->ssid, &preq_bss->ssid,
6932 			   sizeof(mlan_802_11_ssid),
6933 			   sizeof(preq_ssid_bssid->ssid));
6934 		memcpy_ext(pmadapter, (t_u8 *)&preq_ssid_bssid->bssid,
6935 			   (t_u8 *)&preq_bss->mac_address, MLAN_MAC_ADDR_LENGTH,
6936 			   MLAN_MAC_ADDR_LENGTH);
6937 
6938 		/* Make sure we are in the right mode */
6939 		if (pmpriv->bss_mode == MLAN_BSS_MODE_AUTO)
6940 			pmpriv->bss_mode = preq_bss->bss_mode;
6941 		preq_ssid_bssid->channel = (t_u16)preq_bss->channel;
6942 		if (preq_bss->pmd_ie &&
6943 		    wlan_ft_akm_is_used(pmpriv, (t_u8 *)preq_bss->prsn_ie)) {
6944 			preq_ssid_bssid->ft_md = preq_bss->pmd_ie->mdid;
6945 			preq_ssid_bssid->ft_cap = preq_bss->pmd_ie->ft_cap;
6946 		}
6947 		preq_ssid_bssid->bss_band = preq_bss->bss_band;
6948 		preq_ssid_bssid->idx = i + 1;
6949 	}
6950 
6951 	if (!preq_ssid_bssid->ssid.ssid_len) {
6952 		ret = MLAN_STATUS_FAILURE;
6953 		goto done;
6954 	}
6955 
6956 	PRINTM(MINFO,
6957 	       "Best network found = [%s], "
6958 	       "[" MACSTR "]\n",
6959 	       preq_ssid_bssid->ssid.ssid, MAC2STR(preq_ssid_bssid->bssid));
6960 
6961 done:
6962 	LEAVE();
6963 	return ret;
6964 }
6965 
6966 /**
6967  *  @brief Send a scan command for all available channels filtered on a spec
6968  *
6969  *  @param pmpriv       A pointer to mlan_private structure
6970  *  @param pioctl_buf   A pointer to MLAN IOCTL Request buffer
6971  *  @param preq_ssid    A pointer to AP's ssid returned
6972  *
6973  *  @return             MLAN_STATUS_SUCCESS--success, otherwise--fail
6974  */
wlan_scan_specific_ssid(mlan_private * pmpriv,t_void * pioctl_buf,mlan_802_11_ssid * preq_ssid)6975 mlan_status wlan_scan_specific_ssid(mlan_private *pmpriv, t_void *pioctl_buf,
6976 				    mlan_802_11_ssid *preq_ssid)
6977 {
6978 	mlan_status ret = MLAN_STATUS_SUCCESS;
6979 	mlan_callbacks *pcb = (mlan_callbacks *)&pmpriv->adapter->callbacks;
6980 	wlan_user_scan_cfg *pscan_cfg;
6981 	pmlan_ioctl_req pioctl_req = (mlan_ioctl_req *)pioctl_buf;
6982 
6983 	ENTER();
6984 
6985 	if (!preq_ssid) {
6986 		if (pioctl_req)
6987 			pioctl_req->status_code = MLAN_ERROR_CMD_SCAN_FAIL;
6988 		ret = MLAN_STATUS_FAILURE;
6989 		goto done;
6990 	}
6991 	wlan_scan_delete_ssid_table_entry(pmpriv, preq_ssid);
6992 
6993 	ret = pcb->moal_malloc(pmpriv->adapter->pmoal_handle,
6994 			       sizeof(wlan_user_scan_cfg),
6995 			       MLAN_MEM_DEF | MLAN_MEM_FLAG_ATOMIC,
6996 			       (t_u8 **)&pscan_cfg);
6997 
6998 	if (ret != MLAN_STATUS_SUCCESS || !pscan_cfg) {
6999 		PRINTM(MERROR, "Memory allocation for pscan_cfg failed!\n");
7000 		if (pioctl_req)
7001 			pioctl_req->status_code = MLAN_ERROR_NO_MEM;
7002 		ret = MLAN_STATUS_FAILURE;
7003 		goto done;
7004 	}
7005 
7006 	memset(pmpriv->adapter, pscan_cfg, 0x00, sizeof(wlan_user_scan_cfg));
7007 
7008 	memcpy_ext(pmpriv->adapter, pscan_cfg->ssid_list[0].ssid,
7009 		   preq_ssid->ssid, preq_ssid->ssid_len, MLAN_MAX_SSID_LENGTH);
7010 	pscan_cfg->keep_previous_scan = MFALSE;
7011 
7012 	ret = wlan_scan_networks(pmpriv, pioctl_buf, pscan_cfg);
7013 
7014 	if (pscan_cfg)
7015 		pcb->moal_mfree(pmpriv->adapter->pmoal_handle,
7016 				(t_u8 *)pscan_cfg);
7017 
7018 done:
7019 	LEAVE();
7020 	return ret;
7021 }
7022 
7023 /**
7024  *  @brief Save a beacon buffer of the current bss descriptor
7025  *  Save the current beacon buffer to restore in the following cases that
7026  *  makes the bcn_buf not to contain the current ssid's beacon buffer.
7027  *    - the current ssid was not found somehow in the last scan.
7028  *    - the current ssid was the last entry of the scan table and overloaded.
7029  *
7030  *  @param pmpriv       A pointer to mlan_private structure
7031  *
7032  *  @return             N/A
7033  */
wlan_save_curr_bcn(mlan_private * pmpriv)7034 t_void wlan_save_curr_bcn(mlan_private *pmpriv)
7035 {
7036 	mlan_adapter *pmadapter = pmpriv->adapter;
7037 	mlan_callbacks *pcb = (pmlan_callbacks)&pmadapter->callbacks;
7038 	BSSDescriptor_t *pcurr_bss = &pmpriv->curr_bss_params.bss_descriptor;
7039 	mlan_status ret = MLAN_STATUS_SUCCESS;
7040 
7041 	ENTER();
7042 	pcb->moal_spin_lock(pmadapter->pmoal_handle, pmpriv->curr_bcn_buf_lock);
7043 	/* save the beacon buffer if it is not saved or updated */
7044 	if ((pmpriv->pcurr_bcn_buf == MNULL) ||
7045 	    (pmpriv->curr_bcn_size != pcurr_bss->beacon_buf_size) ||
7046 	    (memcmp(pmpriv->adapter, pmpriv->pcurr_bcn_buf,
7047 		    pcurr_bss->pbeacon_buf, pcurr_bss->beacon_buf_size))) {
7048 		if (pmpriv->pcurr_bcn_buf) {
7049 			pcb->moal_mfree(pmadapter->pmoal_handle,
7050 					pmpriv->pcurr_bcn_buf);
7051 			pmpriv->pcurr_bcn_buf = MNULL;
7052 		}
7053 		pmpriv->curr_bcn_size = pcurr_bss->beacon_buf_size;
7054 
7055 		if (pmpriv->curr_bcn_size) {
7056 			ret = pcb->moal_malloc(pmadapter->pmoal_handle,
7057 					       pcurr_bss->beacon_buf_size,
7058 					       MLAN_MEM_DEF |
7059 						       MLAN_MEM_FLAG_ATOMIC,
7060 					       &pmpriv->pcurr_bcn_buf);
7061 
7062 			if ((ret == MLAN_STATUS_SUCCESS) &&
7063 			    pmpriv->pcurr_bcn_buf) {
7064 				memcpy_ext(pmpriv->adapter,
7065 					   pmpriv->pcurr_bcn_buf,
7066 					   pcurr_bss->pbeacon_buf,
7067 					   pcurr_bss->beacon_buf_size,
7068 					   pcurr_bss->beacon_buf_size);
7069 				PRINTM(MINFO, "current beacon saved %d\n",
7070 				       pmpriv->curr_bcn_size);
7071 			} else {
7072 				PRINTM(MERROR,
7073 				       "Fail to allocate curr_bcn_buf\n");
7074 			}
7075 		}
7076 	}
7077 	wlan_update_curr_bcn(pmpriv);
7078 	pcb->moal_spin_unlock(pmadapter->pmoal_handle,
7079 			      pmpriv->curr_bcn_buf_lock);
7080 
7081 	LEAVE();
7082 }
7083 
7084 /**
7085  *  @brief Free a beacon buffer of the current bss descriptor
7086  *
7087  *  @param pmpriv       A pointer to mlan_private structure
7088  *
7089  *  @return             N/A
7090  */
wlan_free_curr_bcn(mlan_private * pmpriv)7091 t_void wlan_free_curr_bcn(mlan_private *pmpriv)
7092 {
7093 	mlan_adapter *pmadapter = pmpriv->adapter;
7094 	mlan_callbacks *pcb = (pmlan_callbacks)&pmadapter->callbacks;
7095 
7096 	ENTER();
7097 	if (pmpriv->pcurr_bcn_buf) {
7098 		pcb->moal_mfree(pmadapter->pmoal_handle, pmpriv->pcurr_bcn_buf);
7099 		pmpriv->pcurr_bcn_buf = MNULL;
7100 	}
7101 	LEAVE();
7102 }
7103