1  /*
2   * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3   * Copyright (c) 2021-2024 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  #include "wlan_mlo_mgr_public_structs.h"
36  #include <utils_mlo.h>
37  #endif
38  #include "wlan_psoc_mlme_api.h"
39  #include "reg_services_public_struct.h"
40  #ifdef WLAN_FEATURE_ACTION_OUI
41  #include <wlan_action_oui_main.h>
42  #include <wlan_action_oui_public_struct.h>
43  #endif
44  #include <wlan_crypto_global_api.h>
45  
46  #define MAX_IE_LEN 1024
47  #define SHORT_SSID_LEN 4
48  #define NEIGHBOR_AP_LEN 1
49  #define BSS_PARAMS_LEN 1
50  
51  const char*
util_scan_get_ev_type_name(enum scan_event_type type)52  util_scan_get_ev_type_name(enum scan_event_type type)
53  {
54  	static const char * const event_name[] = {
55  		[SCAN_EVENT_TYPE_STARTED] = "STARTED",
56  		[SCAN_EVENT_TYPE_COMPLETED] = "COMPLETED",
57  		[SCAN_EVENT_TYPE_BSS_CHANNEL] = "HOME_CHANNEL",
58  		[SCAN_EVENT_TYPE_FOREIGN_CHANNEL] = "FOREIGN_CHANNEL",
59  		[SCAN_EVENT_TYPE_DEQUEUED] = "DEQUEUED",
60  		[SCAN_EVENT_TYPE_PREEMPTED] = "PREEMPTED",
61  		[SCAN_EVENT_TYPE_START_FAILED] = "START_FAILED",
62  		[SCAN_EVENT_TYPE_RESTARTED] = "RESTARTED",
63  		[SCAN_EVENT_TYPE_FOREIGN_CHANNEL_EXIT] = "FOREIGN_CHANNEL_EXIT",
64  		[SCAN_EVENT_TYPE_SUSPENDED] = "SUSPENDED",
65  		[SCAN_EVENT_TYPE_RESUMED] = "RESUMED",
66  		[SCAN_EVENT_TYPE_NLO_COMPLETE] = "NLO_COMPLETE",
67  		[SCAN_EVENT_TYPE_NLO_MATCH] = "NLO_MATCH",
68  		[SCAN_EVENT_TYPE_INVALID] = "INVALID",
69  		[SCAN_EVENT_TYPE_GPIO_TIMEOUT] = "GPIO_TIMEOUT",
70  		[SCAN_EVENT_TYPE_RADIO_MEASUREMENT_START] =
71  			"RADIO_MEASUREMENT_START",
72  		[SCAN_EVENT_TYPE_RADIO_MEASUREMENT_END] =
73  			"RADIO_MEASUREMENT_END",
74  		[SCAN_EVENT_TYPE_BSSID_MATCH] = "BSSID_MATCH",
75  		[SCAN_EVENT_TYPE_FOREIGN_CHANNEL_GET_NF] =
76  			"FOREIGN_CHANNEL_GET_NF",
77  	};
78  
79  	if (type >= SCAN_EVENT_TYPE_MAX)
80  		return "UNKNOWN";
81  
82  	return event_name[type];
83  }
84  
85  
86  const char*
util_scan_get_ev_reason_name(enum scan_completion_reason reason)87  util_scan_get_ev_reason_name(enum scan_completion_reason reason)
88  {
89  	static const char * const reason_name[] = {
90  		[SCAN_REASON_NONE] = "NONE",
91  		[SCAN_REASON_COMPLETED] = "COMPLETED",
92  		[SCAN_REASON_CANCELLED] = "CANCELLED",
93  		[SCAN_REASON_PREEMPTED] = "PREEMPTED",
94  		[SCAN_REASON_TIMEDOUT] = "TIMEDOUT",
95  		[SCAN_REASON_INTERNAL_FAILURE] = "INTERNAL_FAILURE",
96  		[SCAN_REASON_SUSPENDED] = "SUSPENDED",
97  		[SCAN_REASON_RUN_FAILED] = "RUN_FAILED",
98  		[SCAN_REASON_TERMINATION_FUNCTION] = "TERMINATION_FUNCTION",
99  		[SCAN_REASON_MAX_OFFCHAN_RETRIES] = "MAX_OFFCHAN_RETRIES",
100  		[SCAN_REASON_DFS_VIOLATION] = "DFS_NOL_VIOLATION",
101  	};
102  
103  	if (reason >= SCAN_REASON_MAX)
104  		return "UNKNOWN";
105  
106  	return reason_name[reason];
107  }
108  
109  qdf_time_t
util_get_last_scan_time(struct wlan_objmgr_vdev * vdev)110  util_get_last_scan_time(struct wlan_objmgr_vdev *vdev)
111  {
112  	uint8_t pdev_id;
113  	struct wlan_scan_obj *scan_obj;
114  
115  	if (!vdev) {
116  		scm_warn("null vdev");
117  		QDF_ASSERT(0);
118  		return 0;
119  	}
120  	pdev_id = wlan_scan_vdev_get_pdev_id(vdev);
121  	scan_obj = wlan_vdev_get_scan_obj(vdev);
122  
123  	if (scan_obj)
124  		return scan_obj->pdev_info[pdev_id].last_scan_time;
125  	else
126  		return 0;
127  }
128  
129  #ifdef WLAN_FEATURE_11BE_MLO
util_scan_entry_t2lm_len(struct scan_cache_entry * scan_entry)130  uint32_t util_scan_entry_t2lm_len(struct scan_cache_entry *scan_entry)
131  {
132  	int i = 0;
133  	uint32_t len = 0;
134  
135  	if (!scan_entry || !scan_entry->ie_list.t2lm[0])
136  		return 0;
137  
138  	for (i = 0; i < WLAN_MAX_T2LM_IE; i++) {
139  		if (scan_entry->ie_list.t2lm[i])
140  			len += scan_entry->ie_list.t2lm[i][TAG_LEN_POS] +
141  				sizeof(struct ie_header);
142  	}
143  
144  	return len;
145  }
146  #endif
147  
util_is_rsnxe_h2e_capable(const uint8_t * rsnxe)148  bool util_is_rsnxe_h2e_capable(const uint8_t *rsnxe)
149  {
150  	const uint8_t *rsnxe_caps;
151  	uint8_t cap_len;
152  
153  	if (!rsnxe)
154  		return false;
155  
156  	rsnxe_caps = wlan_crypto_parse_rsnxe_ie(rsnxe, &cap_len);
157  	if (!rsnxe_caps)
158  		return false;
159  
160  	return *rsnxe_caps & WLAN_CRYPTO_RSNX_CAP_SAE_H2E;
161  }
162  
util_scan_entry_sae_h2e_capable(struct scan_cache_entry * scan_entry)163  bool util_scan_entry_sae_h2e_capable(struct scan_cache_entry *scan_entry)
164  {
165  	const uint8_t *rsnxe;
166  
167  	/* If RSN caps are not there, then return false */
168  	if (!util_scan_entry_rsn(scan_entry))
169  		return false;
170  
171  	/* If not SAE AKM no need to check H2E capability */
172  	if (!WLAN_CRYPTO_IS_AKM_SAE(scan_entry->neg_sec_info.key_mgmt))
173  		return false;
174  
175  	rsnxe = util_scan_entry_rsnxe(scan_entry);
176  	return util_is_rsnxe_h2e_capable(rsnxe);
177  }
178  
util_scan_scm_freq_to_band(uint16_t freq)179  enum wlan_band util_scan_scm_freq_to_band(uint16_t freq)
180  {
181  	if (WLAN_REG_IS_24GHZ_CH_FREQ(freq))
182  		return WLAN_BAND_2_4_GHZ;
183  
184  	return WLAN_BAND_5_GHZ;
185  }
186  
util_is_scan_entry_match(struct scan_cache_entry * entry1,struct scan_cache_entry * entry2)187  bool util_is_scan_entry_match(
188  	struct scan_cache_entry *entry1,
189  	struct scan_cache_entry *entry2)
190  {
191  
192  	if (entry1->cap_info.wlan_caps.ess !=
193  	   entry2->cap_info.wlan_caps.ess)
194  		return false;
195  
196  	if (entry1->cap_info.wlan_caps.ess &&
197  	   !qdf_mem_cmp(entry1->bssid.bytes,
198  	   entry2->bssid.bytes, QDF_MAC_ADDR_SIZE)) {
199  		/* Check for BSS */
200  		if (util_is_ssid_match(&entry1->ssid, &entry2->ssid) ||
201  		    util_scan_is_null_ssid(&entry1->ssid) ||
202  		    util_scan_is_null_ssid(&entry2->ssid))
203  			return true;
204  	} else if (entry1->cap_info.wlan_caps.ibss &&
205  	   (entry1->channel.chan_freq ==
206  	   entry2->channel.chan_freq)) {
207  		/*
208  		 * Same channel cannot have same SSID for
209  		 * different IBSS, so no need to check BSSID
210  		 */
211  		if (util_is_ssid_match(
212  		   &entry1->ssid, &entry2->ssid))
213  			return true;
214  	} else if (!entry1->cap_info.wlan_caps.ibss &&
215  	   !entry1->cap_info.wlan_caps.ess &&
216  	   !qdf_mem_cmp(entry1->bssid.bytes,
217  	   entry2->bssid.bytes, QDF_MAC_ADDR_SIZE)) {
218  		/* In case of P2P devices, ess and ibss will be set to zero */
219  		return true;
220  	}
221  
222  	return false;
223  }
224  
util_is_pureg_rate(uint8_t * rates,uint8_t nrates)225  static bool util_is_pureg_rate(uint8_t *rates, uint8_t nrates)
226  {
227  	static const uint8_t g_rates[] = {12, 18, 24, 36, 48, 72, 96, 108};
228  	bool pureg = false;
229  	uint8_t i, j;
230  
231  	for (i = 0; i < nrates; i++) {
232  		for (j = 0; j < QDF_ARRAY_SIZE(g_rates); j++) {
233  			if (WLAN_RV(rates[i]) == g_rates[j]) {
234  				pureg = true;
235  				break;
236  			}
237  		}
238  		if (pureg)
239  			break;
240  	}
241  
242  	return pureg;
243  }
244  
245  #ifdef WLAN_FEATURE_11BE
246  static enum wlan_phymode
util_scan_get_phymode_11be(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_params,enum wlan_phymode phymode,uint8_t band_mask)247  util_scan_get_phymode_11be(struct wlan_objmgr_pdev *pdev,
248  			   struct scan_cache_entry *scan_params,
249  			   enum wlan_phymode phymode,
250  			   uint8_t band_mask)
251  {
252  	struct wlan_ie_ehtops *eht_ops;
253  	uint8_t width;
254  
255  	eht_ops = (struct wlan_ie_ehtops *)util_scan_entry_ehtop(scan_params);
256  	if (!util_scan_entry_ehtcap(scan_params) || !eht_ops)
257  		return phymode;
258  
259  	if (QDF_GET_BITS(eht_ops->ehtop_param,
260  			 EHTOP_INFO_PRESENT_IDX, EHTOP_INFO_PRESENT_BITS)) {
261  		width = QDF_GET_BITS(eht_ops->control,
262  				     EHTOP_INFO_CHAN_WIDTH_IDX,
263  				     EHTOP_INFO_CHAN_WIDTH_BITS);
264  		switch (width) {
265  		case WLAN_EHT_CHWIDTH_20:
266  			phymode = WLAN_PHYMODE_11BEA_EHT20;
267  			break;
268  		case WLAN_EHT_CHWIDTH_40:
269  			phymode = WLAN_PHYMODE_11BEA_EHT40;
270  			break;
271  		case WLAN_EHT_CHWIDTH_80:
272  			phymode = WLAN_PHYMODE_11BEA_EHT80;
273  			break;
274  		case WLAN_EHT_CHWIDTH_160:
275  			phymode = WLAN_PHYMODE_11BEA_EHT160;
276  			break;
277  		case WLAN_EHT_CHWIDTH_320:
278  			phymode = WLAN_PHYMODE_11BEA_EHT320;
279  			break;
280  		default:
281  			scm_debug("Invalid eht_ops width: %d", width);
282  			phymode = WLAN_PHYMODE_11BEA_EHT20;
283  			break;
284  		}
285  	} else {
286  		switch (phymode) {
287  		case WLAN_PHYMODE_11AXA_HE20:
288  			phymode = WLAN_PHYMODE_11BEA_EHT20;
289  			break;
290  		case WLAN_PHYMODE_11AXG_HE20:
291  			phymode = WLAN_PHYMODE_11BEG_EHT20;
292  			break;
293  		case WLAN_PHYMODE_11AXA_HE40:
294  			phymode = WLAN_PHYMODE_11BEA_EHT40;
295  			break;
296  		case WLAN_PHYMODE_11AXG_HE40:
297  			phymode = WLAN_PHYMODE_11BEG_EHT40;
298  			break;
299  		case WLAN_PHYMODE_11AXA_HE80:
300  			phymode = WLAN_PHYMODE_11BEA_EHT80;
301  			break;
302  		case WLAN_PHYMODE_11AXA_HE160:
303  			phymode = WLAN_PHYMODE_11BEA_EHT160;
304  			break;
305  		default:
306  			break;
307  		}
308  	}
309  
310  	if (QDF_GET_BITS(eht_ops->ehtop_param,
311  			 EHTOP_INFO_PRESENT_IDX, EHTOP_INFO_PRESENT_BITS)) {
312  		scan_params->channel.cfreq0 =
313  			wlan_reg_chan_band_to_freq(pdev,
314  						   eht_ops->ccfs0,
315  						   band_mask);
316  		scan_params->channel.cfreq1 =
317  			wlan_reg_chan_band_to_freq(pdev,
318  						   eht_ops->ccfs1,
319  						   band_mask);
320  	}
321  
322  	if (QDF_GET_BITS(eht_ops->ehtop_param,
323  			 EHTOP_PARAM_DISABLED_SC_BITMAP_PRESENT_IDX,
324  			 EHTOP_PARAM_DISABLED_SC_BITMAP_PRESENT_BITS)) {
325  		scan_params->channel.puncture_bitmap =
326  			QDF_GET_BITS(eht_ops->disabled_sub_chan_bitmap[0],
327  				     0, 8);
328  		scan_params->channel.puncture_bitmap |=
329  			QDF_GET_BITS(eht_ops->disabled_sub_chan_bitmap[1],
330  				     0, 8) << 8;
331  	} else {
332  		scan_params->channel.puncture_bitmap = 0;
333  	}
334  
335  	return phymode;
336  }
337  #else
338  static enum wlan_phymode
util_scan_get_phymode_11be(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_params,enum wlan_phymode phymode,uint8_t band_mask)339  util_scan_get_phymode_11be(struct wlan_objmgr_pdev *pdev,
340  			   struct scan_cache_entry *scan_params,
341  			   enum wlan_phymode phymode,
342  			   uint8_t band_mask)
343  {
344  	return phymode;
345  }
346  #endif
347  
348  #ifdef CONFIG_BAND_6GHZ
util_scan_get_he_6g_params(uint8_t * he_ops)349  static struct he_oper_6g_param *util_scan_get_he_6g_params(uint8_t *he_ops)
350  {
351  	uint8_t len;
352  	uint32_t he_oper_params;
353  
354  	if (!he_ops)
355  		return NULL;
356  
357  	len = he_ops[1];
358  	he_ops += sizeof(struct ie_header);
359  
360  	if (len < WLAN_HEOP_FIXED_PARAM_LENGTH)
361  		return NULL;
362  
363  	/* element id extension */
364  	he_ops++;
365  	len--;
366  
367  	he_oper_params = LE_READ_4(he_ops);
368  	if (!(he_oper_params & WLAN_HEOP_6GHZ_INFO_PRESENT_MASK))
369  		return NULL;
370  
371  	/* fixed params - element id extension */
372  	he_ops += WLAN_HEOP_FIXED_PARAM_LENGTH - 1;
373  	len -= WLAN_HEOP_FIXED_PARAM_LENGTH - 1;
374  
375  	if (!len)
376  		return NULL;
377  
378  	/* vht oper params */
379  	if (he_oper_params & WLAN_HEOP_VHTOP_PRESENT_MASK) {
380  		if (len < WLAN_HEOP_VHTOP_LENGTH)
381  			return NULL;
382  		he_ops += WLAN_HEOP_VHTOP_LENGTH;
383  		len -= WLAN_HEOP_VHTOP_LENGTH;
384  	}
385  
386  	if (!len)
387  		return NULL;
388  
389  	if (he_oper_params & WLAN_HEOP_CO_LOCATED_BSS_MASK) {
390  		he_ops += WLAN_HEOP_CO_LOCATED_BSS_LENGTH;
391  		len -= WLAN_HEOP_CO_LOCATED_BSS_LENGTH;
392  	}
393  
394  	if (len < sizeof(struct he_oper_6g_param))
395  		return NULL;
396  
397  	return (struct he_oper_6g_param *)he_ops;
398  }
399  
400  #ifdef WLAN_FEATURE_11BE
401  /*
402   * util_scan_is_out_of_band_leak_eht() - Check if eht beacon out of BSS BW
403   * @pdev: pointer to pdev.
404   * @scan_params: scan entry generated by beacon/probe rsp
405   * @band_mask: band mask of frequency beacon/probe rsp received
406   * @current_freq: frequency beacon/probe rsp received
407   *
408   * 1. If BSS BW <= 80MHz
409   * If Absolute value of (Current Channel Channel Center Frequency Segment 0) <=
410   * BSS BW/2 then eht beacon in BSS operating BW
411   * else eht beacon out of BSS operating BW
412   *
413   * 2. If BSS BW > 80MHz
414   * If Absolute value of (Current Channel Channel Center Frequency Segment 1) <=
415   * BSS BW/2 then eht beacon in BSS operating BW
416   * else eht beacon out of BSS operating BW
417   *
418   * Return: bool, whether eht beacon out of BSS operating BW
419   */
420  static bool
util_scan_is_out_of_band_leak_eht(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_params,uint8_t band_mask,qdf_freq_t current_freq)421  util_scan_is_out_of_band_leak_eht(struct wlan_objmgr_pdev *pdev,
422  				  struct scan_cache_entry *scan_params,
423  				  uint8_t band_mask,
424  				  qdf_freq_t current_freq)
425  {
426  	struct wlan_ie_ehtops *eht_ops;
427  	uint8_t ch_width;
428  	uint32_t bw;
429  	uint32_t freq_diff;
430  	qdf_freq_t freq_seg0;
431  	qdf_freq_t freq_seg1;
432  
433  	eht_ops = (struct wlan_ie_ehtops *)util_scan_entry_ehtop(scan_params);
434  	if (!util_scan_entry_ehtcap(scan_params) || !eht_ops)
435  		return false;
436  
437  	if (!QDF_GET_BITS(eht_ops->ehtop_param,
438  			  EHTOP_INFO_PRESENT_IDX, EHTOP_INFO_PRESENT_BITS))
439  		return false;
440  
441  	ch_width = QDF_GET_BITS(eht_ops->control,
442  				EHTOP_INFO_CHAN_WIDTH_IDX,
443  				EHTOP_INFO_CHAN_WIDTH_BITS);
444  	freq_seg0 = wlan_reg_chan_band_to_freq(pdev, eht_ops->ccfs0,
445  					       band_mask);
446  	freq_seg1 = wlan_reg_chan_band_to_freq(pdev, eht_ops->ccfs1,
447  					       band_mask);
448  	if (ch_width == WLAN_EHT_CHWIDTH_320)
449  		bw = BW_320_MHZ;
450  	else if (ch_width == WLAN_EHT_CHWIDTH_160)
451  		bw = BW_160_MHZ;
452  	else if (ch_width == WLAN_EHT_CHWIDTH_80)
453  		bw = BW_80_MHZ;
454  	else  if (ch_width == WLAN_EHT_CHWIDTH_40)
455  		bw = BW_40_MHZ;
456  	else  if (ch_width == WLAN_EHT_CHWIDTH_20)
457  		bw = BW_20_MHZ;
458  	else
459  		bw = BW_20_MHZ;
460  
461  	if (bw <= BW_80_MHZ)
462  		freq_diff = abs(freq_seg0 - current_freq);
463  	else
464  		freq_diff = abs(freq_seg1 - current_freq);
465  	if (freq_diff <= bw / 2)
466  		return false;
467  
468  	scm_debug("Leaked freq:%u ch width:%u freq0:%u freq1:%u",
469  		  current_freq, bw, freq_seg0, freq_seg1);
470  	return true;
471  }
472  #else
473  static bool
util_scan_is_out_of_band_leak_eht(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_params,uint8_t band_mask,qdf_freq_t current_freq)474  util_scan_is_out_of_band_leak_eht(struct wlan_objmgr_pdev *pdev,
475  				  struct scan_cache_entry *scan_params,
476  				  uint8_t band_mask,
477  				  qdf_freq_t current_freq)
478  {
479  	return false;
480  }
481  #endif
482  
483  /*
484   * util_scan_is_out_of_band_leak_he() - Check if HE beacon out of BSS BW
485   * @pdev: pointer to pdev.
486   * @he_6g_params: HE 6 GHz params
487   * @band_mask: band mask of frequency beacon/probe rsp received
488   * @current_freq: frequency beacon/probe rsp received
489   *
490   * 1. If BSS BW <= 80MHz
491   * If Absolute value of (Current Channel Channel Center Frequency Segment 0) <=
492   * BSS BW/2 then HE beacon in BSS operating BW
493   *
494   * 2. If BSS BW is 160MHz
495   * If Absolute value of (Current Channel Channel Center Frequency Segment 1) <=
496   * BSS BW/2 then HE beacon in BSS operating BW
497   *
498   * 3. If BSS BW is 80+80MHz
499   * If absolute value of (Current Channel - Channel Center Frequency Segment 0)
500   * <= 40 or absolute value of (Current Channel - Channel Center Frequency
501   *  Segment 1) <= 40, then HE beacon in BSS operating BW
502   *
503   * Return: bool, whether HE beacon out of BSS operating BW
504   */
505  static bool
util_scan_is_out_of_band_leak_he(struct wlan_objmgr_pdev * pdev,struct he_oper_6g_param * he_6g_params,uint8_t band_mask,qdf_freq_t current_freq)506  util_scan_is_out_of_band_leak_he(struct wlan_objmgr_pdev *pdev,
507  				 struct he_oper_6g_param *he_6g_params,
508  				 uint8_t band_mask,
509  				 qdf_freq_t current_freq)
510  {
511  	uint8_t ch_width;
512  	uint32_t bw;
513  	uint32_t freq_diff;
514  	qdf_freq_t freq_seg0;
515  	qdf_freq_t freq_seg1;
516  
517  	ch_width = he_6g_params->width;
518  	freq_seg0 = wlan_reg_chan_band_to_freq(pdev,
519  					       he_6g_params->chan_freq_seg0,
520  					       band_mask);
521  	freq_seg1 = wlan_reg_chan_band_to_freq(pdev,
522  					       he_6g_params->chan_freq_seg1,
523  					       band_mask);
524  	if (ch_width == WLAN_HE_6GHZ_CHWIDTH_160_80_80)
525  		bw = BW_160_MHZ;
526  	else if (ch_width == WLAN_HE_6GHZ_CHWIDTH_80)
527  		bw = BW_80_MHZ;
528  	else  if (ch_width == WLAN_HE_6GHZ_CHWIDTH_40)
529  		bw = BW_40_MHZ;
530  	else  if (ch_width == WLAN_HE_6GHZ_CHWIDTH_20)
531  		bw = BW_20_MHZ;
532  	else
533  		bw = BW_20_MHZ;
534  
535  	if (bw <= BW_80_MHZ) {
536  		freq_diff = abs(freq_seg0 - current_freq);
537  		if (freq_diff <= bw / 2)
538  			return false;
539  	} else if (WLAN_IS_HE160(he_6g_params)) {
540  		freq_diff = abs(freq_seg1 - current_freq);
541  		if (freq_diff <= bw / 2)
542  			return false;
543  	} else if (WLAN_IS_HE80_80(he_6g_params)) {
544  		freq_diff = abs(freq_seg0 - current_freq);
545  		if (freq_diff <= BW_40_MHZ)
546  			return false;
547  		freq_diff = abs(freq_seg1 - current_freq);
548  		if (freq_diff <= BW_40_MHZ)
549  			return false;
550  	}
551  
552  	scm_debug("Leaked freq:%u ch width:%u freq0:%u freq1:%u",
553  		  current_freq, bw, freq_seg0, freq_seg1);
554  
555  	return true;
556  }
557  
558  /*
559   * util_scan_get_chan_from_he_6g_params() - Get chan info from 6 GHz param
560   * @pdev: pointer to pdev.
561   * @scan_params: scan entry generated by beacon/probe rsp
562   * @chan_freq: output parameter, primary freq from 6 GHz he params
563   * @is_6g_dup_bcon: output parameter, bool, if false, invalid 6g duplicated
564  	beacon out of BSS operating BW or not duplicated beacon, can drop if
565  	channel mismatch
566   * @band_mask: band mask of frequency beacon/probe rsp received
567   * @current_freq: frequency beacon/probe rsp received
568   *
569   * Return: QDF_STATUS
570   */
571  static QDF_STATUS
util_scan_get_chan_from_he_6g_params(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_params,qdf_freq_t * chan_freq,bool * is_6g_dup_bcon,uint8_t band_mask,qdf_freq_t current_freq)572  util_scan_get_chan_from_he_6g_params(struct wlan_objmgr_pdev *pdev,
573  				     struct scan_cache_entry *scan_params,
574  				     qdf_freq_t *chan_freq,
575  				     bool *is_6g_dup_bcon, uint8_t band_mask,
576  				     qdf_freq_t current_freq)
577  {
578  	struct he_oper_6g_param *he_6g_params;
579  	uint8_t *he_ops;
580  	struct wlan_scan_obj *scan_obj;
581  	struct wlan_objmgr_psoc *psoc;
582  	bool is_out_of_band_leak = true;
583  
584  	psoc = wlan_pdev_get_psoc(pdev);
585  	if (!psoc) {
586  		scm_err("psoc is NULL");
587  		return QDF_STATUS_E_INVAL;
588  	}
589  
590  	scan_obj = wlan_psoc_get_scan_obj(psoc);
591  	if (!scan_obj) {
592  		scm_err("scan_obj is NULL");
593  		return QDF_STATUS_E_INVAL;
594  	}
595  
596  	*is_6g_dup_bcon = false;
597  
598  	he_ops = util_scan_entry_heop(scan_params);
599  	if (!util_scan_entry_hecap(scan_params) || !he_ops)
600  		return QDF_STATUS_SUCCESS;
601  
602  	he_6g_params = util_scan_get_he_6g_params(he_ops);
603  	if (!he_6g_params)
604  		return QDF_STATUS_SUCCESS;
605  
606  	*chan_freq = wlan_reg_chan_band_to_freq(pdev,
607  						he_6g_params->primary_channel,
608  						band_mask);
609  	if (scan_obj->drop_bcn_on_invalid_freq &&
610  	    !wlan_reg_is_freq_enabled(pdev, *chan_freq, REG_BEST_PWR_MODE)) {
611  		scm_debug_rl(QDF_MAC_ADDR_FMT": Drop as invalid channel %d freq %d in HE 6Ghz params",
612  			     QDF_MAC_ADDR_REF(scan_params->bssid.bytes),
613  			     he_6g_params->primary_channel, *chan_freq);
614  		return QDF_STATUS_E_INVAL;
615  	}
616  
617  	if (!he_6g_params->duplicate_beacon) {
618  		*is_6g_dup_bcon = false;
619  		return QDF_STATUS_SUCCESS;
620  	}
621  	is_out_of_band_leak =
622  		util_scan_is_out_of_band_leak_eht(pdev, scan_params, band_mask,
623  						  current_freq);
624  	if (is_out_of_band_leak) {
625  		*is_6g_dup_bcon = false;
626  		return QDF_STATUS_SUCCESS;
627  	}
628  	is_out_of_band_leak =
629  		util_scan_is_out_of_band_leak_he(pdev, he_6g_params, band_mask,
630  						 current_freq);
631  	if (is_out_of_band_leak) {
632  		*is_6g_dup_bcon = false;
633  		return QDF_STATUS_SUCCESS;
634  	}
635  
636  	*is_6g_dup_bcon = true;
637  
638  	return QDF_STATUS_SUCCESS;
639  }
640  
641  static enum wlan_phymode
util_scan_get_phymode_6g(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_params)642  util_scan_get_phymode_6g(struct wlan_objmgr_pdev *pdev,
643  			 struct scan_cache_entry *scan_params)
644  {
645  	struct he_oper_6g_param *he_6g_params;
646  	enum wlan_phymode phymode = WLAN_PHYMODE_11AXA_HE20;
647  	uint8_t *he_ops;
648  	uint8_t band_mask = BIT(REG_BAND_6G);
649  
650  	he_ops = util_scan_entry_heop(scan_params);
651  	if (!util_scan_entry_hecap(scan_params) || !he_ops)
652  		return phymode;
653  
654  	he_6g_params = util_scan_get_he_6g_params(he_ops);
655  	if (!he_6g_params)
656  		return phymode;
657  
658  	switch (he_6g_params->width) {
659  	case WLAN_HE_6GHZ_CHWIDTH_20:
660  		phymode = WLAN_PHYMODE_11AXA_HE20;
661  		break;
662  	case WLAN_HE_6GHZ_CHWIDTH_40:
663  		phymode = WLAN_PHYMODE_11AXA_HE40;
664  		break;
665  	case WLAN_HE_6GHZ_CHWIDTH_80:
666  		phymode = WLAN_PHYMODE_11AXA_HE80;
667  		break;
668  	case WLAN_HE_6GHZ_CHWIDTH_160_80_80:
669  		if (WLAN_IS_HE80_80(he_6g_params))
670  			phymode = WLAN_PHYMODE_11AXA_HE80_80;
671  		else if (WLAN_IS_HE160(he_6g_params))
672  			phymode = WLAN_PHYMODE_11AXA_HE160;
673  		else
674  			phymode = WLAN_PHYMODE_11AXA_HE80;
675  		break;
676  	default:
677  		scm_err("Invalid he_6g_params width: %d", he_6g_params->width);
678  		phymode = WLAN_PHYMODE_11AXA_HE20;
679  		break;
680  	}
681  
682  	if (he_6g_params->chan_freq_seg0)
683  		scan_params->channel.cfreq0 =
684  			wlan_reg_chan_band_to_freq(pdev,
685  					he_6g_params->chan_freq_seg0,
686  					band_mask);
687  	if (he_6g_params->chan_freq_seg1)
688  		scan_params->channel.cfreq1 =
689  			wlan_reg_chan_band_to_freq(pdev,
690  					he_6g_params->chan_freq_seg1,
691  					band_mask);
692  
693  	phymode = util_scan_get_phymode_11be(pdev, scan_params,
694  					     phymode, band_mask);
695  
696  	return phymode;
697  }
698  
699  uint8_t
util_scan_get_6g_oper_channel(uint8_t * he_op_ie)700  util_scan_get_6g_oper_channel(uint8_t *he_op_ie)
701  {
702  	struct he_oper_6g_param *he_6g_params;
703  
704  	he_6g_params = util_scan_get_he_6g_params(he_op_ie);
705  	if (!he_6g_params)
706  		return 0;
707  
708  	return he_6g_params->primary_channel;
709  }
710  
711  #else
712  static QDF_STATUS
util_scan_get_chan_from_he_6g_params(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_params,qdf_freq_t * chan_freq,bool * is_6g_dup_bcon,uint8_t band_mask,qdf_freq_t current_freq)713  util_scan_get_chan_from_he_6g_params(struct wlan_objmgr_pdev *pdev,
714  				     struct scan_cache_entry *scan_params,
715  				     qdf_freq_t *chan_freq,
716  				     bool *is_6g_dup_bcon,
717  				     uint8_t band_mask,
718  				     qdf_freq_t current_freq)
719  {
720  	return QDF_STATUS_SUCCESS;
721  }
722  static inline enum wlan_phymode
util_scan_get_phymode_6g(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_params)723  util_scan_get_phymode_6g(struct wlan_objmgr_pdev *pdev,
724  			 struct scan_cache_entry *scan_params)
725  {
726  	return WLAN_PHYMODE_AUTO;
727  }
728  #endif
729  
730  static inline
util_scan_ccfs0_from_htinfo(struct wlan_ie_htinfo_cmn * htinfo,uint32_t primary_chan_freq)731  uint32_t util_scan_ccfs0_from_htinfo(struct wlan_ie_htinfo_cmn *htinfo,
732  				     uint32_t primary_chan_freq)
733  {
734  	if (htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_ABOVE)
735  		return primary_chan_freq + WLAN_CHAN_SPACING_20MHZ / 2;
736  	else if (htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_BELOW)
737  		return primary_chan_freq - WLAN_CHAN_SPACING_20MHZ / 2;
738  
739  	return 0;
740  }
741  
742  static enum wlan_phymode
util_scan_get_phymode_5g(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_params)743  util_scan_get_phymode_5g(struct wlan_objmgr_pdev *pdev,
744  			 struct scan_cache_entry *scan_params)
745  {
746  	enum wlan_phymode phymode = WLAN_PHYMODE_AUTO;
747  	uint16_t ht_cap = 0;
748  	struct htcap_cmn_ie *htcap;
749  	struct wlan_ie_htinfo_cmn *htinfo;
750  	struct wlan_ie_vhtop *vhtop;
751  	uint8_t band_mask = BIT(REG_BAND_5G);
752  
753  	htcap = (struct htcap_cmn_ie *)
754  		util_scan_entry_htcap(scan_params);
755  	htinfo = (struct wlan_ie_htinfo_cmn *)
756  		util_scan_entry_htinfo(scan_params);
757  	vhtop = (struct wlan_ie_vhtop *)
758  		util_scan_entry_vhtop(scan_params);
759  
760  	if (!(htcap && htinfo))
761  		return WLAN_PHYMODE_11A;
762  
763  	if (htcap)
764  		ht_cap = le16toh(htcap->hc_cap);
765  
766  	if ((ht_cap & WLAN_HTCAP_C_CHWIDTH40) &&
767  	    (htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_ABOVE ||
768  	     htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_BELOW))
769  		phymode = WLAN_PHYMODE_11NA_HT40;
770  	else
771  		phymode = WLAN_PHYMODE_11NA_HT20;
772  
773  	scan_params->channel.cfreq0 =
774  		util_scan_ccfs0_from_htinfo(htinfo,
775  					    scan_params->channel.chan_freq);
776  
777  	if (util_scan_entry_vhtcap(scan_params) && vhtop) {
778  		switch (vhtop->vht_op_chwidth) {
779  		case WLAN_VHTOP_CHWIDTH_2040:
780  			if (phymode == WLAN_PHYMODE_11NA_HT40)
781  				phymode = WLAN_PHYMODE_11AC_VHT40;
782  			else
783  				phymode = WLAN_PHYMODE_11AC_VHT20;
784  			break;
785  		case WLAN_VHTOP_CHWIDTH_80:
786  			if (WLAN_IS_REVSIG_VHT80_80(vhtop))
787  				phymode = WLAN_PHYMODE_11AC_VHT80_80;
788  			else if (WLAN_IS_REVSIG_VHT160(vhtop))
789  				phymode = WLAN_PHYMODE_11AC_VHT160;
790  			else
791  				phymode = WLAN_PHYMODE_11AC_VHT80;
792  			break;
793  		case WLAN_VHTOP_CHWIDTH_160:
794  			phymode = WLAN_PHYMODE_11AC_VHT160;
795  			break;
796  		case WLAN_VHTOP_CHWIDTH_80_80:
797  			phymode = WLAN_PHYMODE_11AC_VHT80_80;
798  			break;
799  		default:
800  			scm_debug("bad channel: %d",
801  				  vhtop->vht_op_chwidth);
802  			phymode = WLAN_PHYMODE_11AC_VHT20;
803  			break;
804  		}
805  		if (vhtop->vht_op_ch_freq_seg1)
806  			scan_params->channel.cfreq0 =
807  				wlan_reg_chan_band_to_freq(pdev,
808  						vhtop->vht_op_ch_freq_seg1,
809  						band_mask);
810  		if (vhtop->vht_op_ch_freq_seg2)
811  			scan_params->channel.cfreq1 =
812  				wlan_reg_chan_band_to_freq(pdev,
813  						vhtop->vht_op_ch_freq_seg2,
814  						band_mask);
815  	}
816  
817  	if (!util_scan_entry_hecap(scan_params))
818  		return phymode;
819  
820  	/* for 5Ghz Check for HE, only if VHT cap and HE cap are present */
821  	if (!IS_WLAN_PHYMODE_VHT(phymode))
822  		return phymode;
823  
824  	switch (phymode) {
825  	case WLAN_PHYMODE_11AC_VHT20:
826  		phymode = WLAN_PHYMODE_11AXA_HE20;
827  		break;
828  	case WLAN_PHYMODE_11AC_VHT40:
829  		phymode = WLAN_PHYMODE_11AXA_HE40;
830  		break;
831  	case WLAN_PHYMODE_11AC_VHT80:
832  		phymode = WLAN_PHYMODE_11AXA_HE80;
833  		break;
834  	case WLAN_PHYMODE_11AC_VHT160:
835  		phymode = WLAN_PHYMODE_11AXA_HE160;
836  		break;
837  	case WLAN_PHYMODE_11AC_VHT80_80:
838  		phymode = WLAN_PHYMODE_11AXA_HE80_80;
839  		break;
840  	default:
841  		phymode = WLAN_PHYMODE_11AXA_HE20;
842  		break;
843  	}
844  
845  	phymode = util_scan_get_phymode_11be(pdev, scan_params,
846  					     phymode, band_mask);
847  
848  	return phymode;
849  }
850  
851  #ifdef WLAN_FEATURE_11BE
852  static enum wlan_phymode
util_scan_get_phymode_2g_11be(struct scan_cache_entry * scan_params,enum wlan_phymode phymode)853  util_scan_get_phymode_2g_11be(struct scan_cache_entry *scan_params,
854  			      enum wlan_phymode  phymode)
855  {
856  	if (!util_scan_entry_ehtcap(scan_params))
857  		return phymode;
858  
859  	if (phymode == WLAN_PHYMODE_11AXG_HE40PLUS)
860  		phymode = WLAN_PHYMODE_11BEG_EHT40PLUS;
861  	else if (phymode == WLAN_PHYMODE_11AXG_HE40MINUS)
862  		phymode = WLAN_PHYMODE_11BEG_EHT40MINUS;
863  	else
864  		phymode = WLAN_PHYMODE_11BEG_EHT20;
865  
866  	return phymode;
867  }
868  #else
869  static enum wlan_phymode
util_scan_get_phymode_2g_11be(struct scan_cache_entry * scan_params,enum wlan_phymode phymode)870  util_scan_get_phymode_2g_11be(struct scan_cache_entry *scan_params,
871  			      enum wlan_phymode  phymode)
872  {
873  	return phymode;
874  }
875  #endif
876  
877  static enum wlan_phymode
util_scan_get_phymode_2g(struct scan_cache_entry * scan_params)878  util_scan_get_phymode_2g(struct scan_cache_entry *scan_params)
879  {
880  	enum wlan_phymode phymode = WLAN_PHYMODE_AUTO;
881  	uint16_t ht_cap = 0;
882  	struct htcap_cmn_ie *htcap;
883  	struct wlan_ie_htinfo_cmn *htinfo;
884  	struct wlan_ie_vhtop *vhtop;
885  
886  	htcap = (struct htcap_cmn_ie *)
887  		util_scan_entry_htcap(scan_params);
888  	htinfo = (struct wlan_ie_htinfo_cmn *)
889  		util_scan_entry_htinfo(scan_params);
890  	vhtop = (struct wlan_ie_vhtop *)
891  		util_scan_entry_vhtop(scan_params);
892  
893  	if (htcap)
894  		ht_cap = le16toh(htcap->hc_cap);
895  
896  	if (htcap && htinfo) {
897  		if ((ht_cap & WLAN_HTCAP_C_CHWIDTH40) &&
898  		   (htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_ABOVE))
899  			phymode = WLAN_PHYMODE_11NG_HT40PLUS;
900  		else if ((ht_cap & WLAN_HTCAP_C_CHWIDTH40) &&
901  		   (htinfo->hi_extchoff == WLAN_HTINFO_EXTOFFSET_BELOW))
902  			phymode = WLAN_PHYMODE_11NG_HT40MINUS;
903  		else
904  			phymode = WLAN_PHYMODE_11NG_HT20;
905  	} else if (util_scan_entry_xrates(scan_params)) {
906  		/* only 11G stations will have more than 8 rates */
907  		phymode = WLAN_PHYMODE_11G;
908  	} else {
909  		/* Some mischievous g-only APs do not set extended rates */
910  		if (util_scan_entry_rates(scan_params)) {
911  			if (util_is_pureg_rate(&scan_params->ie_list.rates[2],
912  			   scan_params->ie_list.rates[1]))
913  				phymode = WLAN_PHYMODE_11G;
914  			else
915  				phymode = WLAN_PHYMODE_11B;
916  		} else {
917  			phymode = WLAN_PHYMODE_11B;
918  		}
919  	}
920  
921  	/* Check for VHT only if HT cap is present */
922  	if (!IS_WLAN_PHYMODE_HT(phymode))
923  		return phymode;
924  
925  	scan_params->channel.cfreq0 =
926  		util_scan_ccfs0_from_htinfo(htinfo,
927  					    scan_params->channel.chan_freq);
928  
929  	if (util_scan_entry_vhtcap(scan_params) && vhtop) {
930  		switch (vhtop->vht_op_chwidth) {
931  		case WLAN_VHTOP_CHWIDTH_2040:
932  			if (phymode == WLAN_PHYMODE_11NG_HT40PLUS)
933  				phymode = WLAN_PHYMODE_11AC_VHT40PLUS_2G;
934  			else if (phymode == WLAN_PHYMODE_11NG_HT40MINUS)
935  				phymode = WLAN_PHYMODE_11AC_VHT40MINUS_2G;
936  			else
937  				phymode = WLAN_PHYMODE_11AC_VHT20_2G;
938  
939  			break;
940  		default:
941  			scm_info("bad vht_op_chwidth: %d",
942  				 vhtop->vht_op_chwidth);
943  			phymode = WLAN_PHYMODE_11AC_VHT20_2G;
944  			break;
945  		}
946  	}
947  
948  	if (!util_scan_entry_hecap(scan_params))
949  		return phymode;
950  
951  	if (phymode == WLAN_PHYMODE_11AC_VHT40PLUS_2G ||
952  	    phymode == WLAN_PHYMODE_11NG_HT40PLUS)
953  		phymode = WLAN_PHYMODE_11AXG_HE40PLUS;
954  	else if (phymode == WLAN_PHYMODE_11AC_VHT40MINUS_2G ||
955  		 phymode == WLAN_PHYMODE_11NG_HT40MINUS)
956  		phymode = WLAN_PHYMODE_11AXG_HE40MINUS;
957  	else
958  		phymode = WLAN_PHYMODE_11AXG_HE20;
959  
960  	phymode = util_scan_get_phymode_2g_11be(scan_params, phymode);
961  
962  	return phymode;
963  }
964  
965  static enum wlan_phymode
util_scan_get_phymode(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_params)966  util_scan_get_phymode(struct wlan_objmgr_pdev *pdev,
967  		      struct scan_cache_entry *scan_params)
968  {
969  	if (WLAN_REG_IS_24GHZ_CH_FREQ(scan_params->channel.chan_freq))
970  		return util_scan_get_phymode_2g(scan_params);
971  	else if (WLAN_REG_IS_6GHZ_CHAN_FREQ(scan_params->channel.chan_freq))
972  		return util_scan_get_phymode_6g(pdev, scan_params);
973  	else
974  		return util_scan_get_phymode_5g(pdev, scan_params);
975  }
976  
977  static QDF_STATUS
util_scan_parse_chan_switch_wrapper_ie(struct scan_cache_entry * scan_params,struct ie_header * sub_ie,qdf_size_t sub_ie_len)978  util_scan_parse_chan_switch_wrapper_ie(struct scan_cache_entry *scan_params,
979  	struct ie_header *sub_ie, qdf_size_t sub_ie_len)
980  {
981  	/* Walk through to check nothing is malformed */
982  	while (sub_ie_len >= sizeof(struct ie_header)) {
983  		/* At least one more header is present */
984  		sub_ie_len -= sizeof(struct ie_header);
985  
986  		if (sub_ie->ie_len == 0) {
987  			sub_ie += 1;
988  			continue;
989  		}
990  		if (sub_ie_len < sub_ie->ie_len) {
991  			scm_debug_rl(QDF_MAC_ADDR_FMT": Incomplete corrupted IE:%x",
992  				     QDF_MAC_ADDR_REF(scan_params->bssid.bytes),
993  				     WLAN_ELEMID_CHAN_SWITCH_WRAP);
994  			return QDF_STATUS_E_INVAL;
995  		}
996  		switch (sub_ie->ie_id) {
997  		case WLAN_ELEMID_COUNTRY:
998  			if (sub_ie->ie_len < WLAN_COUNTRY_IE_MIN_LEN)
999  				return QDF_STATUS_E_INVAL;
1000  			scan_params->ie_list.country = (uint8_t *)sub_ie;
1001  			break;
1002  		case WLAN_ELEMID_WIDE_BAND_CHAN_SWITCH:
1003  			if (sub_ie->ie_len < WLAN_WIDE_BW_CHAN_SWITCH_IE_LEN)
1004  				return QDF_STATUS_E_INVAL;
1005  			scan_params->ie_list.widebw = (uint8_t *)sub_ie;
1006  			break;
1007  		case WLAN_ELEMID_VHT_TX_PWR_ENVLP:
1008  			if (sub_ie->ie_len > WLAN_TPE_IE_MAX_LEN)
1009  				return QDF_STATUS_E_INVAL;
1010  			scan_params->ie_list.txpwrenvlp = (uint8_t *)sub_ie;
1011  			break;
1012  #ifdef WLAN_FEATURE_11BE
1013  		case WLAN_EXTN_ELEMID_BW_IND:
1014  			if (sub_ie->ie_len > WLAN_BW_IND_IE_MAX_LEN)
1015  				return QDF_STATUS_E_INVAL;
1016  			scan_params->ie_list.bw_ind = (uint8_t *)sub_ie;
1017  			break;
1018  #endif
1019  		}
1020  		/* Consume sub info element */
1021  		sub_ie_len -= sub_ie->ie_len;
1022  		/* go to next Sub IE */
1023  		sub_ie = (struct ie_header *)
1024  			(((uint8_t *) sub_ie) +
1025  			sizeof(struct ie_header) + sub_ie->ie_len);
1026  	}
1027  
1028  	return QDF_STATUS_SUCCESS;
1029  }
1030  
1031  bool
util_scan_is_hidden_ssid(struct ie_ssid * ssid)1032  util_scan_is_hidden_ssid(struct ie_ssid *ssid)
1033  {
1034  	uint8_t i;
1035  
1036  	/*
1037  	 * We flag this as Hidden SSID if the Length is 0
1038  	 * of the SSID only contains 0's
1039  	 */
1040  	if (!ssid || !ssid->ssid_len)
1041  		return true;
1042  
1043  	for (i = 0; i < ssid->ssid_len; i++)
1044  		if (ssid->ssid[i] != 0)
1045  			return false;
1046  
1047  	/* All 0's */
1048  	return true;
1049  }
1050  
1051  #ifdef WLAN_FEATURE_11BE_MLO
util_scan_update_rnr_mld(struct rnr_bss_info * rnr,uint8_t * data,uint8_t tbtt_info_length)1052  static void util_scan_update_rnr_mld(struct rnr_bss_info *rnr, uint8_t *data,
1053  				     uint8_t tbtt_info_length)
1054  {
1055  	bool mld_info_present = false;
1056  
1057  	switch (tbtt_info_length) {
1058  	case TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM_20MHZ_PSD_MLD_PARAM:
1059  		qdf_mem_copy(&rnr->mld_info, &data[13],
1060  			     sizeof(struct rnr_mld_info));
1061  		mld_info_present = true;
1062  		break;
1063  	};
1064  
1065  	rnr->mld_info_valid = mld_info_present;
1066  }
1067  #else
1068  static inline void
util_scan_update_rnr_mld(struct rnr_bss_info * rnr,uint8_t * data,uint8_t tbtt_info_length)1069  util_scan_update_rnr_mld(struct rnr_bss_info *rnr, uint8_t *data,
1070  			 uint8_t tbtt_info_length)
1071  {
1072  }
1073  #endif
1074  
1075  static QDF_STATUS
util_scan_update_rnr(struct rnr_bss_info * rnr,struct neighbor_ap_info_field * ap_info,uint8_t * data)1076  util_scan_update_rnr(struct rnr_bss_info *rnr,
1077  		     struct neighbor_ap_info_field *ap_info,
1078  		     uint8_t *data)
1079  {
1080  	uint8_t tbtt_info_length;
1081  
1082  	tbtt_info_length = ap_info->tbtt_header.tbtt_info_length;
1083  
1084  	/*
1085  	 * Max TBTT sub-element length in RNR IE is 255 bytes and AP can send
1086  	 * data above defined length and the bytes in excess to this length
1087  	 * shall be treated as reserved.
1088  	 *
1089  	 * Limit the TBTT sub-element read operation to current supported
1090  	 * length i.e TBTT_NEIGHBOR_AP_PARAM_MAX
1091  	 */
1092  	if (tbtt_info_length > TBTT_NEIGHBOR_AP_PARAM_MAX)
1093  		tbtt_info_length = TBTT_NEIGHBOR_AP_PARAM_MAX;
1094  
1095  	switch (tbtt_info_length) {
1096  	case TBTT_NEIGHBOR_AP_OFFSET_ONLY:
1097  		/* Dont store it skip*/
1098  		break;
1099  
1100  	case TBTT_NEIGHBOR_AP_BSS_PARAM:
1101  		/* Dont store it skip*/
1102  		break;
1103  
1104  	case TBTT_NEIGHBOR_AP_S_SSID_BSS_PARAM:
1105  		rnr->bss_params = data[5];
1106  		fallthrough;
1107  	case TBTT_NEIGHBOR_AP_SHORTSSID:
1108  		rnr->channel_number = ap_info->channel_number;
1109  		rnr->operating_class = ap_info->operting_class;
1110  		qdf_mem_copy(&rnr->short_ssid, &data[1], SHORT_SSID_LEN);
1111  		break;
1112  
1113  	case TBTT_NEIGHBOR_AP_BSSID_BSS_PARAM_20MHZ_PSD:
1114  		rnr->psd_20mhz = data[8];
1115  		fallthrough;
1116  	case TBTT_NEIGHBOR_AP_BSSID_BSS_PARAM:
1117  		rnr->bss_params = data[7];
1118  		fallthrough;
1119  	case TBTT_NEIGHBOR_AP_BSSID:
1120  		rnr->channel_number = ap_info->channel_number;
1121  		rnr->operating_class = ap_info->operting_class;
1122  		qdf_mem_copy(&rnr->bssid, &data[1], QDF_MAC_ADDR_SIZE);
1123  		break;
1124  
1125  	case TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM_20MHZ_PSD_MLD_PARAM:
1126  		util_scan_update_rnr_mld(rnr, data, tbtt_info_length);
1127  		fallthrough;
1128  	case TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM_20MHZ_PSD:
1129  		rnr->psd_20mhz = data[12];
1130  		fallthrough;
1131  	case TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM:
1132  		rnr->bss_params = data[11];
1133  		fallthrough;
1134  	case TBTT_NEIGHBOR_AP_BSSSID_S_SSID:
1135  		rnr->channel_number = ap_info->channel_number;
1136  		rnr->operating_class = ap_info->operting_class;
1137  		qdf_mem_copy(&rnr->bssid, &data[1], QDF_MAC_ADDR_SIZE);
1138  		qdf_mem_copy(&rnr->short_ssid, &data[7], SHORT_SSID_LEN);
1139  		break;
1140  
1141  	default:
1142  		scm_debug("Wrong fieldtype");
1143  	}
1144  
1145  	return QDF_STATUS_SUCCESS;
1146  }
1147  
1148  static QDF_STATUS
util_scan_parse_rnr_ie(struct scan_cache_entry * scan_entry,struct ie_header * ie)1149  util_scan_parse_rnr_ie(struct scan_cache_entry *scan_entry,
1150  		       struct ie_header *ie)
1151  {
1152  	uint32_t rnr_ie_len;
1153  	uint16_t tbtt_count, tbtt_length, i, fieldtype, idx;
1154  	uint8_t *data;
1155  	struct neighbor_ap_info_field *neighbor_ap_info;
1156  
1157  	rnr_ie_len = ie->ie_len;
1158  	data = (uint8_t *)ie + sizeof(struct ie_header);
1159  	idx = scan_entry->rnr.count;
1160  
1161  	while ((data + sizeof(struct neighbor_ap_info_field)) <=
1162  					((uint8_t *)ie + rnr_ie_len + 2)) {
1163  		neighbor_ap_info = (struct neighbor_ap_info_field *)data;
1164  		tbtt_count = neighbor_ap_info->tbtt_header.tbtt_info_count;
1165  		tbtt_length = neighbor_ap_info->tbtt_header.tbtt_info_length;
1166  		fieldtype = neighbor_ap_info->tbtt_header.tbbt_info_fieldtype;
1167  		scm_debug("chan %d, opclass %d tbtt_cnt %d, tbtt_len %d, fieldtype %d",
1168  			  neighbor_ap_info->channel_number,
1169  			  neighbor_ap_info->operting_class,
1170  			  tbtt_count, tbtt_length, fieldtype);
1171  		data += sizeof(struct neighbor_ap_info_field);
1172  
1173  		if (tbtt_count > TBTT_INFO_COUNT)
1174  			break;
1175  
1176  		for (i = 0; i < (tbtt_count + 1) &&
1177  		     (data + tbtt_length) <=
1178  				((uint8_t *)ie + rnr_ie_len + 2); i++) {
1179  			if ((i < MAX_RNR_BSS) && (idx < MAX_RNR_BSS))
1180  				util_scan_update_rnr(
1181  					&scan_entry->rnr.bss_info[idx++],
1182  					neighbor_ap_info,
1183  					data);
1184  			data += tbtt_length;
1185  		}
1186  	}
1187  
1188  	scan_entry->rnr.count = idx;
1189  
1190  	return QDF_STATUS_SUCCESS;
1191  }
1192  
1193  #ifdef WLAN_FEATURE_11BE_MLO
1194  static void
util_scan_parse_t2lm_ie(struct scan_cache_entry * scan_params,struct extn_ie_header * extn_ie)1195  util_scan_parse_t2lm_ie(struct scan_cache_entry *scan_params,
1196  			struct extn_ie_header *extn_ie)
1197  {
1198  	uint8_t t2lm_idx = 0;
1199  
1200  	if (extn_ie->ie_extn_id == WLAN_EXTN_ELEMID_T2LM)
1201  		for (t2lm_idx = 0; t2lm_idx < WLAN_MAX_T2LM_IE; t2lm_idx++) {
1202  			if (!scan_params->ie_list.t2lm[t2lm_idx]) {
1203  				scan_params->ie_list.t2lm[t2lm_idx] =
1204  					(uint8_t *)extn_ie;
1205  				return;
1206  		}
1207  	}
1208  }
1209  #endif
1210  
1211  #ifdef WLAN_FEATURE_11BE
1212  #ifdef WLAN_FEATURE_11BE_MLO
util_scan_parse_ml_ie(struct scan_cache_entry * scan_params,struct extn_ie_header * extn_ie)1213  static void util_scan_parse_ml_ie(struct scan_cache_entry *scan_params,
1214  				  struct extn_ie_header *extn_ie)
1215  {
1216  	uint8_t *ml_ie;
1217  	uint32_t ml_ie_len;
1218  	enum wlan_ml_variant ml_variant;
1219  	QDF_STATUS ret;
1220  
1221  	if (extn_ie->ie_extn_id != WLAN_EXTN_ELEMID_MULTI_LINK)
1222  		return;
1223  
1224  	ml_ie = (uint8_t *)extn_ie;
1225  	ml_ie_len = ml_ie[TAG_LEN_POS];
1226  
1227  	/* Adding the size of IE header to ML IE length */
1228  	ml_ie_len += sizeof(struct ie_header);
1229  	ret = util_get_mlie_variant(ml_ie, ml_ie_len, (int *)&ml_variant);
1230  	if (ret) {
1231  		scm_err("Unable to get ml variant");
1232  		return;
1233  	}
1234  
1235  	switch (ml_variant) {
1236  	case WLAN_ML_VARIANT_BASIC:
1237  		scan_params->ie_list.multi_link_bv = (uint8_t *)extn_ie;
1238  		break;
1239  	case WLAN_ML_VARIANT_RECONFIG:
1240  		scan_params->ie_list.multi_link_rv = (uint8_t *)extn_ie;
1241  		break;
1242  	default:
1243  		break;
1244  	}
1245  }
1246  #else
util_scan_parse_ml_ie(struct scan_cache_entry * scan_params,struct extn_ie_header * extn_ie)1247  static void util_scan_parse_ml_ie(struct scan_cache_entry *scan_params,
1248  				  struct extn_ie_header *extn_ie)
1249  {
1250  }
1251  #endif
util_scan_parse_eht_ie(struct scan_cache_entry * scan_params,struct extn_ie_header * extn_ie)1252  static void util_scan_parse_eht_ie(struct scan_cache_entry *scan_params,
1253  				   struct extn_ie_header *extn_ie)
1254  {
1255  	switch (extn_ie->ie_extn_id) {
1256  	case WLAN_EXTN_ELEMID_EHTCAP:
1257  		scan_params->ie_list.ehtcap = (uint8_t *)extn_ie;
1258  		break;
1259  	case WLAN_EXTN_ELEMID_EHTOP:
1260  		scan_params->ie_list.ehtop  = (uint8_t *)extn_ie;
1261  		break;
1262  	default:
1263  		break;
1264  	}
1265  
1266  	util_scan_parse_ml_ie(scan_params, extn_ie);
1267  	util_scan_parse_t2lm_ie(scan_params, extn_ie);
1268  }
1269  #else
util_scan_parse_eht_ie(struct scan_cache_entry * scan_params,struct extn_ie_header * extn_ie)1270  static void util_scan_parse_eht_ie(struct scan_cache_entry *scan_params,
1271  				   struct extn_ie_header *extn_ie)
1272  {
1273  }
1274  #endif
1275  
1276  static QDF_STATUS
util_scan_parse_extn_ie(struct scan_cache_entry * scan_params,struct ie_header * ie)1277  util_scan_parse_extn_ie(struct scan_cache_entry *scan_params,
1278  			struct ie_header *ie)
1279  {
1280  	struct extn_ie_header *extn_ie = (struct extn_ie_header *) ie;
1281  
1282  	switch (extn_ie->ie_extn_id) {
1283  	case WLAN_EXTN_ELEMID_MAX_CHAN_SWITCH_TIME:
1284  		if (extn_ie->ie_len != WLAN_MAX_CHAN_SWITCH_TIME_IE_LEN)
1285  			return QDF_STATUS_E_INVAL;
1286  		scan_params->ie_list.mcst  = (uint8_t *)ie;
1287  		break;
1288  	case WLAN_EXTN_ELEMID_SRP:
1289  		if (extn_ie->ie_len > WLAN_MAX_SRP_IE_LEN)
1290  			return QDF_STATUS_E_INVAL;
1291  		scan_params->ie_list.srp   = (uint8_t *)ie;
1292  		break;
1293  	case WLAN_EXTN_ELEMID_HECAP:
1294  		if ((extn_ie->ie_len < WLAN_MIN_HECAP_IE_LEN) ||
1295  		    (extn_ie->ie_len > WLAN_MAX_HECAP_IE_LEN))
1296  			return QDF_STATUS_E_INVAL;
1297  		scan_params->ie_list.hecap = (uint8_t *)ie;
1298  		break;
1299  	case WLAN_EXTN_ELEMID_HEOP:
1300  		if (extn_ie->ie_len > WLAN_MAX_HEOP_IE_LEN)
1301  			return QDF_STATUS_E_INVAL;
1302  		scan_params->ie_list.heop  = (uint8_t *)ie;
1303  		break;
1304  	case WLAN_EXTN_ELEMID_ESP:
1305  		scan_params->ie_list.esp = (uint8_t *)ie;
1306  		break;
1307  	case WLAN_EXTN_ELEMID_MUEDCA:
1308  		if (extn_ie->ie_len > WLAN_MAX_MUEDCA_IE_LEN)
1309  			return QDF_STATUS_E_INVAL;
1310  		scan_params->ie_list.muedca = (uint8_t *)ie;
1311  		break;
1312  	case WLAN_EXTN_ELEMID_HE_6G_CAP:
1313  		if (extn_ie->ie_len > WLAN_MAX_HE_6G_CAP_IE_LEN)
1314  			return QDF_STATUS_E_INVAL;
1315  		scan_params->ie_list.hecap_6g = (uint8_t *)ie;
1316  		break;
1317  	default:
1318  		break;
1319  	}
1320  	util_scan_parse_eht_ie(scan_params, extn_ie);
1321  
1322  	return QDF_STATUS_SUCCESS;
1323  }
1324  
1325  static QDF_STATUS
util_scan_parse_vendor_ie(struct scan_cache_entry * scan_params,struct ie_header * ie)1326  util_scan_parse_vendor_ie(struct scan_cache_entry *scan_params,
1327  	struct ie_header *ie)
1328  {
1329  	if (!scan_params->ie_list.vendor)
1330  		scan_params->ie_list.vendor = (uint8_t *)ie;
1331  
1332  	if (is_wpa_oui((uint8_t *)ie)) {
1333  		scan_params->ie_list.wpa = (uint8_t *)ie;
1334  	} else if (is_wps_oui((uint8_t *)ie)) {
1335  		scan_params->ie_list.wps = (uint8_t *)ie;
1336  		/* WCN IE should be a subset of WPS IE */
1337  		if (is_wcn_oui((uint8_t *)ie))
1338  			scan_params->ie_list.wcn = (uint8_t *)ie;
1339  	} else if (is_wme_param((uint8_t *)ie)) {
1340  		if (ie->ie_len > WLAN_VENDOR_WME_IE_LEN)
1341  			return QDF_STATUS_E_INVAL;
1342  
1343  		scan_params->ie_list.wmeparam = (uint8_t *)ie;
1344  	} else if (is_wme_info((uint8_t *)ie)) {
1345  		scan_params->ie_list.wmeinfo = (uint8_t *)ie;
1346  	} else if (is_atheros_oui((uint8_t *)ie)) {
1347  		if (ie->ie_len > WLAN_VENDOR_ATHCAPS_IE_LEN)
1348  			return QDF_STATUS_E_INVAL;
1349  
1350  		scan_params->ie_list.athcaps = (uint8_t *)ie;
1351  	} else if (is_atheros_extcap_oui((uint8_t *)ie)) {
1352  		if (ie->ie_len > WLAN_VENDOR_ATH_EXTCAP_IE_LEN)
1353  			return QDF_STATUS_E_INVAL;
1354  
1355  		scan_params->ie_list.athextcaps = (uint8_t *)ie;
1356  	} else if (is_sfa_oui((uint8_t *)ie)) {
1357  		if (ie->ie_len > WLAN_VENDOR_SFA_IE_LEN)
1358  			return QDF_STATUS_E_INVAL;
1359  
1360  		scan_params->ie_list.sfa = (uint8_t *)ie;
1361  	} else if (is_p2p_oui((uint8_t *)ie)) {
1362  		scan_params->ie_list.p2p = (uint8_t *)ie;
1363  	} else if (is_qca_son_oui((uint8_t *)ie,
1364  				  QCA_OUI_WHC_AP_INFO_SUBTYPE)) {
1365  
1366  		scan_params->ie_list.sonadv = (uint8_t *)ie;
1367  	} else if (is_ht_cap((uint8_t *)ie)) {
1368  		/* we only care if there isn't already an HT IE (ANA) */
1369  		if (!scan_params->ie_list.htcap) {
1370  			if (ie->ie_len != (WLAN_VENDOR_HT_IE_OFFSET_LEN +
1371  					   sizeof(struct htcap_cmn_ie)))
1372  				return QDF_STATUS_E_INVAL;
1373  			scan_params->ie_list.htcap =
1374  			 (uint8_t *)&(((struct wlan_vendor_ie_htcap *)ie)->ie);
1375  		}
1376  	} else if (is_ht_info((uint8_t *)ie)) {
1377  		/* we only care if there isn't already an HT IE (ANA) */
1378  		if (!scan_params->ie_list.htinfo) {
1379  			if (ie->ie_len != WLAN_VENDOR_HT_IE_OFFSET_LEN +
1380  					  sizeof(struct wlan_ie_htinfo_cmn))
1381  				return QDF_STATUS_E_INVAL;
1382  			scan_params->ie_list.htinfo =
1383  			  (uint8_t *)&(((struct wlan_vendor_ie_htinfo *)
1384  			  ie)->hi_ie);
1385  		}
1386  	} else if (is_interop_vht((uint8_t *)ie) &&
1387  	    !(scan_params->ie_list.vhtcap)) {
1388  		uint8_t *vendor_ie = (uint8_t *)(ie);
1389  
1390  		if (ie->ie_len < ((WLAN_VENDOR_VHTCAP_IE_OFFSET +
1391  				 sizeof(struct wlan_ie_vhtcaps)) -
1392  				 sizeof(struct ie_header)))
1393  			return QDF_STATUS_E_INVAL;
1394  		vendor_ie = ((uint8_t *)(ie)) + WLAN_VENDOR_VHTCAP_IE_OFFSET;
1395  		if (vendor_ie[1] != (sizeof(struct wlan_ie_vhtcaps)) -
1396  				      sizeof(struct ie_header))
1397  			return QDF_STATUS_E_INVAL;
1398  		/* location where Interop Vht Cap IE and VHT OP IE Present */
1399  		scan_params->ie_list.vhtcap = (((uint8_t *)(ie)) +
1400  						WLAN_VENDOR_VHTCAP_IE_OFFSET);
1401  		if (ie->ie_len > ((WLAN_VENDOR_VHTCAP_IE_OFFSET +
1402  				 sizeof(struct wlan_ie_vhtcaps)) -
1403  				 sizeof(struct ie_header))) {
1404  			if (ie->ie_len < ((WLAN_VENDOR_VHTOP_IE_OFFSET +
1405  					  sizeof(struct wlan_ie_vhtop)) -
1406  					  sizeof(struct ie_header)))
1407  				return QDF_STATUS_E_INVAL;
1408  			vendor_ie = ((uint8_t *)(ie)) +
1409  				    WLAN_VENDOR_VHTOP_IE_OFFSET;
1410  			if (vendor_ie[1] != (sizeof(struct wlan_ie_vhtop) -
1411  					     sizeof(struct ie_header)))
1412  				return QDF_STATUS_E_INVAL;
1413  			scan_params->ie_list.vhtop = (((uint8_t *)(ie)) +
1414  						   WLAN_VENDOR_VHTOP_IE_OFFSET);
1415  		}
1416  	} else if (is_bwnss_oui((uint8_t *)ie)) {
1417  		/*
1418  		 * Bandwidth-NSS map has sub-type & version.
1419  		 * hence copy data just after version byte
1420  		 */
1421  		if (ie->ie_len > WLAN_BWNSS_MAP_OFFSET)
1422  			scan_params->ie_list.bwnss_map = (((uint8_t *)ie) + 8);
1423  	} else if (is_mbo_oce_oui((uint8_t *)ie)) {
1424  		scan_params->ie_list.mbo_oce = (uint8_t *)ie;
1425  	} else if (is_extender_oui((uint8_t *)ie)) {
1426  		scan_params->ie_list.extender = (uint8_t *)ie;
1427  	} else if (is_adaptive_11r_oui((uint8_t *)ie)) {
1428  		if ((ie->ie_len < OUI_LENGTH) ||
1429  		    (ie->ie_len > MAX_ADAPTIVE_11R_IE_LEN))
1430  			return QDF_STATUS_E_INVAL;
1431  
1432  		scan_params->ie_list.adaptive_11r = (uint8_t *)ie +
1433  						sizeof(struct ie_header);
1434  	} else if (is_sae_single_pmk_oui((uint8_t *)ie)) {
1435  		if ((ie->ie_len < OUI_LENGTH) ||
1436  		    (ie->ie_len > MAX_SAE_SINGLE_PMK_IE_LEN)) {
1437  			scm_debug("Invalid sae single pmk OUI");
1438  			return QDF_STATUS_E_INVAL;
1439  		}
1440  		scan_params->ie_list.single_pmk = (uint8_t *)ie +
1441  						sizeof(struct ie_header);
1442  	} else if (is_qcn_oui((uint8_t *)ie)) {
1443  		scan_params->ie_list.qcn = (uint8_t *)ie;
1444  	}
1445  
1446  	return QDF_STATUS_SUCCESS;
1447  }
1448  
1449  static QDF_STATUS
util_scan_populate_bcn_ie_list(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_params,qdf_freq_t * chan_freq,uint8_t band_mask)1450  util_scan_populate_bcn_ie_list(struct wlan_objmgr_pdev *pdev,
1451  			       struct scan_cache_entry *scan_params,
1452  			       qdf_freq_t *chan_freq, uint8_t band_mask)
1453  {
1454  	struct ie_header *ie, *sub_ie;
1455  	uint32_t ie_len, sub_ie_len;
1456  	QDF_STATUS status;
1457  	uint8_t chan_idx;
1458  	struct wlan_scan_obj *scan_obj;
1459  	struct wlan_objmgr_psoc *psoc;
1460  	uint8_t tpe_idx = 0;
1461  
1462  	psoc = wlan_pdev_get_psoc(pdev);
1463  	if (!psoc) {
1464  		scm_err("psoc is NULL");
1465  		return QDF_STATUS_E_INVAL;
1466  	}
1467  
1468  	scan_obj = wlan_psoc_get_scan_obj(psoc);
1469  	if (!scan_obj) {
1470  		scm_err("scan_obj is NULL");
1471  		return QDF_STATUS_E_INVAL;
1472  	}
1473  
1474  	ie_len = util_scan_entry_ie_len(scan_params);
1475  	ie = (struct ie_header *)
1476  		  util_scan_entry_ie_data(scan_params);
1477  
1478  	while (ie_len >= sizeof(struct ie_header)) {
1479  		ie_len -= sizeof(struct ie_header);
1480  
1481  		if (!ie->ie_len) {
1482  			ie += 1;
1483  			continue;
1484  		}
1485  
1486  		if (ie_len < ie->ie_len) {
1487  			if (scan_obj->allow_bss_with_incomplete_ie) {
1488  				scm_debug(QDF_MAC_ADDR_FMT": Scan allowed with incomplete corrupted IE:%x, ie_len: %d, ie->ie_len: %d, stop processing further",
1489  					  QDF_MAC_ADDR_REF(scan_params->bssid.bytes),
1490  					  ie->ie_id, ie_len, ie->ie_len);
1491  				break;
1492  			}
1493  			scm_debug(QDF_MAC_ADDR_FMT": Scan not allowed with incomplete corrupted IE:%x, ie_len: %d, ie->ie_len: %d, stop processing further",
1494  				  QDF_MAC_ADDR_REF(scan_params->bssid.bytes),
1495  				  ie->ie_id, ie_len, ie->ie_len);
1496  			return QDF_STATUS_E_INVAL;
1497  		}
1498  
1499  		switch (ie->ie_id) {
1500  		case WLAN_ELEMID_SSID:
1501  			if (ie->ie_len > (sizeof(struct ie_ssid) -
1502  					  sizeof(struct ie_header)))
1503  				goto err;
1504  			scan_params->ie_list.ssid = (uint8_t *)ie;
1505  			break;
1506  		case WLAN_ELEMID_RATES:
1507  			if (ie->ie_len > WLAN_SUPPORTED_RATES_IE_MAX_LEN)
1508  				goto err;
1509  			scan_params->ie_list.rates = (uint8_t *)ie;
1510  			break;
1511  		case WLAN_ELEMID_DSPARMS:
1512  			if (ie->ie_len != WLAN_DS_PARAM_IE_MAX_LEN)
1513  				return QDF_STATUS_E_INVAL;
1514  			scan_params->ie_list.ds_param = (uint8_t *)ie;
1515  			chan_idx = ((struct ds_ie *)ie)->cur_chan;
1516  			*chan_freq = wlan_reg_chan_band_to_freq(pdev, chan_idx,
1517  								band_mask);
1518  			/* Drop if invalid freq */
1519  			if (scan_obj->drop_bcn_on_invalid_freq &&
1520  			    !wlan_reg_is_freq_enabled(pdev,
1521  						      *chan_freq,
1522  						      REG_CURRENT_PWR_MODE)) {
1523  				scm_debug(QDF_MAC_ADDR_FMT": Drop as invalid chan %d in DS IE, freq %d, band_mask %d",
1524  					  QDF_MAC_ADDR_REF(
1525  						  scan_params->bssid.bytes),
1526  					  chan_idx, *chan_freq, band_mask);
1527  				return QDF_STATUS_E_INVAL;
1528  			}
1529  			break;
1530  		case WLAN_ELEMID_TIM:
1531  			if (ie->ie_len < WLAN_TIM_IE_MIN_LENGTH)
1532  				goto err;
1533  			scan_params->ie_list.tim = (uint8_t *)ie;
1534  			scan_params->dtim_period =
1535  				((struct wlan_tim_ie *)ie)->tim_period;
1536  			break;
1537  		case WLAN_ELEMID_COUNTRY:
1538  			if (ie->ie_len < WLAN_COUNTRY_IE_MIN_LEN)
1539  				goto err;
1540  			scan_params->ie_list.country = (uint8_t *)ie;
1541  			break;
1542  		case WLAN_ELEMID_QBSS_LOAD:
1543  			if (ie->ie_len != sizeof(struct qbss_load_ie) -
1544  					  sizeof(struct ie_header)) {
1545  				/*
1546  				 * Expected QBSS IE length is 5Bytes; For some
1547  				 * old cisco AP, QBSS IE length is 4Bytes, which
1548  				 * doesn't match with latest spec, So ignore
1549  				 * QBSS IE in such case.
1550  				 */
1551  				break;
1552  			}
1553  			scan_params->ie_list.qbssload = (uint8_t *)ie;
1554  			break;
1555  		case WLAN_ELEMID_CHANSWITCHANN:
1556  			if (ie->ie_len != WLAN_CSA_IE_MAX_LEN)
1557  				goto err;
1558  			scan_params->ie_list.csa = (uint8_t *)ie;
1559  			break;
1560  		case WLAN_ELEMID_IBSSDFS:
1561  			if (ie->ie_len < WLAN_IBSSDFS_IE_MIN_LEN)
1562  				goto err;
1563  			scan_params->ie_list.ibssdfs = (uint8_t *)ie;
1564  			break;
1565  		case WLAN_ELEMID_QUIET:
1566  			if (ie->ie_len != WLAN_QUIET_IE_MAX_LEN)
1567  				goto err;
1568  			scan_params->ie_list.quiet = (uint8_t *)ie;
1569  			break;
1570  		case WLAN_ELEMID_ERP:
1571  			if (ie->ie_len != (sizeof(struct erp_ie) -
1572  					    sizeof(struct ie_header)))
1573  				goto err;
1574  			scan_params->erp = ((struct erp_ie *)ie)->value;
1575  			break;
1576  		case WLAN_ELEMID_HTCAP_ANA:
1577  			if (ie->ie_len == sizeof(struct htcap_cmn_ie)) {
1578  				scan_params->ie_list.htcap =
1579  				(uint8_t *)&(((struct htcap_ie *)ie)->ie);
1580  			}
1581  			break;
1582  		case WLAN_ELEMID_RSN:
1583  			/*
1584  			 * For security cert TC, RSNIE length can be 1 but if
1585  			 * beacon is dropped, old entry will remain in scan
1586  			 * cache and cause cert TC failure as connection with
1587  			 * old entry with valid RSN IE will pass.
1588  			 * So instead of dropping the frame, do not store the
1589  			 * RSN pointer so that old entry is overwritten.
1590  			 */
1591  			if (ie->ie_len >= WLAN_RSN_IE_MIN_LEN)
1592  				scan_params->ie_list.rsn = (uint8_t *)ie;
1593  			break;
1594  		case WLAN_ELEMID_XRATES:
1595  			if (ie->ie_len > WLAN_EXT_SUPPORTED_RATES_IE_MAX_LEN)
1596  				goto err;
1597  			scan_params->ie_list.xrates = (uint8_t *)ie;
1598  			break;
1599  		case WLAN_ELEMID_EXTCHANSWITCHANN:
1600  			if (ie->ie_len != WLAN_XCSA_IE_MAX_LEN)
1601  				goto err;
1602  			scan_params->ie_list.xcsa = (uint8_t *)ie;
1603  			break;
1604  		case WLAN_ELEMID_SECCHANOFFSET:
1605  			if (ie->ie_len != WLAN_SECCHANOFF_IE_MAX_LEN)
1606  				goto err;
1607  			scan_params->ie_list.secchanoff = (uint8_t *)ie;
1608  			break;
1609  		case WLAN_ELEMID_HTINFO_ANA:
1610  			if (ie->ie_len != sizeof(struct wlan_ie_htinfo_cmn))
1611  				goto err;
1612  			scan_params->ie_list.htinfo =
1613  			  (uint8_t *)&(((struct wlan_ie_htinfo *) ie)->hi_ie);
1614  			chan_idx = ((struct wlan_ie_htinfo_cmn *)
1615  				 (scan_params->ie_list.htinfo))->hi_ctrlchannel;
1616  			*chan_freq = wlan_reg_chan_band_to_freq(pdev, chan_idx,
1617  								band_mask);
1618  			/* Drop if invalid freq */
1619  			if (scan_obj->drop_bcn_on_invalid_freq &&
1620  			    !wlan_reg_is_freq_enabled(pdev,
1621  						      *chan_freq,
1622  						      REG_CURRENT_PWR_MODE)) {
1623  				scm_debug_rl(QDF_MAC_ADDR_FMT": Drop as invalid channel %d freq %d in HT_INFO IE",
1624  					     QDF_MAC_ADDR_REF(scan_params->bssid.bytes),
1625  					     chan_idx, *chan_freq);
1626  				return QDF_STATUS_E_INVAL;
1627  			}
1628  			break;
1629  		case WLAN_ELEMID_WAPI:
1630  			if (ie->ie_len < WLAN_WAPI_IE_MIN_LEN)
1631  				goto err;
1632  			scan_params->ie_list.wapi = (uint8_t *)ie;
1633  			break;
1634  		case WLAN_ELEMID_XCAPS:
1635  			if (ie->ie_len > WLAN_EXTCAP_IE_MAX_LEN)
1636  				goto err;
1637  			scan_params->ie_list.extcaps = (uint8_t *)ie;
1638  			break;
1639  		case WLAN_ELEMID_VHTCAP:
1640  			if (ie->ie_len != (sizeof(struct wlan_ie_vhtcaps) -
1641  					   sizeof(struct ie_header)))
1642  				goto err;
1643  			scan_params->ie_list.vhtcap = (uint8_t *)ie;
1644  			break;
1645  		case WLAN_ELEMID_VHTOP:
1646  			if (ie->ie_len != (sizeof(struct wlan_ie_vhtop) -
1647  					   sizeof(struct ie_header)))
1648  				goto err;
1649  			scan_params->ie_list.vhtop = (uint8_t *)ie;
1650  			break;
1651  		case WLAN_ELEMID_OP_MODE_NOTIFY:
1652  			if (ie->ie_len != WLAN_OPMODE_IE_MAX_LEN)
1653  				goto err;
1654  			scan_params->ie_list.opmode = (uint8_t *)ie;
1655  			break;
1656  		case WLAN_ELEMID_MOBILITY_DOMAIN:
1657  			if (ie->ie_len != WLAN_MOBILITY_DOMAIN_IE_MAX_LEN)
1658  				goto err;
1659  			scan_params->ie_list.mdie = (uint8_t *)ie;
1660  			break;
1661  		case WLAN_ELEMID_VENDOR:
1662  			status = util_scan_parse_vendor_ie(scan_params,
1663  							   ie);
1664  			if (QDF_IS_STATUS_ERROR(status))
1665  				goto err_status;
1666  			break;
1667  		case WLAN_ELEMID_VHT_TX_PWR_ENVLP:
1668  			if (ie->ie_len < WLAN_TPE_IE_MIN_LEN)
1669  				goto err;
1670  			if (tpe_idx >= WLAN_MAX_NUM_TPE_IE)
1671  				goto err;
1672  			scan_params->ie_list.tpe[tpe_idx++] = (uint8_t *)ie;
1673  			break;
1674  		case WLAN_ELEMID_CHAN_SWITCH_WRAP:
1675  			scan_params->ie_list.cswrp = (uint8_t *)ie;
1676  			/* Go to next sub IE */
1677  			sub_ie = (struct ie_header *)
1678  			(((uint8_t *)ie) + sizeof(struct ie_header));
1679  			sub_ie_len = ie->ie_len;
1680  			status =
1681  				util_scan_parse_chan_switch_wrapper_ie(
1682  					scan_params, sub_ie, sub_ie_len);
1683  			if (QDF_IS_STATUS_ERROR(status)) {
1684  				goto err_status;
1685  			}
1686  			break;
1687  		case WLAN_ELEMID_FILS_INDICATION:
1688  			if (ie->ie_len < WLAN_FILS_INDICATION_IE_MIN_LEN)
1689  				goto err;
1690  			scan_params->ie_list.fils_indication = (uint8_t *)ie;
1691  			break;
1692  		case WLAN_ELEMID_RSNXE:
1693  			if (!ie->ie_len)
1694  				goto err;
1695  			scan_params->ie_list.rsnxe = (uint8_t *)ie;
1696  			break;
1697  		case WLAN_ELEMID_EXTN_ELEM:
1698  			status = util_scan_parse_extn_ie(scan_params, ie);
1699  			if (QDF_IS_STATUS_ERROR(status))
1700  				goto err_status;
1701  			break;
1702  		case WLAN_ELEMID_REDUCED_NEIGHBOR_REPORT:
1703  			if (ie->ie_len < WLAN_RNR_IE_MIN_LEN)
1704  				goto err;
1705  			scan_params->ie_list.rnrie = (uint8_t *)ie;
1706  			status = util_scan_parse_rnr_ie(scan_params, ie);
1707  			if (QDF_IS_STATUS_ERROR(status))
1708  				goto err_status;
1709  			break;
1710  		default:
1711  			break;
1712  		}
1713  
1714  		/* Consume info element */
1715  		ie_len -= ie->ie_len;
1716  		/* Go to next IE */
1717  		ie = (struct ie_header *)
1718  			(((uint8_t *) ie) +
1719  			sizeof(struct ie_header) +
1720  			ie->ie_len);
1721  	}
1722  
1723  	return QDF_STATUS_SUCCESS;
1724  
1725  err:
1726  	status = QDF_STATUS_E_INVAL;
1727  err_status:
1728  	scm_debug(QDF_MAC_ADDR_FMT ": failed to parse IE - id: %d, len: %d",
1729  		  QDF_MAC_ADDR_REF(scan_params->bssid.bytes),
1730  		  ie->ie_id, ie->ie_len);
1731  
1732  	return status;
1733  }
1734  
1735  /**
1736   * util_scan_update_esp_data: update ESP params from beacon/probe response
1737   * @esp_information: pointer to wlan_esp_information
1738   * @scan_entry: new received entry
1739   *
1740   * The Estimated Service Parameters element is
1741   * used by a AP to provide information to another STA which
1742   * can then use the information as input to an algorithm to
1743   * generate an estimate of throughput between the two STAs.
1744   * The ESP Information List field contains from 1 to 4 ESP
1745   * Information fields(each field 24 bits), each corresponding
1746   * to an access category for which estimated service parameters
1747   * information is provided.
1748   *
1749   * Return: None
1750   */
util_scan_update_esp_data(struct wlan_esp_ie * esp_information,struct scan_cache_entry * scan_entry)1751  static void util_scan_update_esp_data(struct wlan_esp_ie *esp_information,
1752  		struct scan_cache_entry *scan_entry)
1753  {
1754  
1755  	uint8_t *data;
1756  	int i = 0;
1757  	uint64_t total_elements;
1758  	struct wlan_esp_info *esp_info;
1759  	struct wlan_esp_ie *esp_ie;
1760  
1761  	esp_ie = (struct wlan_esp_ie *)
1762  		util_scan_entry_esp_info(scan_entry);
1763  
1764  	// Ignore ESP_ID_EXTN element
1765  	total_elements  = esp_ie->esp_len - 1;
1766  	data = (uint8_t *)esp_ie + 3;
1767  	do_div(total_elements, ESP_INFORMATION_LIST_LENGTH);
1768  
1769  	if (total_elements > MAX_ESP_INFORMATION_FIELD) {
1770  		scm_err("No of Air time fractions are greater than supported");
1771  		return;
1772  	}
1773  
1774  	for (i = 0; i < total_elements &&
1775  	     data < ((uint8_t *)esp_ie + esp_ie->esp_len); i++) {
1776  		esp_info = (struct wlan_esp_info *)data;
1777  		if (esp_info->access_category == ESP_AC_BK) {
1778  			qdf_mem_copy(&esp_information->esp_info_AC_BK,
1779  					data, 3);
1780  			data = data + ESP_INFORMATION_LIST_LENGTH;
1781  			continue;
1782  		}
1783  		if (esp_info->access_category == ESP_AC_BE) {
1784  			qdf_mem_copy(&esp_information->esp_info_AC_BE,
1785  					data, 3);
1786  			data = data + ESP_INFORMATION_LIST_LENGTH;
1787  			continue;
1788  		}
1789  		if (esp_info->access_category == ESP_AC_VI) {
1790  			qdf_mem_copy(&esp_information->esp_info_AC_VI,
1791  					data, 3);
1792  			data = data + ESP_INFORMATION_LIST_LENGTH;
1793  			continue;
1794  		}
1795  		if (esp_info->access_category == ESP_AC_VO) {
1796  			qdf_mem_copy(&esp_information->esp_info_AC_VO,
1797  					data, 3);
1798  			data = data + ESP_INFORMATION_LIST_LENGTH;
1799  			break;
1800  		}
1801  	}
1802  }
1803  
1804  /**
1805   * util_scan_scm_update_bss_with_esp_data: calculate estimated air time
1806   * fraction
1807   * @scan_entry: new received entry
1808   *
1809   * This function process all Access category ESP params and provide
1810   * best effort air time fraction.
1811   * If best effort is not available, it will choose VI, VO and BK in sequence
1812   *
1813   */
util_scan_scm_update_bss_with_esp_data(struct scan_cache_entry * scan_entry)1814  static void util_scan_scm_update_bss_with_esp_data(
1815  		struct scan_cache_entry *scan_entry)
1816  {
1817  	uint8_t air_time_fraction = 0;
1818  	struct wlan_esp_ie esp_information;
1819  
1820  	if (!scan_entry->ie_list.esp)
1821  		return;
1822  
1823  	util_scan_update_esp_data(&esp_information, scan_entry);
1824  
1825  	/*
1826  	 * If the ESP metric is transmitting multiple airtime fractions, then
1827  	 * follow the sequence AC_BE, AC_VI, AC_VO, AC_BK and pick whichever is
1828  	 * the first one available
1829  	 */
1830  	if (esp_information.esp_info_AC_BE.access_category
1831  			== ESP_AC_BE)
1832  		air_time_fraction =
1833  			esp_information.esp_info_AC_BE.
1834  			estimated_air_fraction;
1835  	else if (esp_information.esp_info_AC_VI.access_category
1836  			== ESP_AC_VI)
1837  		air_time_fraction =
1838  			esp_information.esp_info_AC_VI.
1839  			estimated_air_fraction;
1840  	else if (esp_information.esp_info_AC_VO.access_category
1841  			== ESP_AC_VO)
1842  		air_time_fraction =
1843  			esp_information.esp_info_AC_VO.
1844  			estimated_air_fraction;
1845  	else if (esp_information.esp_info_AC_BK.access_category
1846  			== ESP_AC_BK)
1847  		air_time_fraction =
1848  			esp_information.esp_info_AC_BK.
1849  				estimated_air_fraction;
1850  	scan_entry->air_time_fraction = air_time_fraction;
1851  }
1852  
1853  /**
1854   * util_scan_scm_calc_nss_supported_by_ap() - finds out nss from AP
1855   * @scan_params: new received entry
1856   *
1857   * Return: number of nss advertised by AP
1858   */
util_scan_scm_calc_nss_supported_by_ap(struct scan_cache_entry * scan_params)1859  static int util_scan_scm_calc_nss_supported_by_ap(
1860  		struct scan_cache_entry *scan_params)
1861  {
1862  	struct htcap_cmn_ie *htcap;
1863  	struct wlan_ie_vhtcaps *vhtcaps;
1864  	uint8_t *he_cap;
1865  	uint8_t *end_ptr = NULL;
1866  	uint16_t rx_mcs_map = 0;
1867  	uint8_t *mcs_map_offset;
1868  
1869  	htcap = (struct htcap_cmn_ie *)
1870  		util_scan_entry_htcap(scan_params);
1871  	vhtcaps = (struct wlan_ie_vhtcaps *)
1872  		util_scan_entry_vhtcap(scan_params);
1873  	he_cap = util_scan_entry_hecap(scan_params);
1874  
1875  	if (he_cap) {
1876  		/* Using rx mcs map related to 80MHz or lower as in some
1877  		 * cases higher mcs may support lesser NSS than that
1878  		 * of lowe mcs. Thus giving max NSS capability.
1879  		 */
1880  		end_ptr = he_cap + he_cap[1] + sizeof(struct ie_header);
1881  		mcs_map_offset = (he_cap + sizeof(struct extn_ie_header) +
1882  				  WLAN_HE_MACCAP_LEN + WLAN_HE_PHYCAP_LEN);
1883  		if ((mcs_map_offset + WLAN_HE_MCS_MAP_LEN) <= end_ptr) {
1884  			rx_mcs_map = *(uint16_t *)mcs_map_offset;
1885  		} else {
1886  			rx_mcs_map = WLAN_INVALID_RX_MCS_MAP;
1887  			scm_debug("mcs_map_offset exceeds he cap len");
1888  		}
1889  	} else if (vhtcaps) {
1890  		rx_mcs_map = vhtcaps->rx_mcs_map;
1891  	}
1892  
1893  	if (he_cap || vhtcaps) {
1894  		if ((rx_mcs_map & 0xC000) != 0xC000)
1895  			return 8;
1896  
1897  		if ((rx_mcs_map & 0x3000) != 0x3000)
1898  			return 7;
1899  
1900  		if ((rx_mcs_map & 0x0C00) != 0x0C00)
1901  			return 6;
1902  
1903  		if ((rx_mcs_map & 0x0300) != 0x0300)
1904  			return 5;
1905  
1906  		if ((rx_mcs_map & 0x00C0) != 0x00C0)
1907  			return 4;
1908  
1909  		if ((rx_mcs_map & 0x0030) != 0x0030)
1910  			return 3;
1911  
1912  		if ((rx_mcs_map & 0x000C) != 0x000C)
1913  			return 2;
1914  	} else if (htcap) {
1915  		if (htcap->mcsset[3])
1916  			return 4;
1917  
1918  		if (htcap->mcsset[2])
1919  			return 3;
1920  
1921  		if (htcap->mcsset[1])
1922  			return 2;
1923  
1924  	}
1925  	return 1;
1926  }
1927  
1928  #ifdef WLAN_DFS_CHAN_HIDDEN_SSID
1929  QDF_STATUS
util_scan_add_hidden_ssid(struct wlan_objmgr_pdev * pdev,qdf_nbuf_t bcnbuf)1930  util_scan_add_hidden_ssid(struct wlan_objmgr_pdev *pdev, qdf_nbuf_t bcnbuf)
1931  {
1932  	struct wlan_frame_hdr *hdr;
1933  	struct wlan_bcn_frame *bcn;
1934  	struct wlan_scan_obj *scan_obj;
1935  	struct wlan_ssid *conf_ssid;
1936  	struct  ie_header *ie;
1937  	uint32_t frame_len = qdf_nbuf_len(bcnbuf);
1938  	uint16_t bcn_ie_offset, ssid_ie_start_offset, ssid_ie_end_offset;
1939  	uint16_t tmplen, ie_length;
1940  	uint8_t *pbeacon, *tmp;
1941  	bool     set_ssid_flag = false;
1942  	struct ie_ssid ssid = {0};
1943  	uint8_t pdev_id;
1944  
1945  	if (!pdev) {
1946  		scm_warn("pdev: 0x%pK is NULL", pdev);
1947  		return QDF_STATUS_E_NULL_VALUE;
1948  	}
1949  	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
1950  	scan_obj = wlan_pdev_get_scan_obj(pdev);
1951  	if (!scan_obj) {
1952  		scm_warn("null scan_obj");
1953  		return QDF_STATUS_E_NULL_VALUE;
1954  	}
1955  
1956  	conf_ssid = &scan_obj->pdev_info[pdev_id].conf_ssid;
1957  
1958  	hdr = (struct wlan_frame_hdr *)qdf_nbuf_data(bcnbuf);
1959  
1960  	/* received bssid does not match configured bssid */
1961  	if (qdf_mem_cmp(hdr->i_addr3, scan_obj->pdev_info[pdev_id].conf_bssid,
1962  			QDF_MAC_ADDR_SIZE) ||
1963  			conf_ssid->length == 0) {
1964  		return QDF_STATUS_SUCCESS;
1965  	}
1966  
1967  	bcn = (struct wlan_bcn_frame *)(qdf_nbuf_data(bcnbuf) + sizeof(*hdr));
1968  	pbeacon = (uint8_t *)bcn;
1969  
1970  	ie = (struct ie_header *)(pbeacon +
1971  				  offsetof(struct wlan_bcn_frame, ie));
1972  
1973  	bcn_ie_offset = offsetof(struct wlan_bcn_frame, ie);
1974  	ie_length = (uint16_t)(frame_len - sizeof(*hdr) -
1975  			       bcn_ie_offset);
1976  
1977  	while (ie_length >=  sizeof(struct ie_header)) {
1978  		ie_length -= sizeof(struct ie_header);
1979  
1980  		bcn_ie_offset += sizeof(struct ie_header);
1981  
1982  		if (ie_length < ie->ie_len) {
1983  			scm_debug("Incomplete corrupted IE:%x", ie->ie_id);
1984  			return QDF_STATUS_E_INVAL;
1985  		}
1986  		if (ie->ie_id == WLAN_ELEMID_SSID) {
1987  			if (ie->ie_len > (sizeof(struct ie_ssid) -
1988  						 sizeof(struct ie_header))) {
1989  				return QDF_STATUS_E_INVAL;
1990  			}
1991  			ssid.ssid_id = ie->ie_id;
1992  			ssid.ssid_len = ie->ie_len;
1993  
1994  			if (ssid.ssid_len)
1995  				qdf_mem_copy(ssid.ssid,
1996  					     ie + sizeof(struct ie_header),
1997  					     ssid.ssid_len);
1998  
1999  			if (util_scan_is_hidden_ssid(&ssid)) {
2000  				set_ssid_flag  = true;
2001  				ssid_ie_start_offset = bcn_ie_offset -
2002  					sizeof(struct ie_header);
2003  				ssid_ie_end_offset = bcn_ie_offset +
2004  					ie->ie_len;
2005  			}
2006  		}
2007  		if (ie->ie_len == 0) {
2008  			ie += 1;    /* next IE */
2009  			continue;
2010  		}
2011  		if (ie->ie_id == WLAN_ELEMID_VENDOR &&
2012  		    is_wps_oui((uint8_t *)ie)) {
2013  			set_ssid_flag = false;
2014  			break;
2015  		}
2016  		/* Consume info element */
2017  		ie_length -=  ie->ie_len;
2018  		/* Go to next IE */
2019  		ie = (struct ie_header *)(((uint8_t *)ie) +
2020  				sizeof(struct ie_header) +
2021  				ie->ie_len);
2022  	}
2023  
2024  	if (set_ssid_flag) {
2025  		/* Hidden SSID if the Length is 0 */
2026  		if (!ssid.ssid_len) {
2027  			/* increase the taillength by length of ssid */
2028  			if (qdf_nbuf_put_tail(bcnbuf,
2029  					      conf_ssid->length) == NULL) {
2030  				scm_debug("No enough tailroom");
2031  				return  QDF_STATUS_E_NOMEM;
2032  			}
2033  			/*
2034  			 * "qdf_nbuf_put_tail" might change the data pointer of
2035  			 * the skb. Therefore use the new data area.
2036  			 */
2037  			pbeacon = (qdf_nbuf_data(bcnbuf) + sizeof(*hdr));
2038  			/* length of the buffer to be copied */
2039  			tmplen = frame_len -
2040  				sizeof(*hdr) - ssid_ie_end_offset;
2041  			/*
2042  			 * tmp memory to copy the beacon info
2043  			 * after ssid ie.
2044  			 */
2045  			tmp = qdf_mem_malloc(tmplen * sizeof(u_int8_t));
2046  			if (!tmp)
2047  				return  QDF_STATUS_E_NOMEM;
2048  
2049  			/* Copy beacon data after ssid ie to tmp */
2050  			qdf_nbuf_copy_bits(bcnbuf, (sizeof(*hdr) +
2051  					   ssid_ie_end_offset), tmplen, tmp);
2052  			/* Add ssid length */
2053  			*(pbeacon + (ssid_ie_start_offset + 1))
2054  				= conf_ssid->length;
2055  			/* Insert the  SSID string */
2056  			qdf_mem_copy((pbeacon + ssid_ie_end_offset),
2057  				     conf_ssid->ssid, conf_ssid->length);
2058  			/* Copy rest of the beacon data */
2059  			qdf_mem_copy((pbeacon + ssid_ie_end_offset +
2060  				      conf_ssid->length), tmp, tmplen);
2061  			qdf_mem_free(tmp);
2062  
2063  			/* Hidden ssid with all 0's */
2064  		} else if (ssid.ssid_len == conf_ssid->length) {
2065  			/* Insert the  SSID string */
2066  			qdf_mem_copy((pbeacon + ssid_ie_start_offset +
2067  				      sizeof(struct ie_header)),
2068  				      conf_ssid->ssid, conf_ssid->length);
2069  		} else {
2070  			scm_debug("mismatch in hidden ssid length");
2071  			return QDF_STATUS_E_INVAL;
2072  		}
2073  	}
2074  	return QDF_STATUS_SUCCESS;
2075  }
2076  #endif /* WLAN_DFS_CHAN_HIDDEN_SSID */
2077  
2078  #ifdef WLAN_ADAPTIVE_11R
2079  /**
2080   * scm_fill_adaptive_11r_cap() - Check if the AP supports adaptive 11r
2081   * @scan_entry: Pointer to the scan entry
2082   *
2083   * Return: true if adaptive 11r is advertised else false
2084   */
scm_fill_adaptive_11r_cap(struct scan_cache_entry * scan_entry)2085  static void scm_fill_adaptive_11r_cap(struct scan_cache_entry *scan_entry)
2086  {
2087  	uint8_t *ie;
2088  	uint8_t data;
2089  	bool adaptive_11r;
2090  
2091  	ie = util_scan_entry_adaptive_11r(scan_entry);
2092  	if (!ie)
2093  		return;
2094  
2095  	data = *(ie + OUI_LENGTH);
2096  	adaptive_11r = (data & 0x1) ? true : false;
2097  
2098  	scan_entry->adaptive_11r_ap = adaptive_11r;
2099  }
2100  #else
scm_fill_adaptive_11r_cap(struct scan_cache_entry * scan_entry)2101  static void scm_fill_adaptive_11r_cap(struct scan_cache_entry *scan_entry)
2102  {
2103  	scan_entry->adaptive_11r_ap = false;
2104  }
2105  #endif
2106  
util_scan_set_security(struct scan_cache_entry * scan_params)2107  static void util_scan_set_security(struct scan_cache_entry *scan_params)
2108  {
2109  	if (util_scan_entry_wpa(scan_params))
2110  		scan_params->security_type |= SCAN_SECURITY_TYPE_WPA;
2111  
2112  	if (util_scan_entry_rsn(scan_params))
2113  		scan_params->security_type |= SCAN_SECURITY_TYPE_RSN;
2114  	if (util_scan_entry_wapi(scan_params))
2115  		scan_params->security_type |= SCAN_SECURITY_TYPE_WAPI;
2116  
2117  	if (!scan_params->security_type &&
2118  	    scan_params->cap_info.wlan_caps.privacy)
2119  		scan_params->security_type |= SCAN_SECURITY_TYPE_WEP;
2120  }
2121  
2122  #ifdef WLAN_FEATURE_11BE_MLO
2123  /*
2124   * Multi link IE field offsets
2125   *  ------------------------------------------------------------------------
2126   * | EID(1) | Len (1) | EID_EXT (1) | ML_CONTROL (2) | CMN_INFO (var) | ... |
2127   *  ------------------------------------------------------------------------
2128   */
2129  #define ML_CONTROL_OFFSET 3
2130  #define ML_CMN_INFO_OFFSET ML_CONTROL_OFFSET + 2
2131  
2132  #define CMN_INFO_LINK_ID_PRESENT_BIT      BIT(4)
2133  #define LINK_INFO_MAC_ADDR_PRESENT_BIT    BIT(5)
2134  
2135  /* This function is implemented as per IEEE802.11be D1.0, there is no difference
2136   * in presence bitmap for beacon, probe response and probe request frames.
2137   * This code is to be revisited for future drafts if the presence bitmap values
2138   * changes for the beacon, probe response and probe request frames.
2139   */
util_get_link_info_offset(uint8_t * ml_ie,bool * is_ml_ie_valid)2140  static uint8_t util_get_link_info_offset(uint8_t *ml_ie, bool *is_ml_ie_valid)
2141  {
2142  	qdf_size_t ml_ie_len = 0;
2143  	qdf_size_t parsed_ie_len = 0;
2144  	struct wlan_ie_multilink *mlie_fixed;
2145  	uint16_t mlcontrol;
2146  	uint16_t presencebm;
2147  	qdf_size_t actual_len;
2148  
2149  	if (!ml_ie) {
2150  		scm_err("ml_ie is null");
2151  		return 0;
2152  	}
2153  
2154  	if (!is_ml_ie_valid) {
2155  		scm_err_rl("is_ml_ie_valid is null");
2156  		return 0;
2157  	}
2158  
2159  	ml_ie_len = ml_ie[TAG_LEN_POS];
2160  	if (!ml_ie_len) {
2161  		scm_err("ml_ie_len is zero");
2162  		return 0;
2163  	}
2164  
2165  	if (ml_ie_len < sizeof(struct wlan_ie_multilink)) {
2166  		scm_err_rl("Length %zu octets is smaller than required for the fixed portion of Multi-Link element (%zu octets)",
2167  			   ml_ie_len, sizeof(struct wlan_ie_multilink));
2168  		return 0;
2169  	}
2170  
2171  	mlie_fixed = (struct wlan_ie_multilink *)ml_ie;
2172  	mlcontrol = le16toh(mlie_fixed->mlcontrol);
2173  	presencebm = QDF_GET_BITS(mlcontrol, WLAN_ML_CTRL_PBM_IDX,
2174  				  WLAN_ML_CTRL_PBM_BITS);
2175  
2176  	parsed_ie_len += sizeof(*mlie_fixed);
2177  
2178  	parsed_ie_len += WLAN_ML_BV_CINFO_LENGTH_SIZE;
2179  	parsed_ie_len += QDF_MAC_ADDR_SIZE;
2180  
2181  	/* Check if Link ID info is present */
2182  	if (presencebm & WLAN_ML_BV_CTRL_PBM_LINKIDINFO_P)
2183  		parsed_ie_len += WLAN_ML_BV_CINFO_LINKIDINFO_SIZE;
2184  
2185  	/* Check if BSS parameter change count is present */
2186  	if (presencebm & WLAN_ML_BV_CTRL_PBM_BSSPARAMCHANGECNT_P)
2187  		parsed_ie_len += WLAN_ML_BSSPARAMCHNGCNT_SIZE;
2188  
2189  	/* Check if Medium Sync Delay Info is present */
2190  	if (presencebm & WLAN_ML_BV_CTRL_PBM_MEDIUMSYNCDELAYINFO_P)
2191  		parsed_ie_len += WLAN_ML_BV_CINFO_MEDMSYNCDELAYINFO_SIZE;
2192  
2193  	/* Check if EML cap is present */
2194  	if (presencebm & WLAN_ML_BV_CTRL_PBM_EMLCAP_P)
2195  		parsed_ie_len += WLAN_ML_BV_CINFO_EMLCAP_SIZE;
2196  
2197  	/* Check if MLD cap and op is present */
2198  	if (presencebm & WLAN_ML_BV_CTRL_PBM_MLDCAPANDOP_P)
2199  		parsed_ie_len += WLAN_ML_BV_CINFO_MLDCAPANDOP_SIZE;
2200  
2201  	/* Check if MLD ID is present */
2202  	if (presencebm & WLAN_ML_BV_CTRL_PBM_MLDID_P)
2203  		parsed_ie_len += WLAN_ML_BV_CINFO_MLDID_SIZE;
2204  
2205  	/* Check if Extended MLD Cap and Op is present */
2206  	if (presencebm & WLAN_ML_BV_CTRL_PBM_EXT_MLDCAPANDOP_P)
2207  		parsed_ie_len += WLAN_ML_BV_CINFO_EXT_MLDCAPANDOP_SIZE;
2208  
2209  	/* Offset calculation starts from the beginning of the ML IE (including
2210  	 * EID) hence, adding the size of IE header to ML IE length.
2211  	 */
2212  	actual_len = ml_ie_len + sizeof(struct ie_header);
2213  	if (parsed_ie_len <= actual_len) {
2214  		*is_ml_ie_valid = true;
2215  	} else {
2216  		*is_ml_ie_valid = false;
2217  		scm_err("Invalid ML IE, expect min len: %zu, actual len: %zu",
2218  			parsed_ie_len, actual_len);
2219  	}
2220  	if (parsed_ie_len < actual_len)
2221  		return parsed_ie_len;
2222  
2223  	return 0;
2224  }
2225  
2226  static void
util_get_ml_bv_partner_link_info(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_entry)2227  util_get_ml_bv_partner_link_info(struct wlan_objmgr_pdev *pdev,
2228  				 struct scan_cache_entry *scan_entry)
2229  {
2230  	uint8_t *ml_ie = scan_entry->ie_list.multi_link_bv;
2231  	uint8_t *end_ptr = NULL;
2232  	bool is_ml_ie_valid;
2233  	uint8_t offset = util_get_link_info_offset(ml_ie, &is_ml_ie_valid);
2234  	uint16_t sta_ctrl;
2235  	uint8_t *stactrl_offset = NULL, *ielist_offset;
2236  	uint8_t perstaprof_len = 0, perstaprof_stainfo_len = 0, ielist_len = 0;
2237  	struct partner_link_info *link_info = NULL;
2238  	uint8_t eid = 0;
2239  	uint8_t link_idx = 0;
2240  	uint8_t rnr_idx = 0;
2241  	struct rnr_bss_info *rnr = NULL;
2242  	qdf_size_t ml_ie_len = ml_ie[TAG_LEN_POS] + sizeof(struct ie_header);
2243  
2244  	/* Update partner info  from RNR IE */
2245  	while ((rnr_idx < MAX_RNR_BSS) && (rnr_idx < scan_entry->rnr.count)) {
2246  		if (link_idx >= (MLD_MAX_LINKS - 1))
2247  			break;
2248  		rnr = &scan_entry->rnr.bss_info[rnr_idx];
2249  		if (rnr->mld_info_valid && !rnr->mld_info.mld_id) {
2250  			link_info = &scan_entry->ml_info.link_info[link_idx];
2251  			qdf_mem_copy(&link_info->link_addr,
2252  				     &rnr->bssid, QDF_MAC_ADDR_SIZE);
2253  
2254  			link_info->link_id = rnr->mld_info.link_id;
2255  			link_info->freq =
2256  				wlan_reg_chan_opclass_to_freq(rnr->channel_number,
2257  							      rnr->operating_class,
2258  							      true);
2259  
2260  			if (!link_info->freq)
2261  				scm_debug_rl("freq 0 rnr channel %u op_class %u " QDF_MAC_ADDR_FMT,
2262  					     rnr->channel_number,
2263  					     rnr->operating_class,
2264  					     QDF_MAC_ADDR_REF(rnr->bssid.bytes));
2265  			link_info->op_class = rnr->operating_class;
2266  			link_idx++;
2267  		}
2268  		rnr_idx++;
2269  	}
2270  
2271  	scan_entry->ml_info.num_links = link_idx;
2272  	if (!offset ||
2273  	    (offset + sizeof(struct wlan_ml_bv_linfo_perstaprof) >= ml_ie_len)) {
2274  		scm_debug_rl("incorrect offset value %d", offset);
2275  		return;
2276  	}
2277  
2278  	/* TODO: loop through all the STA info fields */
2279  
2280  	/*
2281  	 * Per-STA Profile subelement format of the Basic Multi-Link element
2282  	 *
2283  	 * |---------------|--------|-------------|----------|-------------|
2284  	 * | Subelement ID | Length | STA control | STA info | STA profile |
2285  	 * |---------------|--------|-------------|----------|-------------|
2286  	 * Octets:  1         1           2         variable     variable
2287  	 */
2288  
2289  	/* Sub element ID 0 represents Per-STA Profile */
2290  	if (ml_ie[offset] == 0) {
2291  		perstaprof_len = ml_ie[offset + 1];
2292  		stactrl_offset = &ml_ie[offset + 2];
2293  		end_ptr = &ml_ie[offset] + perstaprof_len + 2;
2294  
2295  		if (!(end_ptr <= (ml_ie + ml_ie_len))) {
2296  			if (ml_ie[TAG_LEN_POS] >= 255)
2297  				scm_debug_rl("Possible fragmentation in ml_ie for tag_len %d. Ignore the processing",
2298  					     ml_ie[TAG_LEN_POS]);
2299  			else
2300  				scm_debug_rl("perstaprof exceeds ML IE boundary for tag_len %d. Ignore the processing",
2301  					     ml_ie[TAG_LEN_POS]);
2302  			return;
2303  		}
2304  
2305  		/* Skip sub element ID and length fields */
2306  		offset += 2;
2307  
2308  		sta_ctrl = *(uint16_t *)(ml_ie + offset);
2309  
2310  		/* Skip STA control field */
2311  		offset += 2;
2312  
2313  		/*
2314  		 * offset points to the beginning of the STA Info field which
2315  		 * indicates the number of octets in the STA Info field,
2316  		 * including one octet for the STA Info Length subfield.
2317  		 */
2318  		perstaprof_stainfo_len = ml_ie[offset];
2319  
2320  		/* Skip STA Info Length field */
2321  		offset += perstaprof_stainfo_len;
2322  		if (offset >= ml_ie_len) {
2323  			scm_err_rl("incorrect offset value %d", offset);
2324  			return;
2325  		}
2326  
2327  		/*
2328  		 * To point to the ie_list offset move past the STA Info
2329  		 * field.
2330  		 */
2331  		ielist_offset = &ml_ie[offset];
2332  
2333  		/*
2334  		 * Ensure that the STA Control Field + STA Info Field
2335  		 * is smaller than the per-STA profile when incrementing
2336  		 * the pointer to avoid underflow during subtraction.
2337  		 */
2338  		if ((perstaprof_stainfo_len +
2339  		     WLAN_ML_BV_LINFO_PERSTAPROF_STACTRL_SIZE) <
2340  							perstaprof_len) {
2341  			if (!(ielist_offset <= end_ptr))
2342  				ielist_len = 0;
2343  			else
2344  				ielist_len = perstaprof_len -
2345  					(WLAN_ML_BV_LINFO_PERSTAPROF_STACTRL_SIZE +
2346  					 perstaprof_stainfo_len);
2347  		} else {
2348  			scm_debug_rl("No STA profile IE list found for perstaprof_stainfo_len %d perstaprof_len %d",
2349  				     perstaprof_stainfo_len, perstaprof_len);
2350  			ielist_len = 0;
2351  		}
2352  
2353  		link_info = NULL;
2354  		for (link_idx = 0; link_idx < scan_entry->ml_info.num_links;
2355  		     link_idx++) {
2356  			if (scan_entry->ml_info.link_info[link_idx].link_id ==
2357  							(sta_ctrl & 0xF)) {
2358  				link_info = &scan_entry->ml_info.link_info[link_idx];
2359  			}
2360                  }
2361  
2362  		/* Get the pointers to CSA, ECSA, Max Channel Switch Time IE. */
2363  		if (link_info) {
2364  			link_info->csa_ie = wlan_get_ie_ptr_from_eid
2365  				(WLAN_ELEMID_CHANSWITCHANN, ielist_offset,
2366  				 ielist_len);
2367  
2368  			link_info->ecsa_ie = wlan_get_ie_ptr_from_eid
2369  				(WLAN_ELEMID_EXTCHANSWITCHANN, ielist_offset,
2370  				 ielist_len);
2371  
2372  			eid = WLAN_EXTN_ELEMID_MAX_CHAN_SWITCH_TIME;
2373  			link_info->max_cst_ie = wlan_get_ext_ie_ptr_from_ext_id
2374  					(&eid, 1, ielist_offset, ielist_len);
2375  		}
2376  	}
2377  }
2378  
util_scan_update_ml_info(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_entry)2379  static void util_scan_update_ml_info(struct wlan_objmgr_pdev *pdev,
2380  				     struct scan_cache_entry *scan_entry)
2381  {
2382  	uint8_t *ml_ie = scan_entry->ie_list.multi_link_bv;
2383  	uint16_t multi_link_ctrl;
2384  	uint8_t offset;
2385  	uint8_t mlie_min_len;
2386  	bool is_ml_ie_valid = true;
2387  	uint8_t *end_ptr = NULL;
2388  
2389  	if (!scan_entry->ie_list.ehtcap && scan_entry->ie_list.multi_link_bv) {
2390  		scan_entry->ie_list.multi_link_bv = NULL;
2391  		return;
2392  	}
2393  	if (!scan_entry->ie_list.multi_link_bv)
2394  		return;
2395  
2396  	mlie_min_len = util_get_link_info_offset(ml_ie, &is_ml_ie_valid);
2397  	if (!is_ml_ie_valid) {
2398  		scan_entry->ie_list.multi_link_bv = NULL;
2399  		return;
2400  	}
2401  
2402  	end_ptr = ml_ie + ml_ie[TAG_LEN_POS] + sizeof(struct ie_header);
2403  
2404  	multi_link_ctrl = *(uint16_t *)(ml_ie + ML_CONTROL_OFFSET);
2405  
2406  	/* TODO: update ml_info based on ML IE */
2407  
2408  	offset = ML_CMN_INFO_OFFSET;
2409  
2410  	/* Increment the offset to account for the Common Info Length */
2411  	offset += WLAN_ML_BV_CINFO_LENGTH_SIZE;
2412  
2413  	if ((ml_ie + offset + QDF_MAC_ADDR_SIZE) <= end_ptr) {
2414  		qdf_mem_copy(&scan_entry->ml_info.mld_mac_addr,
2415  			     ml_ie + offset, QDF_MAC_ADDR_SIZE);
2416  		offset += QDF_MAC_ADDR_SIZE;
2417  	}
2418  
2419  	/* TODO: Decode it from ML IE */
2420  	scan_entry->ml_info.num_links = 0;
2421  
2422  	/**
2423  	 * Copy Link ID & MAC address of the scan cache entry as first entry
2424  	 * in the partner info list
2425  	 */
2426  	if (multi_link_ctrl & CMN_INFO_LINK_ID_PRESENT_BIT) {
2427  		if (&ml_ie[offset] < end_ptr)
2428  			scan_entry->ml_info.self_link_id = ml_ie[offset] & 0x0F;
2429  	}
2430  
2431  	util_get_ml_bv_partner_link_info(pdev, scan_entry);
2432  }
2433  #else
util_scan_update_ml_info(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_entry)2434  static void util_scan_update_ml_info(struct wlan_objmgr_pdev *pdev,
2435  				     struct scan_cache_entry *scan_entry)
2436  {
2437  }
2438  #endif
2439  
2440  static QDF_STATUS
util_scan_gen_scan_entry(struct wlan_objmgr_pdev * pdev,uint8_t * frame,qdf_size_t frame_len,uint32_t frm_subtype,struct mgmt_rx_event_params * rx_param,struct scan_mbssid_info * mbssid_info,qdf_list_t * scan_list)2441  util_scan_gen_scan_entry(struct wlan_objmgr_pdev *pdev,
2442  			 uint8_t *frame, qdf_size_t frame_len,
2443  			 uint32_t frm_subtype,
2444  			 struct mgmt_rx_event_params *rx_param,
2445  			 struct scan_mbssid_info *mbssid_info,
2446  			 qdf_list_t *scan_list)
2447  {
2448  	struct wlan_frame_hdr *hdr;
2449  	struct wlan_bcn_frame *bcn;
2450  	QDF_STATUS status = QDF_STATUS_SUCCESS;
2451  	struct ie_ssid *ssid;
2452  	struct scan_cache_entry *scan_entry;
2453  	struct qbss_load_ie *qbss_load;
2454  	struct scan_cache_node *scan_node;
2455  	uint8_t i;
2456  	qdf_freq_t chan_freq = 0;
2457  	bool is_6g_dup_bcon = false;
2458  	uint8_t band_mask;
2459  	qdf_freq_t recv_freq = 0;
2460  
2461  	scan_entry = qdf_mem_malloc_atomic(sizeof(*scan_entry));
2462  	if (!scan_entry) {
2463  		scm_err("failed to allocate memory for scan_entry");
2464  		return QDF_STATUS_E_NOMEM;
2465  	}
2466  
2467  	scan_entry->raw_frame.ptr =
2468  			qdf_mem_malloc_atomic(frame_len);
2469  	if (!scan_entry->raw_frame.ptr) {
2470  		scm_err("failed to allocate memory for frame");
2471  		qdf_mem_free(scan_entry);
2472  		return QDF_STATUS_E_NOMEM;
2473  	}
2474  
2475  	bcn = (struct wlan_bcn_frame *)
2476  			   (frame + sizeof(*hdr));
2477  	hdr = (struct wlan_frame_hdr *)frame;
2478  
2479  	/* update timestamp in nanoseconds needed by kernel layers */
2480  	scan_entry->boottime_ns = qdf_get_bootbased_boottime_ns();
2481  
2482  	scan_entry->frm_subtype = frm_subtype;
2483  	qdf_mem_copy(scan_entry->bssid.bytes,
2484  		hdr->i_addr3, QDF_MAC_ADDR_SIZE);
2485  	/* Scr addr */
2486  	qdf_mem_copy(scan_entry->mac_addr.bytes,
2487  		hdr->i_addr2, QDF_MAC_ADDR_SIZE);
2488  	scan_entry->seq_num =
2489  		(le16toh(*(uint16_t *)hdr->i_seq) >> WLAN_SEQ_SEQ_SHIFT);
2490  
2491  	scan_entry->snr = rx_param->snr;
2492  	scan_entry->avg_snr = WLAN_SNR_IN(scan_entry->snr);
2493  	scan_entry->rssi_raw = rx_param->rssi;
2494  	scan_entry->avg_rssi = WLAN_RSSI_IN(scan_entry->rssi_raw);
2495  	scan_entry->tsf_delta = rx_param->tsf_delta;
2496  	scan_entry->pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
2497  
2498  	recv_freq = rx_param->chan_freq;
2499  	/* Copy per chain rssi to scan entry */
2500  	qdf_mem_copy(scan_entry->per_chain_rssi, rx_param->rssi_ctl,
2501  		     WLAN_MGMT_TXRX_HOST_MAX_ANTENNA);
2502  	band_mask = BIT(wlan_reg_freq_to_band(recv_freq));
2503  
2504  	if (!wlan_psoc_nif_fw_ext_cap_get(wlan_pdev_get_psoc(pdev),
2505  					  WLAN_SOC_CEXT_HW_DB2DBM)) {
2506  		for (i = 0; i < WLAN_MGMT_TXRX_HOST_MAX_ANTENNA; i++) {
2507  			if (scan_entry->per_chain_rssi[i] !=
2508  			    WLAN_INVALID_PER_CHAIN_SNR)
2509  				scan_entry->per_chain_rssi[i] +=
2510  						WLAN_NOISE_FLOOR_DBM_DEFAULT;
2511  			else
2512  				scan_entry->per_chain_rssi[i] =
2513  						WLAN_INVALID_PER_CHAIN_RSSI;
2514  		}
2515  	}
2516  
2517  	/* store jiffies */
2518  	scan_entry->rrm_parent_tsf = (uint32_t)qdf_system_ticks();
2519  
2520  	scan_entry->bcn_int = le16toh(bcn->beacon_interval);
2521  
2522  	/*
2523  	 * In case if the beacon doesn't have
2524  	 * valid beacon interval falback to def
2525  	 */
2526  	if (!scan_entry->bcn_int)
2527  		scan_entry->bcn_int = 100;
2528  	scan_entry->cap_info.value = le16toh(bcn->capability.value);
2529  	qdf_mem_copy(scan_entry->tsf_info.data,
2530  		bcn->timestamp, 8);
2531  	scan_entry->erp = ERP_NON_ERP_PRESENT;
2532  
2533  	scan_entry->scan_entry_time =
2534  		qdf_mc_timer_get_system_time();
2535  
2536  	scan_entry->raw_frame.len = frame_len;
2537  	qdf_mem_copy(scan_entry->raw_frame.ptr,
2538  		frame, frame_len);
2539  	status = util_scan_populate_bcn_ie_list(pdev, scan_entry, &chan_freq,
2540  						band_mask);
2541  	if (QDF_IS_STATUS_ERROR(status)) {
2542  		qdf_mem_free(scan_entry->raw_frame.ptr);
2543  		qdf_mem_free(scan_entry);
2544  		return QDF_STATUS_E_FAILURE;
2545  	}
2546  
2547  	ssid = (struct ie_ssid *)
2548  		scan_entry->ie_list.ssid;
2549  
2550  	if (ssid && (ssid->ssid_len > WLAN_SSID_MAX_LEN)) {
2551  		qdf_mem_free(scan_entry->raw_frame.ptr);
2552  		qdf_mem_free(scan_entry);
2553  		return QDF_STATUS_E_FAILURE;
2554  	}
2555  
2556  	if (scan_entry->ie_list.p2p)
2557  		scan_entry->is_p2p = true;
2558  
2559  	if (!chan_freq && util_scan_entry_hecap(scan_entry)) {
2560  		status = util_scan_get_chan_from_he_6g_params(pdev, scan_entry,
2561  							      &chan_freq,
2562  							      &is_6g_dup_bcon,
2563  							      band_mask,
2564  							      recv_freq);
2565  		if (QDF_IS_STATUS_ERROR(status)) {
2566  			qdf_mem_free(scan_entry->raw_frame.ptr);
2567  			qdf_mem_free(scan_entry);
2568  			return QDF_STATUS_E_FAILURE;
2569  		}
2570  	}
2571  
2572  	if (chan_freq)
2573  		scan_entry->channel.chan_freq = chan_freq;
2574  
2575  	/* If no channel info is present in beacon use meta channel */
2576  	if (!scan_entry->channel.chan_freq) {
2577  		scan_entry->channel.chan_freq = recv_freq;
2578  	} else if (recv_freq !=
2579  	   scan_entry->channel.chan_freq) {
2580  		if (!wlan_reg_is_49ghz_freq(scan_entry->channel.chan_freq) &&
2581  		    !is_6g_dup_bcon)
2582  			scan_entry->channel_mismatch = true;
2583  	}
2584  
2585  	if (util_scan_is_hidden_ssid(ssid)) {
2586  		scan_entry->ie_list.ssid = NULL;
2587  		scan_entry->is_hidden_ssid = true;
2588  	} else {
2589  		qdf_mem_copy(scan_entry->ssid.ssid,
2590  				ssid->ssid, ssid->ssid_len);
2591  		scan_entry->ssid.length = ssid->ssid_len;
2592  		scan_entry->hidden_ssid_timestamp =
2593  			scan_entry->scan_entry_time;
2594  	}
2595  	qdf_mem_copy(&scan_entry->mbssid_info, mbssid_info,
2596  		     sizeof(scan_entry->mbssid_info));
2597  
2598  	scan_entry->phy_mode = util_scan_get_phymode(pdev, scan_entry);
2599  
2600  	scan_entry->nss = util_scan_scm_calc_nss_supported_by_ap(scan_entry);
2601  	scm_fill_adaptive_11r_cap(scan_entry);
2602  	util_scan_set_security(scan_entry);
2603  
2604  	util_scan_scm_update_bss_with_esp_data(scan_entry);
2605  	qbss_load = (struct qbss_load_ie *)
2606  			util_scan_entry_qbssload(scan_entry);
2607  	if (qbss_load)
2608  		scan_entry->qbss_chan_load = qbss_load->qbss_chan_load;
2609  
2610  	scan_node = qdf_mem_malloc_atomic(sizeof(*scan_node));
2611  	if (!scan_node) {
2612  		qdf_mem_free(scan_entry->raw_frame.ptr);
2613  		qdf_mem_free(scan_entry);
2614  		scm_err("failed to allocate memory for scan_node");
2615  		return QDF_STATUS_E_FAILURE;
2616  	}
2617  
2618  	util_scan_update_ml_info(pdev, scan_entry);
2619  
2620  	scan_node->entry = scan_entry;
2621  	qdf_list_insert_front(scan_list, &scan_node->node);
2622  
2623  	return status;
2624  }
2625  
2626  #ifdef WLAN_FEATURE_MBSSID
2627  /*
2628   * util_is_noninh_ie() - find the noninhertance information element
2629   * in the received frame's IE list, so that we can stop inheriting that IE
2630   * in the caller function.
2631   *
2632   * @elem_id: Element ID in the received frame's IE, which is being processed.
2633   * @non_inh_list: pointer to the non inherited list of element IDs or
2634   *                list of extension element IDs.
2635   * @len: Length of non inheritance IE list
2636   *
2637   * Return: False if the element ID is not found or else return true
2638   */
util_is_noninh_ie(uint8_t elem_id,uint8_t * non_inh_list,int8_t len)2639  static bool util_is_noninh_ie(uint8_t elem_id,
2640  			      uint8_t *non_inh_list,
2641  			      int8_t len)
2642  {
2643  	int count;
2644  
2645  	for (count = 0; count < len; count++) {
2646  		if (elem_id == non_inh_list[count])
2647  			return true;
2648  	}
2649  
2650  	return false;
2651  }
2652  
2653  /*
2654   * util_scan_find_noninheritance_ie() - find noninheritance information element
2655   * This block of code is to identify if there is any non-inheritance element
2656   * present as part of the nontransmitted BSSID profile.
2657   * @elem_id: element id
2658   * @ies: pointer consisting of IEs
2659   * @len: IE length
2660   *
2661   * Return: NULL if the element ID is not found or if IE pointer is NULL else
2662   * pointer to the first byte of the requested element
2663   */
2664  static uint8_t
util_scan_find_noninheritance_ie(uint8_t elem_id,uint8_t * ies,int32_t len)2665  *util_scan_find_noninheritance_ie(uint8_t elem_id, uint8_t *ies,
2666  				  int32_t len)
2667  {
2668  	if (!ies)
2669  		return NULL;
2670  
2671  	while ((len >= MIN_IE_LEN + 1) && len >= ies[TAG_LEN_POS] + MIN_IE_LEN)
2672  	{
2673  		if ((ies[ID_POS] == elem_id) &&
2674  		    (ies[ELEM_ID_EXTN_POS] ==
2675  		     WLAN_EXTN_ELEMID_NONINHERITANCE)) {
2676  			return ies;
2677  		}
2678  		len -= ies[TAG_LEN_POS] + MIN_IE_LEN;
2679  		ies += ies[TAG_LEN_POS] + MIN_IE_LEN;
2680  	}
2681  
2682  	return NULL;
2683  }
2684  #endif
2685  
2686  /*
2687   * util_scan_find_ie() - find information element
2688   * @eid: element id
2689   * @ies: pointer consisting of IEs
2690   * @len: IE length
2691   *
2692   * Return: NULL if the element ID is not found or if IE pointer is NULL else
2693   * pointer to the first byte of the requested element
2694   */
util_scan_find_ie(uint8_t eid,uint8_t * ies,int32_t len)2695  static uint8_t *util_scan_find_ie(uint8_t eid, uint8_t *ies,
2696  				  int32_t len)
2697  {
2698  	if (!ies)
2699  		return NULL;
2700  
2701  	while (len >= 2 && len >= ies[1] + 2) {
2702  		if (ies[0] == eid)
2703  			return ies;
2704  		len -= ies[1] + 2;
2705  		ies += ies[1] + 2;
2706  	}
2707  
2708  	return NULL;
2709  }
2710  
2711  #ifdef WLAN_FEATURE_MBSSID
util_gen_new_bssid(uint8_t * bssid,uint8_t max_bssid,uint8_t mbssid_index,uint8_t * new_bssid_addr)2712  static void util_gen_new_bssid(uint8_t *bssid, uint8_t max_bssid,
2713  			       uint8_t mbssid_index,
2714  			       uint8_t *new_bssid_addr)
2715  {
2716  	uint8_t lsb_n;
2717  	int i;
2718  
2719  	for (i = 0; i < QDF_MAC_ADDR_SIZE; i++)
2720  		new_bssid_addr[i] = bssid[i];
2721  
2722  	lsb_n = new_bssid_addr[5] & ((1 << max_bssid) - 1);
2723  
2724  	new_bssid_addr[5] &= ~((1 << max_bssid) - 1);
2725  	new_bssid_addr[5] |= (lsb_n + mbssid_index) % (1 << max_bssid);
2726  }
2727  
2728  /*
2729   * util_parse_noninheritance_list() - This block of code will be executed only
2730   * if there is a valid non inheritance IE present in the nontx profile.
2731   * Host need not inherit those list of element IDs and list of element ID
2732   * extensions from the transmitted BSSID profile.
2733   * Since non-inheritance element is an element ID extension, it should
2734   * be part of extension element. So first we need to find if there are
2735   * any extension element present in the nontransmitted BSSID profile.
2736   * @extn_elem: If valid, it points to the element ID field of
2737   * extension element tag in the nontransmitted BSSID profile.
2738   * It may or may not have non inheritance tag present.
2739   *      _____________________________________________
2740   *     |         |       |       |List of|List of    |
2741   *     | Element |Length |Element|Element|Element ID |
2742   *     |  ID     |       |ID extn| IDs   |Extension  |
2743   *     |_________|_______|_______|_______|___________|
2744   * List of Element IDs:
2745   *      __________________
2746   *     |         |        |
2747   *     |  Length |Element |
2748   *     |         |ID List |
2749   *     |_________|________|
2750   * List of Element ID Extensions:
2751   *      __________________________
2752   *     |         |                |
2753   *     |  Length |Element ID      |
2754   *     |         |extension List  |
2755   *     |_________|________________|
2756   * @elem_list: Element ID list
2757   * @extn_elem_list: Element ID exiension list
2758   * @non_inheritance_ie: Non inheritance IE information
2759   */
2760  
util_parse_noninheritance_list(uint8_t * extn_elem,uint8_t ** elem_list,uint8_t ** extn_elem_list,struct non_inheritance_ie * ninh)2761  static void util_parse_noninheritance_list(uint8_t *extn_elem,
2762  					   uint8_t **elem_list,
2763  					   uint8_t **extn_elem_list,
2764  					   struct non_inheritance_ie *ninh)
2765  {
2766  	int8_t extn_rem_len = 0;
2767  
2768  	if (extn_elem[ELEM_ID_LIST_LEN_POS] < extn_elem[TAG_LEN_POS]) {
2769  		/*
2770  		 * extn_rem_len represents the number of bytes after
2771  		 * the length subfield of list of Element IDs.
2772  		 * So here, extn_rem_len should be equal to
2773  		 * Element ID list + Length subfield of Element ID
2774  		 * extension list + Element ID extension list.
2775  		 *
2776  		 * Here we have taken two pointers pointing to the
2777  		 * element ID list and element ID extension list
2778  		 * which we will use to detect the same elements
2779  		 * in the transmitted BSSID profile and choose not
2780  		 * to inherit those elements while constructing the
2781  		 * frame for nontransmitted BSSID profile.
2782  		 */
2783  		extn_rem_len = extn_elem[TAG_LEN_POS] - MIN_IE_LEN;
2784  		ninh->non_inherit = true;
2785  
2786  		if (extn_rem_len && extn_elem[ELEM_ID_LIST_LEN_POS]) {
2787  			if (extn_rem_len >= extn_elem[ELEM_ID_LIST_LEN_POS]) {
2788  				ninh->list_len =
2789  					extn_elem[ELEM_ID_LIST_LEN_POS];
2790  				*elem_list = extn_elem + ELEM_ID_LIST_POS;
2791  				extn_rem_len -= ninh->list_len;
2792  			} else {
2793  				/*
2794  				 * Corrupt frame. length subfield of
2795  				 * element ID list is greater than
2796  				 * what it should be. Go ahead with
2797  				 * frame generation but do not honour
2798  				 * the non inheritance part. Also, mark
2799  				 * the element ID in subcopy as 0, so
2800  				 * that this element info will not
2801  				 * be copied.
2802  				 */
2803  				ninh->non_inherit = false;
2804  				extn_elem[0] = 0;
2805  			}
2806  		}
2807  
2808  		extn_rem_len--;
2809  		if (extn_rem_len > 0) {
2810  			if (!ninh->list_len) {
2811  				ninh->extn_len =
2812  					extn_elem[ELEM_ID_LIST_LEN_POS + 1];
2813  			} else {
2814  				ninh->extn_len =
2815  					extn_elem[ELEM_ID_LIST_POS +
2816  					ninh->list_len];
2817  			}
2818  
2819  			if (extn_rem_len != ninh->extn_len) {
2820  				/*
2821  				 * Corrupt frame. length subfield of
2822  				 * element ID extn list is not
2823  				 * what it should be. Go ahead with
2824  				 * frame generation but do not honour
2825  				 * the non inheritance part. Also, mark
2826  				 * the element ID in subcopy as 0, so
2827  				 * that this element info will not
2828  				 * be copied.
2829  				 */
2830  				ninh->non_inherit = false;
2831  				extn_elem[0] = 0;
2832  			}
2833  
2834  			if (ninh->extn_len) {
2835  				*extn_elem_list =
2836  					(extn_elem + ninh->list_len +
2837  					 ELEM_ID_LIST_POS + 1);
2838  			}
2839  		}
2840  	}
2841  }
2842  
2843  #ifdef WLAN_FEATURE_11BE_MLO
2844  /**
2845   * util_handle_rnr_ie_for_mbssid() - parse and modify RNR IE for MBSSID feature
2846   * @rnr: The pointer to RNR IE
2847   * @bssid_index: BSSID index from MBSSID index IE
2848   * @pos: The buffer pointer to save the transformed RNR IE, caller is expected
2849   *       to supply a buffer that is at least as big as @rnr
2850   *
2851   * Per the description about Neighbor AP Information field about MLD
2852   * parameters subfield in section 9.4.2.170.2 of Draft P802.11be_D1.4.
2853   * If the reported AP is affiliated with the same MLD of the reporting AP,
2854   * the TBTT information is skipped; If the reported AP is affiliated with
2855   * the same MLD of the nontransmitted BSSID, the TBTT information is
2856   * copied and the MLD ID is changed to 0.
2857   *
2858   * Return: Length of the element written to @pos
2859   */
util_handle_rnr_ie_for_mbssid(const uint8_t * rnr,uint8_t bssid_index,uint8_t * pos)2860  static int util_handle_rnr_ie_for_mbssid(const uint8_t *rnr,
2861  					 uint8_t bssid_index, uint8_t *pos)
2862  {
2863  	size_t rnr_len;
2864  	const uint8_t *data, *rnr_end;
2865  	uint8_t *rnr_new;
2866  	struct neighbor_ap_info_field *neighbor_ap_info;
2867  	struct rnr_mld_info *mld_param;
2868  	uint8_t tbtt_type, tbtt_len, tbtt_count;
2869  	uint8_t mld_pos, mld_id;
2870  	int32_t i, copy_len;
2871  	/* The count of TBTT info field whose MLD ID equals to 0 in a neighbor
2872  	 * AP information field.
2873  	 */
2874  	uint32_t tbtt_info_field_count;
2875  	/* The total bytes of TBTT info fields whose MLD ID equals to 0 in
2876  	 * current RNR IE.
2877  	 */
2878  	uint32_t tbtt_info_field_len = 0;
2879  	uint8_t nbr_ap_info_len = sizeof(struct neighbor_ap_info_field);
2880  
2881  	rnr_len = rnr[TAG_LEN_POS];
2882  	rnr_end = rnr + rnr_len + MIN_IE_LEN;
2883  	rnr_new = pos;
2884  	qdf_mem_copy(pos, rnr, MIN_IE_LEN);
2885  	pos += MIN_IE_LEN;
2886  
2887  	data = rnr + PAYLOAD_START_POS;
2888  	while (data + sizeof(struct neighbor_ap_info_field) <= rnr_end) {
2889  		neighbor_ap_info = (struct neighbor_ap_info_field *)data;
2890  		tbtt_count = neighbor_ap_info->tbtt_header.tbtt_info_count;
2891  		tbtt_len = neighbor_ap_info->tbtt_header.tbtt_info_length;
2892  		tbtt_type = neighbor_ap_info->tbtt_header.tbbt_info_fieldtype;
2893  		scm_debug("channel number %d, op class %d, bssid_index %d",
2894  			  neighbor_ap_info->channel_number,
2895  			  neighbor_ap_info->operting_class, bssid_index);
2896  		scm_debug("tbtt_count %d, tbtt_length %d, tbtt_type %d",
2897  			  tbtt_count, tbtt_len, tbtt_type);
2898  
2899  		copy_len = tbtt_len * (tbtt_count + 1) +
2900  			   nbr_ap_info_len;
2901  		if (data + copy_len > rnr_end)
2902  			return 0;
2903  
2904  		if (tbtt_len >=
2905  		    TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM_20MHZ_PSD_MLD_PARAM)
2906  			mld_pos =
2907  			     TBTT_NEIGHBOR_AP_BSSID_S_SSID_BSS_PARAM_20MHZ_PSD;
2908  		else
2909  			mld_pos = 0;
2910  
2911  		/* If MLD params do not exist, copy this neighbor AP
2912  		 * information field.
2913  		 * Per Draft P802.11be_D1.4, tbtt_type value 1, 2 and 3
2914  		 * are reserved,
2915  		 */
2916  		if (mld_pos == 0 || tbtt_type != 0) {
2917  			scm_debug("no MLD params, tbtt_type %d", tbtt_type);
2918  			qdf_mem_copy(pos, data, copy_len);
2919  			pos += copy_len;
2920  			data += copy_len;
2921  			continue;
2922  		}
2923  
2924  		qdf_mem_copy(pos, data, nbr_ap_info_len);
2925  		neighbor_ap_info = (struct neighbor_ap_info_field *)pos;
2926  		pos += nbr_ap_info_len;
2927  		data += nbr_ap_info_len;
2928  
2929  		tbtt_info_field_count = 0;
2930  		for (i = 0; i < tbtt_count + 1; i++) {
2931  			mld_param = (struct rnr_mld_info *)&data[mld_pos];
2932  			mld_id = mld_param->mld_id;
2933  
2934  			/* Refer to Draft P802.11be_D1.4
2935  			 * 9.4.2.170.2 Neighbor AP Information field about
2936  			 * MLD parameters subfield
2937  			 */
2938  			if (mld_id == 0) {
2939  				/* Skip this TBTT information since this
2940  				 * reported AP is affiliated with the same MLD
2941  				 * of the reporting AP who sending the frame
2942  				 * carrying this element.
2943  				 */
2944  				tbtt_info_field_len += tbtt_len;
2945  				data += tbtt_len;
2946  				tbtt_info_field_count++;
2947  			} else if (mld_id == bssid_index) {
2948  				/* Copy this TBTT information and change MLD
2949  				 * to 0 as this reported AP is affiliated with
2950  				 * the same MLD of the nontransmitted BSSID.
2951  				 */
2952  				qdf_mem_copy(pos, data, tbtt_len);
2953  				mld_param =
2954  					(struct rnr_mld_info *)&pos[mld_pos];
2955  				scm_debug("change MLD ID from %d to 0",
2956  					  mld_param->mld_id);
2957  				mld_param->mld_id = 0;
2958  				data += tbtt_len;
2959  				pos += tbtt_len;
2960  			} else {
2961  				qdf_mem_copy(pos, data, tbtt_len);
2962  				data += tbtt_len;
2963  				pos += tbtt_len;
2964  			}
2965  		}
2966  
2967  		scm_debug("skip %d neighbor info", tbtt_info_field_count);
2968  		if (tbtt_info_field_count == (tbtt_count + 1)) {
2969  			/* If all the TBTT information are skipped, then also
2970  			 * revert the neighbor AP info which has been copied.
2971  			 */
2972  			pos -= nbr_ap_info_len;
2973  			tbtt_info_field_len += nbr_ap_info_len;
2974  		} else {
2975  			neighbor_ap_info->tbtt_header.tbtt_info_count -=
2976  							tbtt_info_field_count;
2977  		}
2978  	}
2979  
2980  	rnr_new[TAG_LEN_POS] = rnr_len - tbtt_info_field_len;
2981  	if (rnr_new[TAG_LEN_POS] > 0)
2982  		rnr_len = rnr_new[TAG_LEN_POS] + MIN_IE_LEN;
2983  	else
2984  		rnr_len = 0;
2985  
2986  	return rnr_len;
2987  }
2988  #else
util_handle_rnr_ie_for_mbssid(const uint8_t * rnr,uint8_t bssid_index,uint8_t * pos)2989  static int util_handle_rnr_ie_for_mbssid(const uint8_t *rnr,
2990  					 uint8_t bssid_index, uint8_t *pos)
2991  {
2992  	return 0;
2993  }
2994  #endif
2995  
2996  #ifdef WLAN_FEATURE_ACTION_OUI
util_copy_reporting_ap_vendor_ies(struct wlan_objmgr_psoc * psoc,const uint8_t * ie,uint32_t ie_len,uint8_t * buf_ie)2997  static uint8_t *util_copy_reporting_ap_vendor_ies(struct wlan_objmgr_psoc *psoc,
2998  						  const uint8_t *ie,
2999  						  uint32_t ie_len,
3000  						  uint8_t *buf_ie)
3001  {
3002  	struct action_oui_search_attr attr = {0};
3003  	enum action_oui_id oui_id = ACTION_OUI_RESTRICT_MAX_MLO_LINKS;
3004  
3005  	attr.ie_data = (uint8_t *)ie;
3006  	attr.ie_length = ie_len;
3007  
3008  	if (wlan_action_oui_search(psoc, &attr, oui_id)) {
3009  		qdf_mem_copy(buf_ie, ie, ie_len);
3010  		buf_ie += ie_len;
3011  	}
3012  
3013  	return buf_ie;
3014  }
3015  #else
3016  static inline uint8_t *
util_copy_reporting_ap_vendor_ies(struct wlan_objmgr_psoc * psoc,const uint8_t * ie,uint32_t ie_len,uint8_t * buf_ie)3017  util_copy_reporting_ap_vendor_ies(struct wlan_objmgr_psoc *psoc,
3018  				  const uint8_t *ie, uint32_t ie_len,
3019  				  uint8_t *buf_ie)
3020  {
3021  	return buf_ie;
3022  }
3023  #endif
3024  
util_gen_new_ie(struct wlan_objmgr_pdev * pdev,uint8_t * ie,uint32_t ielen,uint8_t * subelement,size_t subie_len,uint8_t * new_ie,uint8_t bssid_index)3025  static uint32_t util_gen_new_ie(struct wlan_objmgr_pdev *pdev,
3026  				uint8_t *ie, uint32_t ielen,
3027  				uint8_t *subelement,
3028  				size_t subie_len, uint8_t *new_ie,
3029  				uint8_t bssid_index)
3030  {
3031  	struct wlan_objmgr_psoc *psoc;
3032  	uint8_t *pos, *tmp;
3033  	const uint8_t *tmp_old, *tmp_new;
3034  	uint8_t *sub_copy, *extn_elem = NULL;
3035  	struct non_inheritance_ie ninh = {0};
3036  	uint8_t *elem_list = NULL, *extn_elem_list = NULL;
3037  	size_t tmp_rem_len;
3038  
3039  	psoc = wlan_pdev_get_psoc(pdev);
3040  	if (!psoc) {
3041  		scm_err("NULL PSOC");
3042  		return 0;
3043  	}
3044  
3045  	/* copy subelement as we need to change its content to
3046  	 * mark an ie after it is processed.
3047  	 */
3048  	sub_copy = qdf_mem_malloc(subie_len);
3049  	if (!sub_copy)
3050  		return 0;
3051  	qdf_mem_copy(sub_copy, subelement, subie_len);
3052  
3053  	pos = &new_ie[0];
3054  
3055  	/* new ssid */
3056  	tmp_new = util_scan_find_ie(WLAN_ELEMID_SSID, sub_copy, subie_len);
3057  	if (tmp_new) {
3058  		scm_debug(" SSID " QDF_SSID_FMT,
3059  			  QDF_SSID_REF(tmp_new[1],
3060  				       &tmp_new[PAYLOAD_START_POS]));
3061  		if ((pos + tmp_new[1] + MIN_IE_LEN) <=
3062  		    (new_ie + ielen)) {
3063  			qdf_mem_copy(pos, tmp_new,
3064  				     (tmp_new[1] + MIN_IE_LEN));
3065  			pos += (tmp_new[1] + MIN_IE_LEN);
3066  		}
3067  	}
3068  
3069  	extn_elem = util_scan_find_noninheritance_ie(WLAN_ELEMID_EXTN_ELEM,
3070  						     sub_copy, subie_len);
3071  
3072  	if (extn_elem && extn_elem[TAG_LEN_POS] >= VALID_ELEM_LEAST_LEN) {
3073  		if (((extn_elem + extn_elem[1] + MIN_IE_LEN) - sub_copy)
3074  		    < subie_len)
3075  			util_parse_noninheritance_list(extn_elem, &elem_list,
3076  						       &extn_elem_list, &ninh);
3077  	}
3078  
3079  	/* go through IEs in ie (skip SSID) and subelement,
3080  	 * merge them into new_ie
3081  	 */
3082  	tmp_old = util_scan_find_ie(WLAN_ELEMID_SSID, ie, ielen);
3083  	tmp_old = (tmp_old) ? tmp_old + tmp_old[1] + MIN_IE_LEN : ie;
3084  
3085  	if (((tmp_old + MIN_IE_LEN) - ie) >= ielen) {
3086  		qdf_mem_free(sub_copy);
3087  		return 0;
3088  	}
3089  
3090  	while (((tmp_old + tmp_old[1] + MIN_IE_LEN) - ie) <= ielen) {
3091  		ninh.non_inh_ie_found = 0;
3092  		if (ninh.non_inherit) {
3093  			if (ninh.list_len) {
3094  				ninh.non_inh_ie_found =
3095  					util_is_noninh_ie(tmp_old[0],
3096  							  elem_list,
3097  							  ninh.list_len);
3098  			}
3099  
3100  			if (!ninh.non_inh_ie_found &&
3101  			    ninh.extn_len &&
3102  			    (tmp_old[0] == WLAN_ELEMID_EXTN_ELEM)) {
3103  				ninh.non_inh_ie_found =
3104  					util_is_noninh_ie(tmp_old[2],
3105  							  extn_elem_list,
3106  							  ninh.extn_len);
3107  			}
3108  		}
3109  
3110  		if (ninh.non_inh_ie_found || (tmp_old[0] == 0)) {
3111  			if (((tmp_old + tmp_old[1] + MIN_IE_LEN) - ie) >=
3112  			    (ielen - MIN_IE_LEN))
3113  				break;
3114  			tmp_old += tmp_old[1] + MIN_IE_LEN;
3115  			continue;
3116  		}
3117  
3118  		tmp = (uint8_t *)util_scan_find_ie(tmp_old[0], sub_copy,
3119  						   subie_len);
3120  		if (!tmp) {
3121  			/* ie in old ie but not in subelement */
3122  			if (tmp_old[0] == WLAN_ELEMID_REDUCED_NEIGHBOR_REPORT) {
3123  				/* handle rnr ie for mbssid*/
3124  				pos +=
3125  				    util_handle_rnr_ie_for_mbssid(tmp_old,
3126  								  bssid_index,
3127  								  pos);
3128  			} else if (tmp_old[0] != WLAN_ELEMID_MULTIPLE_BSSID) {
3129  				if ((pos + tmp_old[1] + MIN_IE_LEN) <=
3130  				    (new_ie + ielen)) {
3131  					qdf_mem_copy(pos, tmp_old,
3132  						     (tmp_old[1] +
3133  						      MIN_IE_LEN));
3134  					pos += tmp_old[1] + MIN_IE_LEN;
3135  				}
3136  			}
3137  		} else {
3138  			/* ie in transmitting ie also in subelement,
3139  			 * copy from subelement and flag the ie in subelement
3140  			 * as copied (by setting eid field to 0xff).
3141  			 * To determine if the vendor ies are same:
3142  			 * 1. For Cisco OUI, compare only OUI + type
3143  			 * 2. For other OUI, compare OUI + type + subType
3144  			 */
3145  			tmp_rem_len = subie_len - (tmp - sub_copy);
3146  			if (tmp_old[0] == WLAN_ELEMID_VENDOR &&
3147  			    tmp_rem_len >= MIN_VENDOR_TAG_LEN) {
3148  				/*
3149  				 * In order to identify few Vendor APs the
3150  				 * generated frame should contain the reporting
3151  				 * APs matching VSIE or else the entry generated
3152  				 * will not have this VSIE and logic kept to
3153  				 * take certain action on specific Vendor APs
3154  				 * will fail.
3155  				 */
3156  				pos = util_copy_reporting_ap_vendor_ies(psoc,
3157  									tmp_old,
3158  									tmp_old[1] + MIN_IE_LEN,
3159  									pos);
3160  				/* If Vendor IE also presents in STA profile,
3161  				 * then ignore the Vendor IE which is for
3162  				 * reporting STA. It only needs to copy Vendor
3163  				 * IE from STA profile for reported BSSID.
3164  				 * The copy happens when going through the
3165  				 * remaining IEs.
3166  				 */
3167  			} else if (tmp_old[0] == WLAN_ELEMID_EXTN_ELEM &&
3168  				   tmp_rem_len >= (MIN_IE_LEN + 1)) {
3169  				if (tmp_old[PAYLOAD_START_POS] ==
3170  				    tmp[PAYLOAD_START_POS]) {
3171  					/* same ie, copy from subelement */
3172  					if ((pos + tmp[1] + MIN_IE_LEN) <=
3173  					    (new_ie + ielen)) {
3174  						qdf_mem_copy(pos, tmp,
3175  							     tmp[1] +
3176  							     MIN_IE_LEN);
3177  						pos += tmp[1] + MIN_IE_LEN;
3178  						tmp[0] = 0;
3179  					}
3180  				} else {
3181  					if ((pos + tmp_old[1] + MIN_IE_LEN) <=
3182  					    (new_ie + ielen)) {
3183  						qdf_mem_copy(pos, tmp_old,
3184  							     tmp_old[1] +
3185  							     MIN_IE_LEN);
3186  						pos += tmp_old[1] +
3187  							MIN_IE_LEN;
3188  					}
3189  				}
3190  
3191  			} else {
3192  				/* copy ie from subelement into new ie */
3193  				if ((pos + tmp[1] + MIN_IE_LEN) <=
3194  				    (new_ie + ielen)) {
3195  					qdf_mem_copy(pos, tmp,
3196  						     tmp[1] + MIN_IE_LEN);
3197  					pos += tmp[1] + MIN_IE_LEN;
3198  					tmp[0] = 0;
3199  				}
3200  			}
3201  		}
3202  
3203  		if (((tmp_old + tmp_old[1] + MIN_IE_LEN) - ie) >=
3204  		    (ielen - MIN_IE_LEN))
3205  			break;
3206  
3207  		tmp_old += tmp_old[1] + MIN_IE_LEN;
3208  	}
3209  
3210  	/* go through subelement again to check if there is any ie not
3211  	 * copied to new ie, skip ssid, capability, bssid-index ie
3212  	 */
3213  	tmp_new = sub_copy;
3214  	while ((subie_len > 0) &&
3215  	       (((tmp_new + tmp_new[1] + MIN_IE_LEN) - sub_copy) <=
3216  		subie_len)) {
3217  		if (!(tmp_new[0] == WLAN_ELEMID_NONTX_BSSID_CAP ||
3218  		      tmp_new[0] == WLAN_ELEMID_SSID ||
3219  		      tmp_new[0] == WLAN_ELEMID_MULTI_BSSID_IDX ||
3220  		      ((tmp_new[0] == WLAN_ELEMID_EXTN_ELEM) &&
3221  		       (tmp_new[2] == WLAN_EXTN_ELEMID_NONINHERITANCE)))) {
3222  			if ((pos + tmp_new[1] + MIN_IE_LEN) <=
3223  			    (new_ie + ielen)) {
3224  				qdf_mem_copy(pos, tmp_new,
3225  					     tmp_new[1] + MIN_IE_LEN);
3226  				pos += tmp_new[1] + MIN_IE_LEN;
3227  			}
3228  		}
3229  		if (((tmp_new + tmp_new[1] + MIN_IE_LEN) - sub_copy) >=
3230  		    (subie_len - 1))
3231  			break;
3232  		tmp_new += tmp_new[1] + MIN_IE_LEN;
3233  	}
3234  
3235  	qdf_mem_free(sub_copy);
3236  
3237  	if (pos > new_ie)
3238  		return pos - new_ie;
3239  	else
3240  		return 0;
3241  }
3242  
3243  static enum nontx_profile_reasoncode
util_handle_nontx_prof(uint8_t * mbssid_elem,uint8_t * subelement,uint8_t * next_subelement,struct scan_mbssid_info * mbssid_info,char * bssid,char * new_bssid)3244  util_handle_nontx_prof(uint8_t *mbssid_elem, uint8_t *subelement,
3245  		       uint8_t *next_subelement,
3246  		       struct scan_mbssid_info *mbssid_info,
3247  		       char *bssid, char *new_bssid)
3248  {
3249  	uint8_t *mbssid_index_ie;
3250  	uint32_t prof_len;
3251  
3252  	prof_len = subelement[TAG_LEN_POS];
3253  	/*
3254  	 * If we are executing the split portion of the nontx
3255  	 * profile present in the subsequent MBSSID, then there
3256  	 * is no need of any sanity check for valid BSS profile
3257  	 */
3258  
3259  	if (mbssid_info->split_prof_continue) {
3260  		if ((subelement[ID_POS] != 0) ||
3261  		    (subelement[TAG_LEN_POS] < SPLIT_PROF_DATA_LEAST_LEN)) {
3262  			return INVALID_SPLIT_PROF;
3263  		}
3264  	} else {
3265  		if ((subelement[ID_POS] != 0) ||
3266  		    (subelement[TAG_LEN_POS] < VALID_ELEM_LEAST_LEN)) {
3267  			/* not a valid BSS profile */
3268  			return INVALID_NONTX_PROF;
3269  		}
3270  	}
3271  
3272  	if (mbssid_info->split_profile) {
3273  		if (next_subelement[PAYLOAD_START_POS] !=
3274  		    WLAN_ELEMID_NONTX_BSSID_CAP) {
3275  			mbssid_info->prof_residue = true;
3276  		}
3277  	}
3278  
3279  	if (!mbssid_info->split_prof_continue &&
3280  	    ((subelement[PAYLOAD_START_POS] != WLAN_ELEMID_NONTX_BSSID_CAP) ||
3281  	     (subelement[NONTX_BSSID_CAP_TAG_LEN_POS] != CAP_INFO_LEN))) {
3282  		/* The first element within the Nontransmitted
3283  		 * BSSID Profile is not the Nontransmitted
3284  		 * BSSID Capability element.
3285  		 */
3286  		return INVALID_NONTX_PROF;
3287  	}
3288  
3289  	/* found a Nontransmitted BSSID Profile */
3290  	mbssid_index_ie =
3291  		util_scan_find_ie(WLAN_ELEMID_MULTI_BSSID_IDX,
3292  				  (subelement + PAYLOAD_START_POS), prof_len);
3293  
3294  	if (!mbssid_index_ie) {
3295  		if (!mbssid_info->prof_residue)
3296  			return INVALID_NONTX_PROF;
3297  
3298  		mbssid_info->skip_bssid_copy = true;
3299  	} else if ((mbssid_index_ie[TAG_LEN_POS] < 1) ||
3300  		   (mbssid_index_ie[BSS_INDEX_POS] == 0)) {
3301  		/* No valid Multiple BSSID-Index element */
3302  		return INVALID_NONTX_PROF;
3303  	}
3304  
3305  	if (!mbssid_info->skip_bssid_copy) {
3306  		qdf_mem_copy(mbssid_info->trans_bssid,
3307  			     bssid, QDF_MAC_ADDR_SIZE);
3308  		mbssid_info->profile_num =
3309  			mbssid_index_ie[BSS_INDEX_POS];
3310  		util_gen_new_bssid(bssid,
3311  				   mbssid_elem[MBSSID_INDICATOR_POS],
3312  				   mbssid_index_ie[BSS_INDEX_POS],
3313  				   new_bssid);
3314  		qdf_mem_copy(mbssid_info->non_trans_bssid, new_bssid,
3315  			     QDF_MAC_ADDR_SIZE);
3316  	}
3317  	/* In single MBSS IE, there could be subelement holding
3318  	 * remaining vendor IEs of non tx profile from last MBSS IE
3319  	 * [split profile] and new non tx profile, hence reset
3320  	 * skip_bssid_copy flag after each subelement processing
3321  	 */
3322  	mbssid_info->skip_bssid_copy = false;
3323  	return VALID_NONTX_PROF;
3324  }
3325  
3326  /*
3327   * What's split profile:
3328   *  If any nontransmitted BSSID profile is fragmented across
3329   * multiple MBSSID elements, then it is called split profile.
3330   * For a split profile to exist we need to have at least two
3331   * MBSSID elements as part of the RX beacon or probe response
3332   * Hence, first we need to identify the next MBSSID element
3333   * and check for the 5th bit from the starting of the next
3334   * MBSSID IE and if it does not have Nontransmitted BSSID
3335   * capability element, then it's a split profile case.
3336   */
util_scan_is_split_prof_found(uint8_t * next_elem,uint8_t * ie,uint32_t ielen)3337  static bool util_scan_is_split_prof_found(uint8_t *next_elem,
3338  					  uint8_t *ie, uint32_t ielen)
3339  {
3340  	uint8_t *next_mbssid_elem;
3341  
3342  	if ((next_elem + MIN_IE_LEN + VALID_ELEM_LEAST_LEN) > (ie + ielen))
3343  		return false;
3344  
3345  	if (next_elem[0] == WLAN_ELEMID_MULTIPLE_BSSID) {
3346  		if ((next_elem[TAG_LEN_POS] >= VALID_ELEM_LEAST_LEN) &&
3347  		    (next_elem[SUBELEM_DATA_POS_FROM_MBSSID] !=
3348  		     WLAN_ELEMID_NONTX_BSSID_CAP)) {
3349  			return true;
3350  		}
3351  	} else {
3352  		next_mbssid_elem =
3353  			util_scan_find_ie(WLAN_ELEMID_MULTIPLE_BSSID,
3354  					  next_elem,
3355  					  ielen - (next_elem - ie));
3356  		if (!next_mbssid_elem)
3357  			return false;
3358  
3359  		if ((next_mbssid_elem[TAG_LEN_POS] >= VALID_ELEM_LEAST_LEN) &&
3360  		    (next_mbssid_elem[SUBELEM_DATA_POS_FROM_MBSSID] !=
3361  		     WLAN_ELEMID_NONTX_BSSID_CAP)) {
3362  			return true;
3363  		}
3364  	}
3365  
3366  	return false;
3367  }
3368  
util_scan_parse_mbssid(struct wlan_objmgr_pdev * pdev,uint8_t * frame,qdf_size_t frame_len,uint32_t frm_subtype,struct mgmt_rx_event_params * rx_param,qdf_list_t * scan_list)3369  static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev,
3370  					 uint8_t *frame, qdf_size_t frame_len,
3371  					 uint32_t frm_subtype,
3372  					 struct mgmt_rx_event_params *rx_param,
3373  					 qdf_list_t *scan_list)
3374  {
3375  	struct wlan_scan_obj *scan_obj;
3376  	struct wlan_bcn_frame *bcn;
3377  	struct wlan_frame_hdr *hdr;
3378  	struct scan_mbssid_info mbssid_info = {0};
3379  	QDF_STATUS status;
3380  	uint8_t *pos, *subelement, *next_elem;
3381  	uint8_t *mbssid_elem;
3382  	uint32_t subie_len, new_ie_len, ielen;
3383  	uint8_t *next_subelement = NULL;
3384  	uint8_t new_bssid[QDF_MAC_ADDR_SIZE], bssid[QDF_MAC_ADDR_SIZE];
3385  	uint8_t *new_ie, *split_prof_start = NULL, *split_prof_end = NULL;
3386  	uint8_t *ie, *new_frame = NULL;
3387  	int new_frame_len = 0, split_prof_len = 0;
3388  	enum nontx_profile_reasoncode retval;
3389  	uint8_t *nontx_profile = NULL;
3390  
3391  	scan_obj = wlan_pdev_get_scan_obj(pdev);
3392  	if (!scan_obj)
3393  		return QDF_STATUS_E_INVAL;
3394  
3395  	hdr = (struct wlan_frame_hdr *)frame;
3396  	bcn = (struct wlan_bcn_frame *)(frame + sizeof(struct wlan_frame_hdr));
3397  	ie = (uint8_t *)&bcn->ie;
3398  	ielen = (uint16_t)(frame_len -
3399  			   sizeof(struct wlan_frame_hdr) -
3400  			   offsetof(struct wlan_bcn_frame, ie));
3401  	qdf_mem_copy(bssid, hdr->i_addr3, QDF_MAC_ADDR_SIZE);
3402  
3403  	if (!util_scan_find_ie(WLAN_ELEMID_MULTIPLE_BSSID, ie, ielen))
3404  		return QDF_STATUS_E_FAILURE;
3405  
3406  	pos = ie;
3407  
3408  	new_ie = qdf_mem_malloc(ielen);
3409  	if (!new_ie)
3410  		return QDF_STATUS_E_NOMEM;
3411  
3412  	while (pos < (ie + ielen + MIN_IE_LEN)) {
3413  		mbssid_elem =
3414  			util_scan_find_ie(WLAN_ELEMID_MULTIPLE_BSSID, pos,
3415  					  ielen - (pos - ie));
3416  		if (!mbssid_elem)
3417  			break;
3418  
3419  		/*
3420  		 * The max_bssid_indicator field is mandatory, therefore the
3421  		 * length of the MBSSID element should atleast be 1.
3422  		 */
3423  		if (!mbssid_elem[TAG_LEN_POS]) {
3424  			scm_debug_rl("MBSSID IE is of length zero");
3425  			break;
3426  		}
3427  
3428  		mbssid_info.profile_count =
3429  			(1 << mbssid_elem[MBSSID_INDICATOR_POS]);
3430  
3431  		next_elem =
3432  			mbssid_elem + mbssid_elem[TAG_LEN_POS] + MIN_IE_LEN;
3433  
3434  		/* Skip Element ID, Len, MaxBSSID Indicator */
3435  		if (!mbssid_info.split_profile &&
3436  		    (mbssid_elem[TAG_LEN_POS] < VALID_ELEM_LEAST_LEN)) {
3437  			break;
3438  		}
3439  
3440  		/*
3441  		 * Find if the next IE is MBSSID, if not, then scan through
3442  		 * the IE list and find the next MBSSID tag, if present.
3443  		 * Once we find the MBSSID tag, check if this MBSSID tag has
3444  		 * the other fragmented part of the non Tx profile.
3445  		 */
3446  
3447  		mbssid_info.split_profile =
3448  			util_scan_is_split_prof_found(next_elem, ie, ielen);
3449  
3450  		for (subelement = mbssid_elem + SUBELEMENT_START_POS;
3451  		     subelement < (next_elem - 1);
3452  		     subelement += MIN_IE_LEN + subelement[TAG_LEN_POS]) {
3453  			subie_len = subelement[TAG_LEN_POS];
3454  
3455  			/*
3456  			 * if prof_residue is true, that means we are
3457  			 * in the continuation of the fragmented profile part,
3458  			 * present in the next MBSSD IE else this profile
3459  			 * is a non fragmented non tx BSSID profile.
3460  			 */
3461  
3462  			if (mbssid_info.prof_residue)
3463  				mbssid_info.split_prof_continue = true;
3464  			else
3465  				mbssid_info.split_prof_continue = false;
3466  
3467  			if (subie_len > MAX_SUBELEM_LEN) {
3468  				scm_debug_rl("Corrupt frame with subie_len: %d "
3469  					     "split_prof_continue: %d,prof_residue: %d",
3470  					     subie_len,
3471  					     mbssid_info.split_prof_continue,
3472  					     mbssid_info.prof_residue);
3473  				if (mbssid_info.split_prof_continue) {
3474  					qdf_mem_free(split_prof_start);
3475  					split_prof_start = NULL;
3476  				}
3477  
3478  				qdf_mem_free(new_ie);
3479  				return QDF_STATUS_E_INVAL;
3480  			}
3481  
3482  			if ((next_elem - subelement) <
3483  			    (MIN_IE_LEN + subie_len))
3484  				break;
3485  
3486  			next_subelement = subelement + subie_len + MIN_IE_LEN;
3487  			retval = util_handle_nontx_prof(mbssid_elem, subelement,
3488  							next_subelement,
3489  							&mbssid_info,
3490  							bssid, new_bssid);
3491  
3492  			if (retval == INVALID_SPLIT_PROF) {
3493  				scm_debug_rl("Corrupt frame with ID_POS: %d,TAG_LEN_POS: %d",
3494  					     subelement[ID_POS],
3495  					     subelement[TAG_LEN_POS]);
3496  				qdf_mem_free(split_prof_start);
3497  				split_prof_start = NULL;
3498  				qdf_mem_free(new_ie);
3499  				return QDF_STATUS_E_INVAL;
3500  			} else if (retval == INVALID_NONTX_PROF) {
3501  				continue;
3502  			}
3503  
3504  			/*
3505  			 * Merging parts of nontx profile-
3506  			 * Just for understanding, let's make an assumption
3507  			 * that nontx profile is fragmented across MBSSIE1
3508  			 * and MBSSIE2.
3509  			 * mbssid_info.prof_residue being set indicates
3510  			 * that the ongoing nontx profile is part of split
3511  			 * profile, whose other fragmented part is present
3512  			 * in MBSSIE2.
3513  			 * So once prof_residue is set, we need to
3514  			 * identify whether we are accessing the split
3515  			 * profile in MBSSIE1 or MBSSIE2.
3516  			 * If we are in MBSSIE1, then copy the part of split
3517  			 * profile from MBSSIE1 into a new buffer and then
3518  			 * move to the next part of the split profile which
3519  			 * is present in MBSSIE2 and append that part into
3520  			 * the new buffer.
3521  			 * Once the full profile is accumulated, go ahead with
3522  			 * the ie generation and length calculation of the
3523  			 * new frame.
3524  			 */
3525  
3526  			if (mbssid_info.prof_residue) {
3527  				if (!mbssid_info.split_prof_continue) {
3528  					split_prof_start =
3529  						qdf_mem_malloc(ielen);
3530  					if (!split_prof_start) {
3531  						scm_err_rl("Malloc failed");
3532  						qdf_mem_free(new_ie);
3533  						return QDF_STATUS_E_NOMEM;
3534  					}
3535  
3536  					qdf_mem_copy(split_prof_start,
3537  						     subelement,
3538  						     (subie_len +
3539  						      MIN_IE_LEN));
3540  					split_prof_end = (split_prof_start +
3541  							  subie_len +
3542  							  MIN_IE_LEN);
3543  					break;
3544  				}
3545  
3546  				/*
3547  				 * Currently we are accessing other part of the
3548  				 * split profile present in the subsequent
3549  				 * MBSSIE. There is a possibility that one
3550  				 * non tx profile is spread across more than
3551  				 * two MBSSID tag as well. This code will
3552  				 * handle such scenario.
3553  				 */
3554  
3555  				if (split_prof_end) {
3556  					qdf_mem_copy(split_prof_end,
3557  						     (subelement + MIN_IE_LEN),
3558  						     subie_len);
3559  					split_prof_end += subie_len;
3560  				}
3561  
3562  				/*
3563  				 * When to stop the process of accumulating
3564  				 * parts of split profile, is decided by
3565  				 * mbssid_info.prof_residue. prof_residue
3566  				 * could be made false if there is not any
3567  				 * continuation of the split profile.
3568  				 * which could be identified by two factors
3569  				 * 1. By checking if the next MBSSIE's first
3570  				 * non tx profile is not a fragmented one or
3571  				 * 2. there is a probability that first
3572  				 * subelement of MBSSIE2 is end if split
3573  				 * profile and the next subelement of MBSSIE2
3574  				 * is a non split one.
3575  				 */
3576  
3577  				if (!mbssid_info.split_profile ||
3578  				    (next_subelement[PAYLOAD_START_POS] ==
3579  				     WLAN_ELEMID_NONTX_BSSID_CAP)) {
3580  					mbssid_info.prof_residue = false;
3581  				}
3582  
3583  				/*
3584  				 * Until above mentioned conditions are met,
3585  				 * we need to iterate and keep accumulating
3586  				 * the split profile contents.
3587  				 */
3588  
3589  				if (mbssid_info.prof_residue)
3590  					break;
3591  
3592  				if (split_prof_end) {
3593  					split_prof_len =
3594  						(split_prof_end -
3595  						 split_prof_start - MIN_IE_LEN);
3596  				}
3597  			}
3598  
3599  			if (mbssid_info.split_prof_continue) {
3600  				if (!split_prof_start)
3601  					break;
3602  				nontx_profile = split_prof_start;
3603  				subie_len = split_prof_len;
3604  			} else {
3605  				nontx_profile = subelement;
3606  			}
3607  
3608  			new_ie_len =
3609  				util_gen_new_ie(pdev, ie, ielen,
3610  						(nontx_profile +
3611  						 PAYLOAD_START_POS),
3612  						subie_len, new_ie,
3613  						mbssid_info.profile_num);
3614  
3615  			if (!new_ie_len) {
3616  				if (mbssid_info.split_prof_continue) {
3617  					qdf_mem_free(split_prof_start);
3618  					split_prof_start = NULL;
3619  					split_prof_end = NULL;
3620  					split_prof_len = 0;
3621  				}
3622  				continue;
3623  			}
3624  
3625  			new_frame_len = frame_len - ielen + new_ie_len;
3626  
3627  			if (new_frame_len < 0 || new_frame_len > frame_len) {
3628  				if (mbssid_info.split_prof_continue) {
3629  					qdf_mem_free(split_prof_start);
3630  					split_prof_start = NULL;
3631  				}
3632  				qdf_mem_free(new_ie);
3633  				scm_debug_rl("Invalid frame:Stop MBSSIE parsing, Frame_len: %zu "
3634  					     "ielen:%u,new_ie_len:%u",
3635  					     frame_len, ielen, new_ie_len);
3636  				return QDF_STATUS_E_INVAL;
3637  			}
3638  
3639  			new_frame = qdf_mem_malloc(new_frame_len);
3640  			if (!new_frame) {
3641  				if (mbssid_info.split_prof_continue) {
3642  					qdf_mem_free(split_prof_start);
3643  					split_prof_start = NULL;
3644  				}
3645  				qdf_mem_free(new_ie);
3646  				scm_err_rl("Malloc for new_frame failed");
3647  				scm_err_rl("split_prof_continue: %d",
3648  					   mbssid_info.split_prof_continue);
3649  				return QDF_STATUS_E_NOMEM;
3650  			}
3651  
3652  			/*
3653  			 * Copy the header(24byte), timestamp(8 byte),
3654  			 * beaconinterval(2byte) and capability(2byte)
3655  			 */
3656  			qdf_mem_copy(new_frame, frame, FIXED_LENGTH);
3657  			/* Copy the new ie generated from MBSSID profile*/
3658  			hdr = (struct wlan_frame_hdr *)new_frame;
3659  			qdf_mem_copy(hdr->i_addr2, new_bssid,
3660  				     QDF_MAC_ADDR_SIZE);
3661  			qdf_mem_copy(hdr->i_addr3, new_bssid,
3662  				     QDF_MAC_ADDR_SIZE);
3663  			bcn = (struct wlan_bcn_frame *)
3664  				(new_frame + sizeof(struct wlan_frame_hdr));
3665  			/* update the non-tx capability */
3666  			qdf_mem_copy(&bcn->capability,
3667  				     nontx_profile + CAP_INFO_POS,
3668  				     CAP_INFO_LEN);
3669  
3670  			/* Copy the new ie generated from MBSSID profile*/
3671  			qdf_mem_copy(new_frame +
3672  				     offsetof(struct wlan_bcn_frame, ie) +
3673  				     sizeof(struct wlan_frame_hdr),
3674  				     new_ie, new_ie_len);
3675  			if (scan_obj->cb.inform_mbssid_bcn_prb_rsp)
3676  				scan_obj->cb.inform_mbssid_bcn_prb_rsp(
3677  						       new_frame, new_frame_len,
3678  						       frm_subtype, new_bssid);
3679  
3680  			status = util_scan_gen_scan_entry(pdev, new_frame,
3681  							  new_frame_len,
3682  							  frm_subtype,
3683  							  rx_param,
3684  							  &mbssid_info,
3685  							  scan_list);
3686  			if (QDF_IS_STATUS_ERROR(status)) {
3687  				if (mbssid_info.split_prof_continue) {
3688  					qdf_mem_free(split_prof_start);
3689  					split_prof_start = NULL;
3690  					split_prof_end = NULL;
3691  					split_prof_len = 0;
3692  					qdf_mem_zero(&mbssid_info,
3693  						     sizeof(mbssid_info));
3694  				}
3695  				qdf_mem_free(new_frame);
3696  				scm_debug_rl("failed to generate a scan entry "
3697  					     "split_prof_continue: %d",
3698  					     mbssid_info.split_prof_continue);
3699  				break;
3700  			}
3701  			/* scan entry makes its own copy so free the frame*/
3702  			if (mbssid_info.split_prof_continue) {
3703  				qdf_mem_free(split_prof_start);
3704  				split_prof_start = NULL;
3705  				split_prof_end = NULL;
3706  				split_prof_len = 0;
3707  			}
3708  			qdf_mem_free(new_frame);
3709  		}
3710  
3711  		pos = next_elem;
3712  	}
3713  	qdf_mem_free(new_ie);
3714  
3715  	if (split_prof_start)
3716  		qdf_mem_free(split_prof_start);
3717  
3718  	return QDF_STATUS_SUCCESS;
3719  }
3720  #else
util_scan_parse_mbssid(struct wlan_objmgr_pdev * pdev,uint8_t * frame,qdf_size_t frame_len,uint32_t frm_subtype,struct mgmt_rx_event_params * rx_param,qdf_list_t * scan_list)3721  static QDF_STATUS util_scan_parse_mbssid(struct wlan_objmgr_pdev *pdev,
3722  					 uint8_t *frame, qdf_size_t frame_len,
3723  					 uint32_t frm_subtype,
3724  					 struct mgmt_rx_event_params *rx_param,
3725  					 qdf_list_t *scan_list)
3726  {
3727  	return QDF_STATUS_SUCCESS;
3728  }
3729  #endif
3730  
3731  #if defined(WLAN_FEATURE_11BE) && defined(WLAN_FEATURE_11BE_MLO_MBSSID)
3732  /*
3733   * util_scan_gen_txvap_scan_entry() - Strip out the MBSSID tag from the received
3734   * frame and update the modified frame length before generating a scan entry.
3735   * It is redundant to have MBSSID information as part of the TX vap/ profile
3736   * specific scan entry.
3737   *
3738   * @pdev: pdev context
3739   * @frame: Unsoiled frame passed from util_scan_parse_beacon_frame()
3740   * @frame_len: Length of the unsoiled frame
3741   * @ie_list: Points to the start of IE list in parent/ unsoiled frame
3742   * @ielen: Length of the complete IE list from parent/ unsoiled frame
3743   * @frm_subtype: Frame subtype
3744   * @rx_param: host mgmt header params
3745   * @scan_list: Scan entry list of bss candidates after filtering
3746   * @mbssid_info: Data structure to carry MBSSID information
3747   *
3748   * Return: False if the scan entry generation is not successful
3749   */
3750  static QDF_STATUS
util_scan_gen_txvap_scan_entry(struct wlan_objmgr_pdev * pdev,uint8_t * frame,qdf_size_t frame_len,uint8_t * ie_list,uint32_t ielen,uint32_t frm_subtype,struct mgmt_rx_event_params * rx_param,qdf_list_t * scan_list,struct scan_mbssid_info * mbssid_info)3751  util_scan_gen_txvap_scan_entry(struct wlan_objmgr_pdev *pdev,
3752  			       uint8_t *frame, qdf_size_t frame_len,
3753  			       uint8_t *ie_list, uint32_t ielen,
3754  			       uint32_t frm_subtype,
3755  			       struct mgmt_rx_event_params *rx_param,
3756  			       qdf_list_t *scan_list,
3757  			       struct scan_mbssid_info *mbssid_info)
3758  {
3759  	uint8_t *src_ie, *dest_ptr, *container;
3760  	uint16_t new_frame_len, new_ie_len = 0;
3761  	uint8_t *trimmed_frame, fixed_len = 0;
3762  	QDF_STATUS status = QDF_STATUS_SUCCESS;
3763  
3764  	/*
3765  	 * Allocate a buffer to copy only the TX VAP information after
3766  	 * stripping out the MBSSID IE from the parent beacon.
3767  	 * The allocation size should be the size of a frame as at
3768  	 * this point it is unknown what would be the new frame length
3769  	 * after stripping the MBSSID IE.
3770  	 */
3771  	container = qdf_mem_malloc(frame_len);
3772  	if (!container) {
3773  		scm_err_rl("Malloc for container failed");
3774  		return QDF_STATUS_E_NOMEM;
3775  	}
3776  
3777  	dest_ptr = &container[0];
3778  	fixed_len = sizeof(struct wlan_frame_hdr) +
3779  		offsetof(struct wlan_bcn_frame, ie);
3780  
3781  	/*Copy the data till IE list before procesisng the IE one by one*/
3782  	qdf_mem_copy(dest_ptr, frame, fixed_len);
3783  
3784  	dest_ptr += fixed_len;
3785  	src_ie = ie_list;
3786  
3787  	/*
3788  	 * Go through the IE list from the parent beacon and copy one by one.
3789  	 * Skip copying it to the container if it's an MBSSID tag.
3790  	 */
3791  	while (((src_ie + src_ie[TAG_LEN_POS] + MIN_IE_LEN) -
3792  		ie_list) <= ielen) {
3793  		if (src_ie[ID_POS] == WLAN_ELEMID_MULTIPLE_BSSID) {
3794  			src_ie += src_ie[TAG_LEN_POS] + MIN_IE_LEN;
3795  			continue;
3796  		}
3797  
3798  		qdf_mem_copy(dest_ptr, src_ie,
3799  			     (src_ie[TAG_LEN_POS] + MIN_IE_LEN));
3800  
3801  		dest_ptr += src_ie[TAG_LEN_POS] + MIN_IE_LEN;
3802  		if (((src_ie + src_ie[TAG_LEN_POS] +
3803  		      MIN_IE_LEN) - ie_list) >= ielen)
3804  			break;
3805  
3806  		src_ie += src_ie[TAG_LEN_POS] + MIN_IE_LEN;
3807  	}
3808  
3809  	if (dest_ptr > container)
3810  		new_ie_len = dest_ptr - (container + fixed_len);
3811  
3812  	new_frame_len = frame_len - ielen + new_ie_len;
3813  
3814  	/*
3815  	 * At the start of this handler, we have allocated a memory block
3816  	 * of size same as a full beacon frame size, as we are not sure
3817  	 * of what would be the size of the new frame. After stripping out
3818  	 * the MBSSID tag from the parent beacon, there are some unused
3819  	 * memory. Hence do another malloc of the new frame length
3820  	 * (length of the new frame which has only TX VAP information)
3821  	 * and copy the needed data from the container, then free the
3822  	 * memory corresponds to container.
3823  	 * Post copy, use the trimmed frame and the new frame length
3824  	 * to generate scan entry for the TX profile.
3825  	 */
3826  	trimmed_frame = qdf_mem_malloc(new_frame_len);
3827  	if (!trimmed_frame) {
3828  		scm_err_rl("Malloc for trimmed frame failed");
3829  		qdf_mem_free(container);
3830  		return QDF_STATUS_E_NOMEM;
3831  	}
3832  
3833  	qdf_mem_copy(trimmed_frame, container, new_frame_len);
3834  	qdf_mem_free(container);
3835  
3836  	status = util_scan_gen_scan_entry(pdev, trimmed_frame,
3837  					  new_frame_len,
3838  					  frm_subtype,
3839  					  rx_param,
3840  					  mbssid_info,
3841  					  scan_list);
3842  
3843  	if (QDF_IS_STATUS_ERROR(status))
3844  		scm_debug_rl("Failed to create a scan entry");
3845  
3846  	qdf_mem_free(trimmed_frame);
3847  	return status;
3848  }
3849  
3850  /*
3851   * util_scan_parse_eht_beacon() : This API will be executed
3852   * only for 11BE platforms as per current design.
3853   * IF MBSSID IE is present in the beacon then
3854   * scan component will create a new entry for
3855   * each BSSID found in the MBSSID
3856   * util_scan_parse_mbssid() takes care of creating
3857   * scan entries for every non tx profile present in
3858   * the MBSSID tag.
3859   * util_scan_gen_txvap_scan_entry() helps in generating
3860   * scan entry for the tx profile.
3861   */
3862  static QDF_STATUS
util_scan_parse_eht_beacon(struct wlan_objmgr_pdev * pdev,uint8_t * frame,qdf_size_t frame_len,uint8_t * ie_list,uint32_t ielen,uint32_t frm_subtype,struct mgmt_rx_event_params * rx_param,qdf_list_t * scan_list,struct scan_mbssid_info * mbssid_info,uint8_t * mbssid_ie)3863  util_scan_parse_eht_beacon(struct wlan_objmgr_pdev *pdev,
3864  			   uint8_t *frame, qdf_size_t frame_len,
3865  			   uint8_t *ie_list, uint32_t ielen,
3866  			   uint32_t frm_subtype,
3867  			   struct mgmt_rx_event_params *rx_param,
3868  			   qdf_list_t *scan_list,
3869  			   struct scan_mbssid_info *mbssid_info,
3870  			   uint8_t *mbssid_ie)
3871  {
3872  	QDF_STATUS status = QDF_STATUS_SUCCESS;
3873  
3874  	if (mbssid_ie && ie_list) {
3875  		if (ie_list[TAG_LEN_POS] <= 0) {
3876  			scm_debug_rl("Corrupt IE");
3877  			return QDF_STATUS_E_INVAL;
3878  		}
3879  
3880  		status = util_scan_parse_mbssid(pdev, frame, frame_len,
3881  						frm_subtype, rx_param,
3882  						scan_list);
3883  
3884  		if (QDF_IS_STATUS_ERROR(status)) {
3885  			scm_debug_rl("NonTx prof: Failed to create scan entry");
3886  			return status;
3887  		}
3888  
3889  		status = util_scan_gen_txvap_scan_entry(pdev, frame,
3890  							frame_len, ie_list,
3891  							ielen, frm_subtype,
3892  							rx_param, scan_list,
3893  							mbssid_info);
3894  
3895  		if (QDF_IS_STATUS_ERROR(status))
3896  			scm_debug_rl("TX prof: Failed to create scan entry");
3897  
3898  		return status;
3899  	}
3900  
3901  	/*For Non MBSSIE case*/
3902  	status = util_scan_gen_scan_entry(pdev, frame, frame_len,
3903  					  frm_subtype, rx_param,
3904  					  mbssid_info, scan_list);
3905  
3906  	if (QDF_IS_STATUS_ERROR(status))
3907  		scm_debug_rl("Non-MBSSIE frame: Failed to create scan entry");
3908  
3909  	return status;
3910  }
3911  
3912  static bool
util_scan_is_platform_eht_capable(struct wlan_objmgr_pdev * pdev)3913  util_scan_is_platform_eht_capable(struct wlan_objmgr_pdev *pdev)
3914  {
3915  	struct wlan_objmgr_psoc *psoc = NULL;
3916  	struct wlan_lmac_if_tx_ops *tx_ops = NULL;
3917  	struct wlan_lmac_if_scan_tx_ops *scan_ops = NULL;
3918  	uint8_t pdev_id;
3919  
3920  	psoc = wlan_pdev_get_psoc(pdev);
3921  	if (!psoc) {
3922  		scm_debug_rl("psoc is null");
3923  		return false;
3924  	}
3925  	tx_ops = wlan_psoc_get_lmac_if_txops(psoc);
3926  	if (!tx_ops) {
3927  		scm_debug_rl("tx_ops is null");
3928  		return false;
3929  	}
3930  	scan_ops = &tx_ops->scan;
3931  	if (!scan_ops) {
3932  		scm_debug_rl("scan_ops is null");
3933  		return false;
3934  	}
3935  	pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
3936  
3937  	if (scan_ops->is_platform_eht_capable)
3938  		return scan_ops->is_platform_eht_capable(psoc, pdev_id);
3939  
3940  	return false;
3941  }
3942  #else
3943  static QDF_STATUS
util_scan_parse_eht_beacon(struct wlan_objmgr_pdev * pdev,uint8_t * frame,qdf_size_t frame_len,uint8_t * ie_list,uint32_t ielen,uint32_t frm_subtype,struct mgmt_rx_event_params * rx_param,qdf_list_t * scan_list,struct scan_mbssid_info * mbssid_info,uint8_t * mbssid_ie)3944  util_scan_parse_eht_beacon(struct wlan_objmgr_pdev *pdev,
3945  			   uint8_t *frame, qdf_size_t frame_len,
3946  			   uint8_t *ie_list, uint32_t ielen,
3947  			   uint32_t frm_subtype,
3948  			   struct mgmt_rx_event_params *rx_param,
3949  			   qdf_list_t *scan_list,
3950  			   struct scan_mbssid_info *mbssid_info,
3951  			   uint8_t *mbssid_ie)
3952  {
3953  	return QDF_STATUS_SUCCESS;
3954  }
3955  
3956  static bool
util_scan_is_platform_eht_capable(struct wlan_objmgr_pdev * pdev)3957  util_scan_is_platform_eht_capable(struct wlan_objmgr_pdev *pdev)
3958  {
3959  	return false;
3960  }
3961  #endif
3962  
3963  static QDF_STATUS
util_scan_parse_beacon_frame(struct wlan_objmgr_pdev * pdev,uint8_t * frame,qdf_size_t frame_len,uint32_t frm_subtype,struct mgmt_rx_event_params * rx_param,qdf_list_t * scan_list)3964  util_scan_parse_beacon_frame(struct wlan_objmgr_pdev *pdev,
3965  			     uint8_t *frame,
3966  			     qdf_size_t frame_len,
3967  			     uint32_t frm_subtype,
3968  			     struct mgmt_rx_event_params *rx_param,
3969  			     qdf_list_t *scan_list)
3970  {
3971  	struct wlan_bcn_frame *bcn;
3972  	struct wlan_frame_hdr *hdr;
3973  	uint8_t *mbssid_ie = NULL, *extcap_ie;
3974  	uint32_t ie_len = 0;
3975  	QDF_STATUS status = QDF_STATUS_E_FAILURE;
3976  	struct scan_mbssid_info mbssid_info = { 0 };
3977  	uint8_t *ie_list;
3978  	bool eht_support = false;
3979  
3980  	hdr = (struct wlan_frame_hdr *)frame;
3981  	bcn = (struct wlan_bcn_frame *)
3982  		(frame + sizeof(struct wlan_frame_hdr));
3983  	ie_list = (uint8_t *)&bcn->ie;
3984  	ie_len = (uint16_t)(frame_len -
3985  			    sizeof(struct wlan_frame_hdr) -
3986  			    offsetof(struct wlan_bcn_frame, ie));
3987  
3988  	extcap_ie = util_scan_find_ie(WLAN_ELEMID_XCAPS,
3989  				      (uint8_t *)&bcn->ie, ie_len);
3990  	/* Process MBSSID when Multiple BSSID (Bit 22) is set in Ext Caps */
3991  	if (extcap_ie &&
3992  	    extcap_ie[1] >= 3 && extcap_ie[1] <= WLAN_EXTCAP_IE_MAX_LEN &&
3993  	    (extcap_ie[4] & 0x40)) {
3994  		mbssid_ie = util_scan_find_ie(WLAN_ELEMID_MULTIPLE_BSSID,
3995  					      (uint8_t *)&bcn->ie, ie_len);
3996  		if (mbssid_ie) {
3997  			/* some APs announce the MBSSID ie_len as 1 */
3998  			if (mbssid_ie[TAG_LEN_POS] < 1) {
3999  				scm_debug("MBSSID IE length is wrong %d",
4000  					  mbssid_ie[TAG_LEN_POS]);
4001  				return status;
4002  			}
4003  			qdf_mem_copy(&mbssid_info.trans_bssid,
4004  				     hdr->i_addr3, QDF_MAC_ADDR_SIZE);
4005  			mbssid_info.profile_count = 1 << mbssid_ie[2];
4006  		}
4007  	}
4008  
4009  	eht_support = util_scan_is_platform_eht_capable(pdev);
4010  
4011  	if (eht_support) {
4012  		status = util_scan_parse_eht_beacon(pdev, frame, frame_len,
4013  						    ie_list, ie_len,
4014  						    frm_subtype, rx_param,
4015  						    scan_list, &mbssid_info,
4016  						    mbssid_ie);
4017  		return status;
4018  	}
4019  
4020  	status = util_scan_gen_scan_entry(pdev, frame, frame_len,
4021  					  frm_subtype, rx_param,
4022  					  &mbssid_info,
4023  					  scan_list);
4024  
4025  	if (mbssid_ie)
4026  		status = util_scan_parse_mbssid(pdev, frame, frame_len,
4027  						frm_subtype, rx_param,
4028  						scan_list);
4029  
4030  	if (QDF_IS_STATUS_ERROR(status))
4031  		scm_debug_rl("Failed to create scan entry");
4032  
4033  	return status;
4034  }
4035  
4036  qdf_list_t *
util_scan_unpack_beacon_frame(struct wlan_objmgr_pdev * pdev,uint8_t * frame,qdf_size_t frame_len,uint32_t frm_subtype,struct mgmt_rx_event_params * rx_param)4037  util_scan_unpack_beacon_frame(struct wlan_objmgr_pdev *pdev, uint8_t *frame,
4038  			      qdf_size_t frame_len, uint32_t frm_subtype,
4039  			      struct mgmt_rx_event_params *rx_param)
4040  {
4041  	qdf_list_t *scan_list;
4042  	QDF_STATUS status;
4043  
4044  	scan_list = qdf_mem_malloc_atomic(sizeof(*scan_list));
4045  	if (!scan_list) {
4046  		scm_err("failed to allocate scan_list");
4047  		return NULL;
4048  	}
4049  	qdf_list_create(scan_list, MAX_SCAN_CACHE_SIZE);
4050  
4051  	status = util_scan_parse_beacon_frame(pdev, frame, frame_len,
4052  					      frm_subtype, rx_param,
4053  					      scan_list);
4054  	if (QDF_IS_STATUS_ERROR(status)) {
4055  		ucfg_scan_purge_results(scan_list);
4056  		return NULL;
4057  	}
4058  
4059  	return scan_list;
4060  }
4061  
4062  QDF_STATUS
util_scan_entry_update_mlme_info(struct wlan_objmgr_pdev * pdev,struct scan_cache_entry * scan_entry)4063  util_scan_entry_update_mlme_info(struct wlan_objmgr_pdev *pdev,
4064  	struct scan_cache_entry *scan_entry)
4065  {
4066  
4067  	if (!pdev || !scan_entry) {
4068  		scm_err("pdev 0x%pK, scan_entry: 0x%pK", pdev, scan_entry);
4069  		return QDF_STATUS_E_INVAL;
4070  	}
4071  
4072  	return scm_update_scan_mlme_info(pdev, scan_entry);
4073  }
4074  
util_is_scan_completed(struct scan_event * event,bool * success)4075  bool util_is_scan_completed(struct scan_event *event, bool *success)
4076  {
4077  	if ((event->type == SCAN_EVENT_TYPE_COMPLETED) ||
4078  	    (event->type == SCAN_EVENT_TYPE_DEQUEUED) ||
4079  	    (event->type == SCAN_EVENT_TYPE_START_FAILED)) {
4080  		if ((event->type == SCAN_EVENT_TYPE_COMPLETED) &&
4081  		    (event->reason == SCAN_REASON_COMPLETED))
4082  			*success = true;
4083  		else
4084  			*success = false;
4085  
4086  		return true;
4087  	}
4088  
4089  	*success = false;
4090  	return false;
4091  }
4092  
4093  #if defined(WLAN_SAE_SINGLE_PMK) && defined(WLAN_FEATURE_ROAM_OFFLOAD)
4094  bool
util_scan_entry_single_pmk(struct wlan_objmgr_psoc * psoc,struct scan_cache_entry * scan_entry)4095  util_scan_entry_single_pmk(struct wlan_objmgr_psoc *psoc,
4096  			   struct scan_cache_entry *scan_entry)
4097  {
4098  	if (scan_entry->ie_list.single_pmk &&
4099  	    wlan_mlme_is_sae_single_pmk_enabled(psoc))
4100  		return true;
4101  
4102  	return false;
4103  }
4104  #endif
4105  
util_is_bssid_non_tx(struct wlan_objmgr_psoc * psoc,struct qdf_mac_addr * bssid,qdf_freq_t freq)4106  bool util_is_bssid_non_tx(struct wlan_objmgr_psoc *psoc,
4107  			  struct qdf_mac_addr *bssid, qdf_freq_t freq)
4108  {
4109  	int i;
4110  	qdf_list_node_t *cur_node, *next_node;
4111  	struct meta_rnr_channel *channel;
4112  	struct scan_rnr_node *rnr_node;
4113  	struct channel_list_db *rnr_channel_db;
4114  	bool ret = false;
4115  
4116  	if (!psoc)
4117  		return false;
4118  
4119  	rnr_channel_db = scm_get_rnr_channel_db(psoc);
4120  	if (!rnr_channel_db)
4121  		return false;
4122  
4123  	for (i = 0; i < QDF_ARRAY_SIZE(rnr_channel_db->channel); i++) {
4124  		channel = &rnr_channel_db->channel[i];
4125  		if (channel->chan_freq != freq)
4126  			continue;
4127  
4128  		cur_node = NULL;
4129  		qdf_list_peek_front(&channel->rnr_list, &cur_node);
4130  
4131  		while (cur_node) {
4132  			next_node = NULL;
4133  			qdf_list_peek_next(&channel->rnr_list, cur_node,
4134  					   &next_node);
4135  			rnr_node = qdf_container_of(cur_node,
4136  						    struct scan_rnr_node,
4137  						    node);
4138  			if (qdf_is_macaddr_equal(&rnr_node->entry.bssid, bssid) &&
4139  			    (rnr_node->entry.bss_params &
4140  			     TBTT_BSS_PARAM_MBSSID_TX_MASK) ==
4141  			    TBTT_BSS_PARAM_MBSSID_NONTX_MASK) {
4142  				ret = true;
4143  				break;
4144  			}
4145  			cur_node = next_node;
4146  		}
4147  	}
4148  
4149  	return ret;
4150  }
4151