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