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