xref: /wlan-dirver/qca-wifi-host-cmn/umac/scan/dispatcher/src/wlan_scan_utils_api.c (revision 24174b7be8e5a3f313f39a21927ceae5d89964c8)
1 /*
2  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
4  *
5  * Permission to use, copy, modify, and/or distribute this software for
6  * any purpose with or without fee is hereby granted, provided that the
7  * above copyright notice and this permission notice appear in all
8  * copies.
9  *
10  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17  * PERFORMANCE OF THIS SOFTWARE.
18  */
19 
20 /*
21  * DOC: Defines scan utility functions
22  */
23 
24 #include <wlan_cmn.h>
25 #include <wlan_scan_ucfg_api.h>
26 #include <wlan_scan_utils_api.h>
27 #include <../../core/src/wlan_scan_cache_db.h>
28 #include <../../core/src/wlan_scan_main.h>
29 #include <wlan_reg_services_api.h>
30 #if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
31 #include <wlan_mlme_api.h>
32 #endif
33 #ifdef WLAN_FEATURE_11BE_MLO
34 #include <wlan_utility.h>
35 #endif
36 
37 #define MAX_IE_LEN 1024
38 #define SHORT_SSID_LEN 4
39 #define NEIGHBOR_AP_LEN 1
40 #define BSS_PARAMS_LEN 1
41 
42 const char*
43 util_scan_get_ev_type_name(enum scan_event_type type)
44 {
45 	static const char * const event_name[] = {
46 		[SCAN_EVENT_TYPE_STARTED] = "STARTED",
47 		[SCAN_EVENT_TYPE_COMPLETED] = "COMPLETED",
48 		[SCAN_EVENT_TYPE_BSS_CHANNEL] = "HOME_CHANNEL",
49 		[SCAN_EVENT_TYPE_FOREIGN_CHANNEL] = "FOREIGN_CHANNEL",
50 		[SCAN_EVENT_TYPE_DEQUEUED] = "DEQUEUED",
51 		[SCAN_EVENT_TYPE_PREEMPTED] = "PREEMPTED",
52 		[SCAN_EVENT_TYPE_START_FAILED] = "START_FAILED",
53 		[SCAN_EVENT_TYPE_RESTARTED] = "RESTARTED",
54 		[SCAN_EVENT_TYPE_FOREIGN_CHANNEL_EXIT] = "FOREIGN_CHANNEL_EXIT",
55 		[SCAN_EVENT_TYPE_SUSPENDED] = "SUSPENDED",
56 		[SCAN_EVENT_TYPE_RESUMED] = "RESUMED",
57 		[SCAN_EVENT_TYPE_NLO_COMPLETE] = "NLO_COMPLETE",
58 		[SCAN_EVENT_TYPE_NLO_MATCH] = "NLO_MATCH",
59 		[SCAN_EVENT_TYPE_INVALID] = "INVALID",
60 		[SCAN_EVENT_TYPE_GPIO_TIMEOUT] = "GPIO_TIMEOUT",
61 		[SCAN_EVENT_TYPE_RADIO_MEASUREMENT_START] =
62 			"RADIO_MEASUREMENT_START",
63 		[SCAN_EVENT_TYPE_RADIO_MEASUREMENT_END] =
64 			"RADIO_MEASUREMENT_END",
65 		[SCAN_EVENT_TYPE_BSSID_MATCH] = "BSSID_MATCH",
66 		[SCAN_EVENT_TYPE_FOREIGN_CHANNEL_GET_NF] =
67 			"FOREIGN_CHANNEL_GET_NF",
68 	};
69 
70 	if (type >= SCAN_EVENT_TYPE_MAX)
71 		return "UNKNOWN";
72 
73 	return event_name[type];
74 }
75 
76 
77 const char*
78 util_scan_get_ev_reason_name(enum scan_completion_reason reason)
79 {
80 	static const char * const reason_name[] = {
81 		[SCAN_REASON_NONE] = "NONE",
82 		[SCAN_REASON_COMPLETED] = "COMPLETED",
83 		[SCAN_REASON_CANCELLED] = "CANCELLED",
84 		[SCAN_REASON_PREEMPTED] = "PREEMPTED",
85 		[SCAN_REASON_TIMEDOUT] = "TIMEDOUT",
86 		[SCAN_REASON_INTERNAL_FAILURE] = "INTERNAL_FAILURE",
87 		[SCAN_REASON_SUSPENDED] = "SUSPENDED",
88 		[SCAN_REASON_RUN_FAILED] = "RUN_FAILED",
89 		[SCAN_REASON_TERMINATION_FUNCTION] = "TERMINATION_FUNCTION",
90 		[SCAN_REASON_MAX_OFFCHAN_RETRIES] = "MAX_OFFCHAN_RETRIES",
91 		[SCAN_REASON_DFS_VIOLATION] = "DFS_NOL_VIOLATION",
92 	};
93 
94 	if (reason >= SCAN_REASON_MAX)
95 		return "UNKNOWN";
96 
97 	return reason_name[reason];
98 }
99 
100 qdf_time_t
101 util_get_last_scan_time(struct wlan_objmgr_vdev *vdev)
102 {
103 	uint8_t pdev_id;
104 	struct wlan_scan_obj *scan_obj;
105 
106 	if (!vdev) {
107 		scm_warn("null vdev");
108 		QDF_ASSERT(0);
109 		return 0;
110 	}
111 	pdev_id = wlan_scan_vdev_get_pdev_id(vdev);
112 	scan_obj = wlan_vdev_get_scan_obj(vdev);
113 
114 	if (scan_obj)
115 		return scan_obj->pdev_info[pdev_id].last_scan_time;
116 	else
117 		return 0;
118 }
119 
120 enum wlan_band util_scan_scm_freq_to_band(uint16_t freq)
121 {
122 	if (WLAN_REG_IS_24GHZ_CH_FREQ(freq))
123 		return WLAN_BAND_2_4_GHZ;
124 
125 	return WLAN_BAND_5_GHZ;
126 }
127 
128 bool util_is_scan_entry_match(
129 	struct scan_cache_entry *entry1,
130 	struct scan_cache_entry *entry2)
131 {
132 
133 	if (entry1->cap_info.wlan_caps.ess !=
134 	   entry2->cap_info.wlan_caps.ess)
135 		return false;
136 
137 	if (entry1->cap_info.wlan_caps.ess &&
138 	   !qdf_mem_cmp(entry1->bssid.bytes,
139 	   entry2->bssid.bytes, QDF_MAC_ADDR_SIZE)) {
140 		/* Check for BSS */
141 		if (util_is_ssid_match(&entry1->ssid, &entry2->ssid) ||
142 		    util_scan_is_null_ssid(&entry1->ssid) ||
143 		    util_scan_is_null_ssid(&entry2->ssid))
144 			return true;
145 	} else if (entry1->cap_info.wlan_caps.ibss &&
146 	   (entry1->channel.chan_freq ==
147 	   entry2->channel.chan_freq)) {
148 		/*
149 		 * Same channel cannot have same SSID for
150 		 * different IBSS, so no need to check BSSID
151 		 */
152 		if (util_is_ssid_match(
153 		   &entry1->ssid, &entry2->ssid))
154 			return true;
155 	} else if (!entry1->cap_info.wlan_caps.ibss &&
156 	   !entry1->cap_info.wlan_caps.ess &&
157 	   !qdf_mem_cmp(entry1->bssid.bytes,
158 	   entry2->bssid.bytes, QDF_MAC_ADDR_SIZE)) {
159 		/* In case of P2P devices, ess and ibss will be set to zero */
160 		return true;
161 	}
162 
163 	return false;
164 }
165 
166 static bool util_is_pureg_rate(uint8_t *rates, uint8_t nrates)
167 {
168 	static const uint8_t g_rates[] = {12, 18, 24, 36, 48, 72, 96, 108};
169 	bool pureg = false;
170 	uint8_t i, j;
171 
172 	for (i = 0; i < nrates; i++) {
173 		for (j = 0; j < QDF_ARRAY_SIZE(g_rates); j++) {
174 			if (WLAN_RV(rates[i]) == g_rates[j]) {
175 				pureg = true;
176 				break;
177 			}
178 		}
179 		if (pureg)
180 			break;
181 	}
182 
183 	return pureg;
184 }
185 
186 #ifdef WLAN_FEATURE_11BE
187 static enum wlan_phymode
188 util_scan_get_phymode_11be(struct wlan_objmgr_pdev *pdev,
189 			   struct scan_cache_entry *scan_params,
190 			   enum wlan_phymode phymode,
191 			   uint8_t band_mask)
192 {
193 	struct wlan_ie_ehtops *eht_ops;
194 
195 	eht_ops = (struct wlan_ie_ehtops *)util_scan_entry_ehtop(scan_params);
196 	if (!util_scan_entry_ehtcap(scan_params) || !eht_ops)
197 		return phymode;
198 
199 	switch (eht_ops->width) {
200 	case WLAN_EHT_CHWIDTH_20:
201 		phymode = WLAN_PHYMODE_11BEA_EHT20;
202 		break;
203 	case WLAN_EHT_CHWIDTH_40:
204 		phymode = WLAN_PHYMODE_11BEA_EHT40;
205 		break;
206 	case WLAN_EHT_CHWIDTH_80:
207 		phymode = WLAN_PHYMODE_11BEA_EHT80;
208 		break;
209 	case WLAN_EHT_CHWIDTH_160:
210 		phymode = WLAN_PHYMODE_11BEA_EHT160;
211 		break;
212 	case WLAN_EHT_CHWIDTH_320:
213 		phymode = WLAN_PHYMODE_11BEA_EHT320;
214 		break;
215 	default:
216 		scm_err("Invalid eht_ops width: %d", eht_ops->width);
217 		phymode = WLAN_PHYMODE_11BEA_EHT20;
218 		break;
219 	}
220 
221 	scan_params->channel.cfreq0 =
222 		wlan_reg_chan_band_to_freq(pdev,
223 					   eht_ops->chan_freq_seg0,
224 					   band_mask);
225 	scan_params->channel.cfreq1 =
226 		wlan_reg_chan_band_to_freq(pdev,
227 					   eht_ops->chan_freq_seg1,
228 					   band_mask);
229 	scan_params->channel.puncture_bitmap = eht_ops->puncture_pattern;
230 	return phymode;
231 }
232 #else
233 static enum wlan_phymode
234 util_scan_get_phymode_11be(struct wlan_objmgr_pdev *pdev,
235 			   struct scan_cache_entry *scan_params,
236 			   enum wlan_phymode phymode,
237 			   uint8_t band_mask)
238 {
239 	return phymode;
240 }
241 #endif
242 
243 #ifdef CONFIG_BAND_6GHZ
244 static struct he_oper_6g_param *util_scan_get_he_6g_params(uint8_t *he_ops)
245 {
246 	uint8_t len;
247 	uint32_t he_oper_params;
248 
249 	if (!he_ops)
250 		return NULL;
251 
252 	len = he_ops[1];
253 	he_ops += sizeof(struct ie_header);
254 
255 	if (len < WLAN_HEOP_FIXED_PARAM_LENGTH)
256 		return NULL;
257 
258 	/* element id extension */
259 	he_ops++;
260 	len--;
261 
262 	he_oper_params = LE_READ_4(he_ops);
263 	if (!(he_oper_params & WLAN_HEOP_6GHZ_INFO_PRESENT_MASK))
264 		return NULL;
265 
266 	/* fixed params - element id extension */
267 	he_ops += WLAN_HEOP_FIXED_PARAM_LENGTH - 1;
268 	len -= WLAN_HEOP_FIXED_PARAM_LENGTH - 1;
269 
270 	if (!len)
271 		return NULL;
272 
273 	/* vht oper params */
274 	if (he_oper_params & WLAN_HEOP_VHTOP_PRESENT_MASK) {
275 		if (len < WLAN_HEOP_VHTOP_LENGTH)
276 			return NULL;
277 		he_ops += WLAN_HEOP_VHTOP_LENGTH;
278 		len -= WLAN_HEOP_VHTOP_LENGTH;
279 	}
280 
281 	if (!len)
282 		return NULL;
283 
284 	if (he_oper_params & WLAN_HEOP_CO_LOCATED_BSS_MASK) {
285 		he_ops += WLAN_HEOP_CO_LOCATED_BSS_LENGTH;
286 		len -= WLAN_HEOP_CO_LOCATED_BSS_LENGTH;
287 	}
288 
289 	if (len < sizeof(struct he_oper_6g_param))
290 		return NULL;
291 
292 	return (struct he_oper_6g_param *)he_ops;
293 }
294 
295 static QDF_STATUS
296 util_scan_get_chan_from_he_6g_params(struct wlan_objmgr_pdev *pdev,
297 				     struct scan_cache_entry *scan_params,
298 				     qdf_freq_t *chan_freq,
299 				     bool *he_6g_dup_bcon, uint8_t band_mask)
300 {
301 	struct he_oper_6g_param *he_6g_params;
302 	uint8_t *he_ops;
303 	struct wlan_scan_obj *scan_obj;
304 	struct wlan_objmgr_psoc *psoc;
305 
306 	psoc = wlan_pdev_get_psoc(pdev);
307 	if (!psoc) {
308 		scm_err("psoc is NULL");
309 		return QDF_STATUS_E_INVAL;
310 	}
311 
312 	scan_obj = wlan_psoc_get_scan_obj(psoc);
313 	if (!scan_obj) {
314 		scm_err("scan_obj is NULL");
315 		return QDF_STATUS_E_INVAL;
316 	}
317 
318 	*he_6g_dup_bcon = false;
319 
320 	he_ops = util_scan_entry_heop(scan_params);
321 	if (!util_scan_entry_hecap(scan_params) || !he_ops)
322 		return QDF_STATUS_SUCCESS;
323 
324 	he_6g_params = util_scan_get_he_6g_params(he_ops);
325 	if (!he_6g_params)
326 		return QDF_STATUS_SUCCESS;
327 
328 	*chan_freq = wlan_reg_chan_band_to_freq(pdev,
329 						he_6g_params->primary_channel,
330 						band_mask);
331 	if (scan_obj->drop_bcn_on_invalid_freq &&
332 	    wlan_reg_is_disable_for_pwrmode(pdev, *chan_freq,
333 					    REG_CURRENT_PWR_MODE)) {
334 		scm_debug_rl(QDF_MAC_ADDR_FMT": Drop as invalid channel %d freq %d in HE 6Ghz params",
335 			     QDF_MAC_ADDR_REF(scan_params->bssid.bytes),
336 			     he_6g_params->primary_channel, *chan_freq);
337 		return QDF_STATUS_E_INVAL;
338 	}
339 	*he_6g_dup_bcon = he_6g_params->duplicate_beacon ? true : false;
340 
341 	return QDF_STATUS_SUCCESS;
342 }
343 
344 static enum wlan_phymode
345 util_scan_get_phymode_6g(struct wlan_objmgr_pdev *pdev,
346 			 struct scan_cache_entry *scan_params)
347 {
348 	struct he_oper_6g_param *he_6g_params;
349 	enum wlan_phymode phymode = WLAN_PHYMODE_11AXA_HE20;
350 	uint8_t *he_ops;
351 	uint8_t band_mask = BIT(REG_BAND_6G);
352 
353 	he_ops = util_scan_entry_heop(scan_params);
354 	if (!util_scan_entry_hecap(scan_params) || !he_ops)
355 		return phymode;
356 
357 	he_6g_params = util_scan_get_he_6g_params(he_ops);
358 	if (!he_6g_params)
359 		return phymode;
360 
361 	switch (he_6g_params->width) {
362 	case WLAN_HE_6GHZ_CHWIDTH_20:
363 		phymode = WLAN_PHYMODE_11AXA_HE20;
364 		break;
365 	case WLAN_HE_6GHZ_CHWIDTH_40:
366 		phymode = WLAN_PHYMODE_11AXA_HE40;
367 		break;
368 	case WLAN_HE_6GHZ_CHWIDTH_80:
369 		phymode = WLAN_PHYMODE_11AXA_HE80;
370 		break;
371 	case WLAN_HE_6GHZ_CHWIDTH_160_80_80:
372 		if (WLAN_IS_HE80_80(he_6g_params))
373 			phymode = WLAN_PHYMODE_11AXA_HE80_80;
374 		else if (WLAN_IS_HE160(he_6g_params))
375 			phymode = WLAN_PHYMODE_11AXA_HE160;
376 		else
377 			phymode = WLAN_PHYMODE_11AXA_HE80;
378 		break;
379 	default:
380 		scm_err("Invalid he_6g_params width: %d", he_6g_params->width);
381 		phymode = WLAN_PHYMODE_11AXA_HE20;
382 		break;
383 	}
384 
385 	if (he_6g_params->chan_freq_seg0)
386 		scan_params->channel.cfreq0 =
387 			wlan_reg_chan_band_to_freq(pdev,
388 					he_6g_params->chan_freq_seg0,
389 					band_mask);
390 	if (he_6g_params->chan_freq_seg1)
391 		scan_params->channel.cfreq1 =
392 			wlan_reg_chan_band_to_freq(pdev,
393 					he_6g_params->chan_freq_seg1,
394 					band_mask);
395 
396 	phymode = util_scan_get_phymode_11be(pdev, scan_params,
397 					     phymode, band_mask);
398 
399 	return phymode;
400 }
401 
402 uint8_t
403 util_scan_get_6g_oper_channel(uint8_t *he_op_ie)
404 {
405 	struct he_oper_6g_param *he_6g_params;
406 
407 	he_6g_params = util_scan_get_he_6g_params(he_op_ie);
408 	if (!he_6g_params)
409 		return 0;
410 
411 	return he_6g_params->primary_channel;
412 }
413 
414 #else
415 static QDF_STATUS
416 util_scan_get_chan_from_he_6g_params(struct wlan_objmgr_pdev *pdev,
417 				     struct scan_cache_entry *scan_params,
418 				     qdf_freq_t *chan_freq,
419 				     bool *he_6g_dup_bcon,
420 				     uint8_t band_mask)
421 {
422 	return QDF_STATUS_SUCCESS;
423 }
424 static inline enum wlan_phymode
425 util_scan_get_phymode_6g(struct wlan_objmgr_pdev *pdev,
426 			 struct scan_cache_entry *scan_params)
427 {
428 	return WLAN_PHYMODE_AUTO;
429 }
430 #endif
431 
432 static inline
433 uint32_t util_scan_sec_chan_freq_from_htinfo(struct wlan_ie_htinfo_cmn *htinfo,
434 					     uint32_t primary_chan_freq)
435 {
436 	if (htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_ABOVE)
437 		return primary_chan_freq + WLAN_CHAN_SPACING_20MHZ;
438 	else if (htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_BELOW)
439 		return primary_chan_freq - WLAN_CHAN_SPACING_20MHZ;
440 
441 	return 0;
442 }
443 
444 static enum wlan_phymode
445 util_scan_get_phymode_5g(struct wlan_objmgr_pdev *pdev,
446 			 struct scan_cache_entry *scan_params)
447 {
448 	enum wlan_phymode phymode = WLAN_PHYMODE_AUTO;
449 	uint16_t ht_cap = 0;
450 	struct htcap_cmn_ie *htcap;
451 	struct wlan_ie_htinfo_cmn *htinfo;
452 	struct wlan_ie_vhtop *vhtop;
453 	uint8_t band_mask = BIT(REG_BAND_5G);
454 
455 	htcap = (struct htcap_cmn_ie *)
456 		util_scan_entry_htcap(scan_params);
457 	htinfo = (struct wlan_ie_htinfo_cmn *)
458 		util_scan_entry_htinfo(scan_params);
459 	vhtop = (struct wlan_ie_vhtop *)
460 		util_scan_entry_vhtop(scan_params);
461 
462 	if (!(htcap && htinfo))
463 		return WLAN_PHYMODE_11A;
464 
465 	if (htcap)
466 		ht_cap = le16toh(htcap->hc_cap);
467 
468 	if (ht_cap & WLAN_HTCAP_C_CHWIDTH40)
469 		phymode = WLAN_PHYMODE_11NA_HT40;
470 	else
471 		phymode = WLAN_PHYMODE_11NA_HT20;
472 
473 	scan_params->channel.cfreq0 =
474 		util_scan_sec_chan_freq_from_htinfo(htinfo,
475 						scan_params->channel.chan_freq);
476 
477 	if (util_scan_entry_vhtcap(scan_params) && vhtop) {
478 		switch (vhtop->vht_op_chwidth) {
479 		case WLAN_VHTOP_CHWIDTH_2040:
480 			if (ht_cap & WLAN_HTCAP_C_CHWIDTH40)
481 				phymode = WLAN_PHYMODE_11AC_VHT40;
482 			else
483 				phymode = WLAN_PHYMODE_11AC_VHT20;
484 			break;
485 		case WLAN_VHTOP_CHWIDTH_80:
486 			if (WLAN_IS_REVSIG_VHT80_80(vhtop))
487 				phymode = WLAN_PHYMODE_11AC_VHT80_80;
488 			else if (WLAN_IS_REVSIG_VHT160(vhtop))
489 				phymode = WLAN_PHYMODE_11AC_VHT160;
490 			else
491 				phymode = WLAN_PHYMODE_11AC_VHT80;
492 			break;
493 		case WLAN_VHTOP_CHWIDTH_160:
494 			phymode = WLAN_PHYMODE_11AC_VHT160;
495 			break;
496 		case WLAN_VHTOP_CHWIDTH_80_80:
497 			phymode = WLAN_PHYMODE_11AC_VHT80_80;
498 			break;
499 		default:
500 			scm_err("bad channel: %d",
501 					vhtop->vht_op_chwidth);
502 			phymode = WLAN_PHYMODE_11AC_VHT20;
503 			break;
504 		}
505 		if (vhtop->vht_op_ch_freq_seg1)
506 			scan_params->channel.cfreq0 =
507 				wlan_reg_chan_band_to_freq(pdev,
508 						vhtop->vht_op_ch_freq_seg1,
509 						band_mask);
510 		if (vhtop->vht_op_ch_freq_seg2)
511 			scan_params->channel.cfreq1 =
512 				wlan_reg_chan_band_to_freq(pdev,
513 						vhtop->vht_op_ch_freq_seg2,
514 						band_mask);
515 	}
516 
517 	if (!util_scan_entry_hecap(scan_params))
518 		return phymode;
519 
520 	/* for 5Ghz Check for HE, only if VHT cap and HE cap are present */
521 	if (!IS_WLAN_PHYMODE_VHT(phymode))
522 		return phymode;
523 
524 	switch (phymode) {
525 	case WLAN_PHYMODE_11AC_VHT20:
526 		phymode = WLAN_PHYMODE_11AXA_HE20;
527 		break;
528 	case WLAN_PHYMODE_11AC_VHT40:
529 		phymode = WLAN_PHYMODE_11AXA_HE40;
530 		break;
531 	case WLAN_PHYMODE_11AC_VHT80:
532 		phymode = WLAN_PHYMODE_11AXA_HE80;
533 		break;
534 	case WLAN_PHYMODE_11AC_VHT160:
535 		phymode = WLAN_PHYMODE_11AXA_HE160;
536 		break;
537 	case WLAN_PHYMODE_11AC_VHT80_80:
538 		phymode = WLAN_PHYMODE_11AXA_HE80_80;
539 		break;
540 	default:
541 		phymode = WLAN_PHYMODE_11AXA_HE20;
542 		break;
543 	}
544 
545 	phymode = util_scan_get_phymode_11be(pdev, scan_params,
546 					     phymode, band_mask);
547 
548 	return phymode;
549 }
550 
551 #ifdef WLAN_FEATURE_11BE
552 static enum wlan_phymode
553 util_scan_get_phymode_2g_11be(struct scan_cache_entry *scan_params,
554 			      enum wlan_phymode  phymode)
555 {
556 	if (!util_scan_entry_ehtcap(scan_params))
557 		return phymode;
558 
559 	if (phymode == WLAN_PHYMODE_11AXG_HE40PLUS)
560 		phymode = WLAN_PHYMODE_11BEG_EHT40PLUS;
561 	else if (phymode == WLAN_PHYMODE_11AXG_HE40MINUS)
562 		phymode = WLAN_PHYMODE_11BEG_EHT40MINUS;
563 	else
564 		phymode = WLAN_PHYMODE_11BEG_EHT20;
565 
566 	return phymode;
567 }
568 #else
569 static enum wlan_phymode
570 util_scan_get_phymode_2g_11be(struct scan_cache_entry *scan_params,
571 			      enum wlan_phymode  phymode)
572 {
573 	return phymode;
574 }
575 #endif
576 
577 static enum wlan_phymode
578 util_scan_get_phymode_2g(struct scan_cache_entry *scan_params)
579 {
580 	enum wlan_phymode phymode = WLAN_PHYMODE_AUTO;
581 	uint16_t ht_cap = 0;
582 	struct htcap_cmn_ie *htcap;
583 	struct wlan_ie_htinfo_cmn *htinfo;
584 	struct wlan_ie_vhtop *vhtop;
585 
586 	htcap = (struct htcap_cmn_ie *)
587 		util_scan_entry_htcap(scan_params);
588 	htinfo = (struct wlan_ie_htinfo_cmn *)
589 		util_scan_entry_htinfo(scan_params);
590 	vhtop = (struct wlan_ie_vhtop *)
591 		util_scan_entry_vhtop(scan_params);
592 
593 	if (htcap)
594 		ht_cap = le16toh(htcap->hc_cap);
595 
596 	if (htcap && htinfo) {
597 		if ((ht_cap & WLAN_HTCAP_C_CHWIDTH40) &&
598 		   (htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_ABOVE))
599 			phymode = WLAN_PHYMODE_11NG_HT40PLUS;
600 		else if ((ht_cap & WLAN_HTCAP_C_CHWIDTH40) &&
601 		   (htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_BELOW))
602 			phymode = WLAN_PHYMODE_11NG_HT40MINUS;
603 		else
604 			phymode = WLAN_PHYMODE_11NG_HT20;
605 	} else if (util_scan_entry_xrates(scan_params)) {
606 		/* only 11G stations will have more than 8 rates */
607 		phymode = WLAN_PHYMODE_11G;
608 	} else {
609 		/* Some mischievous g-only APs do not set extended rates */
610 		if (util_scan_entry_rates(scan_params)) {
611 			if (util_is_pureg_rate(&scan_params->ie_list.rates[2],
612 			   scan_params->ie_list.rates[1]))
613 				phymode = WLAN_PHYMODE_11G;
614 			else
615 				phymode = WLAN_PHYMODE_11B;
616 		} else {
617 			phymode = WLAN_PHYMODE_11B;
618 		}
619 	}
620 
621 	/* Check for VHT only if HT cap is present */
622 	if (!IS_WLAN_PHYMODE_HT(phymode))
623 		return phymode;
624 
625 	scan_params->channel.cfreq0 =
626 		util_scan_sec_chan_freq_from_htinfo(htinfo,
627 						scan_params->channel.chan_freq);
628 
629 	if (util_scan_entry_vhtcap(scan_params) && vhtop) {
630 		switch (vhtop->vht_op_chwidth) {
631 		case WLAN_VHTOP_CHWIDTH_2040:
632 			if (phymode == WLAN_PHYMODE_11NG_HT40PLUS)
633 				phymode = WLAN_PHYMODE_11AC_VHT40PLUS_2G;
634 			else if (phymode == WLAN_PHYMODE_11NG_HT40MINUS)
635 				phymode = WLAN_PHYMODE_11AC_VHT40MINUS_2G;
636 			else
637 				phymode = WLAN_PHYMODE_11AC_VHT20_2G;
638 
639 			break;
640 		default:
641 			scm_info("bad vht_op_chwidth: %d",
642 				 vhtop->vht_op_chwidth);
643 			phymode = WLAN_PHYMODE_11AC_VHT20_2G;
644 			break;
645 		}
646 	}
647 
648 	if (!util_scan_entry_hecap(scan_params))
649 		return phymode;
650 
651 	if (phymode == WLAN_PHYMODE_11AC_VHT40PLUS_2G ||
652 	    phymode == WLAN_PHYMODE_11NG_HT40PLUS)
653 		phymode = WLAN_PHYMODE_11AXG_HE40PLUS;
654 	else if (phymode == WLAN_PHYMODE_11AC_VHT40MINUS_2G ||
655 		 phymode == WLAN_PHYMODE_11NG_HT40MINUS)
656 		phymode = WLAN_PHYMODE_11AXG_HE40MINUS;
657 	else
658 		phymode = WLAN_PHYMODE_11AXG_HE20;
659 
660 	phymode = util_scan_get_phymode_2g_11be(scan_params, phymode);
661 
662 	return phymode;
663 }
664 
665 static enum wlan_phymode
666 util_scan_get_phymode(struct wlan_objmgr_pdev *pdev,
667 		      struct scan_cache_entry *scan_params)
668 {
669 	if (WLAN_REG_IS_24GHZ_CH_FREQ(scan_params->channel.chan_freq))
670 		return util_scan_get_phymode_2g(scan_params);
671 	else if (WLAN_REG_IS_6GHZ_CHAN_FREQ(scan_params->channel.chan_freq))
672 		return util_scan_get_phymode_6g(pdev, scan_params);
673 	else
674 		return util_scan_get_phymode_5g(pdev, scan_params);
675 }
676 
677 static QDF_STATUS
678 util_scan_parse_chan_switch_wrapper_ie(struct scan_cache_entry *scan_params,
679 	struct ie_header *sub_ie, qdf_size_t sub_ie_len)
680 {
681 	/* Walk through to check nothing is malformed */
682 	while (sub_ie_len >= sizeof(struct ie_header)) {
683 		/* At least one more header is present */
684 		sub_ie_len -= sizeof(struct ie_header);
685 
686 		if (sub_ie->ie_len == 0) {
687 			sub_ie += 1;
688 			continue;
689 		}
690 		if (sub_ie_len < sub_ie->ie_len) {
691 			scm_err("Incomplete corrupted IE:%x",
692 				WLAN_ELEMID_CHAN_SWITCH_WRAP);
693 			return QDF_STATUS_E_INVAL;
694 		}
695 		switch (sub_ie->ie_id) {
696 		case WLAN_ELEMID_COUNTRY:
697 			if (sub_ie->ie_len < WLAN_COUNTRY_IE_MIN_LEN)
698 				return QDF_STATUS_E_INVAL;
699 			scan_params->ie_list.country = (uint8_t *)sub_ie;
700 			break;
701 		case WLAN_ELEMID_WIDE_BAND_CHAN_SWITCH:
702 			if (sub_ie->ie_len < WLAN_WIDE_BW_CHAN_SWITCH_IE_LEN)
703 				return QDF_STATUS_E_INVAL;
704 			scan_params->ie_list.widebw = (uint8_t *)sub_ie;
705 			break;
706 		case WLAN_ELEMID_VHT_TX_PWR_ENVLP:
707 			if (sub_ie->ie_len > WLAN_TPE_IE_MAX_LEN)
708 				return QDF_STATUS_E_INVAL;
709 			scan_params->ie_list.txpwrenvlp = (uint8_t *)sub_ie;
710 			break;
711 		}
712 		/* Consume sub info element */
713 		sub_ie_len -= sub_ie->ie_len;
714 		/* go to next Sub IE */
715 		sub_ie = (struct ie_header *)
716 			(((uint8_t *) sub_ie) +
717 			sizeof(struct ie_header) + sub_ie->ie_len);
718 	}
719 
720 	return QDF_STATUS_SUCCESS;
721 }
722 
723 bool
724 util_scan_is_hidden_ssid(struct ie_ssid *ssid)
725 {
726 	uint8_t i;
727 
728 	/*
729 	 * We flag this as Hidden SSID if the Length is 0
730 	 * of the SSID only contains 0's
731 	 */
732 	if (!ssid || !ssid->ssid_len)
733 		return true;
734 
735 	for (i = 0; i < ssid->ssid_len; i++)
736 		if (ssid->ssid[i] != 0)
737 			return false;
738 
739 	/* All 0's */
740 	return true;
741 }
742 
743 #ifdef WLAN_FEATURE_11BE_MLO
744 static void
745 util_scan_update_rnr_mld(struct rnr_bss_info *rnr,
746 			 struct neighbor_ap_info_field *ap_info, uint8_t *data)
747 {
748 	uint8_t tbtt_info_length;
749 	bool mld_info_present = false;
750 
751 	tbtt_info_length = ap_info->tbtt_header.tbtt_info_length;
752 	if (tbtt_info_length >=
753 		TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM_20MHZ_PSD_MLD_PARAM)
754 		tbtt_info_length =
755 		   TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM_20MHZ_PSD_MLD_PARAM;
756 
757 	switch (tbtt_info_length) {
758 	case TBTT_NEIGHBOR_AP_MLD_PARAM:
759 		rnr->channel_number = ap_info->channel_number;
760 		rnr->operating_class = ap_info->operting_class;
761 		qdf_mem_copy(&rnr->mld_info, &data[1],
762 			     sizeof(struct rnr_mld_info));
763 		mld_info_present = true;
764 		break;
765 	case TBTT_NEIGHBOR_AP_BSSID_MLD_PARAM:
766 		rnr->channel_number = ap_info->channel_number;
767 		rnr->operating_class = ap_info->operting_class;
768 		qdf_mem_copy(&rnr->bssid, &data[1], QDF_MAC_ADDR_SIZE);
769 		qdf_mem_copy(&rnr->mld_info, &data[1 + QDF_MAC_ADDR_SIZE],
770 			     sizeof(struct rnr_mld_info));
771 		mld_info_present = true;
772 		break;
773 	case TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM_20MHZ_PSD_MLD_PARAM:
774 		rnr->channel_number = ap_info->channel_number;
775 		rnr->operating_class = ap_info->operting_class;
776 		qdf_mem_copy(&rnr->bssid, &data[1], QDF_MAC_ADDR_SIZE);
777 		qdf_mem_copy(&rnr->short_ssid, &data[7], SHORT_SSID_LEN);
778 		rnr->bss_params = data[11];
779 		rnr->psd_20mhz = data[12];
780 		qdf_mem_copy(&rnr->mld_info, &data[13],
781 			     sizeof(struct rnr_mld_info));
782 		mld_info_present = true;
783 		break;
784 	};
785 
786 	rnr->mld_info_valid = mld_info_present;
787 }
788 #else
789 static void
790 util_scan_update_rnr_mld(struct rnr_bss_info *rnr,
791 			 struct neighbor_ap_info_field *ap_info, uint8_t *data)
792 {
793 	scm_debug("Wrong fieldtype");
794 }
795 #endif
796 
797 static QDF_STATUS
798 util_scan_update_rnr(struct rnr_bss_info *rnr,
799 		     struct neighbor_ap_info_field *ap_info,
800 		     uint8_t *data)
801 {
802 	uint8_t tbtt_info_length;
803 
804 	tbtt_info_length = ap_info->tbtt_header.tbtt_info_length;
805 
806 	switch (tbtt_info_length) {
807 	case TBTT_NEIGHBOR_AP_OFFSET_ONLY:
808 		/* Dont store it skip*/
809 		break;
810 
811 	case TBTT_NEIGHBOR_AP_BSS_PARAM:
812 		/* Dont store it skip*/
813 		break;
814 
815 	case TBTT_NEIGHBOR_AP_SHORTSSID:
816 		rnr->channel_number = ap_info->channel_number;
817 		rnr->operating_class = ap_info->operting_class;
818 		qdf_mem_copy(&rnr->short_ssid, &data[1], SHORT_SSID_LEN);
819 		break;
820 
821 	case TBTT_NEIGHBOR_AP_S_SSID_BSS_PARAM:
822 		rnr->channel_number = ap_info->channel_number;
823 		rnr->operating_class = ap_info->operting_class;
824 		qdf_mem_copy(&rnr->short_ssid, &data[1], SHORT_SSID_LEN);
825 		rnr->bss_params = data[5];
826 		break;
827 
828 	case TBTT_NEIGHBOR_AP_BSSID:
829 		rnr->channel_number = ap_info->channel_number;
830 		rnr->operating_class = ap_info->operting_class;
831 		qdf_mem_copy(&rnr->bssid, &data[1], QDF_MAC_ADDR_SIZE);
832 		break;
833 
834 	case TBTT_NEIGHBOR_AP_BSSID_BSS_PARAM:
835 		rnr->channel_number = ap_info->channel_number;
836 		rnr->operating_class = ap_info->operting_class;
837 		qdf_mem_copy(&rnr->bssid, &data[1], QDF_MAC_ADDR_SIZE);
838 		rnr->bss_params = data[7];
839 		break;
840 
841 	case TBTT_NEIGHBOR_AP_BSSID_BSS_PARAM_20MHZ_PSD:
842 		rnr->channel_number = ap_info->channel_number;
843 		rnr->operating_class = ap_info->operting_class;
844 		qdf_mem_copy(&rnr->bssid, &data[1], QDF_MAC_ADDR_SIZE);
845 		rnr->bss_params = data[7];
846 		rnr->psd_20mhz = data[8];
847 		break;
848 
849 	case TBTT_NEIGHBOR_AP_BSSSID_S_SSID:
850 		rnr->channel_number = ap_info->channel_number;
851 		rnr->operating_class = ap_info->operting_class;
852 		qdf_mem_copy(&rnr->bssid, &data[1], QDF_MAC_ADDR_SIZE);
853 		qdf_mem_copy(&rnr->short_ssid, &data[7], SHORT_SSID_LEN);
854 		break;
855 
856 	case TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM:
857 		rnr->channel_number = ap_info->channel_number;
858 		rnr->operating_class = ap_info->operting_class;
859 		qdf_mem_copy(&rnr->bssid, &data[1], QDF_MAC_ADDR_SIZE);
860 		qdf_mem_copy(&rnr->short_ssid, &data[7], SHORT_SSID_LEN);
861 		rnr->bss_params = data[11];
862 		break;
863 
864 	case TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM_20MHZ_PSD:
865 		rnr->channel_number = ap_info->channel_number;
866 		rnr->operating_class = ap_info->operting_class;
867 		qdf_mem_copy(&rnr->bssid, &data[1], QDF_MAC_ADDR_SIZE);
868 		qdf_mem_copy(&rnr->short_ssid, &data[7], SHORT_SSID_LEN);
869 		rnr->bss_params = data[11];
870 		rnr->psd_20mhz = data[12];
871 		break;
872 
873 	default:
874 		util_scan_update_rnr_mld(rnr, ap_info, data);
875 	}
876 
877 	return QDF_STATUS_SUCCESS;
878 }
879 
880 static QDF_STATUS
881 util_scan_parse_rnr_ie(struct scan_cache_entry *scan_entry,
882 		       struct ie_header *ie)
883 {
884 	uint32_t rnr_ie_len;
885 	uint16_t tbtt_count, tbtt_length, i, fieldtype, idx = 0;
886 	uint8_t *data;
887 	struct neighbor_ap_info_field *neighbor_ap_info;
888 
889 	rnr_ie_len = ie->ie_len;
890 	data = (uint8_t *)ie + sizeof(struct ie_header);
891 
892 	while (data < ((uint8_t *)ie + rnr_ie_len + 2)) {
893 		neighbor_ap_info = (struct neighbor_ap_info_field *)data;
894 		tbtt_count = neighbor_ap_info->tbtt_header.tbtt_info_count;
895 		tbtt_length = neighbor_ap_info->tbtt_header.tbtt_info_length;
896 		fieldtype = neighbor_ap_info->tbtt_header.tbbt_info_fieldtype;
897 		scm_debug("channel number %d, op class %d",
898 			  neighbor_ap_info->channel_number,
899 			  neighbor_ap_info->operting_class);
900 		scm_debug("tbtt_count %d, tbtt_length %d, fieldtype %d",
901 			  tbtt_count, tbtt_length, fieldtype);
902 		data += sizeof(struct neighbor_ap_info_field);
903 
904 		if (tbtt_count > TBTT_INFO_COUNT)
905 			break;
906 
907 		for (i = 0; i < (tbtt_count + 1) &&
908 		     data < ((uint8_t *)ie + rnr_ie_len + 2); i++) {
909 			if (i < MAX_RNR_BSS || idx < MAX_RNR_BSS)
910 				util_scan_update_rnr(
911 					&scan_entry->rnr.bss_info[idx++],
912 					neighbor_ap_info,
913 					data);
914 			data += tbtt_length;
915 		}
916 	}
917 
918 	scan_entry->rnr.count = idx;
919 
920 	return QDF_STATUS_SUCCESS;
921 }
922 
923 #ifdef WLAN_FEATURE_11BE_MLO
924 static void util_scan_parse_eht_ie(struct scan_cache_entry *scan_params,
925 				   struct extn_ie_header *extn_ie)
926 {
927 	switch (extn_ie->ie_extn_id) {
928 	case WLAN_EXTN_ELEMID_MULTI_LINK:
929 		scan_params->ie_list.multi_link = (uint8_t *)extn_ie;
930 		break;
931 	default:
932 		break;
933 	}
934 }
935 #else
936 static void util_scan_parse_eht_ie(struct scan_cache_entry *scan_params,
937 				   struct extn_ie_header *extn_ie)
938 {
939 }
940 #endif
941 
942 static QDF_STATUS
943 util_scan_parse_extn_ie(struct scan_cache_entry *scan_params,
944 	struct ie_header *ie)
945 {
946 	struct extn_ie_header *extn_ie = (struct extn_ie_header *) ie;
947 
948 	switch (extn_ie->ie_extn_id) {
949 	case WLAN_EXTN_ELEMID_MAX_CHAN_SWITCH_TIME:
950 		if (extn_ie->ie_len != WLAN_MAX_CHAN_SWITCH_TIME_IE_LEN)
951 			return QDF_STATUS_E_INVAL;
952 		scan_params->ie_list.mcst  = (uint8_t *)ie;
953 		break;
954 	case WLAN_EXTN_ELEMID_SRP:
955 		if (extn_ie->ie_len > WLAN_MAX_SRP_IE_LEN)
956 			return QDF_STATUS_E_INVAL;
957 		scan_params->ie_list.srp   = (uint8_t *)ie;
958 		break;
959 	case WLAN_EXTN_ELEMID_HECAP:
960 		scan_params->ie_list.hecap = (uint8_t *)ie;
961 		break;
962 	case WLAN_EXTN_ELEMID_HEOP:
963 		if (extn_ie->ie_len > WLAN_MAX_HEOP_IE_LEN)
964 			return QDF_STATUS_E_INVAL;
965 		scan_params->ie_list.heop  = (uint8_t *)ie;
966 		break;
967 	case WLAN_EXTN_ELEMID_ESP:
968 		scan_params->ie_list.esp = (uint8_t *)ie;
969 		break;
970 	case WLAN_EXTN_ELEMID_MUEDCA:
971 		if (extn_ie->ie_len > WLAN_MAX_MUEDCA_IE_LEN)
972 			return QDF_STATUS_E_INVAL;
973 		scan_params->ie_list.muedca = (uint8_t *)ie;
974 		break;
975 	case WLAN_EXTN_ELEMID_HE_6G_CAP:
976 		if (extn_ie->ie_len > WLAN_MAX_HE_6G_CAP_IE_LEN)
977 			return QDF_STATUS_E_INVAL;
978 		scan_params->ie_list.hecap_6g = (uint8_t *)ie;
979 		break;
980 #ifdef WLAN_FEATURE_11BE
981 	case WLAN_EXTN_ELEMID_EHTCAP:
982 		scan_params->ie_list.ehtcap = (uint8_t *)ie;
983 		break;
984 	case WLAN_EXTN_ELEMID_EHTOP:
985 		scan_params->ie_list.ehtop  = (uint8_t *)ie;
986 		break;
987 #endif
988 	default:
989 		break;
990 	}
991 	util_scan_parse_eht_ie(scan_params, extn_ie);
992 
993 	return QDF_STATUS_SUCCESS;
994 }
995 
996 static QDF_STATUS
997 util_scan_parse_vendor_ie(struct scan_cache_entry *scan_params,
998 	struct ie_header *ie)
999 {
1000 	if (!scan_params->ie_list.vendor)
1001 		scan_params->ie_list.vendor = (uint8_t *)ie;
1002 
1003 	if (is_wpa_oui((uint8_t *)ie)) {
1004 		scan_params->ie_list.wpa = (uint8_t *)ie;
1005 	} else if (is_wps_oui((uint8_t *)ie)) {
1006 		scan_params->ie_list.wps = (uint8_t *)ie;
1007 		/* WCN IE should be a subset of WPS IE */
1008 		if (is_wcn_oui((uint8_t *)ie))
1009 			scan_params->ie_list.wcn = (uint8_t *)ie;
1010 	} else if (is_wme_param((uint8_t *)ie)) {
1011 		if (ie->ie_len > WLAN_VENDOR_WME_IE_LEN)
1012 			return QDF_STATUS_E_INVAL;
1013 
1014 		scan_params->ie_list.wmeparam = (uint8_t *)ie;
1015 	} else if (is_wme_info((uint8_t *)ie)) {
1016 		scan_params->ie_list.wmeinfo = (uint8_t *)ie;
1017 	} else if (is_atheros_oui((uint8_t *)ie)) {
1018 		if (ie->ie_len > WLAN_VENDOR_ATHCAPS_IE_LEN)
1019 			return QDF_STATUS_E_INVAL;
1020 
1021 		scan_params->ie_list.athcaps = (uint8_t *)ie;
1022 	} else if (is_atheros_extcap_oui((uint8_t *)ie)) {
1023 		if (ie->ie_len > WLAN_VENDOR_ATH_EXTCAP_IE_LEN)
1024 			return QDF_STATUS_E_INVAL;
1025 
1026 		scan_params->ie_list.athextcaps = (uint8_t *)ie;
1027 	} else if (is_sfa_oui((uint8_t *)ie)) {
1028 		if (ie->ie_len > WLAN_VENDOR_SFA_IE_LEN)
1029 			return QDF_STATUS_E_INVAL;
1030 
1031 		scan_params->ie_list.sfa = (uint8_t *)ie;
1032 	} else if (is_p2p_oui((uint8_t *)ie)) {
1033 		scan_params->ie_list.p2p = (uint8_t *)ie;
1034 	} else if (is_qca_son_oui((uint8_t *)ie,
1035 				  QCA_OUI_WHC_AP_INFO_SUBTYPE)) {
1036 		if (ie->ie_len > WLAN_VENDOR_SON_IE_LEN)
1037 			return QDF_STATUS_E_INVAL;
1038 
1039 		scan_params->ie_list.sonadv = (uint8_t *)ie;
1040 	} else if (is_ht_cap((uint8_t *)ie)) {
1041 		/* we only care if there isn't already an HT IE (ANA) */
1042 		if (!scan_params->ie_list.htcap) {
1043 			if (ie->ie_len != (WLAN_VENDOR_HT_IE_OFFSET_LEN +
1044 					   sizeof(struct htcap_cmn_ie)))
1045 				return QDF_STATUS_E_INVAL;
1046 			scan_params->ie_list.htcap =
1047 			 (uint8_t *)&(((struct wlan_vendor_ie_htcap *)ie)->ie);
1048 		}
1049 	} else if (is_ht_info((uint8_t *)ie)) {
1050 		/* we only care if there isn't already an HT IE (ANA) */
1051 		if (!scan_params->ie_list.htinfo) {
1052 			if (ie->ie_len != WLAN_VENDOR_HT_IE_OFFSET_LEN +
1053 					  sizeof(struct wlan_ie_htinfo_cmn))
1054 				return QDF_STATUS_E_INVAL;
1055 			scan_params->ie_list.htinfo =
1056 			  (uint8_t *)&(((struct wlan_vendor_ie_htinfo *)
1057 			  ie)->hi_ie);
1058 		}
1059 	} else if (is_interop_vht((uint8_t *)ie) &&
1060 	    !(scan_params->ie_list.vhtcap)) {
1061 		uint8_t *vendor_ie = (uint8_t *)(ie);
1062 
1063 		if (ie->ie_len < ((WLAN_VENDOR_VHTCAP_IE_OFFSET +
1064 				 sizeof(struct wlan_ie_vhtcaps)) -
1065 				 sizeof(struct ie_header)))
1066 			return QDF_STATUS_E_INVAL;
1067 		vendor_ie = ((uint8_t *)(ie)) + WLAN_VENDOR_VHTCAP_IE_OFFSET;
1068 		if (vendor_ie[1] != (sizeof(struct wlan_ie_vhtcaps)) -
1069 				      sizeof(struct ie_header))
1070 			return QDF_STATUS_E_INVAL;
1071 		/* location where Interop Vht Cap IE and VHT OP IE Present */
1072 		scan_params->ie_list.vhtcap = (((uint8_t *)(ie)) +
1073 						WLAN_VENDOR_VHTCAP_IE_OFFSET);
1074 		if (ie->ie_len > ((WLAN_VENDOR_VHTCAP_IE_OFFSET +
1075 				 sizeof(struct wlan_ie_vhtcaps)) -
1076 				 sizeof(struct ie_header))) {
1077 			if (ie->ie_len < ((WLAN_VENDOR_VHTOP_IE_OFFSET +
1078 					  sizeof(struct wlan_ie_vhtop)) -
1079 					  sizeof(struct ie_header)))
1080 				return QDF_STATUS_E_INVAL;
1081 			vendor_ie = ((uint8_t *)(ie)) +
1082 				    WLAN_VENDOR_VHTOP_IE_OFFSET;
1083 			if (vendor_ie[1] != (sizeof(struct wlan_ie_vhtop) -
1084 					     sizeof(struct ie_header)))
1085 				return QDF_STATUS_E_INVAL;
1086 			scan_params->ie_list.vhtop = (((uint8_t *)(ie)) +
1087 						   WLAN_VENDOR_VHTOP_IE_OFFSET);
1088 		}
1089 	} else if (is_bwnss_oui((uint8_t *)ie)) {
1090 		/*
1091 		 * Bandwidth-NSS map has sub-type & version.
1092 		 * hence copy data just after version byte
1093 		 */
1094 		if (ie->ie_len > WLAN_BWNSS_MAP_OFFSET)
1095 			scan_params->ie_list.bwnss_map = (((uint8_t *)ie) + 8);
1096 	} else if (is_mbo_oce_oui((uint8_t *)ie)) {
1097 		scan_params->ie_list.mbo_oce = (uint8_t *)ie;
1098 	} else if (is_extender_oui((uint8_t *)ie)) {
1099 		scan_params->ie_list.extender = (uint8_t *)ie;
1100 	} else if (is_adaptive_11r_oui((uint8_t *)ie)) {
1101 		if ((ie->ie_len < OUI_LENGTH) ||
1102 		    (ie->ie_len > MAX_ADAPTIVE_11R_IE_LEN))
1103 			return QDF_STATUS_E_INVAL;
1104 
1105 		scan_params->ie_list.adaptive_11r = (uint8_t *)ie +
1106 						sizeof(struct ie_header);
1107 	} else if (is_sae_single_pmk_oui((uint8_t *)ie)) {
1108 		if ((ie->ie_len < OUI_LENGTH) ||
1109 		    (ie->ie_len > MAX_SAE_SINGLE_PMK_IE_LEN)) {
1110 			scm_debug("Invalid sae single pmk OUI");
1111 			return QDF_STATUS_E_INVAL;
1112 		}
1113 		scan_params->ie_list.single_pmk = (uint8_t *)ie +
1114 						sizeof(struct ie_header);
1115 	}
1116 	return QDF_STATUS_SUCCESS;
1117 }
1118 
1119 static QDF_STATUS
1120 util_scan_populate_bcn_ie_list(struct wlan_objmgr_pdev *pdev,
1121 			       struct scan_cache_entry *scan_params,
1122 			       qdf_freq_t *chan_freq, uint8_t band_mask)
1123 {
1124 	struct ie_header *ie, *sub_ie;
1125 	uint32_t ie_len, sub_ie_len;
1126 	QDF_STATUS status;
1127 	uint8_t chan_idx;
1128 	struct wlan_scan_obj *scan_obj;
1129 	struct wlan_objmgr_psoc *psoc;
1130 	uint8_t tpe_idx = 0;
1131 
1132 	psoc = wlan_pdev_get_psoc(pdev);
1133 	if (!psoc) {
1134 		scm_err("psoc is NULL");
1135 		return QDF_STATUS_E_INVAL;
1136 	}
1137 
1138 	scan_obj = wlan_psoc_get_scan_obj(psoc);
1139 	if (!scan_obj) {
1140 		scm_err("scan_obj is NULL");
1141 		return QDF_STATUS_E_INVAL;
1142 	}
1143 
1144 	ie_len = util_scan_entry_ie_len(scan_params);
1145 	ie = (struct ie_header *)
1146 		  util_scan_entry_ie_data(scan_params);
1147 
1148 	while (ie_len >= sizeof(struct ie_header)) {
1149 		ie_len -= sizeof(struct ie_header);
1150 
1151 		if (!ie->ie_len) {
1152 			ie += 1;
1153 			continue;
1154 		}
1155 
1156 		if (ie_len < ie->ie_len) {
1157 			if (scan_obj->allow_bss_with_incomplete_ie) {
1158 				scm_debug(QDF_MAC_ADDR_FMT": Scan allowed with incomplete corrupted IE:%x, ie_len: %d, ie->ie_len: %d, stop processing further",
1159 					  QDF_MAC_ADDR_REF(scan_params->bssid.bytes),
1160 					  ie->ie_id, ie_len, ie->ie_len);
1161 				break;
1162 			}
1163 			scm_debug(QDF_MAC_ADDR_FMT": Scan not allowed with incomplete corrupted IE:%x, ie_len: %d, ie->ie_len: %d, stop processing further",
1164 				  QDF_MAC_ADDR_REF(scan_params->bssid.bytes),
1165 				  ie->ie_id, ie_len, ie->ie_len);
1166 			return QDF_STATUS_E_INVAL;
1167 		}
1168 
1169 		switch (ie->ie_id) {
1170 		case WLAN_ELEMID_SSID:
1171 			if (ie->ie_len > (sizeof(struct ie_ssid) -
1172 					  sizeof(struct ie_header)))
1173 				goto err;
1174 			scan_params->ie_list.ssid = (uint8_t *)ie;
1175 			break;
1176 		case WLAN_ELEMID_RATES:
1177 			if (ie->ie_len > WLAN_SUPPORTED_RATES_IE_MAX_LEN)
1178 				goto err;
1179 			scan_params->ie_list.rates = (uint8_t *)ie;
1180 			break;
1181 		case WLAN_ELEMID_DSPARMS:
1182 			if (ie->ie_len != WLAN_DS_PARAM_IE_MAX_LEN)
1183 				return QDF_STATUS_E_INVAL;
1184 			scan_params->ie_list.ds_param = (uint8_t *)ie;
1185 			chan_idx = ((struct ds_ie *)ie)->cur_chan;
1186 			*chan_freq = wlan_reg_chan_band_to_freq(pdev, chan_idx,
1187 								band_mask);
1188 			/* Drop if invalid freq */
1189 			if (scan_obj->drop_bcn_on_invalid_freq &&
1190 			    !wlan_reg_is_freq_present_in_cur_chan_list(pdev,
1191 								*chan_freq)) {
1192 				scm_debug(QDF_MAC_ADDR_FMT": Drop as invalid chan %d in DS IE, freq %d, band_mask %d",
1193 					  QDF_MAC_ADDR_REF(
1194 						  scan_params->bssid.bytes),
1195 					  chan_idx, *chan_freq, band_mask);
1196 				return QDF_STATUS_E_INVAL;
1197 			}
1198 			break;
1199 		case WLAN_ELEMID_TIM:
1200 			if (ie->ie_len < WLAN_TIM_IE_MIN_LENGTH)
1201 				goto err;
1202 			scan_params->ie_list.tim = (uint8_t *)ie;
1203 			scan_params->dtim_period =
1204 				((struct wlan_tim_ie *)ie)->tim_period;
1205 			break;
1206 		case WLAN_ELEMID_COUNTRY:
1207 			if (ie->ie_len < WLAN_COUNTRY_IE_MIN_LEN)
1208 				goto err;
1209 			scan_params->ie_list.country = (uint8_t *)ie;
1210 			break;
1211 		case WLAN_ELEMID_QBSS_LOAD:
1212 			if (ie->ie_len != sizeof(struct qbss_load_ie) -
1213 					  sizeof(struct ie_header)) {
1214 				/*
1215 				 * Expected QBSS IE length is 5Bytes; For some
1216 				 * old cisco AP, QBSS IE length is 4Bytes, which
1217 				 * doesn't match with latest spec, So ignore
1218 				 * QBSS IE in such case.
1219 				 */
1220 				break;
1221 			}
1222 			scan_params->ie_list.qbssload = (uint8_t *)ie;
1223 			break;
1224 		case WLAN_ELEMID_CHANSWITCHANN:
1225 			if (ie->ie_len != WLAN_CSA_IE_MAX_LEN)
1226 				goto err;
1227 			scan_params->ie_list.csa = (uint8_t *)ie;
1228 			break;
1229 		case WLAN_ELEMID_IBSSDFS:
1230 			if (ie->ie_len < WLAN_IBSSDFS_IE_MIN_LEN)
1231 				goto err;
1232 			scan_params->ie_list.ibssdfs = (uint8_t *)ie;
1233 			break;
1234 		case WLAN_ELEMID_QUIET:
1235 			if (ie->ie_len != WLAN_QUIET_IE_MAX_LEN)
1236 				goto err;
1237 			scan_params->ie_list.quiet = (uint8_t *)ie;
1238 			break;
1239 		case WLAN_ELEMID_ERP:
1240 			if (ie->ie_len != (sizeof(struct erp_ie) -
1241 					    sizeof(struct ie_header)))
1242 				goto err;
1243 			scan_params->erp = ((struct erp_ie *)ie)->value;
1244 			break;
1245 		case WLAN_ELEMID_HTCAP_ANA:
1246 			if (ie->ie_len == sizeof(struct htcap_cmn_ie)) {
1247 				scan_params->ie_list.htcap =
1248 				(uint8_t *)&(((struct htcap_ie *)ie)->ie);
1249 			}
1250 			break;
1251 		case WLAN_ELEMID_RSN:
1252 			/*
1253 			 * For security cert TC, RSNIE length can be 1 but if
1254 			 * beacon is dropped, old entry will remain in scan
1255 			 * cache and cause cert TC failure as connection with
1256 			 * old entry with valid RSN IE will pass.
1257 			 * So instead of dropping the frame, do not store the
1258 			 * RSN pointer so that old entry is overwritten.
1259 			 */
1260 			if (ie->ie_len >= WLAN_RSN_IE_MIN_LEN)
1261 				scan_params->ie_list.rsn = (uint8_t *)ie;
1262 			break;
1263 		case WLAN_ELEMID_XRATES:
1264 			if (ie->ie_len > WLAN_EXT_SUPPORTED_RATES_IE_MAX_LEN)
1265 				goto err;
1266 			scan_params->ie_list.xrates = (uint8_t *)ie;
1267 			break;
1268 		case WLAN_ELEMID_EXTCHANSWITCHANN:
1269 			if (ie->ie_len != WLAN_XCSA_IE_MAX_LEN)
1270 				goto err;
1271 			scan_params->ie_list.xcsa = (uint8_t *)ie;
1272 			break;
1273 		case WLAN_ELEMID_SECCHANOFFSET:
1274 			if (ie->ie_len != WLAN_SECCHANOFF_IE_MAX_LEN)
1275 				goto err;
1276 			scan_params->ie_list.secchanoff = (uint8_t *)ie;
1277 			break;
1278 		case WLAN_ELEMID_HTINFO_ANA:
1279 			if (ie->ie_len != sizeof(struct wlan_ie_htinfo_cmn))
1280 				goto err;
1281 			scan_params->ie_list.htinfo =
1282 			  (uint8_t *)&(((struct wlan_ie_htinfo *) ie)->hi_ie);
1283 			chan_idx = ((struct wlan_ie_htinfo_cmn *)
1284 				 (scan_params->ie_list.htinfo))->hi_ctrlchannel;
1285 			*chan_freq = wlan_reg_chan_band_to_freq(pdev, chan_idx,
1286 								band_mask);
1287 			/* Drop if invalid freq */
1288 			if (scan_obj->drop_bcn_on_invalid_freq &&
1289 			    wlan_reg_is_disable_for_pwrmode(
1290 						pdev, *chan_freq,
1291 						REG_CURRENT_PWR_MODE)) {
1292 				scm_debug_rl(QDF_MAC_ADDR_FMT": Drop as invalid channel %d freq %d in HT_INFO IE",
1293 					     QDF_MAC_ADDR_REF(scan_params->bssid.bytes),
1294 					     chan_idx, *chan_freq);
1295 				return QDF_STATUS_E_INVAL;
1296 			}
1297 			break;
1298 		case WLAN_ELEMID_WAPI:
1299 			if (ie->ie_len < WLAN_WAPI_IE_MIN_LEN)
1300 				goto err;
1301 			scan_params->ie_list.wapi = (uint8_t *)ie;
1302 			break;
1303 		case WLAN_ELEMID_XCAPS:
1304 			if (ie->ie_len > WLAN_EXTCAP_IE_MAX_LEN)
1305 				goto err;
1306 			scan_params->ie_list.extcaps = (uint8_t *)ie;
1307 			break;
1308 		case WLAN_ELEMID_VHTCAP:
1309 			if (ie->ie_len != (sizeof(struct wlan_ie_vhtcaps) -
1310 					   sizeof(struct ie_header)))
1311 				goto err;
1312 			scan_params->ie_list.vhtcap = (uint8_t *)ie;
1313 			break;
1314 		case WLAN_ELEMID_VHTOP:
1315 			if (ie->ie_len != (sizeof(struct wlan_ie_vhtop) -
1316 					   sizeof(struct ie_header)))
1317 				goto err;
1318 			scan_params->ie_list.vhtop = (uint8_t *)ie;
1319 			break;
1320 		case WLAN_ELEMID_OP_MODE_NOTIFY:
1321 			if (ie->ie_len != WLAN_OPMODE_IE_MAX_LEN)
1322 				goto err;
1323 			scan_params->ie_list.opmode = (uint8_t *)ie;
1324 			break;
1325 		case WLAN_ELEMID_MOBILITY_DOMAIN:
1326 			if (ie->ie_len != WLAN_MOBILITY_DOMAIN_IE_MAX_LEN)
1327 				goto err;
1328 			scan_params->ie_list.mdie = (uint8_t *)ie;
1329 			break;
1330 		case WLAN_ELEMID_VENDOR:
1331 			status = util_scan_parse_vendor_ie(scan_params,
1332 							   ie);
1333 			if (QDF_IS_STATUS_ERROR(status))
1334 				goto err_status;
1335 			break;
1336 		case WLAN_ELEMID_VHT_TX_PWR_ENVLP:
1337 			if (ie->ie_len < WLAN_TPE_IE_MIN_LEN)
1338 				goto err;
1339 			if (tpe_idx >= WLAN_MAX_NUM_TPE_IE)
1340 				goto err;
1341 			scan_params->ie_list.tpe[tpe_idx++] = (uint8_t *)ie;
1342 			break;
1343 		case WLAN_ELEMID_CHAN_SWITCH_WRAP:
1344 			scan_params->ie_list.cswrp = (uint8_t *)ie;
1345 			/* Go to next sub IE */
1346 			sub_ie = (struct ie_header *)
1347 			(((uint8_t *)ie) + sizeof(struct ie_header));
1348 			sub_ie_len = ie->ie_len;
1349 			status =
1350 				util_scan_parse_chan_switch_wrapper_ie(
1351 					scan_params, sub_ie, sub_ie_len);
1352 			if (QDF_IS_STATUS_ERROR(status)) {
1353 				goto err_status;
1354 			}
1355 			break;
1356 		case WLAN_ELEMID_FILS_INDICATION:
1357 			if (ie->ie_len < WLAN_FILS_INDICATION_IE_MIN_LEN)
1358 				goto err;
1359 			scan_params->ie_list.fils_indication = (uint8_t *)ie;
1360 			break;
1361 		case WLAN_ELEMID_RSNXE:
1362 			if (!ie->ie_len)
1363 				goto err;
1364 			scan_params->ie_list.rsnxe = (uint8_t *)ie;
1365 			break;
1366 		case WLAN_ELEMID_EXTN_ELEM:
1367 			status = util_scan_parse_extn_ie(scan_params, ie);
1368 			if (QDF_IS_STATUS_ERROR(status))
1369 				goto err_status;
1370 			break;
1371 		case WLAN_ELEMID_REDUCED_NEIGHBOR_REPORT:
1372 			if (ie->ie_len < WLAN_RNR_IE_MIN_LEN)
1373 				goto err;
1374 			scan_params->ie_list.rnrie = (uint8_t *)ie;
1375 			status = util_scan_parse_rnr_ie(scan_params, ie);
1376 			if (QDF_IS_STATUS_ERROR(status))
1377 				goto err_status;
1378 			break;
1379 		default:
1380 			break;
1381 		}
1382 
1383 		/* Consume info element */
1384 		ie_len -= ie->ie_len;
1385 		/* Go to next IE */
1386 		ie = (struct ie_header *)
1387 			(((uint8_t *) ie) +
1388 			sizeof(struct ie_header) +
1389 			ie->ie_len);
1390 	}
1391 
1392 	return QDF_STATUS_SUCCESS;
1393 
1394 err:
1395 	status = QDF_STATUS_E_INVAL;
1396 err_status:
1397 	scm_debug("failed to parse IE - id: %d, len: %d",
1398 		  ie->ie_id, ie->ie_len);
1399 
1400 	return status;
1401 }
1402 
1403 /**
1404  * util_scan_update_esp_data: update ESP params from beacon/probe response
1405  * @esp_information: pointer to wlan_esp_information
1406  * @scan_entry: new received entry
1407  *
1408  * The Estimated Service Parameters element is
1409  * used by a AP to provide information to another STA which
1410  * can then use the information as input to an algorithm to
1411  * generate an estimate of throughput between the two STAs.
1412  * The ESP Information List field contains from 1 to 4 ESP
1413  * Information fields(each field 24 bits), each corresponding
1414  * to an access category for which estimated service parameters
1415  * information is provided.
1416  *
1417  * Return: None
1418  */
1419 static void util_scan_update_esp_data(struct wlan_esp_ie *esp_information,
1420 		struct scan_cache_entry *scan_entry)
1421 {
1422 
1423 	uint8_t *data;
1424 	int i = 0;
1425 	uint64_t total_elements;
1426 	struct wlan_esp_info *esp_info;
1427 	struct wlan_esp_ie *esp_ie;
1428 
1429 	esp_ie = (struct wlan_esp_ie *)
1430 		util_scan_entry_esp_info(scan_entry);
1431 
1432 	total_elements  = esp_ie->esp_len;
1433 	data = (uint8_t *)esp_ie + 3;
1434 	do_div(total_elements, ESP_INFORMATION_LIST_LENGTH);
1435 
1436 	if (total_elements > MAX_ESP_INFORMATION_FIELD) {
1437 		scm_err("No of Air time fractions are greater than supported");
1438 		return;
1439 	}
1440 
1441 	for (i = 0; i < total_elements &&
1442 	     data < ((uint8_t *)esp_ie + esp_ie->esp_len + 3); i++) {
1443 		esp_info = (struct wlan_esp_info *)data;
1444 		if (esp_info->access_category == ESP_AC_BK) {
1445 			qdf_mem_copy(&esp_information->esp_info_AC_BK,
1446 					data, 3);
1447 			data = data + ESP_INFORMATION_LIST_LENGTH;
1448 			continue;
1449 		}
1450 		if (esp_info->access_category == ESP_AC_BE) {
1451 			qdf_mem_copy(&esp_information->esp_info_AC_BE,
1452 					data, 3);
1453 			data = data + ESP_INFORMATION_LIST_LENGTH;
1454 			continue;
1455 		}
1456 		if (esp_info->access_category == ESP_AC_VI) {
1457 			qdf_mem_copy(&esp_information->esp_info_AC_VI,
1458 					data, 3);
1459 			data = data + ESP_INFORMATION_LIST_LENGTH;
1460 			continue;
1461 		}
1462 		if (esp_info->access_category == ESP_AC_VO) {
1463 			qdf_mem_copy(&esp_information->esp_info_AC_VO,
1464 					data, 3);
1465 			data = data + ESP_INFORMATION_LIST_LENGTH;
1466 			break;
1467 		}
1468 	}
1469 }
1470 
1471 /**
1472  * util_scan_scm_update_bss_with_esp_dataa: calculate estimated air time
1473  * fraction
1474  * @scan_entry: new received entry
1475  *
1476  * This function process all Access category ESP params and provide
1477  * best effort air time fraction.
1478  * If best effort is not available, it will choose VI, VO and BK in sequence
1479  *
1480  */
1481 static void util_scan_scm_update_bss_with_esp_data(
1482 		struct scan_cache_entry *scan_entry)
1483 {
1484 	uint8_t air_time_fraction = 0;
1485 	struct wlan_esp_ie esp_information;
1486 
1487 	if (!scan_entry->ie_list.esp)
1488 		return;
1489 
1490 	util_scan_update_esp_data(&esp_information, scan_entry);
1491 
1492 	/*
1493 	 * If the ESP metric is transmitting multiple airtime fractions, then
1494 	 * follow the sequence AC_BE, AC_VI, AC_VO, AC_BK and pick whichever is
1495 	 * the first one available
1496 	 */
1497 	if (esp_information.esp_info_AC_BE.access_category
1498 			== ESP_AC_BE)
1499 		air_time_fraction =
1500 			esp_information.esp_info_AC_BE.
1501 			estimated_air_fraction;
1502 	else if (esp_information.esp_info_AC_VI.access_category
1503 			== ESP_AC_VI)
1504 		air_time_fraction =
1505 			esp_information.esp_info_AC_VI.
1506 			estimated_air_fraction;
1507 	else if (esp_information.esp_info_AC_VO.access_category
1508 			== ESP_AC_VO)
1509 		air_time_fraction =
1510 			esp_information.esp_info_AC_VO.
1511 			estimated_air_fraction;
1512 	else if (esp_information.esp_info_AC_BK.access_category
1513 			== ESP_AC_BK)
1514 		air_time_fraction =
1515 			esp_information.esp_info_AC_BK.
1516 				estimated_air_fraction;
1517 	scan_entry->air_time_fraction = air_time_fraction;
1518 }
1519 
1520 /**
1521  * util_scan_scm_calc_nss_supported_by_ap() - finds out nss from AP
1522  * @scan_entry: new received entry
1523  *
1524  * Return: number of nss advertised by AP
1525  */
1526 static int util_scan_scm_calc_nss_supported_by_ap(
1527 		struct scan_cache_entry *scan_params)
1528 {
1529 	struct htcap_cmn_ie *htcap;
1530 	struct wlan_ie_vhtcaps *vhtcaps;
1531 	struct wlan_ie_hecaps *hecaps;
1532 	uint16_t rx_mcs_map = 0;
1533 
1534 	htcap = (struct htcap_cmn_ie *)
1535 		util_scan_entry_htcap(scan_params);
1536 	vhtcaps = (struct wlan_ie_vhtcaps *)
1537 		util_scan_entry_vhtcap(scan_params);
1538 	hecaps = (struct wlan_ie_hecaps *)
1539 		util_scan_entry_hecap(scan_params);
1540 
1541 	if (hecaps) {
1542 		/* Using rx mcs map related to 80MHz or lower as in some
1543 		 * cases higher mcs may suuport lesser NSS than that
1544 		 * of lowe mcs. Thus giving max NSS capability.
1545 		 */
1546 		rx_mcs_map =
1547 			qdf_cpu_to_le16(hecaps->mcs_bw_map[0].rx_mcs_map);
1548 	} else if (vhtcaps) {
1549 		rx_mcs_map = vhtcaps->rx_mcs_map;
1550 	}
1551 
1552 	if (hecaps || vhtcaps) {
1553 		if ((rx_mcs_map & 0xC000) != 0xC000)
1554 			return 8;
1555 
1556 		if ((rx_mcs_map & 0x3000) != 0x3000)
1557 			return 7;
1558 
1559 		if ((rx_mcs_map & 0x0C00) != 0x0C00)
1560 			return 6;
1561 
1562 		if ((rx_mcs_map & 0x0300) != 0x0300)
1563 			return 5;
1564 
1565 		if ((rx_mcs_map & 0x00C0) != 0x00C0)
1566 			return 4;
1567 
1568 		if ((rx_mcs_map & 0x0030) != 0x0030)
1569 			return 3;
1570 
1571 		if ((rx_mcs_map & 0x000C) != 0x000C)
1572 			return 2;
1573 	} else if (htcap) {
1574 		if (htcap->mcsset[3])
1575 			return 4;
1576 
1577 		if (htcap->mcsset[2])
1578 			return 3;
1579 
1580 		if (htcap->mcsset[1])
1581 			return 2;
1582 
1583 	}
1584 	return 1;
1585 }
1586 
1587 #ifdef WLAN_DFS_CHAN_HIDDEN_SSID
1588 QDF_STATUS
1589 util_scan_add_hidden_ssid(struct wlan_objmgr_pdev *pdev, qdf_nbuf_t bcnbuf)
1590 {
1591 	struct wlan_frame_hdr *hdr;
1592 	struct wlan_bcn_frame *bcn;
1593 	struct wlan_scan_obj *scan_obj;
1594 	struct wlan_ssid *conf_ssid;
1595 	struct  ie_header *ie;
1596 	uint32_t frame_len = qdf_nbuf_len(bcnbuf);
1597 	uint16_t bcn_ie_offset, ssid_ie_start_offset, ssid_ie_end_offset;
1598 	uint16_t tmplen, ie_length;
1599 	uint8_t *pbeacon, *tmp;
1600 	bool     set_ssid_flag = false;
1601 	struct ie_ssid ssid = {0};
1602 	uint8_t pdev_id;
1603 
1604 	if (!pdev) {
1605 		scm_warn("pdev: 0x%pK is NULL", pdev);
1606 		return QDF_STATUS_E_NULL_VALUE;
1607 	}
1608 	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
1609 	scan_obj = wlan_pdev_get_scan_obj(pdev);
1610 	if (!scan_obj) {
1611 		scm_warn("null scan_obj");
1612 		return QDF_STATUS_E_NULL_VALUE;
1613 	}
1614 
1615 	conf_ssid = &scan_obj->pdev_info[pdev_id].conf_ssid;
1616 
1617 	hdr = (struct wlan_frame_hdr *)qdf_nbuf_data(bcnbuf);
1618 
1619 	/* received bssid does not match configured bssid */
1620 	if (qdf_mem_cmp(hdr->i_addr3, scan_obj->pdev_info[pdev_id].conf_bssid,
1621 			QDF_MAC_ADDR_SIZE) ||
1622 			conf_ssid->length == 0) {
1623 		return QDF_STATUS_SUCCESS;
1624 	}
1625 
1626 	bcn = (struct wlan_bcn_frame *)(qdf_nbuf_data(bcnbuf) + sizeof(*hdr));
1627 	pbeacon = (uint8_t *)bcn;
1628 
1629 	ie = (struct ie_header *)(pbeacon +
1630 				  offsetof(struct wlan_bcn_frame, ie));
1631 
1632 	bcn_ie_offset = offsetof(struct wlan_bcn_frame, ie);
1633 	ie_length = (uint16_t)(frame_len - sizeof(*hdr) -
1634 			       bcn_ie_offset);
1635 
1636 	while (ie_length >=  sizeof(struct ie_header)) {
1637 		ie_length -= sizeof(struct ie_header);
1638 
1639 		bcn_ie_offset += sizeof(struct ie_header);
1640 
1641 		if (ie_length < ie->ie_len) {
1642 			scm_debug("Incomplete corrupted IE:%x", ie->ie_id);
1643 			return QDF_STATUS_E_INVAL;
1644 		}
1645 		if (ie->ie_id == WLAN_ELEMID_SSID) {
1646 			if (ie->ie_len > (sizeof(struct ie_ssid) -
1647 						 sizeof(struct ie_header))) {
1648 				return QDF_STATUS_E_INVAL;
1649 			}
1650 			ssid.ssid_id = ie->ie_id;
1651 			ssid.ssid_len = ie->ie_len;
1652 
1653 			if (ssid.ssid_len)
1654 				qdf_mem_copy(ssid.ssid,
1655 					     ie + sizeof(struct ie_header),
1656 					     ssid.ssid_len);
1657 
1658 			if (util_scan_is_hidden_ssid(&ssid)) {
1659 				set_ssid_flag  = true;
1660 				ssid_ie_start_offset = bcn_ie_offset -
1661 					sizeof(struct ie_header);
1662 				ssid_ie_end_offset = bcn_ie_offset +
1663 					ie->ie_len;
1664 			}
1665 		}
1666 		if (ie->ie_len == 0) {
1667 			ie += 1;    /* next IE */
1668 			continue;
1669 		}
1670 		if (ie->ie_id == WLAN_ELEMID_VENDOR &&
1671 		    is_wps_oui((uint8_t *)ie)) {
1672 			set_ssid_flag = false;
1673 			break;
1674 		}
1675 		/* Consume info element */
1676 		ie_length -=  ie->ie_len;
1677 		/* Go to next IE */
1678 		ie = (struct ie_header *)(((uint8_t *)ie) +
1679 				sizeof(struct ie_header) +
1680 				ie->ie_len);
1681 	}
1682 
1683 	if (set_ssid_flag) {
1684 		/* Hidden SSID if the Length is 0 */
1685 		if (!ssid.ssid_len) {
1686 			/* increase the taillength by length of ssid */
1687 			if (qdf_nbuf_put_tail(bcnbuf,
1688 					      conf_ssid->length) == NULL) {
1689 				scm_debug("No enough tailroom");
1690 				return  QDF_STATUS_E_NOMEM;
1691 			}
1692 			/* length of the buffer to be copied */
1693 			tmplen = frame_len -
1694 				sizeof(*hdr) - ssid_ie_end_offset;
1695 			/*
1696 			 * tmp memory to copy the beacon info
1697 			 * after ssid ie.
1698 			 */
1699 			tmp = qdf_mem_malloc(tmplen * sizeof(u_int8_t));
1700 			if (!tmp)
1701 				return  QDF_STATUS_E_NOMEM;
1702 
1703 			/* Copy beacon data after ssid ie to tmp */
1704 			qdf_nbuf_copy_bits(bcnbuf, (sizeof(*hdr) +
1705 					   ssid_ie_end_offset), tmplen, tmp);
1706 			/* Add ssid length */
1707 			*(pbeacon + (ssid_ie_start_offset + 1))
1708 				= conf_ssid->length;
1709 			/* Insert the  SSID string */
1710 			qdf_mem_copy((pbeacon + ssid_ie_end_offset),
1711 				     conf_ssid->ssid, conf_ssid->length);
1712 			/* Copy rest of the beacon data */
1713 			qdf_mem_copy((pbeacon + ssid_ie_end_offset +
1714 				      conf_ssid->length), tmp, tmplen);
1715 			qdf_mem_free(tmp);
1716 
1717 			/* Hidden ssid with all 0's */
1718 		} else if (ssid.ssid_len == conf_ssid->length) {
1719 			/* Insert the  SSID string */
1720 			qdf_mem_copy((pbeacon + ssid_ie_start_offset +
1721 				      sizeof(struct ie_header)),
1722 				      conf_ssid->ssid, conf_ssid->length);
1723 		} else {
1724 			scm_debug("mismatch in hidden ssid length");
1725 			return QDF_STATUS_E_INVAL;
1726 		}
1727 	}
1728 	return QDF_STATUS_SUCCESS;
1729 }
1730 #endif /* WLAN_DFS_CHAN_HIDDEN_SSID */
1731 
1732 #ifdef WLAN_ADAPTIVE_11R
1733 /**
1734  * scm_fill_adaptive_11r_cap() - Check if the AP supports adaptive 11r
1735  * @scan_entry: Pointer to the scan entry
1736  *
1737  * Return: true if adaptive 11r is advertised else false
1738  */
1739 static void scm_fill_adaptive_11r_cap(struct scan_cache_entry *scan_entry)
1740 {
1741 	uint8_t *ie;
1742 	uint8_t data;
1743 	bool adaptive_11r;
1744 
1745 	ie = util_scan_entry_adaptive_11r(scan_entry);
1746 	if (!ie)
1747 		return;
1748 
1749 	data = *(ie + OUI_LENGTH);
1750 	adaptive_11r = (data & 0x1) ? true : false;
1751 
1752 	scan_entry->adaptive_11r_ap = adaptive_11r;
1753 }
1754 #else
1755 static void scm_fill_adaptive_11r_cap(struct scan_cache_entry *scan_entry)
1756 {
1757 	scan_entry->adaptive_11r_ap = false;
1758 }
1759 #endif
1760 
1761 static void util_scan_set_security(struct scan_cache_entry *scan_params)
1762 {
1763 	if (util_scan_entry_wpa(scan_params))
1764 		scan_params->security_type |= SCAN_SECURITY_TYPE_WPA;
1765 
1766 	if (util_scan_entry_rsn(scan_params))
1767 		scan_params->security_type |= SCAN_SECURITY_TYPE_RSN;
1768 	if (util_scan_entry_wapi(scan_params))
1769 		scan_params->security_type |= SCAN_SECURITY_TYPE_WAPI;
1770 
1771 	if (!scan_params->security_type &&
1772 	    scan_params->cap_info.wlan_caps.privacy)
1773 		scan_params->security_type |= SCAN_SECURITY_TYPE_WEP;
1774 }
1775 
1776 #ifdef WLAN_FEATURE_11BE_MLO
1777 /**
1778  * Multi link IE field offsets
1779  *  ------------------------------------------------------------------------
1780  * | EID(1) | Len (1) | EID_EXT (1) | ML_CONTROL (2) | CMN_INFO (var) | ... |
1781  *  ------------------------------------------------------------------------
1782  */
1783 #define ML_CONTROL_OFFSET 3
1784 #define ML_CMN_INFO_OFFSET ML_CONTROL_OFFSET + 2
1785 
1786 #define CMN_INFO_MLD_ADDR_PRESENT_BIT     BIT(4)
1787 #define CMN_INFO_LINK_ID_PRESENT_BIT      BIT(5)
1788 #define LINK_INFO_MAC_ADDR_PRESENT_BIT    BIT(5)
1789 
1790 /* This function is implemented as per IEEE802.11be D1.0, there is no difference
1791  * in presence bitmap for beacon, probe response and probe request frames.
1792  * This code is to be revisited for future drafts if the presence bitmap values
1793  * changes for the beacon, probe response and probe request frames.
1794  */
1795 static uint8_t util_get_link_info_offset(uint8_t *ml_ie)
1796 {
1797 	qdf_size_t ml_ie_len = 0;
1798 	qdf_size_t parsed_ie_len = 0;
1799 	struct wlan_ie_multilink *mlie_fixed;
1800 	uint16_t mlcontrol;
1801 	uint16_t presencebm;
1802 
1803 	if (!ml_ie) {
1804 		scm_err("ml_ie is null");
1805 		return 0;
1806 	}
1807 
1808 	ml_ie_len = ml_ie[TAG_LEN_POS];
1809 	if (!ml_ie_len) {
1810 		scm_err("ml_ie_len is zero");
1811 		return 0;
1812 	}
1813 
1814 	if (ml_ie_len < sizeof(struct wlan_ie_multilink)) {
1815 		scm_err_rl("Length %zu octets is smaller than required for the fixed portion of Multi-Link element (%zu octets)",
1816 			   ml_ie_len, sizeof(struct wlan_ie_multilink));
1817 		return 0;
1818 	}
1819 
1820 	mlie_fixed = (struct wlan_ie_multilink *)ml_ie;
1821 	mlcontrol = le16toh(mlie_fixed->mlcontrol);
1822 	presencebm = QDF_GET_BITS(mlcontrol, WLAN_ML_CTRL_PBM_IDX,
1823 				  WLAN_ML_CTRL_PBM_BITS);
1824 
1825 	parsed_ie_len += sizeof(*mlie_fixed);
1826 
1827 	/* Check if MLD MAC address is present */
1828 	if (presencebm & WLAN_ML_BV_CTRL_PBM_MLDMACADDR_P)
1829 		parsed_ie_len += QDF_MAC_ADDR_SIZE;
1830 
1831 	/* Check if Link ID info is present */
1832 	if (presencebm & WLAN_ML_BV_CTRL_PBM_LINKIDINFO_P)
1833 		parsed_ie_len += WLAN_ML_BV_CINFO_LINKIDINFO_SIZE;
1834 
1835 	/* Check if BSS parameter change count is present */
1836 	if (presencebm & WLAN_ML_BV_CTRL_PBM_BSSPARAMCHANGECNT_P)
1837 		parsed_ie_len += WLAN_ML_BV_CINFO_BSSPARAMCHNGCNT_SIZE;
1838 
1839 	/* Check if Medium Sync Delay Info is present */
1840 	if (presencebm & WLAN_ML_BV_CTRL_PBM_MEDIUMSYNCDELAYINFO_P)
1841 		parsed_ie_len += WLAN_ML_BV_CINFO_MEDMSYNCDELAYINFO_SIZE;
1842 
1843 	/* Check if EML cap is present */
1844 	if (presencebm & WLAN_ML_BV_CTRL_PBM_EMLCAP_P)
1845 		parsed_ie_len += WLAN_ML_BV_CINFO_EMLCAP_SIZE;
1846 
1847 	/* Check if MLD cap is present */
1848 	if (presencebm & WLAN_ML_BV_CTRL_PBM_MLDCAP_P)
1849 		parsed_ie_len += WLAN_ML_BV_CINFO_MLDCAP_SIZE;
1850 
1851 	/* Offset calculation starts from the beginning of the ML IE (including
1852 	 * EID) hence, adding the size of IE header to ML IE length.
1853 	 */
1854 	if (parsed_ie_len < (ml_ie_len + sizeof(struct ie_header)))
1855 		return parsed_ie_len;
1856 
1857 	return 0;
1858 }
1859 
1860 static void util_get_partner_link_info(struct scan_cache_entry *scan_entry)
1861 {
1862 	uint8_t *ml_ie = scan_entry->ie_list.multi_link;
1863 	uint8_t offset = util_get_link_info_offset(ml_ie);
1864 	uint16_t sta_ctrl;
1865 	uint8_t *stactrl_offset = NULL;
1866 	uint8_t perstaprof_len = 0;
1867 	struct partner_link_info *link_info = NULL;
1868 	uint8_t eid = 0;
1869 	uint8_t link_idx = 0;
1870 	uint8_t rnr_idx = 0;
1871 	struct rnr_bss_info *rnr = NULL;
1872 
1873 	/* Update partner info  from RNR IE */
1874 	while ((rnr_idx < MAX_RNR_BSS) && (rnr_idx < scan_entry->rnr.count)) {
1875 		if (link_idx >= (MLD_MAX_LINKS - 1))
1876 			break;
1877 		rnr = &scan_entry->rnr.bss_info[rnr_idx];
1878 		if (rnr->mld_info_valid && !rnr->mld_info.mld_id) {
1879 			link_info = &scan_entry->ml_info.link_info[link_idx];
1880 			qdf_mem_copy(&link_info->link_addr,
1881 				     &rnr->bssid, QDF_MAC_ADDR_SIZE);
1882 
1883 			link_info->link_id = rnr->mld_info.link_id;
1884 
1885 			link_idx++;
1886 		}
1887 		rnr_idx++;
1888 	}
1889 
1890 	scan_entry->ml_info.num_links = link_idx;
1891 	if (!offset)
1892 		return;
1893 
1894 	/* TODO: loop through all the STA info fields */
1895 
1896 	/* Sub element ID 0 represents Per-STA Profile */
1897 	if (ml_ie[offset] == 0) {
1898 		perstaprof_len = ml_ie[offset + 1];
1899 		stactrl_offset = &ml_ie[offset + 2];
1900 
1901 		/* Skip sub element ID and length fields */
1902 		offset += 2;
1903 
1904 		sta_ctrl = *(uint16_t *)(ml_ie + offset);
1905 		/* Skip STA control field */
1906 		offset += 2;
1907 
1908 		scan_entry->ml_info.link_info[0].link_id = sta_ctrl & 0xF;
1909 		if (sta_ctrl & LINK_INFO_MAC_ADDR_PRESENT_BIT) {
1910 			qdf_mem_copy(
1911 				&scan_entry->ml_info.link_info[0].link_addr,
1912 				ml_ie + offset, 6);
1913 			scm_debug("Found partner info in ML IE");
1914 		}
1915 
1916 		/* Get the pointers to CSA, ECSA, Max Channel Switch Time IE. */
1917 		link_info = &scan_entry->ml_info.link_info[0];
1918 
1919 		link_info->csa_ie = wlan_get_ie_ptr_from_eid
1920 			(WLAN_ELEMID_CHANSWITCHANN, stactrl_offset,
1921 			 perstaprof_len);
1922 
1923 		link_info->ecsa_ie = wlan_get_ie_ptr_from_eid
1924 			(WLAN_ELEMID_EXTCHANSWITCHANN, stactrl_offset,
1925 			 perstaprof_len);
1926 
1927 		eid = WLAN_EXTN_ELEMID_MAX_CHAN_SWITCH_TIME;
1928 		link_info->max_cst_ie = wlan_get_ext_ie_ptr_from_ext_id
1929 			(&eid, 1, stactrl_offset, perstaprof_len);
1930 
1931 		scan_entry->ml_info.num_links++;
1932 	}
1933 }
1934 
1935 static void util_scan_update_ml_info(struct scan_cache_entry *scan_entry)
1936 {
1937 	uint8_t *ml_ie = scan_entry->ie_list.multi_link;
1938 	uint16_t multi_link_ctrl;
1939 	uint8_t offset;
1940 
1941 	if (!scan_entry->ie_list.multi_link) {
1942 		return;
1943 	}
1944 
1945 	multi_link_ctrl = *(uint16_t *)(ml_ie + ML_CONTROL_OFFSET);
1946 
1947 	/* TODO: update ml_info based on ML IE */
1948 
1949 	multi_link_ctrl = *(uint16_t *)(ml_ie + ML_CONTROL_OFFSET);
1950 	offset = ML_CMN_INFO_OFFSET;
1951 	/* TODO: Add proper parsing based on presense bitmap */
1952 	if (multi_link_ctrl & CMN_INFO_MLD_ADDR_PRESENT_BIT) {
1953 		qdf_mem_copy(&scan_entry->ml_info.mld_mac_addr,
1954 			     ml_ie + offset, 6);
1955 		offset += 6;
1956 	}
1957 
1958 	/* TODO: Decode it from ML IE */
1959 	scan_entry->ml_info.num_links = 0;
1960 
1961 	/**
1962 	 * Copy Link ID & MAC address of the scan cache entry as first entry
1963 	 * in the partner info list
1964 	 */
1965 	if (multi_link_ctrl & CMN_INFO_LINK_ID_PRESENT_BIT)
1966 		scan_entry->ml_info.self_link_id = ml_ie[offset] & 0x0F;
1967 
1968 	util_get_partner_link_info(scan_entry);
1969 }
1970 #else
1971 static void util_scan_update_ml_info(struct scan_cache_entry *scan_entry)
1972 {
1973 }
1974 #endif
1975 
1976 static QDF_STATUS
1977 util_scan_gen_scan_entry(struct wlan_objmgr_pdev *pdev,
1978 			 uint8_t *frame, qdf_size_t frame_len,
1979 			 uint32_t frm_subtype,
1980 			 struct mgmt_rx_event_params *rx_param,
1981 			 struct scan_mbssid_info *mbssid_info,
1982 			 qdf_list_t *scan_list)
1983 {
1984 	struct wlan_frame_hdr *hdr;
1985 	struct wlan_bcn_frame *bcn;
1986 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1987 	struct ie_ssid *ssid;
1988 	struct scan_cache_entry *scan_entry;
1989 	struct qbss_load_ie *qbss_load;
1990 	struct scan_cache_node *scan_node;
1991 	uint8_t i;
1992 	qdf_freq_t chan_freq = 0;
1993 	bool he_6g_dup_bcon = false;
1994 	uint8_t band_mask;
1995 
1996 	scan_entry = qdf_mem_malloc_atomic(sizeof(*scan_entry));
1997 	if (!scan_entry) {
1998 		scm_err("failed to allocate memory for scan_entry");
1999 		return QDF_STATUS_E_NOMEM;
2000 	}
2001 
2002 	scan_entry->raw_frame.ptr =
2003 			qdf_mem_malloc_atomic(frame_len);
2004 	if (!scan_entry->raw_frame.ptr) {
2005 		scm_err("failed to allocate memory for frame");
2006 		qdf_mem_free(scan_entry);
2007 		return QDF_STATUS_E_NOMEM;
2008 	}
2009 
2010 	bcn = (struct wlan_bcn_frame *)
2011 			   (frame + sizeof(*hdr));
2012 	hdr = (struct wlan_frame_hdr *)frame;
2013 
2014 	/* update timestamp in nanoseconds needed by kernel layers */
2015 	scan_entry->boottime_ns = qdf_get_bootbased_boottime_ns();
2016 
2017 	scan_entry->frm_subtype = frm_subtype;
2018 	qdf_mem_copy(scan_entry->bssid.bytes,
2019 		hdr->i_addr3, QDF_MAC_ADDR_SIZE);
2020 	/* Scr addr */
2021 	qdf_mem_copy(scan_entry->mac_addr.bytes,
2022 		hdr->i_addr2, QDF_MAC_ADDR_SIZE);
2023 	scan_entry->seq_num =
2024 		(le16toh(*(uint16_t *)hdr->i_seq) >> WLAN_SEQ_SEQ_SHIFT);
2025 
2026 	scan_entry->snr = rx_param->snr;
2027 	scan_entry->avg_snr = WLAN_SNR_IN(scan_entry->snr);
2028 	scan_entry->rssi_raw = rx_param->rssi;
2029 	scan_entry->avg_rssi = WLAN_RSSI_IN(scan_entry->rssi_raw);
2030 	scan_entry->tsf_delta = rx_param->tsf_delta;
2031 	scan_entry->pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
2032 
2033 	/* Copy per chain rssi to scan entry */
2034 	qdf_mem_copy(scan_entry->per_chain_rssi, rx_param->rssi_ctl,
2035 		     WLAN_MGMT_TXRX_HOST_MAX_ANTENNA);
2036 	band_mask = BIT(wlan_reg_freq_to_band(rx_param->chan_freq));
2037 
2038 	if (!wlan_psoc_nif_fw_ext_cap_get(wlan_pdev_get_psoc(pdev),
2039 					  WLAN_SOC_CEXT_HW_DB2DBM)) {
2040 		for (i = 0; i < WLAN_MGMT_TXRX_HOST_MAX_ANTENNA; i++) {
2041 			if (scan_entry->per_chain_rssi[i] !=
2042 			    WLAN_INVALID_PER_CHAIN_SNR)
2043 				scan_entry->per_chain_rssi[i] +=
2044 						WLAN_NOISE_FLOOR_DBM_DEFAULT;
2045 			else
2046 				scan_entry->per_chain_rssi[i] =
2047 						WLAN_INVALID_PER_CHAIN_RSSI;
2048 		}
2049 	}
2050 
2051 	/* store jiffies */
2052 	scan_entry->rrm_parent_tsf = (uint32_t)qdf_system_ticks();
2053 
2054 	scan_entry->bcn_int = le16toh(bcn->beacon_interval);
2055 
2056 	/*
2057 	 * In case if the beacon dosnt have
2058 	 * valid beacon interval falback to def
2059 	 */
2060 	if (!scan_entry->bcn_int)
2061 		scan_entry->bcn_int = 100;
2062 	scan_entry->cap_info.value = le16toh(bcn->capability.value);
2063 	qdf_mem_copy(scan_entry->tsf_info.data,
2064 		bcn->timestamp, 8);
2065 	scan_entry->erp = ERP_NON_ERP_PRESENT;
2066 
2067 	scan_entry->scan_entry_time =
2068 		qdf_mc_timer_get_system_time();
2069 
2070 	scan_entry->raw_frame.len = frame_len;
2071 	qdf_mem_copy(scan_entry->raw_frame.ptr,
2072 		frame, frame_len);
2073 	status = util_scan_populate_bcn_ie_list(pdev, scan_entry, &chan_freq,
2074 						band_mask);
2075 	if (QDF_IS_STATUS_ERROR(status)) {
2076 		scm_debug(QDF_MAC_ADDR_FMT": failed to parse beacon IE",
2077 			  QDF_MAC_ADDR_REF(scan_entry->bssid.bytes));
2078 		qdf_mem_free(scan_entry->raw_frame.ptr);
2079 		qdf_mem_free(scan_entry);
2080 		return QDF_STATUS_E_FAILURE;
2081 	}
2082 
2083 	ssid = (struct ie_ssid *)
2084 		scan_entry->ie_list.ssid;
2085 
2086 	if (ssid && (ssid->ssid_len > WLAN_SSID_MAX_LEN)) {
2087 		qdf_mem_free(scan_entry->raw_frame.ptr);
2088 		qdf_mem_free(scan_entry);
2089 		return QDF_STATUS_E_FAILURE;
2090 	}
2091 
2092 	if (scan_entry->ie_list.p2p)
2093 		scan_entry->is_p2p = true;
2094 
2095 	if (!chan_freq && util_scan_entry_hecap(scan_entry)) {
2096 		status = util_scan_get_chan_from_he_6g_params(pdev, scan_entry,
2097 							      &chan_freq,
2098 							      &he_6g_dup_bcon,
2099 							      band_mask);
2100 		if (QDF_IS_STATUS_ERROR(status)) {
2101 			qdf_mem_free(scan_entry->raw_frame.ptr);
2102 			qdf_mem_free(scan_entry);
2103 			return QDF_STATUS_E_FAILURE;
2104 		}
2105 	}
2106 
2107 	if (chan_freq)
2108 		scan_entry->channel.chan_freq = chan_freq;
2109 
2110 	/* If no channel info is present in beacon use meta channel */
2111 	if (!scan_entry->channel.chan_freq) {
2112 		scan_entry->channel.chan_freq = rx_param->chan_freq;
2113 	} else if (rx_param->chan_freq !=
2114 	   scan_entry->channel.chan_freq) {
2115 		if (!wlan_reg_is_49ghz_freq(scan_entry->channel.chan_freq) &&
2116 		    !he_6g_dup_bcon)
2117 			scan_entry->channel_mismatch = true;
2118 	}
2119 
2120 	if (util_scan_is_hidden_ssid(ssid)) {
2121 		scan_entry->ie_list.ssid = NULL;
2122 		scan_entry->is_hidden_ssid = true;
2123 	} else {
2124 		qdf_mem_copy(scan_entry->ssid.ssid,
2125 				ssid->ssid, ssid->ssid_len);
2126 		scan_entry->ssid.length = ssid->ssid_len;
2127 		scan_entry->hidden_ssid_timestamp =
2128 			scan_entry->scan_entry_time;
2129 	}
2130 	qdf_mem_copy(&scan_entry->mbssid_info, mbssid_info,
2131 		     sizeof(scan_entry->mbssid_info));
2132 
2133 	scan_entry->phy_mode = util_scan_get_phymode(pdev, scan_entry);
2134 
2135 	scan_entry->nss = util_scan_scm_calc_nss_supported_by_ap(scan_entry);
2136 	scm_fill_adaptive_11r_cap(scan_entry);
2137 	util_scan_set_security(scan_entry);
2138 
2139 	util_scan_scm_update_bss_with_esp_data(scan_entry);
2140 	qbss_load = (struct qbss_load_ie *)
2141 			util_scan_entry_qbssload(scan_entry);
2142 	if (qbss_load)
2143 		scan_entry->qbss_chan_load = qbss_load->qbss_chan_load;
2144 
2145 	scan_node = qdf_mem_malloc_atomic(sizeof(*scan_node));
2146 	if (!scan_node) {
2147 		qdf_mem_free(scan_entry->raw_frame.ptr);
2148 		qdf_mem_free(scan_entry);
2149 		return QDF_STATUS_E_FAILURE;
2150 	}
2151 
2152 	util_scan_update_ml_info(scan_entry);
2153 
2154 	scan_node->entry = scan_entry;
2155 	qdf_list_insert_front(scan_list, &scan_node->node);
2156 
2157 	return status;
2158 }
2159 
2160 #ifdef WLAN_FEATURE_MBSSID
2161 /*
2162  * util_is_noninh_ie() - find the noninhertance information element
2163  * in the received frame's IE list, so that we can stop inheriting that IE
2164  * in the caller function.
2165  *
2166  * @elem_id: Element ID in the received frame's IE, which is being processed.
2167  * @non_inh_list: pointer to the non inherited list of element IDs or
2168  *                list of extension element IDs.
2169  * @len: Length of non inheritance IE list
2170  *
2171  * Return: False if the element ID is not found or else return true
2172  */
2173 static bool util_is_noninh_ie(uint8_t elem_id,
2174 			      uint8_t *non_inh_list,
2175 			      int8_t len)
2176 {
2177 	int count;
2178 
2179 	for (count = 0; count < len; count++) {
2180 		if (elem_id == non_inh_list[count])
2181 			return true;
2182 	}
2183 
2184 	return false;
2185 }
2186 
2187 /*
2188  * util_scan_find_noninheritance_ie() - find noninheritance information element
2189  * This block of code is to identify if there is any non-inheritance element
2190  * present as part of the nontransmitted BSSID profile.
2191  * @elem_id: element id
2192  * @ies: pointer consisting of IEs
2193  * @len: IE length
2194  *
2195  * Return: NULL if the element ID is not found or if IE pointer is NULL else
2196  * pointer to the first byte of the requested element
2197  */
2198 static uint8_t
2199 *util_scan_find_noninheritance_ie(uint8_t elem_id, uint8_t *ies,
2200 				  int32_t len)
2201 {
2202 	if (!ies)
2203 		return NULL;
2204 
2205 	while (len >= MIN_IE_LEN && len >= ies[TAG_LEN_POS] + MIN_IE_LEN) {
2206 		if ((ies[ID_POS] == elem_id) &&
2207 		    (ies[ELEM_ID_EXTN_POS] ==
2208 		     WLAN_EXTN_ELEMID_NONINHERITANCE)) {
2209 			return ies;
2210 		}
2211 		len -= ies[TAG_LEN_POS] + MIN_IE_LEN;
2212 		ies += ies[TAG_LEN_POS] + MIN_IE_LEN;
2213 	}
2214 
2215 	return NULL;
2216 }
2217 #endif
2218 
2219 /*
2220  * util_scan_find_ie() - find information element
2221  * @eid: element id
2222  * @ies: pointer consisting of IEs
2223  * @len: IE length
2224  *
2225  * Return: NULL if the element ID is not found or if IE pointer is NULL else
2226  * pointer to the first byte of the requested element
2227  */
2228 static uint8_t *util_scan_find_ie(uint8_t eid, uint8_t *ies,
2229 				  int32_t len)
2230 {
2231 	if (!ies)
2232 		return NULL;
2233 
2234 	while (len >= 2 && len >= ies[1] + 2) {
2235 		if (ies[0] == eid)
2236 			return ies;
2237 		len -= ies[1] + 2;
2238 		ies += ies[1] + 2;
2239 	}
2240 
2241 	return NULL;
2242 }
2243 
2244 #ifdef WLAN_FEATURE_MBSSID
2245 static void util_gen_new_bssid(uint8_t *bssid, uint8_t max_bssid,
2246 			       uint8_t mbssid_index,
2247 			       uint8_t *new_bssid_addr)
2248 {
2249 	uint8_t lsb_n;
2250 	int i;
2251 
2252 	for (i = 0; i < QDF_MAC_ADDR_SIZE; i++)
2253 		new_bssid_addr[i] = bssid[i];
2254 
2255 	lsb_n = new_bssid_addr[5] & ((1 << max_bssid) - 1);
2256 
2257 	new_bssid_addr[5] &= ~((1 << max_bssid) - 1);
2258 	new_bssid_addr[5] |= (lsb_n + mbssid_index) % (1 << max_bssid);
2259 }
2260 
2261 /*
2262  * util_parse_noninheritance_list() - This block of code will be executed only
2263  * if there is a valid non inheritance IE present in the nontx profile.
2264  * Host need not inherit those list of element IDs and list of element ID
2265  * extensions from the transmitted BSSID profile.
2266  * Since non-inheritance element is an element ID extension, it should
2267  * be part of extension element. So first we need to find if there are
2268  * any extension element present in the nontransmitted BSSID profile.
2269  * @extn_elem: If valid, it points to the element ID field of
2270  * extension element tag in the nontransmitted BSSID profile.
2271  * It may or may not have non inheritance tag present.
2272  *      _____________________________________________
2273  *     |         |       |       |List of|List of    |
2274  *     | Element |Length |Element|Element|Element ID |
2275  *     |  ID     |       |ID extn| IDs   |Extension  |
2276  *     |_________|_______|_______|_______|___________|
2277  * List of Element IDs:
2278  *      __________________
2279  *     |         |        |
2280  *     |  Length |Element |
2281  *     |         |ID List |
2282  *     |_________|________|
2283  * List of Element ID Extensions:
2284  *      __________________________
2285  *     |         |                |
2286  *     |  Length |Element ID      |
2287  *     |         |extension List  |
2288  *     |_________|________________|
2289  * @elem_list: Element ID list
2290  * @extn_elem_list: Element ID exiension list
2291  * @non_inheritance_ie: Non inheritance IE information
2292  */
2293 
2294 static void util_parse_noninheritance_list(uint8_t *extn_elem,
2295 					   uint8_t **elem_list,
2296 					   uint8_t **extn_elem_list,
2297 					   struct non_inheritance_ie *ninh)
2298 {
2299 	int8_t extn_rem_len = 0;
2300 
2301 	if (extn_elem[ELEM_ID_LIST_LEN_POS] < extn_elem[TAG_LEN_POS]) {
2302 		/*
2303 		 * extn_rem_len represents the number of bytes after
2304 		 * the length subfield of list of Element IDs.
2305 		 * So here, extn_rem_len should be equal to
2306 		 * Element ID list + Length subfield of Element ID
2307 		 * extension list + Element ID extension list.
2308 		 *
2309 		 * Here we have taken two pointers pointing to the
2310 		 * element ID list and element ID extension list
2311 		 * which we will use to detect the same elements
2312 		 * in the transmitted BSSID profile and choose not
2313 		 * to inherit those elements while constructing the
2314 		 * frame for nontransmitted BSSID profile.
2315 		 */
2316 		extn_rem_len = extn_elem[TAG_LEN_POS] - MIN_IE_LEN;
2317 		ninh->non_inherit = true;
2318 
2319 		if (extn_rem_len && extn_elem[ELEM_ID_LIST_LEN_POS]) {
2320 			if (extn_rem_len >= extn_elem[ELEM_ID_LIST_LEN_POS]) {
2321 				ninh->list_len =
2322 					extn_elem[ELEM_ID_LIST_LEN_POS];
2323 				*elem_list = extn_elem + ELEM_ID_LIST_POS;
2324 				extn_rem_len -= ninh->list_len;
2325 			} else {
2326 				/*
2327 				 * Corrupt frame. length subfield of
2328 				 * element ID list is greater than
2329 				 * what it should be. Go ahead with
2330 				 * frame generation but do not honour
2331 				 * the non inheritance part. Also, mark
2332 				 * the element ID in subcopy as 0, so
2333 				 * that this element info will not
2334 				 * be copied.
2335 				 */
2336 				ninh->non_inherit = false;
2337 				extn_elem[0] = 0;
2338 			}
2339 		}
2340 
2341 		extn_rem_len--;
2342 		if (extn_rem_len > 0) {
2343 			if (!ninh->list_len) {
2344 				ninh->extn_len =
2345 					extn_elem[ELEM_ID_LIST_LEN_POS + 1];
2346 			} else {
2347 				ninh->extn_len =
2348 					extn_elem[ELEM_ID_LIST_POS +
2349 					ninh->list_len];
2350 			}
2351 
2352 			if (extn_rem_len != ninh->extn_len) {
2353 				/*
2354 				 * Corrupt frame. length subfield of
2355 				 * element ID extn list is not
2356 				 * what it should be. Go ahead with
2357 				 * frame generation but do not honour
2358 				 * the non inheritance part. Also, mark
2359 				 * the element ID in subcopy as 0, so
2360 				 * that this element info will not
2361 				 * be copied.
2362 				 */
2363 				ninh->non_inherit = false;
2364 				extn_elem[0] = 0;
2365 			}
2366 
2367 			if (ninh->extn_len) {
2368 				*extn_elem_list =
2369 					(extn_elem + ninh->list_len +
2370 					 ELEM_ID_LIST_POS + 1);
2371 			}
2372 		}
2373 	}
2374 }
2375 
2376 static size_t util_oui_header_len(uint8_t *ie)
2377 {
2378 	/* Cisco Vendor Specific IEs doesn't have subtype in
2379 	 * their VSIE header, therefore skip subtype
2380 	 */
2381 	if (ie[0] == 0x00 && ie[1] == 0x40 && ie[2] == 0x96)
2382 		return OUI_LEN - 1;
2383 	return OUI_LEN;
2384 }
2385 
2386 static uint32_t util_gen_new_ie(uint8_t *ie, uint32_t ielen,
2387 				uint8_t *subelement,
2388 				size_t subie_len, uint8_t *new_ie)
2389 {
2390 	uint8_t *pos, *tmp;
2391 	const uint8_t *tmp_old, *tmp_new;
2392 	uint8_t *sub_copy, *extn_elem = NULL;
2393 	struct non_inheritance_ie ninh = {0};
2394 	uint8_t *elem_list = NULL, *extn_elem_list = NULL;
2395 	size_t tmp_rem_len;
2396 
2397 	/* copy subelement as we need to change its content to
2398 	 * mark an ie after it is processed.
2399 	 */
2400 	sub_copy = qdf_mem_malloc(subie_len);
2401 	if (!sub_copy)
2402 		return 0;
2403 	qdf_mem_copy(sub_copy, subelement, subie_len);
2404 
2405 	pos = &new_ie[0];
2406 
2407 	/* new ssid */
2408 	tmp_new = util_scan_find_ie(WLAN_ELEMID_SSID, sub_copy, subie_len);
2409 	if (tmp_new) {
2410 		scm_debug(" SSID %.*s", tmp_new[1],
2411 			  &tmp_new[PAYLOAD_START_POS]);
2412 		if ((pos + tmp_new[1] + MIN_IE_LEN) <=
2413 		    (new_ie + ielen)) {
2414 			qdf_mem_copy(pos, tmp_new,
2415 				     (tmp_new[1] + MIN_IE_LEN));
2416 			pos += (tmp_new[1] + MIN_IE_LEN);
2417 		}
2418 	}
2419 
2420 	extn_elem = util_scan_find_noninheritance_ie(WLAN_ELEMID_EXTN_ELEM,
2421 						     sub_copy, subie_len);
2422 
2423 	if (extn_elem && extn_elem[TAG_LEN_POS]) {
2424 		util_parse_noninheritance_list(extn_elem, &elem_list,
2425 					       &extn_elem_list, &ninh);
2426 	}
2427 
2428 	/* go through IEs in ie (skip SSID) and subelement,
2429 	 * merge them into new_ie
2430 	 */
2431 	tmp_old = util_scan_find_ie(WLAN_ELEMID_SSID, ie, ielen);
2432 	tmp_old = (tmp_old) ? tmp_old + tmp_old[1] + MIN_IE_LEN : ie;
2433 
2434 	while (((tmp_old + tmp_old[1] + MIN_IE_LEN) - ie) <= ielen) {
2435 		ninh.non_inh_ie_found = 0;
2436 		if (ninh.non_inherit) {
2437 			if (ninh.list_len) {
2438 				ninh.non_inh_ie_found =
2439 					util_is_noninh_ie(tmp_old[0],
2440 							  elem_list,
2441 							  ninh.list_len);
2442 			}
2443 
2444 			if (!ninh.non_inh_ie_found &&
2445 			    ninh.extn_len &&
2446 			    (tmp_old[0] == WLAN_ELEMID_EXTN_ELEM)) {
2447 				ninh.non_inh_ie_found =
2448 					util_is_noninh_ie(tmp_old[2],
2449 							  extn_elem_list,
2450 							  ninh.extn_len);
2451 			}
2452 		}
2453 
2454 		if (ninh.non_inh_ie_found || (tmp_old[0] == 0)) {
2455 			tmp_old += tmp_old[1] + MIN_IE_LEN;
2456 			continue;
2457 		}
2458 
2459 		tmp = (uint8_t *)util_scan_find_ie(tmp_old[0], sub_copy,
2460 						   subie_len);
2461 		if (!tmp) {
2462 			/* ie in old ie but not in subelement */
2463 			if (tmp_old[0] != WLAN_ELEMID_MULTIPLE_BSSID) {
2464 				if ((pos + tmp_old[1] + MIN_IE_LEN) <=
2465 				    (new_ie + ielen)) {
2466 					qdf_mem_copy(pos, tmp_old,
2467 						     (tmp_old[1] +
2468 						      MIN_IE_LEN));
2469 					pos += tmp_old[1] + MIN_IE_LEN;
2470 				}
2471 			}
2472 		} else {
2473 			/* ie in transmitting ie also in subelement,
2474 			 * copy from subelement and flag the ie in subelement
2475 			 * as copied (by setting eid field to 0xff).
2476 			 * To determine if the vendor ies are same:
2477 			 * 1. For Cisco OUI, compare only OUI + type
2478 			 * 2. For other OUI, compare OUI + type + subType
2479 			 */
2480 			tmp_rem_len = subie_len - (tmp - sub_copy);
2481 			if (tmp_old[0] == WLAN_ELEMID_VENDOR &&
2482 			    tmp_rem_len >= MIN_VENDOR_TAG_LEN) {
2483 				if (!qdf_mem_cmp(tmp_old + PAYLOAD_START_POS,
2484 						 tmp + PAYLOAD_START_POS,
2485 						 util_oui_header_len(tmp +
2486 								     PAYLOAD_START_POS))) {
2487 					/* same vendor ie, copy from
2488 					 * subelement
2489 					 */
2490 					if ((pos + tmp[1] + MIN_IE_LEN) <=
2491 					    (new_ie + ielen)) {
2492 						qdf_mem_copy(pos, tmp,
2493 							     tmp[1] +
2494 							     MIN_IE_LEN);
2495 						pos += tmp[1] + MIN_IE_LEN;
2496 						tmp[0] = 0;
2497 					}
2498 				} else {
2499 					if ((pos + tmp_old[1] +
2500 					     MIN_IE_LEN) <=
2501 					    (new_ie + ielen)) {
2502 						qdf_mem_copy(pos, tmp_old,
2503 							     tmp_old[1] +
2504 							     MIN_IE_LEN);
2505 						pos += tmp_old[1] +
2506 							MIN_IE_LEN;
2507 					}
2508 				}
2509 			} else if (tmp_old[0] == WLAN_ELEMID_EXTN_ELEM) {
2510 				if (tmp_old[PAYLOAD_START_POS] ==
2511 				    tmp[PAYLOAD_START_POS]) {
2512 					/* same ie, copy from subelement */
2513 					if ((pos + tmp[1] + MIN_IE_LEN) <=
2514 					    (new_ie + ielen)) {
2515 						qdf_mem_copy(pos, tmp,
2516 							     tmp[1] +
2517 							     MIN_IE_LEN);
2518 						pos += tmp[1] + MIN_IE_LEN;
2519 						tmp[0] = 0;
2520 					}
2521 				} else {
2522 					if ((pos + tmp_old[1] + MIN_IE_LEN) <=
2523 					    (new_ie + ielen)) {
2524 						qdf_mem_copy(pos, tmp_old,
2525 							     tmp_old[1] +
2526 							     MIN_IE_LEN);
2527 						pos += tmp_old[1] +
2528 							MIN_IE_LEN;
2529 					}
2530 				}
2531 
2532 			} else {
2533 				/* copy ie from subelement into new ie */
2534 				if ((pos + tmp[1] + MIN_IE_LEN) <=
2535 				    (new_ie + ielen)) {
2536 					qdf_mem_copy(pos, tmp,
2537 						     tmp[1] + MIN_IE_LEN);
2538 					pos += tmp[1] + MIN_IE_LEN;
2539 					tmp[0] = 0;
2540 				}
2541 			}
2542 		}
2543 
2544 		if (((tmp_old + tmp_old[1] + MIN_IE_LEN) - ie) >= ielen)
2545 			break;
2546 
2547 		tmp_old += tmp_old[1] + MIN_IE_LEN;
2548 	}
2549 
2550 	/* go through subelement again to check if there is any ie not
2551 	 * copied to new ie, skip ssid, capability, bssid-index ie
2552 	 */
2553 	tmp_new = sub_copy;
2554 	while (((tmp_new + tmp_new[1] + MIN_IE_LEN) - sub_copy) <=
2555 	       subie_len) {
2556 		if (!(tmp_new[0] == WLAN_ELEMID_NONTX_BSSID_CAP ||
2557 		      tmp_new[0] == WLAN_ELEMID_SSID ||
2558 		      tmp_new[0] == WLAN_ELEMID_MULTI_BSSID_IDX ||
2559 		      ((tmp_new[0] == WLAN_ELEMID_EXTN_ELEM) &&
2560 		       (tmp_new[2] == WLAN_EXTN_ELEMID_NONINHERITANCE)))) {
2561 			if ((pos + tmp_new[1] + MIN_IE_LEN) <=
2562 			    (new_ie + ielen)) {
2563 				qdf_mem_copy(pos, tmp_new,
2564 					     tmp_new[1] + MIN_IE_LEN);
2565 				pos += tmp_new[1] + MIN_IE_LEN;
2566 			}
2567 		}
2568 		if (((tmp_new + tmp_new[1] + MIN_IE_LEN) - sub_copy) >=
2569 		    subie_len)
2570 			break;
2571 		tmp_new += tmp_new[1] + MIN_IE_LEN;
2572 	}
2573 
2574 	qdf_mem_free(sub_copy);
2575 
2576 	if (pos > new_ie)
2577 		return pos - new_ie;
2578 	else
2579 		return 0;
2580 }
2581 
2582 static enum nontx_profile_reasoncode
2583 util_handle_nontx_prof(uint8_t *mbssid_elem, uint8_t *subelement,
2584 		       uint8_t *next_subelement,
2585 		       struct scan_mbssid_info *mbssid_info,
2586 		       char *bssid, char *new_bssid)
2587 {
2588 	uint8_t *mbssid_index_ie;
2589 	uint32_t prof_len;
2590 
2591 	prof_len = subelement[TAG_LEN_POS];
2592 	/*
2593 	 * If we are executing the split portion of the nontx
2594 	 * profile present in the subsequent MBSSID, then there
2595 	 * is no need of any sanity check for valid BSS profile
2596 	 */
2597 
2598 	if (mbssid_info->split_prof_continue) {
2599 		if ((subelement[ID_POS] != 0) ||
2600 		    (subelement[TAG_LEN_POS] < SPLIT_PROF_DATA_LEAST_LEN)) {
2601 			return INVALID_SPLIT_PROF;
2602 		}
2603 	} else {
2604 		if ((subelement[ID_POS] != 0) ||
2605 		    (subelement[TAG_LEN_POS] < VALID_ELEM_LEAST_LEN)) {
2606 			/* not a valid BSS profile */
2607 			return INVALID_NONTX_PROF;
2608 		}
2609 	}
2610 
2611 	if (mbssid_info->split_profile) {
2612 		if (next_subelement[PAYLOAD_START_POS] !=
2613 		    WLAN_ELEMID_NONTX_BSSID_CAP) {
2614 			mbssid_info->prof_residue = true;
2615 		}
2616 	}
2617 
2618 	if (!mbssid_info->split_prof_continue &&
2619 	    ((subelement[PAYLOAD_START_POS] != WLAN_ELEMID_NONTX_BSSID_CAP) ||
2620 	     (subelement[NONTX_BSSID_CAP_TAG_LEN_POS] != CAP_INFO_LEN))) {
2621 		/* The first element within the Nontransmitted
2622 		 * BSSID Profile is not the Nontransmitted
2623 		 * BSSID Capability element.
2624 		 */
2625 		return INVALID_NONTX_PROF;
2626 	}
2627 
2628 	/* found a Nontransmitted BSSID Profile */
2629 	mbssid_index_ie =
2630 		util_scan_find_ie(WLAN_ELEMID_MULTI_BSSID_IDX,
2631 				  (subelement + PAYLOAD_START_POS), prof_len);
2632 
2633 	if (!mbssid_index_ie) {
2634 		if (!mbssid_info->prof_residue)
2635 			return INVALID_NONTX_PROF;
2636 
2637 		mbssid_info->skip_bssid_copy = true;
2638 	} else if ((mbssid_index_ie[TAG_LEN_POS] < 1) ||
2639 		   (mbssid_index_ie[BSS_INDEX_POS] == 0)) {
2640 		/* No valid Multiple BSSID-Index element */
2641 		return INVALID_NONTX_PROF;
2642 	}
2643 
2644 	if (!mbssid_info->skip_bssid_copy) {
2645 		qdf_mem_copy(mbssid_info->trans_bssid,
2646 			     bssid, QDF_MAC_ADDR_SIZE);
2647 		mbssid_info->profile_num =
2648 			mbssid_index_ie[BSS_INDEX_POS];
2649 		util_gen_new_bssid(bssid,
2650 				   mbssid_elem[MBSSID_INDICATOR_POS],
2651 				   mbssid_index_ie[BSS_INDEX_POS],
2652 				   new_bssid);
2653 	}
2654 	/* In single MBSS IE, there could be subelement holding
2655 	 * remaining vendor IEs of non tx profile from last MBSS IE
2656 	 * [split profile] and new non tx profile, hence reset
2657 	 * skip_bssid_copy flag after each subelement processing
2658 	 */
2659 	mbssid_info->skip_bssid_copy = false;
2660 	return VALID_NONTX_PROF;
2661 }
2662 
2663 /*
2664  * What's split profile:
2665  *  If any nontransmitted BSSID profile is fragmented across
2666  * multiple MBSSID elements, then it is called split profile.
2667  * For a split profile to exist we need to have at least two
2668  * MBSSID elements as part of the RX beacon or probe response
2669  * Hence, first we need to identify the next MBSSID element
2670  * and check for the 5th bit from the starting of the next
2671  * MBSSID IE and if it does not have Nontransmitted BSSID
2672  * capability element, then it's a split profile case.
2673  */
2674 static bool util_scan_is_split_prof_found(uint8_t *next_elem,
2675 					  uint8_t *ie, uint32_t ielen)
2676 {
2677 	uint8_t *next_mbssid_elem;
2678 
2679 	if (next_elem[0] == WLAN_ELEMID_MULTIPLE_BSSID) {
2680 		if ((next_elem[TAG_LEN_POS] >= VALID_ELEM_LEAST_LEN) &&
2681 		    (next_elem[SUBELEM_DATA_POS_FROM_MBSSID] !=
2682 		     WLAN_ELEMID_NONTX_BSSID_CAP)) {
2683 			return true;
2684 		}
2685 	} else {
2686 		next_mbssid_elem =
2687 			util_scan_find_ie(WLAN_ELEMID_MULTIPLE_BSSID,
2688 					  next_elem,
2689 					  ielen - (next_elem - ie));
2690 		if (!next_mbssid_elem)
2691 			return false;
2692 
2693 		if ((next_mbssid_elem[TAG_LEN_POS] >= VALID_ELEM_LEAST_LEN) &&
2694 		    (next_mbssid_elem[SUBELEM_DATA_POS_FROM_MBSSID] !=
2695 		     WLAN_ELEMID_NONTX_BSSID_CAP)) {
2696 			return true;
2697 		}
2698 	}
2699 
2700 	return false;
2701 }
2702 
2703 static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev,
2704 					 uint8_t *frame, qdf_size_t frame_len,
2705 					 uint32_t frm_subtype,
2706 					 struct mgmt_rx_event_params *rx_param,
2707 					 qdf_list_t *scan_list)
2708 {
2709 	struct wlan_bcn_frame *bcn;
2710 	struct wlan_frame_hdr *hdr;
2711 	struct scan_mbssid_info mbssid_info = {0};
2712 	QDF_STATUS status;
2713 	uint8_t *pos, *subelement, *next_elem;
2714 	uint8_t *mbssid_elem;
2715 	uint32_t subie_len, new_ie_len, ielen;
2716 	uint8_t *next_subelement = NULL;
2717 	uint8_t new_bssid[QDF_MAC_ADDR_SIZE], bssid[QDF_MAC_ADDR_SIZE];
2718 	uint8_t *new_ie, *split_prof_start = NULL, *split_prof_end = NULL;
2719 	uint8_t *ie, *new_frame = NULL;
2720 	int new_frame_len = 0, split_prof_len = 0;
2721 	enum nontx_profile_reasoncode retval;
2722 	uint8_t *nontx_profile = NULL;
2723 
2724 	hdr = (struct wlan_frame_hdr *)frame;
2725 	bcn = (struct wlan_bcn_frame *)(frame + sizeof(struct wlan_frame_hdr));
2726 	ie = (uint8_t *)&bcn->ie;
2727 	ielen = (uint16_t)(frame_len -
2728 			   sizeof(struct wlan_frame_hdr) -
2729 			   offsetof(struct wlan_bcn_frame, ie));
2730 	qdf_mem_copy(bssid, hdr->i_addr3, QDF_MAC_ADDR_SIZE);
2731 
2732 	if (!util_scan_find_ie(WLAN_ELEMID_MULTIPLE_BSSID, ie, ielen))
2733 		return QDF_STATUS_E_FAILURE;
2734 
2735 	pos = ie;
2736 
2737 	new_ie = qdf_mem_malloc(ielen);
2738 	if (!new_ie)
2739 		return QDF_STATUS_E_NOMEM;
2740 
2741 	while (pos < (ie + ielen + MIN_IE_LEN)) {
2742 		mbssid_elem =
2743 			util_scan_find_ie(WLAN_ELEMID_MULTIPLE_BSSID, pos,
2744 					  ielen - (pos - ie));
2745 		if (!mbssid_elem)
2746 			break;
2747 
2748 		mbssid_info.profile_count =
2749 			(1 << mbssid_elem[MBSSID_INDICATOR_POS]);
2750 
2751 		next_elem =
2752 			mbssid_elem + mbssid_elem[TAG_LEN_POS] + MIN_IE_LEN;
2753 
2754 		/* Skip Element ID, Len, MaxBSSID Indicator */
2755 		if (!mbssid_info.split_profile &&
2756 		    (mbssid_elem[TAG_LEN_POS] < VALID_ELEM_LEAST_LEN)) {
2757 			break;
2758 		}
2759 
2760 		/*
2761 		 * Find if the next IE is MBSSID, if not, then scan through
2762 		 * the IE list and find the next MBSSID tag, if present.
2763 		 * Once we find the MBSSID tag, check if this MBSSID tag has
2764 		 * the other fragmented part of the non Tx profile.
2765 		 */
2766 
2767 		mbssid_info.split_profile =
2768 			util_scan_is_split_prof_found(next_elem, ie, ielen);
2769 
2770 		for (subelement = mbssid_elem + SUBELEMENT_START_POS;
2771 		     subelement < (next_elem - 1);
2772 		     subelement += MIN_IE_LEN + subelement[TAG_LEN_POS]) {
2773 			subie_len = subelement[TAG_LEN_POS];
2774 
2775 			/*
2776 			 * if prof_residue is true, that means we are
2777 			 * in the continuation of the fragmented profile part,
2778 			 * present in the next MBSSD IE else this profile
2779 			 * is a non fragmented non tx BSSID profile.
2780 			 */
2781 
2782 			if (mbssid_info.prof_residue)
2783 				mbssid_info.split_prof_continue = true;
2784 			else
2785 				mbssid_info.split_prof_continue = false;
2786 
2787 			if (subie_len > MAX_SUBELEM_LEN) {
2788 				scm_err_rl("Corrupt frame with subie_len: %d\n"
2789 					   "split_prof_continue: %d\n"
2790 					   "prof_residue: %d\n",
2791 					   subie_len,
2792 					   mbssid_info.split_prof_continue,
2793 					   mbssid_info.prof_residue);
2794 				if (mbssid_info.split_prof_continue)
2795 					qdf_mem_free(split_prof_start);
2796 
2797 				qdf_mem_free(new_ie);
2798 				return QDF_STATUS_E_INVAL;
2799 			}
2800 
2801 			if ((next_elem - subelement) <
2802 			    (MIN_IE_LEN + subie_len))
2803 				break;
2804 
2805 			next_subelement = subelement + subie_len + MIN_IE_LEN;
2806 			retval = util_handle_nontx_prof(mbssid_elem, subelement,
2807 							next_subelement,
2808 							&mbssid_info,
2809 							bssid, new_bssid);
2810 
2811 			if (retval == INVALID_SPLIT_PROF) {
2812 				scm_err_rl("Corrupt frame with ID_POS: %d\n"
2813 					   "TAG_LEN_POS: %d\n",
2814 					   subelement[ID_POS],
2815 					   subelement[TAG_LEN_POS]);
2816 				qdf_mem_free(split_prof_start);
2817 				qdf_mem_free(new_ie);
2818 				return QDF_STATUS_E_INVAL;
2819 			} else if (retval == INVALID_NONTX_PROF) {
2820 				continue;
2821 			}
2822 
2823 			/*
2824 			 * Merging parts of nontx profile-
2825 			 * Just for understanding, let's make an assumption
2826 			 * that nontx profile is fragmented across MBSSIE1
2827 			 * and MBSSIE2.
2828 			 * mbssid_info.prof_residue being set indicates
2829 			 * that the ongoing nontx profile is part of split
2830 			 * profile, whose other fragmented part is present
2831 			 * in MBSSIE2.
2832 			 * So once prof_residue is set, we need to
2833 			 * identify whether we are accessing the split
2834 			 * profile in MBSSIE1 or MBSSIE2.
2835 			 * If we are in MBSSIE1, then copy the part of split
2836 			 * profile from MBSSIE1 into a new buffer and then
2837 			 * move to the next part of the split profile which
2838 			 * is present in MBSSIE2 and append that part into
2839 			 * the new buffer.
2840 			 * Once the full profile is accumulated, go ahead with
2841 			 * the ie generation and length calculation of the
2842 			 * new frame.
2843 			 */
2844 
2845 			if (mbssid_info.prof_residue) {
2846 				if (!mbssid_info.split_prof_continue) {
2847 					split_prof_start =
2848 						qdf_mem_malloc(ielen);
2849 					if (!split_prof_start) {
2850 						scm_err_rl("Malloc failed");
2851 						qdf_mem_free(new_ie);
2852 						return QDF_STATUS_E_NOMEM;
2853 					}
2854 
2855 					qdf_mem_copy(split_prof_start,
2856 						     subelement,
2857 						     (subie_len +
2858 						      MIN_IE_LEN));
2859 					split_prof_end = (split_prof_start +
2860 							  subie_len +
2861 							  MIN_IE_LEN);
2862 					break;
2863 				}
2864 
2865 				/*
2866 				 * Currently we are accessing other part of the
2867 				 * split profile present in the subsequent
2868 				 * MBSSIE. There is a possibility that one
2869 				 * non tx profile is spread across more than
2870 				 * two MBSSID tag as well. This code will
2871 				 * handle such scenario.
2872 				 */
2873 
2874 				qdf_mem_copy(split_prof_end,
2875 					     (subelement + MIN_IE_LEN),
2876 					     subie_len);
2877 				split_prof_end =
2878 					(split_prof_end + subie_len);
2879 
2880 				/*
2881 				 * When to stop the process of accumulating
2882 				 * parts of split profile, is decided by
2883 				 * mbssid_info.prof_residue. prof_residue
2884 				 * could be made false if there is not any
2885 				 * continuation of the split profile.
2886 				 * which could be identified by two factors
2887 				 * 1. By checking if the next MBSSIE's first
2888 				 * non tx profile is not a fragmented one or
2889 				 * 2. there is a probability that first
2890 				 * subelement of MBSSIE2 is end if split
2891 				 * profile and the next subelement of MBSSIE2
2892 				 * is a non split one.
2893 				 */
2894 
2895 				if (!mbssid_info.split_profile ||
2896 				    (next_subelement[PAYLOAD_START_POS] ==
2897 				     WLAN_ELEMID_NONTX_BSSID_CAP)) {
2898 					mbssid_info.prof_residue = false;
2899 				}
2900 
2901 				/*
2902 				 * Until above mentioned conditions are met,
2903 				 * we need to iterate and keep accumulating
2904 				 * the split profile contents.
2905 				 */
2906 
2907 				if (mbssid_info.prof_residue)
2908 					break;
2909 
2910 				split_prof_len =
2911 					(split_prof_end -
2912 					 split_prof_start - MIN_IE_LEN);
2913 			}
2914 
2915 			if (mbssid_info.split_prof_continue) {
2916 				nontx_profile = split_prof_start;
2917 				subie_len = split_prof_len;
2918 			} else {
2919 				nontx_profile = subelement;
2920 			}
2921 
2922 			new_ie_len =
2923 				util_gen_new_ie(ie, ielen,
2924 						(nontx_profile +
2925 						 PAYLOAD_START_POS),
2926 						subie_len, new_ie);
2927 
2928 			if (!new_ie_len)
2929 				continue;
2930 
2931 			new_frame_len = frame_len - ielen + new_ie_len;
2932 
2933 			if (new_frame_len < 0) {
2934 				if (mbssid_info.split_prof_continue)
2935 					qdf_mem_free(split_prof_start);
2936 				qdf_mem_free(new_ie);
2937 				scm_err("Invalid frame:Stop MBSSIE parsing");
2938 				scm_err("Frame_len: %zu,ielen:%u,new_ie_len:%u",
2939 					frame_len, ielen, new_ie_len);
2940 				return QDF_STATUS_E_INVAL;
2941 			}
2942 
2943 			new_frame = qdf_mem_malloc(new_frame_len);
2944 			if (!new_frame) {
2945 				if (mbssid_info.split_prof_continue)
2946 					qdf_mem_free(split_prof_start);
2947 				qdf_mem_free(new_ie);
2948 				scm_err_rl("Malloc for new_frame failed");
2949 				scm_err_rl("split_prof_continue: %d",
2950 					   mbssid_info.split_prof_continue);
2951 				return QDF_STATUS_E_NOMEM;
2952 			}
2953 
2954 			/*
2955 			 * Copy the header(24byte), timestamp(8 byte),
2956 			 * beaconinterval(2byte) and capability(2byte)
2957 			 */
2958 			qdf_mem_copy(new_frame, frame, FIXED_LENGTH);
2959 			/* Copy the new ie generated from MBSSID profile*/
2960 			hdr = (struct wlan_frame_hdr *)new_frame;
2961 			qdf_mem_copy(hdr->i_addr2, new_bssid,
2962 				     QDF_MAC_ADDR_SIZE);
2963 			qdf_mem_copy(hdr->i_addr3, new_bssid,
2964 				     QDF_MAC_ADDR_SIZE);
2965 			bcn = (struct wlan_bcn_frame *)
2966 				(new_frame + sizeof(struct wlan_frame_hdr));
2967 			/* update the non-tx capability */
2968 			qdf_mem_copy(&bcn->capability,
2969 				     nontx_profile + CAP_INFO_POS,
2970 				     CAP_INFO_LEN);
2971 
2972 			/* Copy the new ie generated from MBSSID profile*/
2973 			qdf_mem_copy(new_frame +
2974 				     offsetof(struct wlan_bcn_frame, ie) +
2975 				     sizeof(struct wlan_frame_hdr),
2976 				     new_ie, new_ie_len);
2977 			status = util_scan_gen_scan_entry(pdev, new_frame,
2978 							  new_frame_len,
2979 							  frm_subtype,
2980 							  rx_param,
2981 							  &mbssid_info,
2982 							  scan_list);
2983 			if (QDF_IS_STATUS_ERROR(status)) {
2984 				if (mbssid_info.split_prof_continue) {
2985 					qdf_mem_free(split_prof_start);
2986 					qdf_mem_zero(&mbssid_info,
2987 						     sizeof(mbssid_info));
2988 				}
2989 				qdf_mem_free(new_frame);
2990 				scm_err_rl("failed to generate a scan entry");
2991 				scm_err_rl("split_prof_continue: %d",
2992 					   mbssid_info.split_prof_continue);
2993 				break;
2994 			}
2995 			/* scan entry makes its own copy so free the frame*/
2996 			if (mbssid_info.split_prof_continue)
2997 				qdf_mem_free(split_prof_start);
2998 			qdf_mem_free(new_frame);
2999 		}
3000 
3001 		pos = next_elem;
3002 	}
3003 	qdf_mem_free(new_ie);
3004 
3005 	return QDF_STATUS_SUCCESS;
3006 }
3007 #else
3008 static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev,
3009 					 uint8_t *frame, qdf_size_t frame_len,
3010 					 uint32_t frm_subtype,
3011 					 struct mgmt_rx_event_params *rx_param,
3012 					 qdf_list_t *scan_list)
3013 {
3014 	return QDF_STATUS_SUCCESS;
3015 }
3016 #endif
3017 
3018 static QDF_STATUS
3019 util_scan_parse_beacon_frame(struct wlan_objmgr_pdev *pdev,
3020 			     uint8_t *frame,
3021 			     qdf_size_t frame_len,
3022 			     uint32_t frm_subtype,
3023 			     struct mgmt_rx_event_params *rx_param,
3024 			     qdf_list_t *scan_list)
3025 {
3026 	struct wlan_bcn_frame *bcn;
3027 	struct wlan_frame_hdr *hdr;
3028 	uint8_t *mbssid_ie = NULL;
3029 	uint32_t ie_len = 0;
3030 	QDF_STATUS status = QDF_STATUS_E_FAILURE;
3031 	struct scan_mbssid_info mbssid_info = { 0 };
3032 
3033 	hdr = (struct wlan_frame_hdr *)frame;
3034 	bcn = (struct wlan_bcn_frame *)
3035 			   (frame + sizeof(struct wlan_frame_hdr));
3036 	ie_len = (uint16_t)(frame_len -
3037 		sizeof(struct wlan_frame_hdr) -
3038 		offsetof(struct wlan_bcn_frame, ie));
3039 
3040 	mbssid_ie = util_scan_find_ie(WLAN_ELEMID_MULTIPLE_BSSID,
3041 				      (uint8_t *)&bcn->ie, ie_len);
3042 	if (mbssid_ie) {
3043 		if (mbssid_ie[1] <= 0) {
3044 			scm_debug("MBSSID IE length is wrong %d", mbssid_ie[1]);
3045 			return status;
3046 		}
3047 		qdf_mem_copy(&mbssid_info.trans_bssid,
3048 			     hdr->i_addr3, QDF_MAC_ADDR_SIZE);
3049 		mbssid_info.profile_count = 1 << mbssid_ie[2];
3050 	}
3051 
3052 	status = util_scan_gen_scan_entry(pdev, frame, frame_len,
3053 					  frm_subtype, rx_param,
3054 					  &mbssid_info,
3055 					  scan_list);
3056 
3057 	/*
3058 	 * IF MBSSID IE is present in the beacon then
3059 	 * scan component will create a new entry for
3060 	 * each BSSID found in the MBSSID
3061 	 */
3062 	if (mbssid_ie)
3063 		status = util_scan_parse_mbssid(pdev, frame, frame_len,
3064 						frm_subtype, rx_param,
3065 						scan_list);
3066 
3067 	if (QDF_IS_STATUS_ERROR(status))
3068 		scm_debug_rl("Failed to create a scan entry");
3069 
3070 	return status;
3071 }
3072 
3073 qdf_list_t *
3074 util_scan_unpack_beacon_frame(struct wlan_objmgr_pdev *pdev, uint8_t *frame,
3075 			      qdf_size_t frame_len, uint32_t frm_subtype,
3076 			      struct mgmt_rx_event_params *rx_param)
3077 {
3078 	qdf_list_t *scan_list;
3079 	QDF_STATUS status;
3080 
3081 	scan_list = qdf_mem_malloc_atomic(sizeof(*scan_list));
3082 	if (!scan_list) {
3083 		scm_err("failed to allocate scan_list");
3084 		return NULL;
3085 	}
3086 	qdf_list_create(scan_list, MAX_SCAN_CACHE_SIZE);
3087 
3088 	status = util_scan_parse_beacon_frame(pdev, frame, frame_len,
3089 					      frm_subtype, rx_param,
3090 					      scan_list);
3091 	if (QDF_IS_STATUS_ERROR(status)) {
3092 		ucfg_scan_purge_results(scan_list);
3093 		return NULL;
3094 	}
3095 
3096 	return scan_list;
3097 }
3098 
3099 QDF_STATUS
3100 util_scan_entry_update_mlme_info(struct wlan_objmgr_pdev *pdev,
3101 	struct scan_cache_entry *scan_entry)
3102 {
3103 
3104 	if (!pdev || !scan_entry) {
3105 		scm_err("pdev 0x%pK, scan_entry: 0x%pK", pdev, scan_entry);
3106 		return QDF_STATUS_E_INVAL;
3107 	}
3108 
3109 	return scm_update_scan_mlme_info(pdev, scan_entry);
3110 }
3111 
3112 bool util_is_scan_completed(struct scan_event *event, bool *success)
3113 {
3114 	if ((event->type == SCAN_EVENT_TYPE_COMPLETED) ||
3115 	    (event->type == SCAN_EVENT_TYPE_DEQUEUED) ||
3116 	    (event->type == SCAN_EVENT_TYPE_START_FAILED)) {
3117 		if ((event->type == SCAN_EVENT_TYPE_COMPLETED) &&
3118 		    (event->reason == SCAN_REASON_COMPLETED))
3119 			*success = true;
3120 		else
3121 			*success = false;
3122 
3123 		return true;
3124 	}
3125 
3126 	*success = false;
3127 	return false;
3128 }
3129 
3130 #if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
3131 bool
3132 util_scan_entry_single_pmk(struct wlan_objmgr_psoc *psoc,
3133 			   struct scan_cache_entry *scan_entry)
3134 {
3135 	if (scan_entry->ie_list.single_pmk &&
3136 	    wlan_mlme_is_sae_single_pmk_enabled(psoc))
3137 		return true;
3138 
3139 	return false;
3140 }
3141 #endif
3142