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