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