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