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