xref: /wlan-dirver/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_cache_db.c (revision 9bad623d0717f5b62b79068bdfb8bc4fbc6948c3)
1 /*
2  * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved.
3  * Copyright (c) 2021-2023 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: contains scan cache api and functionality
22  * The Scan entries are protected by scan_db_lock. Holding the lock
23  * for whole scan operation during get/flush scan results may take
24  * more than 5 ms and thus ref count is used along with scan_db_lock.
25  * Below are the operation on scan cache entry:
26  * - While adding new node to the entry scan_db_lock is taken and ref_cnt
27  *   is initialized and incremented. Also the cookie will be set to valid value.
28  * - The ref count incremented during adding new node should be decremented only
29  *   by a delete operation on the node. But there can be multiple concurrent
30  *   delete operations on a node from different threads which may lead to ref
31  *   count being decremented multiple time and freeing the node even if node
32  *   is in use. So to maintain atomicity between multiple delete operations
33  *   on a same node from different threads, a cookie is used to check if node is
34  *   logically deleted or not. A delete operation will set the cookie to 0
35  *   making it invalid. So if the 2nd thread find the cookie as invalid it will
36  *   not try to delete and decrement the ref count of the node again.
37  * - This Cookie is also used to check if node is valid while iterating through
38  *   the scan cache to avoid duplicate entries.
39  * - Once ref_cnt become 0, i.e. it is logically deleted and no thread is using
40  *   it the node is physically deleted from the scan cache.
41  * - While reading the node the ref_cnt should be incremented. Once reading
42  *   operation is done ref_cnt is decremented.
43  */
44 #include <qdf_status.h>
45 #include <wlan_objmgr_psoc_obj.h>
46 #include <wlan_objmgr_pdev_obj.h>
47 #include <wlan_objmgr_vdev_obj.h>
48 #include <wlan_scan_public_structs.h>
49 #include <wlan_scan_utils_api.h>
50 #include "wlan_scan_main.h"
51 #include "wlan_scan_cache_db_i.h"
52 #include "wlan_reg_services_api.h"
53 #include "wlan_reg_ucfg_api.h"
54 #include <wlan_objmgr_vdev_obj.h>
55 #include <wlan_dfs_utils_api.h>
56 #include "wlan_crypto_global_def.h"
57 #include "wlan_crypto_global_api.h"
58 #include "wlan_cm_bss_score_param.h"
59 
60 #ifdef FEATURE_6G_SCAN_CHAN_SORT_ALGO
61 
62 struct channel_list_db *scm_get_rnr_channel_db(struct wlan_objmgr_psoc *psoc)
63 {
64 	struct wlan_scan_obj *scan_obj = NULL;
65 
66 	scan_obj = wlan_psoc_get_scan_obj(psoc);
67 
68 	if (!scan_obj)
69 		return NULL;
70 
71 	return &scan_obj->rnr_channel_db;
72 }
73 
74 struct meta_rnr_channel *scm_get_chan_meta(struct wlan_objmgr_psoc *psoc,
75 					   uint32_t chan_freq)
76 {
77 	int i;
78 	struct channel_list_db *rnr_channel_db;
79 
80 	if (!psoc || !chan_freq || !wlan_reg_is_6ghz_chan_freq(chan_freq))
81 		return NULL;
82 
83 	rnr_channel_db = scm_get_rnr_channel_db(psoc);
84 	if (!rnr_channel_db)
85 		return NULL;
86 
87 	for (i = 0; i < QDF_ARRAY_SIZE(rnr_channel_db->channel); i++)
88 		if (rnr_channel_db->channel[i].chan_freq == chan_freq)
89 			return &rnr_channel_db->channel[i];
90 
91 	return NULL;
92 }
93 
94 static bool scm_is_rnr_present(struct meta_rnr_channel *chan,
95 			       struct qdf_mac_addr *bssid,
96 			       uint32_t short_ssid)
97 {
98 	qdf_list_node_t *cur_node = NULL, *next_node = NULL;
99 	struct scan_rnr_node *rnr_node;
100 	QDF_STATUS status;
101 
102 	if (!chan || qdf_list_empty(&chan->rnr_list))
103 		return false;
104 
105 	qdf_list_peek_front(&chan->rnr_list, &cur_node);
106 	while (cur_node) {
107 		rnr_node = qdf_container_of(cur_node,
108 					    struct scan_rnr_node,
109 					    node);
110 		if (qdf_is_macaddr_equal(&rnr_node->entry.bssid, bssid) &&
111 		    rnr_node->entry.short_ssid == short_ssid)
112 			return true;
113 
114 		status = qdf_list_peek_next(&chan->rnr_list, cur_node,
115 					    &next_node);
116 		if (QDF_IS_STATUS_ERROR(status))
117 			break;
118 		cur_node = next_node;
119 		next_node = NULL;
120 	}
121 
122 	return false;
123 }
124 
125 static void scm_add_rnr_channel_db(struct wlan_objmgr_psoc *psoc,
126 				   struct scan_cache_entry *entry)
127 {
128 	uint32_t chan_freq;
129 	uint8_t is_6g_bss, i;
130 	struct meta_rnr_channel *channel;
131 	struct rnr_bss_info *rnr_bss;
132 	struct scan_rnr_node *rnr_node;
133 
134 	chan_freq = entry->channel.chan_freq;
135 	is_6g_bss = wlan_reg_is_6ghz_chan_freq(chan_freq);
136 
137 	/* Return if the BSS is not 6G and RNR IE is not present */
138 	if (!(is_6g_bss || entry->ie_list.rnrie))
139 		return;
140 
141 	scm_debug("BSS freq %d BSSID: "QDF_MAC_ADDR_FMT, chan_freq,
142 		  QDF_MAC_ADDR_REF(entry->bssid.bytes));
143 	if (is_6g_bss) {
144 		channel = scm_get_chan_meta(psoc, chan_freq);
145 		if (!channel) {
146 			scm_debug("Failed to get chan Meta freq %d", chan_freq);
147 			return;
148 		}
149 		channel->bss_beacon_probe_count++;
150 		channel->beacon_probe_last_time_found = entry->scan_entry_time;
151 	}
152 
153 	/*
154 	 * If scan entry got RNR IE then loop through all
155 	 * entries and increase the BSS count in respective channels
156 	 */
157 	if (!entry->ie_list.rnrie)
158 		return;
159 
160 	for (i = 0; i < MAX_RNR_BSS; i++) {
161 		rnr_bss = &entry->rnr.bss_info[i];
162 		/* Skip if entry is not valid */
163 		if (!rnr_bss->channel_number)
164 			continue;
165 		chan_freq = wlan_reg_chan_opclass_to_freq(rnr_bss->channel_number,
166 							  rnr_bss->operating_class,
167 							  true);
168 		channel = scm_get_chan_meta(psoc, chan_freq);
169 		if (!channel) {
170 			scm_debug("Failed to get chan Meta freq %d", chan_freq);
171 			continue;
172 		}
173 		channel->bss_beacon_probe_count++;
174 		/* Don't add RNR entry if list is full */
175 		if (qdf_list_size(&channel->rnr_list) >= WLAN_MAX_RNR_COUNT) {
176 			scm_debug("List is full");
177 			return;
178 		}
179 		if (scm_is_rnr_present(channel, &rnr_bss->bssid,
180 				       rnr_bss->short_ssid)) {
181 			scm_debug("skip dup freq %d: "QDF_MAC_ADDR_FMT" short ssid %x",
182 				  chan_freq,
183 				  QDF_MAC_ADDR_REF(rnr_bss->bssid.bytes),
184 				  rnr_bss->short_ssid);
185 			continue;
186 		}
187 		rnr_node = qdf_mem_malloc(sizeof(struct scan_rnr_node));
188 		if (!rnr_node)
189 			return;
190 		rnr_node->entry.timestamp = entry->scan_entry_time;
191 		if (!qdf_is_macaddr_zero(&rnr_bss->bssid))
192 			qdf_mem_copy(&rnr_node->entry.bssid,
193 				     &rnr_bss->bssid,
194 				     QDF_MAC_ADDR_SIZE);
195 		if (rnr_bss->short_ssid)
196 			rnr_node->entry.short_ssid = rnr_bss->short_ssid;
197 		if (rnr_bss->bss_params)
198 			rnr_node->entry.bss_params = rnr_bss->bss_params;
199 		scm_debug("Add freq %d: "QDF_MAC_ADDR_FMT" short ssid %x", chan_freq,
200 			  QDF_MAC_ADDR_REF(rnr_bss->bssid.bytes),
201 			  rnr_bss->short_ssid);
202 		qdf_list_insert_back(&channel->rnr_list,
203 				     &rnr_node->node);
204 	}
205 }
206 
207 void scm_filter_rnr_flag_pno(struct wlan_objmgr_vdev *vdev,
208 			     uint32_t short_ssid,
209 			     struct chan_list *pno_chan_list)
210 {
211 	uint8_t i;
212 	uint32_t freq;
213 	struct meta_rnr_channel *chan;
214 	struct scan_rnr_node *rnr_node;
215 	enum scan_mode_6ghz scan_mode;
216 	struct wlan_scan_obj *scan_obj;
217 	struct wlan_objmgr_psoc *psoc;
218 
219 	psoc = wlan_vdev_get_psoc(vdev);
220 	if (!psoc)
221 		return;
222 
223 	scan_obj = wlan_vdev_get_scan_obj(vdev);
224 	if (!scan_obj) {
225 		scm_err("scan_obj is NULL");
226 		return;
227 	}
228 
229 	scan_mode = scan_obj->scan_def.scan_mode_6g;
230 	/* No Filteration required for below scan modes since
231 	 * no RNR flag marked.
232 	 */
233 	if (scan_mode == SCAN_MODE_6G_NO_CHANNEL ||
234 	    scan_mode == SCAN_MODE_6G_ALL_CHANNEL ||
235 	    scan_mode == SCAN_MODE_6G_ALL_DUTY_CYCLE)
236 		return;
237 
238 	for (i = 0; i < pno_chan_list->num_chan; i++) {
239 		freq = pno_chan_list->chan[i].freq;
240 
241 		chan = scm_get_chan_meta(psoc, freq);
242 		if (!chan || qdf_list_empty(&chan->rnr_list))
243 			continue;
244 
245 		qdf_list_for_each(&chan->rnr_list, rnr_node, node) {
246 			if (rnr_node->entry.short_ssid) {
247 				if (rnr_node->entry.short_ssid == short_ssid) {
248 			/* If short ssid entry present in RNR db cache, remove
249 			 * FLAG_SCAN_ONLY_IF_RNR_FOUND flag from the channel.
250 			 */
251 					pno_chan_list->chan[i].flags &=
252 						~FLAG_SCAN_ONLY_IF_RNR_FOUND;
253 					break;
254 				}
255 			}
256 		}
257 	}
258 }
259 #endif
260 
261 /**
262  * scm_del_scan_node() - API to remove scan node from the list
263  * @list: hash list
264  * @scan_node: node to be removed
265  *
266  * This should be called while holding scan_db_lock.
267  *
268  * Return: void
269  */
270 static void scm_del_scan_node(qdf_list_t *list,
271 	struct scan_cache_node *scan_node)
272 {
273 	QDF_STATUS status;
274 
275 	status = qdf_list_remove_node(list, &scan_node->node);
276 	if (QDF_IS_STATUS_SUCCESS(status)) {
277 		util_scan_free_cache_entry(scan_node->entry);
278 		qdf_mem_free(scan_node);
279 	}
280 }
281 
282 /**
283  * scm_del_scan_node_from_db() - API to del the scan entry
284  * @scan_db: scan database
285  * @scan_node:entry scan_node
286  *
287  * API to flush the scan entry. This should be called while
288  * holding scan_db_lock.
289  *
290  * Return: QDF status.
291  */
292 static QDF_STATUS scm_del_scan_node_from_db(struct scan_dbs *scan_db,
293 	struct scan_cache_node *scan_node)
294 {
295 	QDF_STATUS status = QDF_STATUS_SUCCESS;
296 	uint8_t hash_idx;
297 
298 	if (!scan_node)
299 		return QDF_STATUS_E_INVAL;
300 
301 	hash_idx = SCAN_GET_HASH(scan_node->entry->bssid.bytes);
302 	scm_del_scan_node(&scan_db->scan_hash_tbl[hash_idx], scan_node);
303 	scan_db->num_entries--;
304 
305 	return status;
306 }
307 
308 /**
309  * scm_scan_entry_get_ref() - api to increase ref count of scan entry
310  * @scan_node: scan node
311  *
312  * Return: void
313  */
314 static void scm_scan_entry_get_ref(struct scan_cache_node *scan_node)
315 {
316 	if (!scan_node) {
317 		scm_err("scan_node is NULL");
318 		QDF_ASSERT(0);
319 		return;
320 	}
321 	qdf_atomic_inc(&scan_node->ref_cnt);
322 }
323 
324 /**
325  * scm_scan_entry_put_ref() - Api to decrease ref count of scan entry
326  * and free if it become 0
327  * @scan_db: scan database
328  * @scan_node: scan node
329  * @lock_needed: if scan_db_lock is needed
330  *
331  * Return: void
332  */
333 static void scm_scan_entry_put_ref(struct scan_dbs *scan_db,
334 	struct scan_cache_node *scan_node, bool lock_needed)
335 {
336 
337 	if (!scan_node) {
338 		scm_err("scan_node is NULL");
339 		QDF_ASSERT(0);
340 		return;
341 	}
342 
343 	if (lock_needed)
344 		qdf_spin_lock_bh(&scan_db->scan_db_lock);
345 
346 	if (!qdf_atomic_read(&scan_node->ref_cnt)) {
347 		if (lock_needed)
348 			qdf_spin_unlock_bh(&scan_db->scan_db_lock);
349 		scm_err("scan_node ref cnt is 0");
350 		QDF_ASSERT(0);
351 		return;
352 	}
353 
354 	/* Decrement ref count, free scan_node, if ref count == 0 */
355 	if (qdf_atomic_dec_and_test(&scan_node->ref_cnt))
356 		scm_del_scan_node_from_db(scan_db, scan_node);
357 
358 	if (lock_needed)
359 		qdf_spin_unlock_bh(&scan_db->scan_db_lock);
360 }
361 
362 /**
363  * scm_scan_entry_del() - API to delete scan node
364  * @scan_db: data base
365  * @scan_node: node to be deleted
366  *
367  * Call must be protected by scan_db->scan_db_lock
368  *
369  * Return: void
370  */
371 
372 static void scm_scan_entry_del(struct scan_dbs *scan_db,
373 			       struct scan_cache_node *scan_node)
374 {
375 	if (!scan_node) {
376 		scm_err("scan node is NULL");
377 		QDF_ASSERT(0);
378 		return;
379 	}
380 
381 	if (scan_node->cookie != SCAN_NODE_ACTIVE_COOKIE) {
382 		scm_debug("node is already deleted");
383 		return;
384 	}
385 	/* Seems node is already deleted */
386 	if (!qdf_atomic_read(&scan_node->ref_cnt)) {
387 		scm_debug("node is already deleted ref 0");
388 		return;
389 	}
390 	scan_node->cookie = 0;
391 	scm_scan_entry_put_ref(scan_db, scan_node, false);
392 }
393 
394 /**
395  * scm_add_scan_node() - API to add scan node
396  * @scan_db: data base
397  * @scan_node: node to be added
398  * @dup_node: node before which new node to be added
399  * if it's not NULL, otherwise add node to tail
400  *
401  * Call must be protected by scan_db->scan_db_lock
402  *
403  * Return: void
404  */
405 static void scm_add_scan_node(struct scan_dbs *scan_db,
406 	struct scan_cache_node *scan_node,
407 	struct scan_cache_node *dup_node)
408 {
409 	uint8_t hash_idx;
410 
411 	hash_idx =
412 		SCAN_GET_HASH(scan_node->entry->bssid.bytes);
413 
414 	qdf_atomic_init(&scan_node->ref_cnt);
415 	scan_node->cookie = SCAN_NODE_ACTIVE_COOKIE;
416 	scm_scan_entry_get_ref(scan_node);
417 	if (!dup_node)
418 		qdf_list_insert_back(&scan_db->scan_hash_tbl[hash_idx],
419 				     &scan_node->node);
420 	else
421 		qdf_list_insert_before(&scan_db->scan_hash_tbl[hash_idx],
422 				       &scan_node->node, &dup_node->node);
423 
424 	scan_db->num_entries++;
425 }
426 
427 
428 /**
429  * scm_get_next_valid_node() - API get the next valid scan node from
430  * the list
431  * @list: hash list
432  * @cur_node: current node pointer
433  *
434  * API to get next active node from the list. If cur_node is NULL
435  * it will return first node of the list.
436  * Call must be protected by scan_db->scan_db_lock
437  *
438  * Return: next scan node
439  */
440 static qdf_list_node_t *
441 scm_get_next_valid_node(qdf_list_t *list,
442 	qdf_list_node_t *cur_node)
443 {
444 	qdf_list_node_t *next_node = NULL;
445 	qdf_list_node_t *temp_node = NULL;
446 	struct scan_cache_node *scan_node;
447 
448 	if (cur_node)
449 		qdf_list_peek_next(list, cur_node, &next_node);
450 	else
451 		qdf_list_peek_front(list, &next_node);
452 
453 	while (next_node) {
454 		scan_node = qdf_container_of(next_node,
455 			struct scan_cache_node, node);
456 		if (scan_node->cookie == SCAN_NODE_ACTIVE_COOKIE)
457 			return next_node;
458 		/*
459 		 * If node is not valid check for next entry
460 		 * to get next valid node.
461 		 */
462 		qdf_list_peek_next(list, next_node, &temp_node);
463 		next_node = temp_node;
464 		temp_node = NULL;
465 	}
466 
467 	return next_node;
468 }
469 
470 /**
471  * scm_get_next_node() - API get the next scan node from
472  * the list
473  * @scan_db: scan data base
474  * @list: hash list
475  * @cur_node: current node pointer
476  *
477  * API get the next node from the list. If cur_node is NULL
478  * it will return first node of the list
479  *
480  * Return: next scan cache node
481  */
482 static struct scan_cache_node *
483 scm_get_next_node(struct scan_dbs *scan_db,
484 	qdf_list_t *list, struct scan_cache_node *cur_node)
485 {
486 	struct scan_cache_node *next_node = NULL;
487 	qdf_list_node_t *next_list = NULL;
488 
489 	qdf_spin_lock_bh(&scan_db->scan_db_lock);
490 	if (cur_node) {
491 		next_list = scm_get_next_valid_node(list, &cur_node->node);
492 		/* Decrement the ref count of the previous node */
493 		scm_scan_entry_put_ref(scan_db,
494 			cur_node, false);
495 	} else {
496 		next_list = scm_get_next_valid_node(list, NULL);
497 	}
498 	/* Increase the ref count of the obtained node */
499 	if (next_list) {
500 		next_node = qdf_container_of(next_list,
501 			struct scan_cache_node, node);
502 		scm_scan_entry_get_ref(next_node);
503 	}
504 	qdf_spin_unlock_bh(&scan_db->scan_db_lock);
505 
506 	return next_node;
507 }
508 
509 /**
510  * scm_check_and_age_out() - check and age out the old entries
511  * @scan_db: scan db
512  * @node: node to check for age out
513  * @scan_aging_time: scan cache aging time
514  *
515  * Return: void
516  */
517 static void scm_check_and_age_out(struct scan_dbs *scan_db,
518 	struct scan_cache_node *node,
519 	qdf_time_t scan_aging_time)
520 {
521 	if (util_scan_entry_age(node->entry) >=
522 	   scan_aging_time) {
523 		scm_debug("Aging out BSSID: "QDF_MAC_ADDR_FMT" with age %lu ms",
524 			  QDF_MAC_ADDR_REF(node->entry->bssid.bytes),
525 			  util_scan_entry_age(node->entry));
526 		qdf_spin_lock_bh(&scan_db->scan_db_lock);
527 		scm_scan_entry_del(scan_db, node);
528 		qdf_spin_unlock_bh(&scan_db->scan_db_lock);
529 	}
530 }
531 
532 static bool scm_bss_is_connected(struct scan_cache_entry *entry)
533 {
534 	if (entry->mlme_info.assoc_state == SCAN_ENTRY_CON_STATE_ASSOC)
535 		return true;
536 	return false;
537 }
538 
539 /**
540  * scm_get_conn_node() - Get the scan cache entry node of the connected BSS
541  * @scan_db: scan DB pointer
542  *
543  * Return: scan cache entry node of connected BSS if exists, NULL otherwise
544  */
545 static
546 struct scan_cache_node *scm_get_conn_node(struct scan_dbs *scan_db)
547 {
548 	int i;
549 	struct scan_cache_node *cur_node = NULL;
550 	struct scan_cache_node *next_node = NULL;
551 
552 	for (i = 0 ; i < SCAN_HASH_SIZE; i++) {
553 		cur_node = scm_get_next_node(scan_db,
554 			&scan_db->scan_hash_tbl[i], NULL);
555 		while (cur_node) {
556 			if (scm_bss_is_connected(cur_node->entry))
557 				return cur_node;
558 			next_node = scm_get_next_node(scan_db,
559 				&scan_db->scan_hash_tbl[i], cur_node);
560 			cur_node = next_node;
561 			next_node = NULL;
562 		}
563 	}
564 
565 	return NULL;
566 }
567 
568 static bool
569 scm_bss_is_nontx_of_conn_bss(struct scan_cache_node *conn_node,
570 			     struct scan_cache_node *cur_node)
571 {
572 	if (cur_node->entry->mbssid_info.profile_num &&
573 	    !memcmp(conn_node->entry->mbssid_info.trans_bssid,
574 		    cur_node->entry->mbssid_info.trans_bssid,
575 		    QDF_MAC_ADDR_SIZE))
576 		return true;
577 
578 	return false;
579 }
580 
581 void scm_age_out_entries(struct wlan_objmgr_psoc *psoc,
582 	struct scan_dbs *scan_db)
583 {
584 	int i;
585 	struct scan_cache_node *cur_node = NULL;
586 	struct scan_cache_node *next_node = NULL;
587 	struct scan_cache_node *conn_node = NULL;
588 	struct scan_default_params *def_param;
589 
590 	def_param = wlan_scan_psoc_get_def_params(psoc);
591 	if (!def_param) {
592 		scm_err("wlan_scan_psoc_get_def_params failed");
593 		return;
594 	}
595 
596 	conn_node = scm_get_conn_node(scan_db);
597 	for (i = 0 ; i < SCAN_HASH_SIZE; i++) {
598 		cur_node = scm_get_next_node(scan_db,
599 			&scan_db->scan_hash_tbl[i], NULL);
600 		while (cur_node) {
601 			if (!conn_node /* if there is no connected node */ ||
602 			    /* OR cur_node is not part of the MBSSID of the
603 			     * connected node
604 			     */
605 			    (!scm_bss_is_connected(cur_node->entry) &&
606 			     !scm_bss_is_nontx_of_conn_bss(conn_node,
607 							  cur_node))) {
608 				scm_check_and_age_out(scan_db, cur_node,
609 					def_param->scan_cache_aging_time);
610 			}
611 			next_node = scm_get_next_node(scan_db,
612 				&scan_db->scan_hash_tbl[i], cur_node);
613 			cur_node = next_node;
614 			next_node = NULL;
615 		}
616 	}
617 
618 	if (conn_node)
619 		scm_scan_entry_put_ref(scan_db, conn_node, true);
620 }
621 
622 /**
623  * scm_flush_oldest_entry() - Iterate over scan db and flust out the
624  *  oldest entry
625  * @scan_db: scan db from which oldest entry needs to be flushed
626  *
627  * Return: QDF_STATUS
628  */
629 static QDF_STATUS scm_flush_oldest_entry(struct scan_dbs *scan_db)
630 {
631 	int i;
632 	struct scan_cache_node *oldest_node = NULL;
633 	struct scan_cache_node *cur_node;
634 
635 	for (i = 0 ; i < SCAN_HASH_SIZE; i++) {
636 		/* Get the first valid node for the hash */
637 		cur_node = scm_get_next_node(scan_db,
638 					     &scan_db->scan_hash_tbl[i],
639 					     NULL);
640 		 /* Iterate scan db and flush out oldest node
641 		  * take ref_cnt for oldest_node
642 		  */
643 
644 		while (cur_node) {
645 			if (!oldest_node ||
646 			   (util_scan_entry_age(oldest_node->entry) <
647 			    util_scan_entry_age(cur_node->entry))) {
648 				if (oldest_node)
649 					scm_scan_entry_put_ref(scan_db,
650 							       oldest_node,
651 							       true);
652 				qdf_spin_lock_bh(&scan_db->scan_db_lock);
653 				oldest_node = cur_node;
654 				scm_scan_entry_get_ref(oldest_node);
655 				qdf_spin_unlock_bh(&scan_db->scan_db_lock);
656 			}
657 
658 			cur_node = scm_get_next_node(scan_db,
659 					&scan_db->scan_hash_tbl[i],
660 					cur_node);
661 		};
662 	}
663 
664 	if (oldest_node) {
665 		scm_debug("Flush oldest BSSID: "QDF_MAC_ADDR_FMT" with age %lu ms",
666 			  QDF_MAC_ADDR_REF(oldest_node->entry->bssid.bytes),
667 			  util_scan_entry_age(oldest_node->entry));
668 		/* Release ref_cnt taken for oldest_node and delete it */
669 		qdf_spin_lock_bh(&scan_db->scan_db_lock);
670 		scm_scan_entry_del(scan_db, oldest_node);
671 		scm_scan_entry_put_ref(scan_db, oldest_node, false);
672 		qdf_spin_unlock_bh(&scan_db->scan_db_lock);
673 	}
674 
675 	return QDF_STATUS_SUCCESS;
676 }
677 
678 /**
679  * scm_update_alt_wcn_ie() - update the alternate WCN IE
680  * @from: copy from
681  * @dst: copy to
682  *
683  * Return: void
684  */
685 static void scm_update_alt_wcn_ie(struct scan_cache_entry *from,
686 	struct scan_cache_entry *dst)
687 {
688 	uint32_t alt_wcn_ie_len;
689 
690 	if (from->frm_subtype == dst->frm_subtype)
691 		return;
692 
693 	if (!from->ie_list.wcn && !dst->ie_list.wcn)
694 		return;
695 
696 	/* Existing WCN IE is empty. */
697 	if (!from->ie_list.wcn)
698 		return;
699 
700 	alt_wcn_ie_len = 2 + from->ie_list.wcn[1];
701 	if (alt_wcn_ie_len > WLAN_MAX_IE_LEN + 2) {
702 		scm_err("invalid IE len");
703 		return;
704 	}
705 
706 	if (!dst->alt_wcn_ie.ptr) {
707 		/* allocate this additional buffer for alternate WCN IE */
708 		dst->alt_wcn_ie.ptr =
709 			qdf_mem_malloc_atomic(WLAN_MAX_IE_LEN + 2);
710 		if (!dst->alt_wcn_ie.ptr) {
711 			scm_err("failed to allocate memory");
712 			return;
713 		}
714 	}
715 	qdf_mem_copy(dst->alt_wcn_ie.ptr,
716 		from->ie_list.wcn, alt_wcn_ie_len);
717 	dst->alt_wcn_ie.len = alt_wcn_ie_len;
718 }
719 
720 /**
721  * scm_update_mlme_info() - update mlme info
722  * @src: source scan entry
723  * @dest: destination scan entry
724  *
725  * Return: void
726  */
727 static inline void
728 scm_update_mlme_info(struct scan_cache_entry *src,
729 	struct scan_cache_entry *dest)
730 {
731 	qdf_mem_copy(&dest->mlme_info, &src->mlme_info,
732 		sizeof(struct mlme_info));
733 }
734 
735 /**
736  * scm_copy_info_from_dup_entry() - copy duplicate node info
737  * to new scan entry
738  * @pdev: pdev ptr
739  * @scan_obj: scan obj ptr
740  * @scan_db: scan database
741  * @scan_params: new entry to be added
742  * @scan_node: duplicate entry
743  *
744  * Copy duplicate node info to new entry.
745  *
746  * Return: void
747  */
748 static void
749 scm_copy_info_from_dup_entry(struct wlan_objmgr_pdev *pdev,
750 			     struct wlan_scan_obj *scan_obj,
751 			     struct scan_dbs *scan_db,
752 			     struct scan_cache_entry *scan_params,
753 			     struct scan_cache_node *scan_node)
754 {
755 	struct scan_cache_entry *scan_entry;
756 	uint64_t time_gap;
757 
758 	scan_entry = scan_node->entry;
759 
760 	/* Update probe resp entry as well if AP is in hidden mode */
761 	if (scan_params->frm_subtype == MGMT_SUBTYPE_PROBE_RESP &&
762 	    scan_entry->is_hidden_ssid)
763 		scan_params->is_hidden_ssid = true;
764 
765 	/*
766 	 * If AP changed its beacon from not having an SSID to showing it the
767 	 * kernel will drop the entry asumming that something is wrong with AP.
768 	 * This can result in connection failure while updating the bss during
769 	 * connection. So flush the hidden entry from kernel before indicating
770 	 * the new entry.
771 	 */
772 	if (scan_entry->is_hidden_ssid &&
773 	    scan_params->frm_subtype == MGMT_SUBTYPE_BEACON &&
774 	    !util_scan_is_null_ssid(&scan_params->ssid)) {
775 		if (scan_obj->cb.unlink_bss) {
776 			scm_debug("Hidden AP "QDF_MAC_ADDR_FMT" switch to non-hidden SSID, So unlink the entry",
777 				  QDF_MAC_ADDR_REF(scan_entry->bssid.bytes));
778 			scan_obj->cb.unlink_bss(pdev, scan_entry);
779 		}
780 	}
781 
782 	/* If old entry have the ssid but new entry does not */
783 	if (util_scan_is_null_ssid(&scan_params->ssid) &&
784 	    scan_entry->ssid.length) {
785 		/*
786 		 * New entry has a hidden SSID and old one has the SSID.
787 		 * Add the entry by using the ssid of the old entry
788 		 * only if diff of saved SSID time and current time is
789 		 * less than HIDDEN_SSID_TIME time.
790 		 * This will avoid issues in case AP changes its SSID
791 		 * while remain hidden.
792 		 */
793 		time_gap =
794 			qdf_mc_timer_get_system_time() -
795 			scan_entry->hidden_ssid_timestamp;
796 		if (time_gap <= HIDDEN_SSID_TIME) {
797 			scan_params->hidden_ssid_timestamp =
798 				scan_entry->hidden_ssid_timestamp;
799 			scan_params->ssid.length =
800 				scan_entry->ssid.length;
801 			qdf_mem_copy(scan_params->ssid.ssid,
802 				scan_entry->ssid.ssid,
803 				scan_entry->ssid.length);
804 		}
805 	}
806 
807 	/*
808 	 * Due to Rx sensitivity issue, sometime beacons are seen on adjacent
809 	 * channel so workaround in software is needed. If DS params or HT info
810 	 * are present driver can get proper channel info from these IEs and set
811 	 * channel_mismatch so that the older RSSI values are used in new entry.
812 	 *
813 	 * For the cases where DS params and HT info is not present, driver
814 	 * needs to check below conditions to get proper channel and set
815 	 * channel_mismatch so that the older RSSI values are used in new entry:
816 	 *   -- The old entry channel and new entry channel are not same
817 	 *   -- RSSI is less than -80, this indicate that the signal has leaked
818 	 *       in adjacent channel.
819 	 */
820 	time_gap =
821 		scan_params->scan_entry_time -
822 		scan_entry->rssi_timestamp;
823 
824 	if ((scan_params->frm_subtype == MGMT_SUBTYPE_BEACON ||
825 	     scan_params->frm_subtype == MGMT_SUBTYPE_PROBE_RESP) &&
826 	    !util_scan_entry_htinfo(scan_params) &&
827 	    !util_scan_entry_ds_param(scan_params) &&
828 	    !util_scan_entry_vhtop(scan_params) &&
829 	    !util_scan_entry_heop(scan_params) &&
830 	    (scan_params->channel.chan_freq != scan_entry->channel.chan_freq) &&
831 	    (scan_params->rssi_raw  < ADJACENT_CHANNEL_RSSI_THRESHOLD ||
832 	     (time_gap < WLAN_RSSI_AVERAGING_TIME &&
833 	      (scan_params->rssi_raw + ADJACENT_CHANNEL_RSSI_DIFF_THRESHOLD) <
834 	      scan_entry->rssi_raw))) {
835 		scan_params->channel.chan_freq = scan_entry->channel.chan_freq;
836 		scan_params->channel_mismatch = true;
837 	}
838 
839 	/* Use old value for rssi if beacon was heard on adjacent channel. */
840 	if (scan_params->channel_mismatch) {
841 		scan_params->snr = scan_entry->snr;
842 		scan_params->avg_snr = scan_entry->avg_snr;
843 		scan_params->rssi_raw = scan_entry->rssi_raw;
844 		scan_params->avg_rssi = scan_entry->avg_rssi;
845 		scan_params->rssi_timestamp =
846 			scan_entry->rssi_timestamp;
847 	} else {
848 		/* If elapsed time since last rssi and snr update for this
849 		 * entry is smaller than a threshold, calculate a
850 		 * running average of the RSSI and SNR values.
851 		 * Otherwise new frames RSSI and SNR are more representative
852 		 * of the signal strength.
853 		 */
854 		if (time_gap > WLAN_RSSI_AVERAGING_TIME) {
855 			scan_params->avg_rssi =
856 				WLAN_RSSI_IN(scan_params->rssi_raw);
857 			scan_params->avg_snr =
858 				WLAN_SNR_IN(scan_params->snr);
859 		}
860 		else {
861 			/* Copy previous average rssi and snr to new entry */
862 			scan_params->avg_snr = scan_entry->avg_snr;
863 			scan_params->avg_rssi = scan_entry->avg_rssi;
864 			/* Average with previous samples */
865 			WLAN_RSSI_LPF(scan_params->avg_rssi,
866 				      scan_params->rssi_raw);
867 			WLAN_SNR_LPF(scan_params->avg_snr,
868 				     scan_params->snr);
869 		}
870 
871 		scan_params->rssi_timestamp = scan_params->scan_entry_time;
872 	}
873 
874 	/* copy wsn ie from scan_entry to scan_params*/
875 	scm_update_alt_wcn_ie(scan_entry, scan_params);
876 
877 	/* copy mlme info from scan_entry to scan_params*/
878 	scm_update_mlme_info(scan_entry, scan_params);
879 }
880 
881 /**
882  * scm_find_duplicate() - find duplicate entry,
883  * if present, add input scan entry before it and delete
884  * duplicate entry. otherwise add entry to tail
885  * @pdev: pdev ptr
886  * @scan_obj: scan obj ptr
887  * @scan_db: scan db
888  * @entry: input scan cache entry
889  * @dup_node: node before which new entry to be added
890  *
891  * ref_cnt is taken for dup_node, caller should release ref taken
892  * if returns true.
893  *
894  * Return: bool
895  */
896 static bool
897 scm_find_duplicate(struct wlan_objmgr_pdev *pdev,
898 		   struct wlan_scan_obj *scan_obj,
899 		   struct scan_dbs *scan_db,
900 		   struct scan_cache_entry *entry,
901 		   struct scan_cache_node **dup_node)
902 {
903 	uint8_t hash_idx;
904 	struct scan_cache_node *cur_node;
905 	struct scan_cache_node *next_node = NULL;
906 
907 	hash_idx = SCAN_GET_HASH(entry->bssid.bytes);
908 
909 	cur_node = scm_get_next_node(scan_db,
910 				     &scan_db->scan_hash_tbl[hash_idx],
911 				     NULL);
912 
913 	while (cur_node) {
914 		if (util_is_scan_entry_match(entry,
915 		   cur_node->entry)) {
916 			scm_copy_info_from_dup_entry(pdev, scan_obj, scan_db,
917 						     entry, cur_node);
918 			*dup_node = cur_node;
919 			return true;
920 		}
921 		next_node = scm_get_next_node(scan_db,
922 			 &scan_db->scan_hash_tbl[hash_idx], cur_node);
923 		cur_node = next_node;
924 		next_node = NULL;
925 	}
926 
927 	return false;
928 }
929 
930 /*
931  * Buffer len size to add the dynamic scan frame debug info
932  * 7 (pdev id) + 21 (security info) + 8 (hidden info) + 15 (chan mismatch) +
933  * 8 (CSA IE info) + 31 (ML info) + 5 extra
934  */
935 #define SCAN_DUMP_MAX_LEN 95
936 
937 #ifdef WLAN_FEATURE_11BE_MLO
938 /**
939  * scm_dump_ml_scan_info(): Dump ml scan info
940  * @scan_params: new received entry
941  * @log_str: Buffer pointer
942  * @str_len: max string length
943  * @len: already filled length in buffer
944  *
945  * Return: length filled in buffer
946  */
947 static uint32_t scm_dump_ml_scan_info(struct scan_cache_entry *scan_params,
948 				      char *log_str, uint32_t str_len,
949 				      uint32_t len)
950 {
951 	/* Scenario: When both STA and AP support ML then
952 	 * Driver will fill ml_info structure and print the MLD address and no.
953 	 * of links.
954 	 */
955 	if (qdf_is_macaddr_zero(&scan_params->ml_info.mld_mac_addr))
956 		return 0;
957 
958 	return qdf_scnprintf(log_str + len, str_len - len,
959 		", MLD " QDF_MAC_ADDR_FMT " links %d",
960 		QDF_MAC_ADDR_REF(scan_params->ml_info.mld_mac_addr.bytes),
961 		scan_params->ml_info.num_links);
962 }
963 #else
964 static uint32_t scm_dump_ml_scan_info(struct scan_cache_entry *scan_params,
965 				      char *log_str, uint32_t str_len,
966 				      uint32_t len)
967 {
968 	return 0;
969 }
970 #endif
971 
972 static void scm_dump_scan_entry(struct wlan_objmgr_pdev *pdev,
973 				struct scan_cache_entry *scan_params)
974 {
975 	uint8_t security_type;
976 	char log_str[SCAN_DUMP_MAX_LEN] = {0};
977 	uint32_t str_len = SCAN_DUMP_MAX_LEN;
978 	uint8_t pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev);
979 	uint32_t len = 0;
980 
981 	/* Add pdev_id if its non zero */
982 	if (pdev_id)
983 		len += qdf_scnprintf(log_str + len, str_len - len,
984 				     "pdev %d ", pdev_id);
985 
986 	/* Add WPA/RSN/WAPI/WEP info if its non zero */
987 	security_type = scan_params->security_type;
988 	if (security_type)
989 		len += qdf_scnprintf(log_str + len, str_len - len,
990 				     "%s%s%s%s",
991 				     security_type & SCAN_SECURITY_TYPE_WPA ?
992 				     "[WPA]" : "",
993 				     security_type & SCAN_SECURITY_TYPE_RSN ?
994 				     "[RSN]" : "",
995 				     security_type & SCAN_SECURITY_TYPE_WAPI ?
996 				     "[WAPI]" : "",
997 				     security_type & SCAN_SECURITY_TYPE_WEP ?
998 				     "[WEP]" : "");
999 
1000 	/* Add hidden info if present */
1001 	if (scan_params->is_hidden_ssid)
1002 		len += qdf_scnprintf(log_str + len, str_len - len, "[hidden]");
1003 
1004 	/* Add channel mismatch info if present */
1005 	if (scan_params->channel_mismatch)
1006 		len += qdf_scnprintf(log_str + len, str_len - len,
1007 				     "[Chan mismatch]");
1008 
1009 	/* Add CSA IE info if present */
1010 	if (scan_params->ie_list.csa ||
1011 	    scan_params->ie_list.xcsa ||
1012 	    scan_params->ie_list.cswrp)
1013 		len += qdf_scnprintf(log_str + len, str_len - len, "[CSA IE]");
1014 
1015 	/* Add ML info */
1016 	len += scm_dump_ml_scan_info(scan_params, log_str, str_len, len);
1017 
1018 	scm_nofl_debug("Rcvd %s(%d): " QDF_MAC_ADDR_FMT " \"" QDF_SSID_FMT "\" freq %d rssi %d tsf %u seq %d snr %d phy %d %s",
1019 		       (scan_params->frm_subtype == MGMT_SUBTYPE_PROBE_RESP) ?
1020 		       "prb rsp" : "bcn", scan_params->raw_frame.len,
1021 		       QDF_MAC_ADDR_REF(scan_params->bssid.bytes),
1022 		       QDF_SSID_REF(scan_params->ssid.length,
1023 				    scan_params->ssid.ssid),
1024 		       scan_params->channel.chan_freq, scan_params->rssi_raw,
1025 		       scan_params->tsf_delta, scan_params->seq_num,
1026 		       scan_params->snr, scan_params->phy_mode, log_str);
1027 }
1028 
1029 /**
1030  * scm_add_update_entry() - add or update scan entry
1031  * @psoc: psoc ptr
1032  * @pdev: pdev pointer
1033  * @scan_params: new received entry
1034  *
1035  * Return: QDF_STATUS
1036  */
1037 static QDF_STATUS scm_add_update_entry(struct wlan_objmgr_psoc *psoc,
1038 	struct wlan_objmgr_pdev *pdev, struct scan_cache_entry *scan_params)
1039 {
1040 	struct scan_cache_node *dup_node = NULL;
1041 	struct scan_cache_node *scan_node = NULL;
1042 	bool is_dup_found = false;
1043 	QDF_STATUS status;
1044 	struct scan_dbs *scan_db;
1045 	struct wlan_scan_obj *scan_obj;
1046 
1047 	scan_db = wlan_pdev_get_scan_db(psoc, pdev);
1048 	if (!scan_db) {
1049 		scm_err("scan_db is NULL");
1050 		return QDF_STATUS_E_INVAL;
1051 	}
1052 
1053 	scan_obj = wlan_psoc_get_scan_obj(psoc);
1054 	if (!scan_obj) {
1055 		scm_err("scan_obj is NULL");
1056 		return QDF_STATUS_E_INVAL;
1057 	}
1058 
1059 	if (scan_params->frm_subtype ==
1060 	   MGMT_SUBTYPE_PROBE_RESP &&
1061 	   !scan_params->ie_list.ssid)
1062 		scm_debug("Probe resp doesn't contain SSID");
1063 
1064 	is_dup_found = scm_find_duplicate(pdev, scan_obj, scan_db, scan_params,
1065 					  &dup_node);
1066 
1067 	scm_dump_scan_entry(pdev, scan_params);
1068 
1069 	if (scan_obj->cb.inform_beacon)
1070 		scan_obj->cb.inform_beacon(pdev, scan_params);
1071 
1072 	if (scan_db->num_entries >= MAX_SCAN_CACHE_SIZE) {
1073 		status = scm_flush_oldest_entry(scan_db);
1074 		if (QDF_IS_STATUS_ERROR(status)) {
1075 			/* release ref taken for dup node */
1076 			if (is_dup_found)
1077 				scm_scan_entry_put_ref(scan_db, dup_node, true);
1078 			return status;
1079 		}
1080 	}
1081 
1082 	scan_node = qdf_mem_malloc(sizeof(*scan_node));
1083 	if (!scan_node) {
1084 		/* release ref taken for dup node */
1085 		if (is_dup_found)
1086 			scm_scan_entry_put_ref(scan_db, dup_node, true);
1087 		return QDF_STATUS_E_NOMEM;
1088 	}
1089 
1090 	scan_node->entry = scan_params;
1091 	qdf_spin_lock_bh(&scan_db->scan_db_lock);
1092 	scm_add_scan_node(scan_db, scan_node, dup_node);
1093 
1094 	if (is_dup_found) {
1095 		/* release ref taken for dup node and delete it */
1096 		scm_scan_entry_del(scan_db, dup_node);
1097 		scm_scan_entry_put_ref(scan_db, dup_node, false);
1098 	}
1099 	qdf_spin_unlock_bh(&scan_db->scan_db_lock);
1100 
1101 	return QDF_STATUS_SUCCESS;
1102 }
1103 
1104 #ifdef CONFIG_REG_CLIENT
1105 /**
1106  * scm_is_bss_allowed_for_country() - Check if bss is allowed to start for a
1107  * specific country and power mode (VLP?LPI/SP) for 6GHz.
1108  * @psoc: psoc ptr
1109  * @scan_entry: ptr to scan entry
1110  *
1111  * Return: True if allowed, False if not.
1112  */
1113 static bool scm_is_bss_allowed_for_country(struct wlan_objmgr_psoc *psoc,
1114 					   struct scan_cache_entry *scan_entry)
1115 {
1116 	struct wlan_country_ie *cc_ie;
1117 	uint8_t programmed_country[REG_ALPHA2_LEN + 1];
1118 
1119 	if (wlan_reg_is_6ghz_chan_freq(scan_entry->channel.chan_freq)) {
1120 		cc_ie = util_scan_entry_country(scan_entry);
1121 		if (!cc_ie)
1122 			return false;
1123 		wlan_reg_read_current_country(psoc, programmed_country);
1124 		if (cc_ie && qdf_mem_cmp(cc_ie->cc, programmed_country,
1125 					 REG_ALPHA2_LEN)) {
1126 			if (wlan_reg_is_us(programmed_country))
1127 				return false;
1128 		}
1129 	}
1130 	return true;
1131 }
1132 #else
1133 static bool scm_is_bss_allowed_for_country(struct wlan_objmgr_psoc *psoc,
1134 					   struct scan_cache_entry *scan_entry)
1135 {
1136 	return true;
1137 }
1138 #endif
1139 
1140 /**
1141  * scm_is_p2p_wildcard_ssid() - check p2p wildcard ssid or not
1142  * @scan_entry: scan entry
1143  *
1144  * Return: true if SSID is wildcard "DIRECT-" ssid
1145  */
1146 static bool scm_is_p2p_wildcard_ssid(struct scan_cache_entry *scan_entry)
1147 {
1148 	static const char wildcard_ssid[] = "DIRECT-";
1149 	uint8_t len = sizeof(wildcard_ssid) - 1;
1150 
1151 	if (!scan_entry->is_p2p)
1152 		return false;
1153 	if (!qdf_mem_cmp(scan_entry->ssid.ssid,
1154 			 wildcard_ssid, len) &&
1155 	    (scan_entry->ssid.length == len))
1156 		return true;
1157 
1158 	return false;
1159 }
1160 
1161 QDF_STATUS __scm_handle_bcn_probe(struct scan_bcn_probe_event *bcn)
1162 {
1163 	struct wlan_objmgr_psoc *psoc;
1164 	struct wlan_objmgr_pdev *pdev = NULL;
1165 	struct scan_cache_entry *scan_entry;
1166 	struct wlan_scan_obj *scan_obj;
1167 	qdf_list_t *scan_list = NULL;
1168 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1169 	uint32_t list_count, i;
1170 	qdf_list_node_t *next_node = NULL;
1171 	struct scan_cache_node *scan_node;
1172 	struct wlan_frame_hdr *hdr = NULL;
1173 	struct wlan_crypto_params sec_params;
1174 
1175 	if (!bcn) {
1176 		scm_err("bcn is NULL");
1177 		return QDF_STATUS_E_INVAL;
1178 	}
1179 	if (!bcn->rx_data) {
1180 		scm_err("rx_data is NULL");
1181 		status = QDF_STATUS_E_INVAL;
1182 		goto free_nbuf;
1183 	}
1184 	if (!bcn->buf) {
1185 		scm_err("buf is NULL");
1186 		status = QDF_STATUS_E_INVAL;
1187 		goto free_nbuf;
1188 	}
1189 
1190 	hdr = (struct wlan_frame_hdr *)qdf_nbuf_data(bcn->buf);
1191 	psoc = bcn->psoc;
1192 	pdev = wlan_objmgr_get_pdev_by_id(psoc,
1193 			   bcn->rx_data->pdev_id, WLAN_SCAN_ID);
1194 	if (!pdev) {
1195 		scm_err("pdev is NULL for pdev %d", bcn->rx_data->pdev_id);
1196 		status = QDF_STATUS_E_INVAL;
1197 		goto free_nbuf;
1198 	}
1199 	scan_obj = wlan_psoc_get_scan_obj(psoc);
1200 	if (!scan_obj) {
1201 		status = QDF_STATUS_E_INVAL;
1202 		goto free_nbuf;
1203 	}
1204 
1205 	if (qdf_nbuf_len(bcn->buf) <=
1206 	   (sizeof(struct wlan_frame_hdr) +
1207 	   offsetof(struct wlan_bcn_frame, ie))) {
1208 		scm_debug("invalid beacon/probe length");
1209 		status = QDF_STATUS_E_INVAL;
1210 		goto free_nbuf;
1211 	}
1212 
1213 	if (bcn->frm_type == MGMT_SUBTYPE_BEACON &&
1214 	    wlan_reg_is_dfs_for_freq(pdev, bcn->rx_data->chan_freq)) {
1215 		util_scan_add_hidden_ssid(pdev, bcn->buf);
1216 	}
1217 
1218 	scan_list =
1219 		 util_scan_unpack_beacon_frame(pdev, qdf_nbuf_data(bcn->buf),
1220 			qdf_nbuf_len(bcn->buf), bcn->frm_type,
1221 			bcn->rx_data);
1222 	if (!scan_list || qdf_list_empty(scan_list)) {
1223 		scm_debug(QDF_MAC_ADDR_FMT ": failed to unpack %d frame",
1224 			  QDF_MAC_ADDR_REF(hdr->i_addr3), bcn->frm_type);
1225 		status = QDF_STATUS_E_INVAL;
1226 		goto free_nbuf;
1227 	}
1228 
1229 	list_count = qdf_list_size(scan_list);
1230 	for (i = 0; i < list_count; i++) {
1231 		status = qdf_list_remove_front(scan_list, &next_node);
1232 		if (QDF_IS_STATUS_ERROR(status) || !next_node) {
1233 			scm_debug(QDF_MAC_ADDR_FMT ": list remove failure i %d, lsize %d",
1234 				  QDF_MAC_ADDR_REF(hdr->i_addr3), i,
1235 				  list_count);
1236 			status = QDF_STATUS_E_INVAL;
1237 			goto free_nbuf;
1238 		}
1239 
1240 		scan_node = qdf_container_of(next_node,
1241 			struct scan_cache_node, node);
1242 
1243 		scan_entry = scan_node->entry;
1244 
1245 		if (scan_obj->drop_bcn_on_chan_mismatch &&
1246 		    scan_entry->channel_mismatch) {
1247 			scm_nofl_debug(QDF_MAC_ADDR_FMT ": Drop frame(%d) for chan mismatch, seq %d frame freq %d rx data freq %d RSSI %d",
1248 				       QDF_MAC_ADDR_REF(
1249 				       scan_entry->bssid.bytes),
1250 				       bcn->frm_type,
1251 				       scan_entry->seq_num,
1252 				       scan_entry->channel.chan_freq,
1253 				       bcn->rx_data->chan_freq,
1254 				       scan_entry->rssi_raw);
1255 			util_scan_free_cache_entry(scan_entry);
1256 			qdf_mem_free(scan_node);
1257 			continue;
1258 		}
1259 		/* Do not add invalid channel entry as kernel will reject it */
1260 		if (scan_obj->drop_bcn_on_invalid_freq &&
1261 		    !wlan_reg_is_freq_enabled(pdev,
1262 					      scan_entry->channel.chan_freq,
1263 					      REG_BEST_PWR_MODE)) {
1264 			scm_nofl_debug(QDF_MAC_ADDR_FMT ": Drop frame(%d) for invalid freq %d seq %d RSSI %d",
1265 				       QDF_MAC_ADDR_REF(
1266 				       scan_entry->bssid.bytes),
1267 				       bcn->frm_type,
1268 				       scan_entry->channel.chan_freq,
1269 				       scan_entry->seq_num,
1270 				       scan_entry->rssi_raw);
1271 			util_scan_free_cache_entry(scan_entry);
1272 			qdf_mem_free(scan_node);
1273 			continue;
1274 		}
1275 		if (util_scan_entry_rsn(scan_entry)) {
1276 			status = wlan_crypto_rsnie_check(
1277 					&sec_params,
1278 					util_scan_entry_rsn(scan_entry));
1279 			if (QDF_IS_STATUS_ERROR(status) &&
1280 			    !scm_is_p2p_wildcard_ssid(scan_entry)) {
1281 				scm_nofl_debug(QDF_MAC_ADDR_FMT ": Drop frame(%d) with invalid RSN IE freq %d, parse status %d",
1282 					       QDF_MAC_ADDR_REF(
1283 					       scan_entry->bssid.bytes),
1284 					       bcn->frm_type,
1285 					       scan_entry->channel.chan_freq,
1286 					       status);
1287 				util_scan_free_cache_entry(scan_entry);
1288 				qdf_mem_free(scan_node);
1289 				continue;
1290 			}
1291 		}
1292 		if (wlan_cm_get_check_6ghz_security(psoc) &&
1293 		    wlan_reg_is_6ghz_chan_freq(scan_entry->channel.chan_freq)) {
1294 			if (!util_scan_entry_rsn(scan_entry)) {
1295 				scm_info_rl(QDF_MAC_ADDR_FMT ": Drop frame(%d) with No RSN IE in 6GHz(%d)",
1296 					    QDF_MAC_ADDR_REF(
1297 					    scan_entry->bssid.bytes),
1298 					    bcn->frm_type,
1299 					    scan_entry->channel.chan_freq);
1300 				util_scan_free_cache_entry(scan_entry);
1301 				qdf_mem_free(scan_node);
1302 				continue;
1303 			}
1304 			status = wlan_crypto_rsnie_check(&sec_params,
1305 					util_scan_entry_rsn(scan_entry));
1306 			if (QDF_IS_STATUS_ERROR(status)) {
1307 				scm_info_rl(QDF_MAC_ADDR_FMT ": Drop frame(%d) with invalid RSN IE in 6GHz(%d), parse status %d",
1308 					    QDF_MAC_ADDR_REF(
1309 					    scan_entry->bssid.bytes),
1310 					    bcn->frm_type,
1311 					    scan_entry->channel.chan_freq,
1312 					    status);
1313 				util_scan_free_cache_entry(scan_entry);
1314 				qdf_mem_free(scan_node);
1315 				continue;
1316 			}
1317 			if ((QDF_HAS_PARAM(sec_params.ucastcipherset,
1318 					   WLAN_CRYPTO_CIPHER_NONE)) ||
1319 			    (QDF_HAS_PARAM(sec_params.ucastcipherset,
1320 					   WLAN_CRYPTO_CIPHER_TKIP)) ||
1321 			    (QDF_HAS_PARAM(sec_params.ucastcipherset,
1322 					   WLAN_CRYPTO_CIPHER_WEP_40)) ||
1323 			    (QDF_HAS_PARAM(sec_params.ucastcipherset,
1324 					   WLAN_CRYPTO_CIPHER_WEP_104))) {
1325 				scm_info_rl(QDF_MAC_ADDR_FMT ": Drop frame(%d) with Invalid sec type %0X for 6GHz(%d)",
1326 					    QDF_MAC_ADDR_REF(
1327 					    scan_entry->bssid.bytes),
1328 					    bcn->frm_type,
1329 					    sec_params.ucastcipherset,
1330 					    scan_entry->channel.chan_freq);
1331 				util_scan_free_cache_entry(scan_entry);
1332 				qdf_mem_free(scan_node);
1333 				continue;
1334 			}
1335 			if (!wlan_cm_6ghz_allowed_for_akm(psoc,
1336 					sec_params.key_mgmt,
1337 					sec_params.rsn_caps,
1338 					util_scan_entry_rsnxe(scan_entry),
1339 					0, false)) {
1340 				scm_info_rl(QDF_MAC_ADDR_FMT ": Drop frame(%d) with Invalid AKM suite %0X for 6GHz(%d)",
1341 					    QDF_MAC_ADDR_REF(
1342 					    scan_entry->bssid.bytes),
1343 					    bcn->frm_type,
1344 					    sec_params.key_mgmt,
1345 					    scan_entry->channel.chan_freq);
1346 				util_scan_free_cache_entry(scan_entry);
1347 				qdf_mem_free(scan_node);
1348 				continue;
1349 			}
1350 		}
1351 
1352 		scan_entry->non_intersected_phymode = scan_entry->phy_mode;
1353 
1354 		if (scan_obj->cb.update_beacon)
1355 			scan_obj->cb.update_beacon(pdev, scan_entry);
1356 
1357 		/**
1358 		 * Do not drop the frame if Wi-Fi safe mode or RF test mode is
1359 		 * enabled. wlan_cm_get_check_6ghz_security API returns true if
1360 		 * neither Safe mode nor RF test mode are enabled.
1361 		 */
1362 		if (!wlan_cm_get_standard_6ghz_conn_policy(psoc) &&
1363 		    !scm_is_bss_allowed_for_country(psoc, scan_entry) &&
1364 		    wlan_cm_get_check_6ghz_security(psoc)) {
1365 			scm_info_rl(QDF_MAC_ADDR_FMT ": Drop frame(%d) freq %d, as country not present OR VLP mode not supported for US",
1366 				    QDF_MAC_ADDR_REF(scan_entry->bssid.bytes),
1367 				    bcn->frm_type,
1368 				    scan_entry->channel.chan_freq);
1369 			util_scan_free_cache_entry(scan_entry);
1370 			qdf_mem_free(scan_node);
1371 			continue;
1372 		}
1373 
1374 		status = scm_add_update_entry(psoc, pdev, scan_entry);
1375 		if (QDF_IS_STATUS_ERROR(status)) {
1376 			scm_debug(QDF_MAC_ADDR_FMT ": Failed to add entry for frame(%d) seq %d freq %d",
1377 				  QDF_MAC_ADDR_REF(scan_entry->bssid.bytes),
1378 				  bcn->frm_type,
1379 				  scan_entry->seq_num,
1380 				  scan_entry->channel.chan_freq);
1381 			util_scan_free_cache_entry(scan_entry);
1382 			qdf_mem_free(scan_node);
1383 			continue;
1384 		}
1385 
1386 		qdf_mem_free(scan_node);
1387 	}
1388 
1389 free_nbuf:
1390 	if (scan_list)
1391 		qdf_mem_free(scan_list);
1392 	if (bcn->psoc)
1393 		wlan_objmgr_psoc_release_ref(bcn->psoc, WLAN_SCAN_ID);
1394 	if (pdev)
1395 		wlan_objmgr_pdev_release_ref(pdev, WLAN_SCAN_ID);
1396 	if (bcn->rx_data)
1397 		qdf_mem_free(bcn->rx_data);
1398 	if (bcn->buf)
1399 		qdf_nbuf_free(bcn->buf);
1400 	qdf_mem_free(bcn);
1401 
1402 	return status;
1403 }
1404 
1405 QDF_STATUS scm_handle_bcn_probe(struct scheduler_msg *msg)
1406 {
1407 	if (!msg) {
1408 		scm_err("msg is NULL");
1409 		return QDF_STATUS_E_NULL_VALUE;
1410 	}
1411 
1412 	return __scm_handle_bcn_probe(msg->bodyptr);
1413 }
1414 
1415 /**
1416  * scm_scan_apply_filter_get_entry() - apply filter and get the
1417  * scan entry
1418  * @psoc: psoc pointer
1419  * @db_entry: scan entry
1420  * @filter: filter to be applied
1421  * @scan_list: scan list to which entry is added
1422  *
1423  * Return: QDF_STATUS
1424  */
1425 static QDF_STATUS
1426 scm_scan_apply_filter_get_entry(struct wlan_objmgr_psoc *psoc,
1427 	struct scan_cache_entry *db_entry,
1428 	struct scan_filter *filter,
1429 	qdf_list_t *scan_list)
1430 {
1431 	struct scan_cache_node *scan_node = NULL;
1432 	struct security_info security = {0};
1433 	bool match;
1434 
1435 	if (!filter)
1436 		match = true;
1437 	else
1438 		match = scm_filter_match(psoc, db_entry,
1439 					filter, &security);
1440 
1441 	if (!match)
1442 		return QDF_STATUS_SUCCESS;
1443 
1444 	scan_node = qdf_mem_malloc_atomic(sizeof(*scan_node));
1445 	if (!scan_node)
1446 		return QDF_STATUS_E_NOMEM;
1447 
1448 	scan_node->entry =
1449 		util_scan_copy_cache_entry(db_entry);
1450 
1451 	if (!scan_node->entry) {
1452 		qdf_mem_free(scan_node);
1453 		return QDF_STATUS_E_NOMEM;
1454 	}
1455 
1456 	qdf_mem_copy(&scan_node->entry->neg_sec_info,
1457 		&security, sizeof(scan_node->entry->neg_sec_info));
1458 
1459 	qdf_list_insert_front(scan_list, &scan_node->node);
1460 
1461 	return QDF_STATUS_SUCCESS;
1462 }
1463 
1464 /**
1465  * scm_get_results() - Iterate and get scan results
1466  * @psoc: psoc ptr
1467  * @scan_db: scan db
1468  * @filter: filter to be applied
1469  * @scan_list: scan list to which entry is added
1470  *
1471  * Return: void
1472  */
1473 static void scm_get_results(struct wlan_objmgr_psoc *psoc,
1474 	struct scan_dbs *scan_db, struct scan_filter *filter,
1475 	qdf_list_t *scan_list)
1476 {
1477 	int i, count;
1478 	struct scan_cache_node *cur_node;
1479 	struct scan_cache_node *next_node = NULL;
1480 
1481 	for (i = 0 ; i < SCAN_HASH_SIZE; i++) {
1482 		cur_node = scm_get_next_node(scan_db,
1483 			   &scan_db->scan_hash_tbl[i], NULL);
1484 		count = qdf_list_size(&scan_db->scan_hash_tbl[i]);
1485 		if (!count)
1486 			continue;
1487 		while (cur_node) {
1488 			scm_scan_apply_filter_get_entry(psoc,
1489 				cur_node->entry, filter, scan_list);
1490 			next_node = scm_get_next_node(scan_db,
1491 				&scan_db->scan_hash_tbl[i], cur_node);
1492 			cur_node = next_node;
1493 		}
1494 	}
1495 }
1496 
1497 QDF_STATUS scm_purge_scan_results(qdf_list_t *scan_list)
1498 {
1499 	QDF_STATUS status;
1500 	struct scan_cache_node *cur_node;
1501 	qdf_list_node_t *cur_lst = NULL, *next_lst = NULL;
1502 
1503 	if (!scan_list) {
1504 		scm_err("scan_result is NULL");
1505 		return QDF_STATUS_E_INVAL;
1506 	}
1507 
1508 	status = qdf_list_peek_front(scan_list, &cur_lst);
1509 
1510 	while (cur_lst) {
1511 		qdf_list_peek_next(
1512 			scan_list, cur_lst, &next_lst);
1513 		cur_node = qdf_container_of(cur_lst,
1514 			struct scan_cache_node, node);
1515 		status = qdf_list_remove_node(scan_list,
1516 					cur_lst);
1517 		if (QDF_IS_STATUS_SUCCESS(status)) {
1518 			util_scan_free_cache_entry(cur_node->entry);
1519 			qdf_mem_free(cur_node);
1520 		}
1521 		cur_lst = next_lst;
1522 		next_lst = NULL;
1523 	}
1524 
1525 	qdf_list_destroy(scan_list);
1526 	qdf_mem_free(scan_list);
1527 
1528 	return status;
1529 }
1530 
1531 qdf_list_t *scm_get_scan_result(struct wlan_objmgr_pdev *pdev,
1532 	struct scan_filter *filter)
1533 {
1534 	struct wlan_objmgr_psoc *psoc;
1535 	struct scan_dbs *scan_db;
1536 	qdf_list_t *tmp_list;
1537 
1538 	if (!pdev) {
1539 		scm_err("pdev is NULL");
1540 		return NULL;
1541 	}
1542 
1543 	psoc = wlan_pdev_get_psoc(pdev);
1544 	if (!psoc) {
1545 		scm_err("psoc is NULL");
1546 		return NULL;
1547 	}
1548 
1549 	scan_db = wlan_pdev_get_scan_db(psoc, pdev);
1550 	if (!scan_db) {
1551 		scm_err("scan_db is NULL");
1552 		return NULL;
1553 	}
1554 
1555 	tmp_list = qdf_mem_malloc_atomic(sizeof(*tmp_list));
1556 	if (!tmp_list) {
1557 		scm_err("failed tp allocate scan_result");
1558 		return NULL;
1559 	}
1560 	qdf_list_create(tmp_list,
1561 			MAX_SCAN_CACHE_SIZE);
1562 	scm_age_out_entries(psoc, scan_db);
1563 	scm_get_results(psoc, scan_db, filter, tmp_list);
1564 
1565 	return tmp_list;
1566 }
1567 
1568 /**
1569  * scm_iterate_db_and_call_func() - iterate and call the func
1570  * @scan_db: scan db
1571  * @func: func to be called
1572  * @arg: func arg
1573  *
1574  * Return: QDF_STATUS
1575  */
1576 static QDF_STATUS
1577 scm_iterate_db_and_call_func(struct scan_dbs *scan_db,
1578 	scan_iterator_func func, void *arg)
1579 {
1580 	int i;
1581 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1582 	struct scan_cache_node *cur_node;
1583 	struct scan_cache_node *next_node = NULL;
1584 
1585 	if (!func)
1586 		return QDF_STATUS_E_INVAL;
1587 
1588 	for (i = 0 ; i < SCAN_HASH_SIZE; i++) {
1589 		cur_node = scm_get_next_node(scan_db,
1590 			&scan_db->scan_hash_tbl[i], NULL);
1591 		while (cur_node) {
1592 			status = func(arg, cur_node->entry);
1593 			if (QDF_IS_STATUS_ERROR(status)) {
1594 				scm_scan_entry_put_ref(scan_db,
1595 					cur_node, true);
1596 				return status;
1597 			}
1598 			next_node = scm_get_next_node(scan_db,
1599 				&scan_db->scan_hash_tbl[i], cur_node);
1600 			cur_node = next_node;
1601 		}
1602 	}
1603 
1604 	return status;
1605 }
1606 
1607 QDF_STATUS
1608 scm_iterate_scan_db(struct wlan_objmgr_pdev *pdev,
1609 	scan_iterator_func func, void *arg)
1610 {
1611 	struct wlan_objmgr_psoc *psoc;
1612 	struct scan_dbs *scan_db;
1613 	QDF_STATUS status;
1614 
1615 	if (!func) {
1616 		scm_err("func is NULL");
1617 		return QDF_STATUS_E_INVAL;
1618 	}
1619 
1620 	if (!pdev) {
1621 		scm_err("pdev is NULL");
1622 		return QDF_STATUS_E_INVAL;
1623 	}
1624 
1625 	psoc = wlan_pdev_get_psoc(pdev);
1626 	if (!psoc) {
1627 		scm_err("psoc is NULL");
1628 		return QDF_STATUS_E_INVAL;
1629 	}
1630 	scan_db = wlan_pdev_get_scan_db(psoc, pdev);
1631 	if (!scan_db) {
1632 		scm_err("scan_db is NULL");
1633 		return QDF_STATUS_E_INVAL;
1634 	}
1635 
1636 	scm_age_out_entries(psoc, scan_db);
1637 	status = scm_iterate_db_and_call_func(scan_db, func, arg);
1638 
1639 	return status;
1640 }
1641 
1642 /**
1643  * scm_scan_apply_filter_flush_entry() -flush scan entries depending
1644  * on filter
1645  * @psoc: psoc ptr
1646  * @scan_db: scan db
1647  * @db_node: node on which filters are applied
1648  * @filter: filter to be applied
1649  *
1650  * Return: QDF_STATUS
1651  */
1652 static QDF_STATUS
1653 scm_scan_apply_filter_flush_entry(struct wlan_objmgr_psoc *psoc,
1654 	struct scan_dbs *scan_db,
1655 	struct scan_cache_node *db_node,
1656 	struct scan_filter *filter)
1657 {
1658 	struct security_info security = {0};
1659 	bool match;
1660 
1661 	if (!filter)
1662 		match = true;
1663 	else
1664 		match = scm_filter_match(psoc, db_node->entry,
1665 					filter, &security);
1666 
1667 	if (!match)
1668 		return QDF_STATUS_SUCCESS;
1669 
1670 	qdf_spin_lock_bh(&scan_db->scan_db_lock);
1671 	scm_scan_entry_del(scan_db, db_node);
1672 	qdf_spin_unlock_bh(&scan_db->scan_db_lock);
1673 
1674 	return QDF_STATUS_SUCCESS;
1675 }
1676 
1677 /**
1678  * scm_flush_scan_entries() - API to flush scan entries depending on filters
1679  * @psoc: psoc ptr
1680  * @scan_db: scan db
1681  * @filter: filter
1682  * @pdev_id: pdev id of the scan db
1683  *
1684  * Return: void
1685  */
1686 static void scm_flush_scan_entries(struct wlan_objmgr_psoc *psoc,
1687 	struct scan_dbs *scan_db, struct scan_filter *filter, uint8_t pdev_id)
1688 {
1689 	int i;
1690 	struct scan_cache_node *cur_node;
1691 	struct scan_cache_node *next_node = NULL;
1692 
1693 	for (i = 0 ; i < SCAN_HASH_SIZE; i++) {
1694 		cur_node = scm_get_next_node(scan_db,
1695 			   &scan_db->scan_hash_tbl[i], NULL);
1696 		while (cur_node) {
1697 			scm_scan_apply_filter_flush_entry(psoc, scan_db,
1698 				cur_node, filter);
1699 			next_node = scm_get_next_node(scan_db,
1700 				&scan_db->scan_hash_tbl[i], cur_node);
1701 			cur_node = next_node;
1702 		}
1703 	}
1704 	/* if all scan results are flushed reset scan channel info as well */
1705 	if (!filter)
1706 		scm_reset_scan_chan_info(psoc, pdev_id);
1707 }
1708 
1709 QDF_STATUS scm_flush_results(struct wlan_objmgr_pdev *pdev,
1710 	struct scan_filter *filter)
1711 {
1712 	struct wlan_objmgr_psoc *psoc;
1713 	struct scan_dbs *scan_db;
1714 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1715 
1716 	if (!pdev) {
1717 		scm_err("pdev is NULL");
1718 		return QDF_STATUS_E_INVAL;
1719 	}
1720 
1721 	psoc = wlan_pdev_get_psoc(pdev);
1722 	if (!psoc) {
1723 		scm_err("psoc is NULL");
1724 		return QDF_STATUS_E_INVAL;
1725 	}
1726 
1727 	scan_db = wlan_pdev_get_scan_db(psoc, pdev);
1728 	if (!scan_db) {
1729 		scm_err("scan_db is NULL");
1730 		return QDF_STATUS_E_INVAL;
1731 	}
1732 
1733 	scm_flush_scan_entries(psoc, scan_db, filter,
1734 			       wlan_objmgr_pdev_get_pdev_id(pdev));
1735 
1736 	return status;
1737 }
1738 
1739 /**
1740  * scm_filter_channels() - Remove entries not belonging to channel list
1741  * @pdev: pointer to pdev
1742  * @scan_db: scan db
1743  * @db_node: node on which filters are applied
1744  * @chan_freq_list: valid channel frequency (in MHz) list
1745  * @num_chan: number of channels
1746  *
1747  * Return: QDF_STATUS
1748  */
1749 static void scm_filter_channels(struct wlan_objmgr_pdev *pdev,
1750 				struct scan_dbs *scan_db,
1751 				struct scan_cache_node *db_node,
1752 				uint32_t *chan_freq_list, uint32_t num_chan)
1753 {
1754 	int i;
1755 	bool match = false;
1756 
1757 	for (i = 0; i < num_chan; i++) {
1758 		if (chan_freq_list[i] == util_scan_entry_channel_frequency(
1759 							db_node->entry)) {
1760 			match = true;
1761 			break;
1762 		}
1763 	}
1764 
1765 	if (!match) {
1766 		qdf_spin_lock_bh(&scan_db->scan_db_lock);
1767 		scm_scan_entry_del(scan_db, db_node);
1768 		qdf_spin_unlock_bh(&scan_db->scan_db_lock);
1769 	}
1770 }
1771 
1772 void scm_filter_valid_channel(struct wlan_objmgr_pdev *pdev,
1773 	uint32_t *chan_freq_list, uint32_t num_chan)
1774 {
1775 	int i;
1776 	struct wlan_objmgr_psoc *psoc;
1777 	struct scan_dbs *scan_db;
1778 	struct scan_cache_node *cur_node;
1779 	struct scan_cache_node *next_node = NULL;
1780 
1781 	scm_debug("num_chan = %d", num_chan);
1782 
1783 	if (!pdev) {
1784 		scm_err("pdev is NULL");
1785 		return;
1786 	}
1787 
1788 	psoc = wlan_pdev_get_psoc(pdev);
1789 	if (!psoc) {
1790 		scm_err("psoc is NULL");
1791 		return;
1792 	}
1793 
1794 	scan_db = wlan_pdev_get_scan_db(psoc, pdev);
1795 	if (!scan_db) {
1796 		scm_err("scan_db is NULL");
1797 		return;
1798 	}
1799 
1800 	for (i = 0 ; i < SCAN_HASH_SIZE; i++) {
1801 		cur_node = scm_get_next_node(scan_db,
1802 			   &scan_db->scan_hash_tbl[i], NULL);
1803 		while (cur_node) {
1804 			scm_filter_channels(pdev, scan_db,
1805 					    cur_node, chan_freq_list, num_chan);
1806 			next_node = scm_get_next_node(scan_db,
1807 				&scan_db->scan_hash_tbl[i], cur_node);
1808 			cur_node = next_node;
1809 		}
1810 	}
1811 }
1812 
1813 QDF_STATUS scm_scan_register_mbssid_cb(struct wlan_objmgr_psoc *psoc,
1814 				       update_mbssid_bcn_prb_rsp cb)
1815 {
1816 	struct wlan_scan_obj *scan_obj;
1817 
1818 	scan_obj = wlan_psoc_get_scan_obj(psoc);
1819 	if (!scan_obj) {
1820 		scm_err("scan obj is NULL");
1821 		return QDF_STATUS_E_INVAL;
1822 	}
1823 
1824 	scan_obj->cb.inform_mbssid_bcn_prb_rsp = cb;
1825 
1826 	return QDF_STATUS_SUCCESS;
1827 }
1828 
1829 QDF_STATUS scm_scan_register_bcn_cb(struct wlan_objmgr_psoc *psoc,
1830 	update_beacon_cb cb, enum scan_cb_type type)
1831 {
1832 	struct wlan_scan_obj *scan_obj;
1833 
1834 	scan_obj = wlan_psoc_get_scan_obj(psoc);
1835 	if (!scan_obj) {
1836 		scm_err("scan obj is NULL");
1837 		return QDF_STATUS_E_INVAL;
1838 	}
1839 	switch (type) {
1840 	case SCAN_CB_TYPE_INFORM_BCN:
1841 		scan_obj->cb.inform_beacon = cb;
1842 		break;
1843 	case SCAN_CB_TYPE_UPDATE_BCN:
1844 		scan_obj->cb.update_beacon = cb;
1845 		break;
1846 	case SCAN_CB_TYPE_UNLINK_BSS:
1847 		scan_obj->cb.unlink_bss = cb;
1848 		break;
1849 	default:
1850 		scm_err("invalid cb type %d", type);
1851 	}
1852 
1853 	return QDF_STATUS_SUCCESS;
1854 }
1855 
1856 void scm_reset_scan_chan_info(struct wlan_objmgr_psoc *psoc, uint8_t pdev_id)
1857 {
1858 	struct wlan_scan_obj *scan_obj;
1859 
1860 	scan_obj = wlan_psoc_get_scan_obj(psoc);
1861 	if (!scan_obj)
1862 		return;
1863 
1864 	scm_debug("pdev %d, Reset all channel info", pdev_id);
1865 	qdf_mem_zero(&scan_obj->pdev_info[pdev_id].chan_scan_info,
1866 		     sizeof(scan_obj->pdev_info[pdev_id].chan_scan_info));
1867 }
1868 
1869 QDF_STATUS scm_db_init(struct wlan_objmgr_psoc *psoc)
1870 {
1871 	int i, j;
1872 	struct scan_dbs *scan_db;
1873 
1874 	if (!psoc) {
1875 		scm_err("psoc is NULL");
1876 		return QDF_STATUS_E_INVAL;
1877 	}
1878 
1879 	/* Initialize the scan database per pdev */
1880 	for (i = 0; i < WLAN_UMAC_MAX_PDEVS; i++) {
1881 		scan_db = wlan_pdevid_get_scan_db(psoc, i);
1882 		if (!scan_db) {
1883 			scm_err("scan_db is NULL %d", i);
1884 			continue;
1885 		}
1886 		scan_db->num_entries = 0;
1887 		qdf_spinlock_create(&scan_db->scan_db_lock);
1888 		for (j = 0; j < SCAN_HASH_SIZE; j++)
1889 			qdf_list_create(&scan_db->scan_hash_tbl[j],
1890 				MAX_SCAN_CACHE_SIZE);
1891 		scm_reset_scan_chan_info(psoc, i);
1892 	}
1893 	return QDF_STATUS_SUCCESS;
1894 }
1895 
1896 QDF_STATUS scm_db_deinit(struct wlan_objmgr_psoc *psoc)
1897 {
1898 	int i, j;
1899 	struct scan_dbs *scan_db;
1900 
1901 	if (!psoc) {
1902 		scm_err("scan obj is NULL");
1903 		return QDF_STATUS_E_INVAL;
1904 	}
1905 
1906 	/* Initialize the scan database per pdev */
1907 	for (i = 0; i < WLAN_UMAC_MAX_PDEVS; i++) {
1908 		scan_db = wlan_pdevid_get_scan_db(psoc, i);
1909 		if (!scan_db) {
1910 			scm_err("scan_db is NULL %d", i);
1911 			continue;
1912 		}
1913 
1914 		scm_flush_scan_entries(psoc, scan_db, NULL, i);
1915 		for (j = 0; j < SCAN_HASH_SIZE; j++)
1916 			qdf_list_destroy(&scan_db->scan_hash_tbl[j]);
1917 		qdf_spinlock_destroy(&scan_db->scan_db_lock);
1918 	}
1919 
1920 	return QDF_STATUS_SUCCESS;
1921 }
1922 
1923 #ifdef FEATURE_6G_SCAN_CHAN_SORT_ALGO
1924 QDF_STATUS scm_channel_list_db_init(struct wlan_objmgr_psoc *psoc)
1925 {
1926 	uint32_t i, j;
1927 	uint32_t min_freq, max_freq;
1928 	struct channel_list_db *rnr_channel_db;
1929 
1930 	min_freq = wlan_reg_min_6ghz_chan_freq();
1931 	max_freq = wlan_reg_max_6ghz_chan_freq();
1932 
1933 	scm_info("min_freq %d max_freq %d", min_freq, max_freq);
1934 	i = min_freq;
1935 	rnr_channel_db = scm_get_rnr_channel_db(psoc);
1936 	if (!rnr_channel_db)
1937 		return QDF_STATUS_E_INVAL;
1938 
1939 	for (j = 0; j < QDF_ARRAY_SIZE(rnr_channel_db->channel); j++) {
1940 		if (i >= min_freq && i <= max_freq)
1941 			rnr_channel_db->channel[j].chan_freq = i;
1942 		i += 20;
1943 		/* init list for all to avoid uninitialized list */
1944 		qdf_list_create(&rnr_channel_db->channel[j].rnr_list,
1945 				WLAN_MAX_RNR_COUNT);
1946 	}
1947 	return QDF_STATUS_SUCCESS;
1948 }
1949 
1950 QDF_STATUS scm_channel_list_db_deinit(struct wlan_objmgr_psoc *psoc)
1951 {
1952 	int i;
1953 	qdf_list_node_t *cur_node, *next_node;
1954 	struct meta_rnr_channel *channel;
1955 	struct scan_rnr_node *rnr_node;
1956 	struct channel_list_db *rnr_channel_db;
1957 
1958 	rnr_channel_db = scm_get_rnr_channel_db(psoc);
1959 	if (!rnr_channel_db)
1960 		return QDF_STATUS_E_INVAL;
1961 
1962 	for (i = 0; i < QDF_ARRAY_SIZE(rnr_channel_db->channel); i++) {
1963 		channel = &rnr_channel_db->channel[i];
1964 		channel->chan_freq = 0;
1965 		channel->beacon_probe_last_time_found = 0;
1966 		channel->bss_beacon_probe_count = 0;
1967 		channel->saved_profile_count = 0;
1968 		cur_node = NULL;
1969 		qdf_list_peek_front(&channel->rnr_list, &cur_node);
1970 		while (cur_node) {
1971 			next_node = NULL;
1972 			qdf_list_peek_next(&channel->rnr_list, cur_node,
1973 					   &next_node);
1974 			rnr_node = qdf_container_of(cur_node,
1975 						    struct scan_rnr_node,
1976 						    node);
1977 			qdf_list_remove_node(&channel->rnr_list,
1978 					     &rnr_node->node);
1979 			qdf_mem_free(rnr_node);
1980 			cur_node = next_node;
1981 			next_node = NULL;
1982 		}
1983 		qdf_list_destroy(&channel->rnr_list);
1984 	}
1985 
1986 	return QDF_STATUS_SUCCESS;
1987 }
1988 
1989 QDF_STATUS scm_rnr_db_flush(struct wlan_objmgr_psoc *psoc)
1990 {
1991 	int i;
1992 	qdf_list_node_t *cur_node, *next_node;
1993 	struct meta_rnr_channel *channel;
1994 	struct scan_rnr_node *rnr_node;
1995 	struct channel_list_db *rnr_channel_db;
1996 
1997 	rnr_channel_db = scm_get_rnr_channel_db(psoc);
1998 	if (!rnr_channel_db)
1999 		return QDF_STATUS_E_INVAL;
2000 
2001 	for (i = 0; i < QDF_ARRAY_SIZE(rnr_channel_db->channel); i++) {
2002 		channel = &rnr_channel_db->channel[i];
2003 		cur_node = NULL;
2004 		qdf_list_peek_front(&channel->rnr_list, &cur_node);
2005 		while (cur_node) {
2006 			next_node = NULL;
2007 			qdf_list_peek_next(&channel->rnr_list, cur_node,
2008 					   &next_node);
2009 			rnr_node = qdf_container_of(cur_node,
2010 						    struct scan_rnr_node,
2011 						    node);
2012 			qdf_list_remove_node(&channel->rnr_list,
2013 					     &rnr_node->node);
2014 			qdf_mem_free(rnr_node);
2015 			cur_node = next_node;
2016 			next_node = NULL;
2017 		}
2018 		/* Reset beacon info */
2019 		channel->beacon_probe_last_time_found = 0;
2020 		channel->bss_beacon_probe_count = 0;
2021 	}
2022 
2023 	return QDF_STATUS_SUCCESS;
2024 }
2025 
2026 void scm_update_rnr_from_scan_cache(struct wlan_objmgr_pdev *pdev)
2027 {
2028 	uint8_t i;
2029 	struct scan_dbs *scan_db;
2030 	struct scan_cache_node *cur_node;
2031 	struct scan_cache_node *next_node = NULL;
2032 	struct wlan_objmgr_psoc *psoc;
2033 	struct scan_cache_entry *entry;
2034 
2035 	psoc = wlan_pdev_get_psoc(pdev);
2036 	if (!psoc) {
2037 		scm_err("psoc is NULL");
2038 		return;
2039 	}
2040 	scan_db = wlan_pdev_get_scan_db(psoc, pdev);
2041 	if (!scan_db) {
2042 		scm_err("scan_db is NULL");
2043 		return;
2044 	}
2045 
2046 	for (i = 0 ; i < SCAN_HASH_SIZE; i++) {
2047 		cur_node = scm_get_next_node(scan_db,
2048 					     &scan_db->scan_hash_tbl[i], NULL);
2049 		while (cur_node) {
2050 			entry = cur_node->entry;
2051 			scm_add_rnr_channel_db(psoc, entry);
2052 			next_node =
2053 				scm_get_next_node(scan_db,
2054 						  &scan_db->scan_hash_tbl[i],
2055 						  cur_node);
2056 			cur_node = next_node;
2057 			next_node = NULL;
2058 		}
2059 	}
2060 }
2061 #endif
2062 
2063 QDF_STATUS scm_update_scan_mlme_info(struct wlan_objmgr_pdev *pdev,
2064 	struct scan_cache_entry *entry)
2065 {
2066 	uint8_t hash_idx;
2067 	struct scan_dbs *scan_db;
2068 	struct scan_cache_node *cur_node;
2069 	struct scan_cache_node *next_node = NULL;
2070 	struct wlan_objmgr_psoc *psoc;
2071 
2072 	psoc = wlan_pdev_get_psoc(pdev);
2073 	if (!psoc) {
2074 		scm_err("psoc is NULL");
2075 		return QDF_STATUS_E_INVAL;
2076 	}
2077 	scan_db = wlan_pdev_get_scan_db(psoc, pdev);
2078 	if (!scan_db) {
2079 		scm_err("scan_db is NULL");
2080 		return QDF_STATUS_E_INVAL;
2081 	}
2082 
2083 	hash_idx = SCAN_GET_HASH(entry->bssid.bytes);
2084 
2085 	cur_node = scm_get_next_node(scan_db,
2086 			&scan_db->scan_hash_tbl[hash_idx], NULL);
2087 
2088 	while (cur_node) {
2089 		if (util_is_scan_entry_match(entry,
2090 					cur_node->entry)) {
2091 			/* Acquire db lock to prevent simultaneous update */
2092 			qdf_spin_lock_bh(&scan_db->scan_db_lock);
2093 			scm_update_mlme_info(entry, cur_node->entry);
2094 			qdf_spin_unlock_bh(&scan_db->scan_db_lock);
2095 			scm_scan_entry_put_ref(scan_db,
2096 					cur_node, true);
2097 			return QDF_STATUS_SUCCESS;
2098 		}
2099 		next_node = scm_get_next_node(scan_db,
2100 				&scan_db->scan_hash_tbl[hash_idx], cur_node);
2101 		cur_node = next_node;
2102 	}
2103 
2104 	return QDF_STATUS_E_INVAL;
2105 }
2106 
2107 QDF_STATUS scm_scan_update_mlme_by_bssinfo(struct wlan_objmgr_pdev *pdev,
2108 		struct bss_info *bss_info, struct mlme_info *mlme)
2109 {
2110 	uint8_t hash_idx;
2111 	struct scan_dbs *scan_db;
2112 	struct scan_cache_node *cur_node;
2113 	struct scan_cache_node *next_node = NULL;
2114 	struct wlan_objmgr_psoc *psoc;
2115 	struct scan_cache_entry *entry;
2116 
2117 	psoc = wlan_pdev_get_psoc(pdev);
2118 	if (!psoc) {
2119 		scm_err("psoc is NULL");
2120 		return QDF_STATUS_E_INVAL;
2121 	}
2122 	scan_db = wlan_pdev_get_scan_db(psoc, pdev);
2123 	if (!scan_db) {
2124 		scm_err("scan_db is NULL");
2125 		return QDF_STATUS_E_INVAL;
2126 	}
2127 
2128 	hash_idx = SCAN_GET_HASH(bss_info->bssid.bytes);
2129 	cur_node = scm_get_next_node(scan_db,
2130 			&scan_db->scan_hash_tbl[hash_idx], NULL);
2131 	while (cur_node) {
2132 		entry = cur_node->entry;
2133 		if (qdf_is_macaddr_equal(&bss_info->bssid, &entry->bssid) &&
2134 			(util_is_ssid_match(&bss_info->ssid, &entry->ssid)) &&
2135 			(bss_info->freq == entry->channel.chan_freq)) {
2136 			/* Acquire db lock to prevent simultaneous update */
2137 			qdf_spin_lock_bh(&scan_db->scan_db_lock);
2138 			qdf_mem_copy(&entry->mlme_info, mlme,
2139 					sizeof(struct mlme_info));
2140 			scm_debug("BSSID: "QDF_MAC_ADDR_FMT" set assoc_state to %d with age %lu ms",
2141 				  QDF_MAC_ADDR_REF(entry->bssid.bytes),
2142 				  mlme->assoc_state,
2143 				  util_scan_entry_age(entry));
2144 			scm_scan_entry_put_ref(scan_db,
2145 					cur_node, false);
2146 			qdf_spin_unlock_bh(&scan_db->scan_db_lock);
2147 			return QDF_STATUS_SUCCESS;
2148 		}
2149 		next_node = scm_get_next_node(scan_db,
2150 				&scan_db->scan_hash_tbl[hash_idx], cur_node);
2151 		cur_node = next_node;
2152 	}
2153 
2154 	return QDF_STATUS_E_INVAL;
2155 }
2156 
2157 uint32_t scm_get_last_scan_time_per_channel(struct wlan_objmgr_vdev *vdev,
2158 					    uint32_t freq)
2159 {
2160 	struct wlan_scan_obj *scan;
2161 	struct chan_list_scan_info *chan_info;
2162 	uint8_t pdev_id;
2163 	int i;
2164 
2165 	scan = wlan_vdev_get_scan_obj(vdev);
2166 	if (!scan)
2167 		return 0;
2168 
2169 	pdev_id = wlan_scan_vdev_get_pdev_id(vdev);
2170 	chan_info = &scan->pdev_info[pdev_id].chan_scan_info;
2171 
2172 	for (i = 0; i < chan_info->num_chan ; i++) {
2173 		if (chan_info->ch_scan_info[i].freq == freq)
2174 			return chan_info->ch_scan_info[i].last_scan_time;
2175 	}
2176 
2177 	return 0;
2178 }
2179 
2180 struct scan_cache_entry *
2181 scm_scan_get_scan_entry_by_mac_freq(struct wlan_objmgr_pdev *pdev,
2182 				    struct qdf_mac_addr *bssid,
2183 				    uint16_t freq)
2184 {
2185 	struct scan_filter *scan_filter;
2186 	qdf_list_t *list = NULL;
2187 	struct scan_cache_node *first_node = NULL;
2188 	qdf_list_node_t *cur_node = NULL;
2189 	struct scan_cache_entry *scan_entry = NULL;
2190 
2191 	scan_filter = qdf_mem_malloc(sizeof(*scan_filter));
2192 	if (!scan_filter)
2193 		return NULL;
2194 	scan_filter->num_of_bssid = 1;
2195 	scan_filter->chan_freq_list[0] = freq;
2196 	scan_filter->num_of_channels = 1;
2197 	qdf_copy_macaddr(&scan_filter->bssid_list[0], bssid);
2198 
2199 	list = scm_get_scan_result(pdev, scan_filter);
2200 	qdf_mem_free(scan_filter);
2201 	if (!list || (list && !qdf_list_size(list))) {
2202 		scm_debug("Scan entry for bssid:"
2203 			  QDF_MAC_ADDR_FMT "and freq %d not found",
2204 			  QDF_MAC_ADDR_REF(bssid->bytes), freq);
2205 		goto done;
2206 	}
2207 	/*
2208 	 * There might be multiple scan results in the scan db with given mac
2209 	 * address(e.g. SSID/some capabilities of the AP have just changed and
2210 	 * old entry is not aged out yet). scm_get_scan_result() inserts the
2211 	 * latest scan result at the front of the given list. So, it's ok to
2212 	 * pick scan result from the front node alone.
2213 	 */
2214 	qdf_list_peek_front(list, &cur_node);
2215 	first_node = qdf_container_of(cur_node,
2216 				      struct scan_cache_node,
2217 				      node);
2218 
2219 	if (first_node && first_node->entry)
2220 		scan_entry = util_scan_copy_cache_entry(first_node->entry);
2221 
2222 done:
2223 	if (list)
2224 		scm_purge_scan_results(list);
2225 
2226 	return scan_entry;
2227 }
2228 
2229 QDF_STATUS
2230 scm_scan_get_entry_by_mac_addr(struct wlan_objmgr_pdev *pdev,
2231 			       struct qdf_mac_addr *bssid,
2232 			       struct element_info *frame)
2233 {
2234 	struct scan_filter *scan_filter;
2235 	qdf_list_t *list = NULL;
2236 	struct scan_cache_node *first_node = NULL;
2237 	qdf_list_node_t *cur_node = NULL;
2238 	QDF_STATUS status = QDF_STATUS_SUCCESS;
2239 
2240 	scan_filter = qdf_mem_malloc(sizeof(*scan_filter));
2241 	if (!scan_filter)
2242 		return QDF_STATUS_E_NOMEM;
2243 	scan_filter->num_of_bssid = 1;
2244 	qdf_copy_macaddr(&scan_filter->bssid_list[0], bssid);
2245 	list = scm_get_scan_result(pdev, scan_filter);
2246 	qdf_mem_free(scan_filter);
2247 	if (!list || (list && !qdf_list_size(list))) {
2248 		status = QDF_STATUS_E_INVAL;
2249 		goto done;
2250 	}
2251 	/*
2252 	 * There might be multiple scan results in the scan db with given mac
2253 	 * address(e.g. SSID/some capabilities of the AP have just changed and
2254 	 * old entry is not aged out yet). scm_get_scan_result() inserts the
2255 	 * latest scan result at the front of the given list. So, it's ok to
2256 	 * pick scan result from the front node alone.
2257 	 */
2258 	qdf_list_peek_front(list, &cur_node);
2259 	first_node = qdf_container_of(cur_node,
2260 				      struct scan_cache_node,
2261 				      node);
2262 	if (first_node && first_node->entry) {
2263 		frame->len = first_node->entry->raw_frame.len;
2264 		frame->ptr = qdf_mem_malloc(frame->len);
2265 		if (!frame->ptr) {
2266 			status = QDF_STATUS_E_NOMEM;
2267 			goto done;
2268 		}
2269 		qdf_mem_copy(frame->ptr,
2270 			     first_node->entry->raw_frame.ptr,
2271 			     frame->len);
2272 	}
2273 
2274 done:
2275 	if (list)
2276 		scm_purge_scan_results(list);
2277 
2278 	return status;
2279 }
2280 
2281 #ifdef WLAN_FEATURE_11BE_MLO
2282 QDF_STATUS scm_get_mld_addr_by_link_addr(struct wlan_objmgr_pdev *pdev,
2283 					 struct qdf_mac_addr *link_addr,
2284 					 struct qdf_mac_addr *mld_mac_addr)
2285 {
2286 	struct scan_cache_entry *entry = NULL;
2287 
2288 	/* For ML connection, BSSID is link address */
2289 	entry = scm_scan_get_entry_by_bssid(pdev, link_addr);
2290 	if (!entry) {
2291 		scm_err("scan entry not found for link addr: " QDF_MAC_ADDR_FMT,
2292 			QDF_MAC_ADDR_REF(link_addr->bytes));
2293 		return QDF_STATUS_E_FAILURE;
2294 	}
2295 
2296 	if (qdf_is_macaddr_zero(&entry->ml_info.mld_mac_addr)) {
2297 		util_scan_free_cache_entry(entry);
2298 		return QDF_STATUS_E_FAILURE;
2299 	}
2300 
2301 	qdf_mem_copy(mld_mac_addr, &entry->ml_info.mld_mac_addr,
2302 		     QDF_MAC_ADDR_SIZE);
2303 	util_scan_free_cache_entry(entry);
2304 
2305 	return QDF_STATUS_SUCCESS;
2306 }
2307 #endif
2308 
2309 struct scan_cache_entry *
2310 scm_scan_get_entry_by_bssid(struct wlan_objmgr_pdev *pdev,
2311 			    struct qdf_mac_addr *bssid)
2312 {
2313 	struct scan_filter *scan_filter;
2314 	qdf_list_t *list = NULL;
2315 	struct scan_cache_node *first_node = NULL;
2316 	qdf_list_node_t *cur_node = NULL;
2317 	struct scan_cache_entry *entry = NULL, *scan_entry = NULL;
2318 
2319 	if (!pdev)
2320 		return NULL;
2321 
2322 	scan_filter = qdf_mem_malloc(sizeof(*scan_filter));
2323 	if (!scan_filter)
2324 		return NULL;
2325 
2326 	scan_filter->num_of_bssid = 1;
2327 	qdf_mem_copy(scan_filter->bssid_list[0].bytes,
2328 		     bssid, sizeof(struct qdf_mac_addr));
2329 	list = scm_get_scan_result(pdev, scan_filter);
2330 	qdf_mem_free(scan_filter);
2331 
2332 	if (!list || (!qdf_list_size(list))) {
2333 		scm_debug("Scan entry for bssid: "QDF_MAC_ADDR_FMT" not found",
2334 			  QDF_MAC_ADDR_REF(bssid->bytes));
2335 		goto exit;
2336 	}
2337 
2338 	qdf_list_peek_front(list, &cur_node);
2339 	first_node = qdf_container_of(cur_node, struct scan_cache_node,
2340 				      node);
2341 	if (first_node && first_node->entry) {
2342 		entry = first_node->entry;
2343 		scan_entry = util_scan_copy_cache_entry(entry);
2344 	}
2345 exit:
2346 	if (list)
2347 		scm_purge_scan_results(list);
2348 
2349 	return scan_entry;
2350 }
2351