xref: /wlan-dirver/qca-wifi-host-cmn/umac/scan/core/src/wlan_scan_cache_db.c (revision 70a19e16789e308182f63b15c75decec7bf0b342)
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 conside the 8 char for MLD print, 17 char MLD address
887  * 3 char for space and 3 char for number of link.
888  */
889 #define ML_MAX_CHAR_LENGTH 32
890 
891 #ifdef WLAN_FEATURE_11BE_MLO
892 /**
893  * scm_dump_ml_scan_info(): Dump ml scan info
894  * @scan_params: new received entry
895  * @int_ctx_str: Buffer pointer
896  *
897  * Return: void
898  */
899 static void scm_dump_ml_scan_info(struct scan_cache_entry *scan_params,
900 				  char *int_ctx_str)
901 {
902 	char *buf;
903 	int buf_len;
904 
905 	buf = int_ctx_str;
906 	buf_len = ML_MAX_CHAR_LENGTH;
907 
908 	/* Scenario: When both STA and AP support ML then
909 	 * Driver will fill ml_info structure and print the MLD address and no.
910 	 * of links.
911 	 */
912 	if (!qdf_is_macaddr_zero(&scan_params->ml_info.mld_mac_addr))
913 		qdf_scnprintf(buf, buf_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 void scm_dump_ml_scan_info(struct scan_cache_entry *scan_params,
920 				  char *int_ctx_str)
921 {
922 }
923 #endif
924 
925 /**
926  * scm_add_update_entry() - add or update scan entry
927  * @psoc: psoc ptr
928  * @pdev: pdev pointer
929  * @scan_params: new received entry
930  *
931  * Return: QDF_STATUS
932  */
933 static QDF_STATUS scm_add_update_entry(struct wlan_objmgr_psoc *psoc,
934 	struct wlan_objmgr_pdev *pdev, struct scan_cache_entry *scan_params)
935 {
936 	struct scan_cache_node *dup_node = NULL;
937 	struct scan_cache_node *scan_node = NULL;
938 	bool is_dup_found = false;
939 	QDF_STATUS status;
940 	struct scan_dbs *scan_db;
941 	struct wlan_scan_obj *scan_obj;
942 	uint8_t security_type;
943 	char *int_ctx_str = NULL;
944 
945 	scan_db = wlan_pdev_get_scan_db(psoc, pdev);
946 	if (!scan_db) {
947 		scm_err("scan_db is NULL");
948 		return QDF_STATUS_E_INVAL;
949 	}
950 
951 	scan_obj = wlan_psoc_get_scan_obj(psoc);
952 	if (!scan_obj) {
953 		scm_err("scan_obj is NULL");
954 		return QDF_STATUS_E_INVAL;
955 	}
956 
957 	if (scan_params->frm_subtype ==
958 	   MGMT_SUBTYPE_PROBE_RESP &&
959 	   !scan_params->ie_list.ssid)
960 		scm_debug("Probe resp doesn't contain SSID");
961 
962 
963 	if (scan_params->ie_list.csa ||
964 	   scan_params->ie_list.xcsa ||
965 	   scan_params->ie_list.cswrp)
966 		scm_debug("CSA IE present for BSSID: "QDF_MAC_ADDR_FMT,
967 			  QDF_MAC_ADDR_REF(scan_params->bssid.bytes));
968 
969 	is_dup_found = scm_find_duplicate(pdev, scan_obj, scan_db, scan_params,
970 					  &dup_node);
971 
972 	security_type = scan_params->security_type;
973 	int_ctx_str = qdf_mem_malloc(ML_MAX_CHAR_LENGTH);
974 	if (!int_ctx_str)
975 		return QDF_STATUS_E_INVAL;
976 
977 	scm_dump_ml_scan_info(scan_params, int_ctx_str);
978 
979 	scm_nofl_debug("Received %s: " QDF_MAC_ADDR_FMT " \"" QDF_SSID_FMT "\" freq %d rssi %d tsf_delta %u seq %d snr %d phy %d hidden %d mismatch %d %s%s%s%s pdev %d boot_time %llu ns %s",
980 		       (scan_params->frm_subtype == MGMT_SUBTYPE_PROBE_RESP) ?
981 		       "prb rsp" : "bcn",
982 		       QDF_MAC_ADDR_REF(scan_params->bssid.bytes),
983 		       QDF_SSID_REF(scan_params->ssid.length,
984 				    scan_params->ssid.ssid),
985 		       scan_params->channel.chan_freq, scan_params->rssi_raw,
986 		       scan_params->tsf_delta, scan_params->seq_num,
987 		       scan_params->snr, scan_params->phy_mode,
988 		       scan_params->is_hidden_ssid,
989 		       scan_params->channel_mismatch,
990 		       security_type & SCAN_SECURITY_TYPE_WPA ? "[WPA]" : "",
991 		       security_type & SCAN_SECURITY_TYPE_RSN ? "[RSN]" : "",
992 		       security_type & SCAN_SECURITY_TYPE_WAPI ? "[WAPI]" : "",
993 		       security_type & SCAN_SECURITY_TYPE_WEP ? "[WEP]" : "",
994 		       wlan_objmgr_pdev_get_pdev_id(pdev),
995 		       scan_params->boottime_ns, int_ctx_str);
996 
997 	qdf_mem_free(int_ctx_str);
998 
999 	if (scan_obj->cb.inform_beacon)
1000 		scan_obj->cb.inform_beacon(pdev, scan_params);
1001 
1002 	if (scan_db->num_entries >= MAX_SCAN_CACHE_SIZE) {
1003 		status = scm_flush_oldest_entry(scan_db);
1004 		if (QDF_IS_STATUS_ERROR(status)) {
1005 			/* release ref taken for dup node */
1006 			if (is_dup_found)
1007 				scm_scan_entry_put_ref(scan_db, dup_node, true);
1008 			return status;
1009 		}
1010 	}
1011 
1012 	scan_node = qdf_mem_malloc(sizeof(*scan_node));
1013 	if (!scan_node) {
1014 		/* release ref taken for dup node */
1015 		if (is_dup_found)
1016 			scm_scan_entry_put_ref(scan_db, dup_node, true);
1017 		return QDF_STATUS_E_NOMEM;
1018 	}
1019 
1020 	scan_node->entry = scan_params;
1021 	qdf_spin_lock_bh(&scan_db->scan_db_lock);
1022 	scm_add_scan_node(scan_db, scan_node, dup_node);
1023 
1024 	if (is_dup_found) {
1025 		/* release ref taken for dup node and delete it */
1026 		scm_scan_entry_del(scan_db, dup_node);
1027 		scm_scan_entry_put_ref(scan_db, dup_node, false);
1028 	}
1029 	qdf_spin_unlock_bh(&scan_db->scan_db_lock);
1030 
1031 	return QDF_STATUS_SUCCESS;
1032 }
1033 
1034 #ifdef CONFIG_REG_CLIENT
1035 /**
1036  * scm_is_bss_allowed_for_country() - Check if bss is allowed to start for a
1037  * specific country and power mode (VLP?LPI/SP) for 6GHz.
1038  * @psoc: psoc ptr
1039  * @scan_entry: ptr to scan entry
1040  *
1041  * Return: True if allowed, False if not.
1042  */
1043 static bool scm_is_bss_allowed_for_country(struct wlan_objmgr_psoc *psoc,
1044 					   struct scan_cache_entry *scan_entry)
1045 {
1046 	struct wlan_country_ie *cc_ie;
1047 	uint8_t programmed_country[REG_ALPHA2_LEN + 1];
1048 
1049 	if (wlan_reg_is_6ghz_chan_freq(scan_entry->channel.chan_freq)) {
1050 		cc_ie = util_scan_entry_country(scan_entry);
1051 		if (!cc_ie)
1052 			return false;
1053 		wlan_reg_read_current_country(psoc, programmed_country);
1054 		if (cc_ie && qdf_mem_cmp(cc_ie->cc, programmed_country,
1055 					 REG_ALPHA2_LEN)) {
1056 			if (wlan_reg_is_us(programmed_country))
1057 				return false;
1058 		}
1059 	}
1060 	return true;
1061 }
1062 #else
1063 static bool scm_is_bss_allowed_for_country(struct wlan_objmgr_psoc *psoc,
1064 					   struct scan_cache_entry *scan_entry)
1065 {
1066 	return true;
1067 }
1068 #endif
1069 
1070 /**
1071  * scm_is_p2p_wildcard_ssid() - check p2p wildcard ssid or not
1072  * @scan_entry: scan entry
1073  *
1074  * Return: true if SSID is wildcard "DIRECT-" ssid
1075  */
1076 static bool scm_is_p2p_wildcard_ssid(struct scan_cache_entry *scan_entry)
1077 {
1078 	static const char wildcard_ssid[] = "DIRECT-";
1079 	uint8_t len = sizeof(wildcard_ssid) - 1;
1080 
1081 	if (!scan_entry->is_p2p)
1082 		return false;
1083 	if (!qdf_mem_cmp(scan_entry->ssid.ssid,
1084 			 wildcard_ssid, len) &&
1085 	    (scan_entry->ssid.length == len))
1086 		return true;
1087 
1088 	return false;
1089 }
1090 
1091 QDF_STATUS __scm_handle_bcn_probe(struct scan_bcn_probe_event *bcn)
1092 {
1093 	struct wlan_objmgr_psoc *psoc;
1094 	struct wlan_objmgr_pdev *pdev = NULL;
1095 	struct scan_cache_entry *scan_entry;
1096 	struct wlan_scan_obj *scan_obj;
1097 	qdf_list_t *scan_list = NULL;
1098 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1099 	uint32_t list_count, i;
1100 	qdf_list_node_t *next_node = NULL;
1101 	struct scan_cache_node *scan_node;
1102 	struct wlan_frame_hdr *hdr = NULL;
1103 	struct wlan_crypto_params sec_params;
1104 
1105 	if (!bcn) {
1106 		scm_err("bcn is NULL");
1107 		return QDF_STATUS_E_INVAL;
1108 	}
1109 	if (!bcn->rx_data) {
1110 		scm_err("rx_data iS NULL");
1111 		status = QDF_STATUS_E_INVAL;
1112 		goto free_nbuf;
1113 	}
1114 	if (!bcn->buf) {
1115 		scm_err("buf is NULL");
1116 		status = QDF_STATUS_E_INVAL;
1117 		goto free_nbuf;
1118 	}
1119 
1120 	hdr = (struct wlan_frame_hdr *)qdf_nbuf_data(bcn->buf);
1121 	psoc = bcn->psoc;
1122 	pdev = wlan_objmgr_get_pdev_by_id(psoc,
1123 			   bcn->rx_data->pdev_id, WLAN_SCAN_ID);
1124 	if (!pdev) {
1125 		scm_err("pdev is NULL");
1126 		status = QDF_STATUS_E_INVAL;
1127 		goto free_nbuf;
1128 	}
1129 	scan_obj = wlan_psoc_get_scan_obj(psoc);
1130 	if (!scan_obj) {
1131 		scm_err("scan_obj is NULL");
1132 		status = QDF_STATUS_E_INVAL;
1133 		goto free_nbuf;
1134 	}
1135 
1136 	if (qdf_nbuf_len(bcn->buf) <=
1137 	   (sizeof(struct wlan_frame_hdr) +
1138 	   offsetof(struct wlan_bcn_frame, ie))) {
1139 		scm_debug("invalid beacon/probe length");
1140 		status = QDF_STATUS_E_INVAL;
1141 		goto free_nbuf;
1142 	}
1143 
1144 	if (bcn->frm_type == MGMT_SUBTYPE_BEACON &&
1145 	    wlan_reg_is_dfs_for_freq(pdev, bcn->rx_data->chan_freq)) {
1146 		util_scan_add_hidden_ssid(pdev, bcn->buf);
1147 	}
1148 
1149 	scan_list =
1150 		 util_scan_unpack_beacon_frame(pdev, qdf_nbuf_data(bcn->buf),
1151 			qdf_nbuf_len(bcn->buf), bcn->frm_type,
1152 			bcn->rx_data);
1153 	if (!scan_list || qdf_list_empty(scan_list)) {
1154 		scm_debug("failed to unpack %d frame BSSID: "QDF_MAC_ADDR_FMT,
1155 			  bcn->frm_type, QDF_MAC_ADDR_REF(hdr->i_addr3));
1156 		status = QDF_STATUS_E_INVAL;
1157 		goto free_nbuf;
1158 	}
1159 
1160 	list_count = qdf_list_size(scan_list);
1161 	for (i = 0; i < list_count; i++) {
1162 		status = qdf_list_remove_front(scan_list, &next_node);
1163 		if (QDF_IS_STATUS_ERROR(status) || !next_node) {
1164 			scm_debug("list remove failure i:%d, lsize:%d, BSSID: "QDF_MAC_ADDR_FMT,
1165 				  i, list_count, QDF_MAC_ADDR_REF(hdr->i_addr3));
1166 			status = QDF_STATUS_E_INVAL;
1167 			goto free_nbuf;
1168 		}
1169 
1170 		scan_node = qdf_container_of(next_node,
1171 			struct scan_cache_node, node);
1172 
1173 		scan_entry = scan_node->entry;
1174 
1175 		if (scan_obj->drop_bcn_on_chan_mismatch &&
1176 		    scan_entry->channel_mismatch) {
1177 			scm_nofl_debug("Drop frame for chan mismatch "QDF_MAC_ADDR_FMT" Seq Num: %d freq %d RSSI %d",
1178 				       QDF_MAC_ADDR_REF(scan_entry->bssid.bytes),
1179 				       scan_entry->seq_num,
1180 				       scan_entry->channel.chan_freq,
1181 				       scan_entry->rssi_raw);
1182 			util_scan_free_cache_entry(scan_entry);
1183 			qdf_mem_free(scan_node);
1184 			continue;
1185 		}
1186 		/* Do not add invalid channel entry as kernel will reject it */
1187 		if (scan_obj->drop_bcn_on_invalid_freq &&
1188 		    wlan_reg_is_disable_for_pwrmode(
1189 					pdev,
1190 					scan_entry->channel.chan_freq,
1191 					REG_BEST_PWR_MODE)) {
1192 			scm_nofl_debug("Drop frame for invalid freq %d: "QDF_MAC_ADDR_FMT" Seq Num: %d RSSI %d",
1193 				       scan_entry->channel.chan_freq,
1194 				       QDF_MAC_ADDR_REF(scan_entry->bssid.bytes),
1195 				       scan_entry->seq_num,
1196 				       scan_entry->rssi_raw);
1197 			util_scan_free_cache_entry(scan_entry);
1198 			qdf_mem_free(scan_node);
1199 			continue;
1200 		}
1201 		if (util_scan_entry_rsn(scan_entry)) {
1202 			status = wlan_crypto_rsnie_check(
1203 					&sec_params,
1204 					util_scan_entry_rsn(scan_entry));
1205 			if (QDF_IS_STATUS_ERROR(status) &&
1206 			    !scm_is_p2p_wildcard_ssid(scan_entry)) {
1207 				scm_nofl_debug("Drop frame from invalid RSN IE AP"
1208 					       QDF_MAC_ADDR_FMT
1209 					       ": RSN IE parse failed, status %d",
1210 					       QDF_MAC_ADDR_REF(
1211 					       scan_entry->bssid.bytes),
1212 					       status);
1213 				util_scan_free_cache_entry(scan_entry);
1214 				qdf_mem_free(scan_node);
1215 				continue;
1216 			}
1217 		}
1218 		if (wlan_cm_get_check_6ghz_security(psoc) &&
1219 		    wlan_reg_is_6ghz_chan_freq(scan_entry->channel.chan_freq)) {
1220 			if (!util_scan_entry_rsn(scan_entry)) {
1221 				scm_info_rl(
1222 					"Drop frame from "QDF_MAC_ADDR_FMT
1223 					": No RSN IE for 6GHz AP",
1224 					QDF_MAC_ADDR_REF(
1225 						scan_entry->bssid.bytes));
1226 				util_scan_free_cache_entry(scan_entry);
1227 				qdf_mem_free(scan_node);
1228 				continue;
1229 			}
1230 			status = wlan_crypto_rsnie_check(&sec_params,
1231 					util_scan_entry_rsn(scan_entry));
1232 			if (QDF_IS_STATUS_ERROR(status)) {
1233 				scm_info_rl(
1234 					"Drop frame from 6GHz AP "
1235 					QDF_MAC_ADDR_FMT
1236 					": RSN IE parse failed, status %d",
1237 					QDF_MAC_ADDR_REF(
1238 						scan_entry->bssid.bytes),
1239 					status);
1240 				util_scan_free_cache_entry(scan_entry);
1241 				qdf_mem_free(scan_node);
1242 				continue;
1243 			}
1244 			if ((QDF_HAS_PARAM(sec_params.ucastcipherset,
1245 					   WLAN_CRYPTO_CIPHER_NONE)) ||
1246 			    (QDF_HAS_PARAM(sec_params.ucastcipherset,
1247 					   WLAN_CRYPTO_CIPHER_TKIP)) ||
1248 			    (QDF_HAS_PARAM(sec_params.ucastcipherset,
1249 					   WLAN_CRYPTO_CIPHER_WEP_40)) ||
1250 			    (QDF_HAS_PARAM(sec_params.ucastcipherset,
1251 					   WLAN_CRYPTO_CIPHER_WEP_104))) {
1252 				scm_info_rl(
1253 					"Drop frame from "QDF_MAC_ADDR_FMT
1254 					": Invalid sec type %0X for 6GHz AP",
1255 					QDF_MAC_ADDR_REF(
1256 						scan_entry->bssid.bytes),
1257 					sec_params.ucastcipherset);
1258 				util_scan_free_cache_entry(scan_entry);
1259 				qdf_mem_free(scan_node);
1260 				continue;
1261 			}
1262 			if (!wlan_cm_6ghz_allowed_for_akm(psoc,
1263 					sec_params.key_mgmt,
1264 					sec_params.rsn_caps,
1265 					util_scan_entry_rsnxe(scan_entry),
1266 					0, false)) {
1267 				scm_info_rl(
1268 					"Drop frame from "QDF_MAC_ADDR_FMT
1269 					": Invalid AKM suite %0X for 6GHz AP",
1270 					QDF_MAC_ADDR_REF(
1271 						scan_entry->bssid.bytes),
1272 					sec_params.key_mgmt);
1273 				util_scan_free_cache_entry(scan_entry);
1274 				qdf_mem_free(scan_node);
1275 				continue;
1276 			}
1277 		}
1278 		if (scan_obj->cb.update_beacon)
1279 			scan_obj->cb.update_beacon(pdev, scan_entry);
1280 
1281 		/**
1282 		 * Do not drop the frame if Wi-Fi safe mode or RF test mode is
1283 		 * enabled. wlan_cm_get_check_6ghz_security API returns true if
1284 		 * neither Safe mode nor RF test mode are enabled.
1285 		 */
1286 		if (!wlan_cm_get_standard_6ghz_conn_policy(psoc) &&
1287 		    !scm_is_bss_allowed_for_country(psoc, scan_entry) &&
1288 		    wlan_cm_get_check_6ghz_security(psoc)) {
1289 			scm_info_rl(
1290 				"Drop frame from "QDF_MAC_ADDR_FMT
1291 				": AP in VLP mode not supported for US",
1292 				QDF_MAC_ADDR_REF(scan_entry->bssid.bytes));
1293 			util_scan_free_cache_entry(scan_entry);
1294 			qdf_mem_free(scan_node);
1295 			continue;
1296 		}
1297 
1298 		status = scm_add_update_entry(psoc, pdev, scan_entry);
1299 		if (QDF_IS_STATUS_ERROR(status)) {
1300 			scm_debug("failed to add entry for BSSID: "QDF_MAC_ADDR_FMT" Seq Num: %d",
1301 				  QDF_MAC_ADDR_REF(scan_entry->bssid.bytes),
1302 				  scan_entry->seq_num);
1303 			util_scan_free_cache_entry(scan_entry);
1304 			qdf_mem_free(scan_node);
1305 			continue;
1306 		}
1307 
1308 		qdf_mem_free(scan_node);
1309 	}
1310 
1311 free_nbuf:
1312 	if (scan_list)
1313 		qdf_mem_free(scan_list);
1314 	if (bcn->psoc)
1315 		wlan_objmgr_psoc_release_ref(bcn->psoc, WLAN_SCAN_ID);
1316 	if (pdev)
1317 		wlan_objmgr_pdev_release_ref(pdev, WLAN_SCAN_ID);
1318 	if (bcn->rx_data)
1319 		qdf_mem_free(bcn->rx_data);
1320 	if (bcn->buf)
1321 		qdf_nbuf_free(bcn->buf);
1322 	qdf_mem_free(bcn);
1323 
1324 	return status;
1325 }
1326 
1327 QDF_STATUS scm_handle_bcn_probe(struct scheduler_msg *msg)
1328 {
1329 	if (!msg) {
1330 		scm_err("msg is NULL");
1331 		return QDF_STATUS_E_NULL_VALUE;
1332 	}
1333 
1334 	return __scm_handle_bcn_probe(msg->bodyptr);
1335 }
1336 
1337 /**
1338  * scm_scan_apply_filter_get_entry() - apply filter and get the
1339  * scan entry
1340  * @psoc: psoc pointer
1341  * @db_entry: scan entry
1342  * @filter: filter to be applied
1343  * @scan_list: scan list to which entry is added
1344  *
1345  * Return: QDF_STATUS
1346  */
1347 static QDF_STATUS
1348 scm_scan_apply_filter_get_entry(struct wlan_objmgr_psoc *psoc,
1349 	struct scan_cache_entry *db_entry,
1350 	struct scan_filter *filter,
1351 	qdf_list_t *scan_list)
1352 {
1353 	struct scan_cache_node *scan_node = NULL;
1354 	struct security_info security = {0};
1355 	bool match;
1356 
1357 	if (!filter)
1358 		match = true;
1359 	else
1360 		match = scm_filter_match(psoc, db_entry,
1361 					filter, &security);
1362 
1363 	if (!match)
1364 		return QDF_STATUS_SUCCESS;
1365 
1366 	scan_node = qdf_mem_malloc_atomic(sizeof(*scan_node));
1367 	if (!scan_node)
1368 		return QDF_STATUS_E_NOMEM;
1369 
1370 	scan_node->entry =
1371 		util_scan_copy_cache_entry(db_entry);
1372 
1373 	if (!scan_node->entry) {
1374 		qdf_mem_free(scan_node);
1375 		return QDF_STATUS_E_NOMEM;
1376 	}
1377 
1378 	qdf_mem_copy(&scan_node->entry->neg_sec_info,
1379 		&security, sizeof(scan_node->entry->neg_sec_info));
1380 
1381 	qdf_list_insert_front(scan_list, &scan_node->node);
1382 
1383 	return QDF_STATUS_SUCCESS;
1384 }
1385 
1386 /**
1387  * scm_get_results() - Iterate and get scan results
1388  * @psoc: psoc ptr
1389  * @scan_db: scan db
1390  * @filter: filter to be applied
1391  * @scan_list: scan list to which entry is added
1392  *
1393  * Return: void
1394  */
1395 static void scm_get_results(struct wlan_objmgr_psoc *psoc,
1396 	struct scan_dbs *scan_db, struct scan_filter *filter,
1397 	qdf_list_t *scan_list)
1398 {
1399 	int i, count;
1400 	struct scan_cache_node *cur_node;
1401 	struct scan_cache_node *next_node = NULL;
1402 
1403 	for (i = 0 ; i < SCAN_HASH_SIZE; i++) {
1404 		cur_node = scm_get_next_node(scan_db,
1405 			   &scan_db->scan_hash_tbl[i], NULL);
1406 		count = qdf_list_size(&scan_db->scan_hash_tbl[i]);
1407 		if (!count)
1408 			continue;
1409 		while (cur_node) {
1410 			scm_scan_apply_filter_get_entry(psoc,
1411 				cur_node->entry, filter, scan_list);
1412 			next_node = scm_get_next_node(scan_db,
1413 				&scan_db->scan_hash_tbl[i], cur_node);
1414 			cur_node = next_node;
1415 		}
1416 	}
1417 }
1418 
1419 QDF_STATUS scm_purge_scan_results(qdf_list_t *scan_list)
1420 {
1421 	QDF_STATUS status;
1422 	struct scan_cache_node *cur_node;
1423 	qdf_list_node_t *cur_lst = NULL, *next_lst = NULL;
1424 
1425 	if (!scan_list) {
1426 		scm_err("scan_result is NULL");
1427 		return QDF_STATUS_E_INVAL;
1428 	}
1429 
1430 	status = qdf_list_peek_front(scan_list, &cur_lst);
1431 
1432 	while (cur_lst) {
1433 		qdf_list_peek_next(
1434 			scan_list, cur_lst, &next_lst);
1435 		cur_node = qdf_container_of(cur_lst,
1436 			struct scan_cache_node, node);
1437 		status = qdf_list_remove_node(scan_list,
1438 					cur_lst);
1439 		if (QDF_IS_STATUS_SUCCESS(status)) {
1440 			util_scan_free_cache_entry(cur_node->entry);
1441 			qdf_mem_free(cur_node);
1442 		}
1443 		cur_lst = next_lst;
1444 		next_lst = NULL;
1445 	}
1446 
1447 	qdf_list_destroy(scan_list);
1448 	qdf_mem_free(scan_list);
1449 
1450 	return status;
1451 }
1452 
1453 qdf_list_t *scm_get_scan_result(struct wlan_objmgr_pdev *pdev,
1454 	struct scan_filter *filter)
1455 {
1456 	struct wlan_objmgr_psoc *psoc;
1457 	struct scan_dbs *scan_db;
1458 	qdf_list_t *tmp_list;
1459 
1460 	if (!pdev) {
1461 		scm_err("pdev is NULL");
1462 		return NULL;
1463 	}
1464 
1465 	psoc = wlan_pdev_get_psoc(pdev);
1466 	if (!psoc) {
1467 		scm_err("psoc is NULL");
1468 		return NULL;
1469 	}
1470 
1471 	scan_db = wlan_pdev_get_scan_db(psoc, pdev);
1472 	if (!scan_db) {
1473 		scm_err("scan_db is NULL");
1474 		return NULL;
1475 	}
1476 
1477 	tmp_list = qdf_mem_malloc_atomic(sizeof(*tmp_list));
1478 	if (!tmp_list) {
1479 		scm_err("failed tp allocate scan_result");
1480 		return NULL;
1481 	}
1482 	qdf_list_create(tmp_list,
1483 			MAX_SCAN_CACHE_SIZE);
1484 	scm_age_out_entries(psoc, scan_db);
1485 	scm_get_results(psoc, scan_db, filter, tmp_list);
1486 
1487 	return tmp_list;
1488 }
1489 
1490 /**
1491  * scm_iterate_db_and_call_func() - iterate and call the func
1492  * @scan_db: scan db
1493  * @func: func to be called
1494  * @arg: func arg
1495  *
1496  * Return: QDF_STATUS
1497  */
1498 static QDF_STATUS
1499 scm_iterate_db_and_call_func(struct scan_dbs *scan_db,
1500 	scan_iterator_func func, void *arg)
1501 {
1502 	int i;
1503 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1504 	struct scan_cache_node *cur_node;
1505 	struct scan_cache_node *next_node = NULL;
1506 
1507 	if (!func)
1508 		return QDF_STATUS_E_INVAL;
1509 
1510 	for (i = 0 ; i < SCAN_HASH_SIZE; i++) {
1511 		cur_node = scm_get_next_node(scan_db,
1512 			&scan_db->scan_hash_tbl[i], NULL);
1513 		while (cur_node) {
1514 			status = func(arg, cur_node->entry);
1515 			if (QDF_IS_STATUS_ERROR(status)) {
1516 				scm_scan_entry_put_ref(scan_db,
1517 					cur_node, true);
1518 				return status;
1519 			}
1520 			next_node = scm_get_next_node(scan_db,
1521 				&scan_db->scan_hash_tbl[i], cur_node);
1522 			cur_node = next_node;
1523 		}
1524 	}
1525 
1526 	return status;
1527 }
1528 
1529 QDF_STATUS
1530 scm_iterate_scan_db(struct wlan_objmgr_pdev *pdev,
1531 	scan_iterator_func func, void *arg)
1532 {
1533 	struct wlan_objmgr_psoc *psoc;
1534 	struct scan_dbs *scan_db;
1535 	QDF_STATUS status;
1536 
1537 	if (!func) {
1538 		scm_err("func is NULL");
1539 		return QDF_STATUS_E_INVAL;
1540 	}
1541 
1542 	if (!pdev) {
1543 		scm_err("pdev is NULL");
1544 		return QDF_STATUS_E_INVAL;
1545 	}
1546 
1547 	psoc = wlan_pdev_get_psoc(pdev);
1548 	if (!psoc) {
1549 		scm_err("psoc is NULL");
1550 		return QDF_STATUS_E_INVAL;
1551 	}
1552 	scan_db = wlan_pdev_get_scan_db(psoc, pdev);
1553 	if (!scan_db) {
1554 		scm_err("scan_db is NULL");
1555 		return QDF_STATUS_E_INVAL;
1556 	}
1557 
1558 	scm_age_out_entries(psoc, scan_db);
1559 	status = scm_iterate_db_and_call_func(scan_db, func, arg);
1560 
1561 	return status;
1562 }
1563 
1564 /**
1565  * scm_scan_apply_filter_flush_entry() -flush scan entries depending
1566  * on filter
1567  * @psoc: psoc ptr
1568  * @scan_db: scan db
1569  * @db_node: node on which filters are applied
1570  * @filter: filter to be applied
1571  *
1572  * Return: QDF_STATUS
1573  */
1574 static QDF_STATUS
1575 scm_scan_apply_filter_flush_entry(struct wlan_objmgr_psoc *psoc,
1576 	struct scan_dbs *scan_db,
1577 	struct scan_cache_node *db_node,
1578 	struct scan_filter *filter)
1579 {
1580 	struct security_info security = {0};
1581 	bool match;
1582 
1583 	if (!filter)
1584 		match = true;
1585 	else
1586 		match = scm_filter_match(psoc, db_node->entry,
1587 					filter, &security);
1588 
1589 	if (!match)
1590 		return QDF_STATUS_SUCCESS;
1591 
1592 	qdf_spin_lock_bh(&scan_db->scan_db_lock);
1593 	scm_scan_entry_del(scan_db, db_node);
1594 	qdf_spin_unlock_bh(&scan_db->scan_db_lock);
1595 
1596 	return QDF_STATUS_SUCCESS;
1597 }
1598 
1599 /**
1600  * scm_flush_scan_entries() - API to flush scan entries depending on filters
1601  * @psoc: psoc ptr
1602  * @scan_db: scan db
1603  * @filter: filter
1604  *
1605  * Return: void
1606  */
1607 static void scm_flush_scan_entries(struct wlan_objmgr_psoc *psoc,
1608 	struct scan_dbs *scan_db,
1609 	struct scan_filter *filter)
1610 {
1611 	int i;
1612 	struct scan_cache_node *cur_node;
1613 	struct scan_cache_node *next_node = NULL;
1614 
1615 	for (i = 0 ; i < SCAN_HASH_SIZE; i++) {
1616 		cur_node = scm_get_next_node(scan_db,
1617 			   &scan_db->scan_hash_tbl[i], NULL);
1618 		while (cur_node) {
1619 			scm_scan_apply_filter_flush_entry(psoc, scan_db,
1620 				cur_node, filter);
1621 			next_node = scm_get_next_node(scan_db,
1622 				&scan_db->scan_hash_tbl[i], cur_node);
1623 			cur_node = next_node;
1624 		}
1625 	}
1626 }
1627 
1628 QDF_STATUS scm_flush_results(struct wlan_objmgr_pdev *pdev,
1629 	struct scan_filter *filter)
1630 {
1631 	struct wlan_objmgr_psoc *psoc;
1632 	struct scan_dbs *scan_db;
1633 	QDF_STATUS status = QDF_STATUS_SUCCESS;
1634 
1635 	if (!pdev) {
1636 		scm_err("pdev is NULL");
1637 		return QDF_STATUS_E_INVAL;
1638 	}
1639 
1640 	psoc = wlan_pdev_get_psoc(pdev);
1641 	if (!psoc) {
1642 		scm_err("psoc is NULL");
1643 		return QDF_STATUS_E_INVAL;
1644 	}
1645 
1646 	scan_db = wlan_pdev_get_scan_db(psoc, pdev);
1647 	if (!scan_db) {
1648 		scm_err("scan_db is NULL");
1649 		return QDF_STATUS_E_INVAL;
1650 	}
1651 
1652 	scm_flush_scan_entries(psoc, scan_db, filter);
1653 
1654 	return status;
1655 }
1656 
1657 /**
1658  * scm_filter_channels() - Remove entries not belonging to channel list
1659  * @pdev: pointer to pdev
1660  * @scan_db: scan db
1661  * @db_node: node on which filters are applied
1662  * @chan_freq_list: valid channel frequency (in MHz) list
1663  * @num_chan: number of channels
1664  *
1665  * Return: QDF_STATUS
1666  */
1667 static void scm_filter_channels(struct wlan_objmgr_pdev *pdev,
1668 				struct scan_dbs *scan_db,
1669 				struct scan_cache_node *db_node,
1670 				uint32_t *chan_freq_list, uint32_t num_chan)
1671 {
1672 	int i;
1673 	bool match = false;
1674 
1675 	for (i = 0; i < num_chan; i++) {
1676 		if (chan_freq_list[i] == util_scan_entry_channel_frequency(
1677 							db_node->entry)) {
1678 			match = true;
1679 			break;
1680 		}
1681 	}
1682 
1683 	if (!match) {
1684 		qdf_spin_lock_bh(&scan_db->scan_db_lock);
1685 		scm_scan_entry_del(scan_db, db_node);
1686 		qdf_spin_unlock_bh(&scan_db->scan_db_lock);
1687 	}
1688 }
1689 
1690 void scm_filter_valid_channel(struct wlan_objmgr_pdev *pdev,
1691 	uint32_t *chan_freq_list, uint32_t num_chan)
1692 {
1693 	int i;
1694 	struct wlan_objmgr_psoc *psoc;
1695 	struct scan_dbs *scan_db;
1696 	struct scan_cache_node *cur_node;
1697 	struct scan_cache_node *next_node = NULL;
1698 
1699 	scm_debug("num_chan = %d", num_chan);
1700 
1701 	if (!pdev) {
1702 		scm_err("pdev is NULL");
1703 		return;
1704 	}
1705 
1706 	psoc = wlan_pdev_get_psoc(pdev);
1707 	if (!psoc) {
1708 		scm_err("psoc is NULL");
1709 		return;
1710 	}
1711 
1712 	scan_db = wlan_pdev_get_scan_db(psoc, pdev);
1713 	if (!scan_db) {
1714 		scm_err("scan_db is NULL");
1715 		return;
1716 	}
1717 
1718 	for (i = 0 ; i < SCAN_HASH_SIZE; i++) {
1719 		cur_node = scm_get_next_node(scan_db,
1720 			   &scan_db->scan_hash_tbl[i], NULL);
1721 		while (cur_node) {
1722 			scm_filter_channels(pdev, scan_db,
1723 					    cur_node, chan_freq_list, num_chan);
1724 			next_node = scm_get_next_node(scan_db,
1725 				&scan_db->scan_hash_tbl[i], cur_node);
1726 			cur_node = next_node;
1727 		}
1728 	}
1729 }
1730 
1731 QDF_STATUS scm_scan_register_bcn_cb(struct wlan_objmgr_psoc *psoc,
1732 	update_beacon_cb cb, enum scan_cb_type type)
1733 {
1734 	struct wlan_scan_obj *scan_obj;
1735 
1736 	scan_obj = wlan_psoc_get_scan_obj(psoc);
1737 	if (!scan_obj) {
1738 		scm_err("scan obj is NULL");
1739 		return QDF_STATUS_E_INVAL;
1740 	}
1741 	switch (type) {
1742 	case SCAN_CB_TYPE_INFORM_BCN:
1743 		scan_obj->cb.inform_beacon = cb;
1744 		break;
1745 	case SCAN_CB_TYPE_UPDATE_BCN:
1746 		scan_obj->cb.update_beacon = cb;
1747 		break;
1748 	case SCAN_CB_TYPE_UNLINK_BSS:
1749 		scan_obj->cb.unlink_bss = cb;
1750 		break;
1751 	default:
1752 		scm_err("invalid cb type %d", type);
1753 	}
1754 
1755 	return QDF_STATUS_SUCCESS;
1756 }
1757 
1758 QDF_STATUS scm_db_init(struct wlan_objmgr_psoc *psoc)
1759 {
1760 	int i, j;
1761 	struct scan_dbs *scan_db;
1762 
1763 	if (!psoc) {
1764 		scm_err("psoc is NULL");
1765 		return QDF_STATUS_E_INVAL;
1766 	}
1767 
1768 	/* Initialize the scan database per pdev */
1769 	for (i = 0; i < WLAN_UMAC_MAX_PDEVS; i++) {
1770 		scan_db = wlan_pdevid_get_scan_db(psoc, i);
1771 		if (!scan_db) {
1772 			scm_err("scan_db is NULL %d", i);
1773 			continue;
1774 		}
1775 		scan_db->num_entries = 0;
1776 		qdf_spinlock_create(&scan_db->scan_db_lock);
1777 		for (j = 0; j < SCAN_HASH_SIZE; j++)
1778 			qdf_list_create(&scan_db->scan_hash_tbl[j],
1779 				MAX_SCAN_CACHE_SIZE);
1780 	}
1781 	return QDF_STATUS_SUCCESS;
1782 }
1783 
1784 QDF_STATUS scm_db_deinit(struct wlan_objmgr_psoc *psoc)
1785 {
1786 	int i, j;
1787 	struct scan_dbs *scan_db;
1788 
1789 	if (!psoc) {
1790 		scm_err("scan obj is NULL");
1791 		return QDF_STATUS_E_INVAL;
1792 	}
1793 
1794 	/* Initialize the scan database per pdev */
1795 	for (i = 0; i < WLAN_UMAC_MAX_PDEVS; i++) {
1796 		scan_db = wlan_pdevid_get_scan_db(psoc, i);
1797 		if (!scan_db) {
1798 			scm_err("scan_db is NULL %d", i);
1799 			continue;
1800 		}
1801 
1802 		scm_flush_scan_entries(psoc, scan_db, NULL);
1803 		for (j = 0; j < SCAN_HASH_SIZE; j++)
1804 			qdf_list_destroy(&scan_db->scan_hash_tbl[j]);
1805 		qdf_spinlock_destroy(&scan_db->scan_db_lock);
1806 	}
1807 
1808 	return QDF_STATUS_SUCCESS;
1809 }
1810 
1811 #ifdef FEATURE_6G_SCAN_CHAN_SORT_ALGO
1812 QDF_STATUS scm_channel_list_db_init(struct wlan_objmgr_psoc *psoc)
1813 {
1814 	uint32_t i, j;
1815 	uint32_t min_freq, max_freq;
1816 	struct channel_list_db *rnr_channel_db;
1817 
1818 	min_freq = wlan_reg_min_6ghz_chan_freq();
1819 	max_freq = wlan_reg_max_6ghz_chan_freq();
1820 
1821 	scm_info("min_freq %d max_freq %d", min_freq, max_freq);
1822 	i = min_freq;
1823 	rnr_channel_db = scm_get_rnr_channel_db(psoc);
1824 	if (!rnr_channel_db)
1825 		return QDF_STATUS_E_INVAL;
1826 
1827 	for (j = 0; j < QDF_ARRAY_SIZE(rnr_channel_db->channel); j++) {
1828 		if (i >= min_freq && i <= max_freq)
1829 			rnr_channel_db->channel[j].chan_freq = i;
1830 		i += 20;
1831 		/* init list for all to avoid uninitialized list */
1832 		qdf_list_create(&rnr_channel_db->channel[j].rnr_list,
1833 				WLAN_MAX_RNR_COUNT);
1834 	}
1835 	return QDF_STATUS_SUCCESS;
1836 }
1837 
1838 QDF_STATUS scm_channel_list_db_deinit(struct wlan_objmgr_psoc *psoc)
1839 {
1840 	int i;
1841 	qdf_list_node_t *cur_node, *next_node;
1842 	struct meta_rnr_channel *channel;
1843 	struct scan_rnr_node *rnr_node;
1844 	struct channel_list_db *rnr_channel_db;
1845 
1846 	rnr_channel_db = scm_get_rnr_channel_db(psoc);
1847 	if (!rnr_channel_db)
1848 		return QDF_STATUS_E_INVAL;
1849 
1850 	for (i = 0; i < QDF_ARRAY_SIZE(rnr_channel_db->channel); i++) {
1851 		channel = &rnr_channel_db->channel[i];
1852 		channel->chan_freq = 0;
1853 		channel->beacon_probe_last_time_found = 0;
1854 		channel->bss_beacon_probe_count = 0;
1855 		channel->saved_profile_count = 0;
1856 		cur_node = NULL;
1857 		qdf_list_peek_front(&channel->rnr_list, &cur_node);
1858 		while (cur_node) {
1859 			next_node = NULL;
1860 			qdf_list_peek_next(&channel->rnr_list, cur_node,
1861 					   &next_node);
1862 			rnr_node = qdf_container_of(cur_node,
1863 						    struct scan_rnr_node,
1864 						    node);
1865 			qdf_list_remove_node(&channel->rnr_list,
1866 					     &rnr_node->node);
1867 			qdf_mem_free(rnr_node);
1868 			cur_node = next_node;
1869 			next_node = NULL;
1870 		}
1871 		qdf_list_destroy(&channel->rnr_list);
1872 	}
1873 
1874 	return QDF_STATUS_SUCCESS;
1875 }
1876 
1877 QDF_STATUS scm_rnr_db_flush(struct wlan_objmgr_psoc *psoc)
1878 {
1879 	int i;
1880 	qdf_list_node_t *cur_node, *next_node;
1881 	struct meta_rnr_channel *channel;
1882 	struct scan_rnr_node *rnr_node;
1883 	struct channel_list_db *rnr_channel_db;
1884 
1885 	rnr_channel_db = scm_get_rnr_channel_db(psoc);
1886 	if (!rnr_channel_db)
1887 		return QDF_STATUS_E_INVAL;
1888 
1889 	for (i = 0; i < QDF_ARRAY_SIZE(rnr_channel_db->channel); i++) {
1890 		channel = &rnr_channel_db->channel[i];
1891 		cur_node = NULL;
1892 		qdf_list_peek_front(&channel->rnr_list, &cur_node);
1893 		while (cur_node) {
1894 			next_node = NULL;
1895 			qdf_list_peek_next(&channel->rnr_list, cur_node,
1896 					   &next_node);
1897 			rnr_node = qdf_container_of(cur_node,
1898 						    struct scan_rnr_node,
1899 						    node);
1900 			qdf_list_remove_node(&channel->rnr_list,
1901 					     &rnr_node->node);
1902 			qdf_mem_free(rnr_node);
1903 			cur_node = next_node;
1904 			next_node = NULL;
1905 		}
1906 		/* Reset beacon info */
1907 		channel->beacon_probe_last_time_found = 0;
1908 		channel->bss_beacon_probe_count = 0;
1909 	}
1910 
1911 	return QDF_STATUS_SUCCESS;
1912 }
1913 
1914 void scm_update_rnr_from_scan_cache(struct wlan_objmgr_pdev *pdev)
1915 {
1916 	uint8_t i;
1917 	struct scan_dbs *scan_db;
1918 	struct scan_cache_node *cur_node;
1919 	struct scan_cache_node *next_node = NULL;
1920 	struct wlan_objmgr_psoc *psoc;
1921 	struct scan_cache_entry *entry;
1922 
1923 	psoc = wlan_pdev_get_psoc(pdev);
1924 	if (!psoc) {
1925 		scm_err("psoc is NULL");
1926 		return;
1927 	}
1928 	scan_db = wlan_pdev_get_scan_db(psoc, pdev);
1929 	if (!scan_db) {
1930 		scm_err("scan_db is NULL");
1931 		return;
1932 	}
1933 
1934 	for (i = 0 ; i < SCAN_HASH_SIZE; i++) {
1935 		cur_node = scm_get_next_node(scan_db,
1936 					     &scan_db->scan_hash_tbl[i], NULL);
1937 		while (cur_node) {
1938 			entry = cur_node->entry;
1939 			scm_add_rnr_channel_db(psoc, entry);
1940 			next_node =
1941 				scm_get_next_node(scan_db,
1942 						  &scan_db->scan_hash_tbl[i],
1943 						  cur_node);
1944 			cur_node = next_node;
1945 			next_node = NULL;
1946 		}
1947 	}
1948 }
1949 #endif
1950 
1951 QDF_STATUS scm_update_scan_mlme_info(struct wlan_objmgr_pdev *pdev,
1952 	struct scan_cache_entry *entry)
1953 {
1954 	uint8_t hash_idx;
1955 	struct scan_dbs *scan_db;
1956 	struct scan_cache_node *cur_node;
1957 	struct scan_cache_node *next_node = NULL;
1958 	struct wlan_objmgr_psoc *psoc;
1959 
1960 	psoc = wlan_pdev_get_psoc(pdev);
1961 	if (!psoc) {
1962 		scm_err("psoc is NULL");
1963 		return QDF_STATUS_E_INVAL;
1964 	}
1965 	scan_db = wlan_pdev_get_scan_db(psoc, pdev);
1966 	if (!scan_db) {
1967 		scm_err("scan_db is NULL");
1968 		return QDF_STATUS_E_INVAL;
1969 	}
1970 
1971 	hash_idx = SCAN_GET_HASH(entry->bssid.bytes);
1972 
1973 	cur_node = scm_get_next_node(scan_db,
1974 			&scan_db->scan_hash_tbl[hash_idx], NULL);
1975 
1976 	while (cur_node) {
1977 		if (util_is_scan_entry_match(entry,
1978 					cur_node->entry)) {
1979 			/* Acquire db lock to prevent simultaneous update */
1980 			qdf_spin_lock_bh(&scan_db->scan_db_lock);
1981 			scm_update_mlme_info(entry, cur_node->entry);
1982 			qdf_spin_unlock_bh(&scan_db->scan_db_lock);
1983 			scm_scan_entry_put_ref(scan_db,
1984 					cur_node, true);
1985 			return QDF_STATUS_SUCCESS;
1986 		}
1987 		next_node = scm_get_next_node(scan_db,
1988 				&scan_db->scan_hash_tbl[hash_idx], cur_node);
1989 		cur_node = next_node;
1990 	}
1991 
1992 	return QDF_STATUS_E_INVAL;
1993 }
1994 
1995 QDF_STATUS scm_scan_update_mlme_by_bssinfo(struct wlan_objmgr_pdev *pdev,
1996 		struct bss_info *bss_info, struct mlme_info *mlme)
1997 {
1998 	uint8_t hash_idx;
1999 	struct scan_dbs *scan_db;
2000 	struct scan_cache_node *cur_node;
2001 	struct scan_cache_node *next_node = NULL;
2002 	struct wlan_objmgr_psoc *psoc;
2003 	struct scan_cache_entry *entry;
2004 
2005 	psoc = wlan_pdev_get_psoc(pdev);
2006 	if (!psoc) {
2007 		scm_err("psoc is NULL");
2008 		return QDF_STATUS_E_INVAL;
2009 	}
2010 	scan_db = wlan_pdev_get_scan_db(psoc, pdev);
2011 	if (!scan_db) {
2012 		scm_err("scan_db is NULL");
2013 		return QDF_STATUS_E_INVAL;
2014 	}
2015 
2016 	hash_idx = SCAN_GET_HASH(bss_info->bssid.bytes);
2017 	cur_node = scm_get_next_node(scan_db,
2018 			&scan_db->scan_hash_tbl[hash_idx], NULL);
2019 	while (cur_node) {
2020 		entry = cur_node->entry;
2021 		if (qdf_is_macaddr_equal(&bss_info->bssid, &entry->bssid) &&
2022 			(util_is_ssid_match(&bss_info->ssid, &entry->ssid)) &&
2023 			(bss_info->freq == entry->channel.chan_freq)) {
2024 			/* Acquire db lock to prevent simultaneous update */
2025 			qdf_spin_lock_bh(&scan_db->scan_db_lock);
2026 			qdf_mem_copy(&entry->mlme_info, mlme,
2027 					sizeof(struct mlme_info));
2028 			scm_debug("BSSID: "QDF_MAC_ADDR_FMT" set assoc_state to %d with age %lu ms",
2029 				  QDF_MAC_ADDR_REF(entry->bssid.bytes),
2030 				  mlme->assoc_state,
2031 				  util_scan_entry_age(entry));
2032 			scm_scan_entry_put_ref(scan_db,
2033 					cur_node, false);
2034 			qdf_spin_unlock_bh(&scan_db->scan_db_lock);
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 uint32_t scm_get_last_scan_time_per_channel(struct wlan_objmgr_vdev *vdev,
2046 					    uint32_t freq)
2047 {
2048 	struct wlan_scan_obj *scan;
2049 	struct chan_list_scan_info *chan_info;
2050 	uint8_t pdev_id;
2051 	int i;
2052 
2053 	scan = wlan_vdev_get_scan_obj(vdev);
2054 	if (!scan)
2055 		return 0;
2056 
2057 	pdev_id = wlan_scan_vdev_get_pdev_id(vdev);
2058 	chan_info = &scan->pdev_info[pdev_id].chan_scan_info;
2059 
2060 	for (i = 0; i < chan_info->num_chan ; i++) {
2061 		if (chan_info->ch_scan_info[i].freq == freq)
2062 			return chan_info->ch_scan_info[i].last_scan_time;
2063 	}
2064 
2065 	return 0;
2066 }
2067 
2068 QDF_STATUS
2069 scm_scan_get_entry_by_mac_addr(struct wlan_objmgr_pdev *pdev,
2070 			       struct qdf_mac_addr *bssid,
2071 			       struct element_info *frame)
2072 {
2073 	struct scan_filter *scan_filter;
2074 	qdf_list_t *list = NULL;
2075 	struct scan_cache_node *first_node = NULL;
2076 	qdf_list_node_t *cur_node = NULL;
2077 	QDF_STATUS status = QDF_STATUS_SUCCESS;
2078 
2079 	scan_filter = qdf_mem_malloc(sizeof(*scan_filter));
2080 	if (!scan_filter)
2081 		return QDF_STATUS_E_NOMEM;
2082 	scan_filter->num_of_bssid = 1;
2083 	qdf_copy_macaddr(&scan_filter->bssid_list[0], bssid);
2084 	list = scm_get_scan_result(pdev, scan_filter);
2085 	qdf_mem_free(scan_filter);
2086 	if (!list || (list && !qdf_list_size(list))) {
2087 		status = QDF_STATUS_E_INVAL;
2088 		goto done;
2089 	}
2090 	/*
2091 	 * There might be multiple scan results in the scan db with given mac
2092 	 * address(e.g. SSID/some capabilities of the AP have just changed and
2093 	 * old entry is not aged out yet). scm_get_scan_result() inserts the
2094 	 * latest scan result at the front of the given list. So, it's ok to
2095 	 * pick scan result from the front node alone.
2096 	 */
2097 	qdf_list_peek_front(list, &cur_node);
2098 	first_node = qdf_container_of(cur_node,
2099 				      struct scan_cache_node,
2100 				      node);
2101 	if (first_node && first_node->entry) {
2102 		frame->len = first_node->entry->raw_frame.len;
2103 		frame->ptr = qdf_mem_malloc(frame->len);
2104 		if (!frame->ptr) {
2105 			status = QDF_STATUS_E_NOMEM;
2106 			goto done;
2107 		}
2108 		qdf_mem_copy(frame->ptr,
2109 			     first_node->entry->raw_frame.ptr,
2110 			     frame->len);
2111 	}
2112 
2113 done:
2114 	if (list)
2115 		scm_purge_scan_results(list);
2116 
2117 	return status;
2118 }
2119 
2120 struct scan_cache_entry *
2121 scm_scan_get_entry_by_bssid(struct wlan_objmgr_pdev *pdev,
2122 			    struct qdf_mac_addr *bssid)
2123 {
2124 	struct scan_filter *scan_filter;
2125 	qdf_list_t *list = NULL;
2126 	struct scan_cache_node *first_node = NULL;
2127 	qdf_list_node_t *cur_node = NULL;
2128 	struct scan_cache_entry *entry = NULL, *scan_entry = NULL;
2129 
2130 	if (!pdev)
2131 		return NULL;
2132 
2133 	scan_filter = qdf_mem_malloc(sizeof(*scan_filter));
2134 	if (!scan_filter)
2135 		return NULL;
2136 
2137 	scan_filter->num_of_bssid = 1;
2138 	qdf_mem_copy(scan_filter->bssid_list[0].bytes,
2139 		     bssid, sizeof(struct qdf_mac_addr));
2140 	list = scm_get_scan_result(pdev, scan_filter);
2141 	qdf_mem_free(scan_filter);
2142 
2143 	if (!list || (!qdf_list_size(list))) {
2144 		scm_debug("Scan entry for bssid: "QDF_MAC_ADDR_FMT" not found",
2145 			  QDF_MAC_ADDR_REF(bssid->bytes));
2146 		goto exit;
2147 	}
2148 
2149 	qdf_list_peek_front(list, &cur_node);
2150 	first_node = qdf_container_of(cur_node, struct scan_cache_node,
2151 				      node);
2152 	if (first_node && first_node->entry) {
2153 		entry = first_node->entry;
2154 		scan_entry = util_scan_copy_cache_entry(entry);
2155 	}
2156 exit:
2157 	if (list)
2158 		scm_purge_scan_results(list);
2159 
2160 	return scan_entry;
2161 }
2162