1 /* 2 * Copyright (c) 2020-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 any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 /* 19 * DOC: contains interface manager roam public api 20 */ 21 #include "wlan_objmgr_psoc_obj.h" 22 #include "wlan_objmgr_pdev_obj.h" 23 #include "wlan_objmgr_vdev_obj.h" 24 #include "wlan_policy_mgr_api.h" 25 #include "wlan_policy_mgr_i.h" 26 #include "wlan_if_mgr_roam.h" 27 #include "wlan_if_mgr_public_struct.h" 28 #include "wlan_cm_roam_api.h" 29 #include "wlan_if_mgr_main.h" 30 #include "wlan_p2p_ucfg_api.h" 31 #include "cds_api.h" 32 #include "sme_api.h" 33 #include "wlan_vdev_mgr_utils_api.h" 34 #include "wni_api.h" 35 #include "wlan_mlme_vdev_mgr_interface.h" 36 #include "wlan_cm_api.h" 37 #include "wlan_scan_api.h" 38 #include "wlan_mlo_mgr_roam.h" 39 #include "wlan_mlo_mgr_sta.h" 40 #include "wlan_mlo_mgr_link_switch.h" 41 42 #ifdef WLAN_FEATURE_11BE_MLO 43 static inline bool 44 if_mgr_is_assoc_link_of_vdev(struct wlan_objmgr_pdev *pdev, 45 struct wlan_objmgr_vdev *vdev, 46 uint8_t cur_vdev_id) 47 { 48 struct wlan_objmgr_vdev *cur_vdev, *assoc_vdev; 49 50 cur_vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, cur_vdev_id, 51 WLAN_IF_MGR_ID); 52 if (!cur_vdev) 53 return false; 54 55 assoc_vdev = wlan_mlo_get_assoc_link_vdev(cur_vdev); 56 57 wlan_objmgr_vdev_release_ref(cur_vdev, WLAN_IF_MGR_ID); 58 if (vdev == assoc_vdev) 59 return true; 60 61 return false; 62 } 63 #else 64 static inline bool 65 if_mgr_is_assoc_link_of_vdev(struct wlan_objmgr_pdev *pdev, 66 struct wlan_objmgr_vdev *vdev, 67 uint8_t cur_vdev_id) 68 { 69 return false; 70 } 71 #endif 72 73 static void if_mgr_enable_roaming_on_vdev(struct wlan_objmgr_pdev *pdev, 74 void *object, void *arg) 75 { 76 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object; 77 struct change_roam_state_arg *roam_arg = arg; 78 uint8_t vdev_id, curr_vdev_id; 79 80 vdev_id = wlan_vdev_get_id(vdev); 81 curr_vdev_id = roam_arg->curr_vdev_id; 82 83 if (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE) 84 return; 85 86 if (wlan_vdev_mlme_is_mlo_link_vdev(vdev) || 87 if_mgr_is_assoc_link_of_vdev(pdev, vdev, curr_vdev_id)) 88 return; 89 90 if (curr_vdev_id != vdev_id && 91 vdev->vdev_mlme.mlme_state == WLAN_VDEV_S_UP) { 92 ifmgr_debug("Enable roaming for vdev_id %d", vdev_id); 93 wlan_cm_enable_rso(pdev, vdev_id, 94 roam_arg->requestor, 95 REASON_DRIVER_ENABLED); 96 } 97 } 98 99 QDF_STATUS if_mgr_enable_roaming(struct wlan_objmgr_pdev *pdev, 100 struct wlan_objmgr_vdev *vdev, 101 enum wlan_cm_rso_control_requestor requestor) 102 { 103 QDF_STATUS status = QDF_STATUS_SUCCESS; 104 struct change_roam_state_arg roam_arg; 105 uint8_t vdev_id; 106 107 vdev_id = wlan_vdev_get_id(vdev); 108 109 roam_arg.requestor = requestor; 110 roam_arg.curr_vdev_id = vdev_id; 111 112 status = wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, 113 if_mgr_enable_roaming_on_vdev, 114 &roam_arg, 0, 115 WLAN_IF_MGR_ID); 116 117 return status; 118 } 119 120 static void if_mgr_disable_roaming_on_vdev(struct wlan_objmgr_pdev *pdev, 121 void *object, void *arg) 122 { 123 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object; 124 struct change_roam_state_arg *roam_arg = arg; 125 uint8_t vdev_id, curr_vdev_id; 126 127 vdev_id = wlan_vdev_get_id(vdev); 128 curr_vdev_id = roam_arg->curr_vdev_id; 129 130 if (curr_vdev_id == vdev_id || 131 wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE || 132 wlan_cm_is_vdev_roam_sync_inprogress(vdev) || 133 vdev->vdev_mlme.mlme_state != WLAN_VDEV_S_UP) 134 return; 135 136 /* 137 * Disable roaming only for the STA vdev which is not is roam sync state 138 * and VDEV is in UP state. 139 */ 140 ifmgr_debug("Roaming disabled on vdev_id %d", vdev_id); 141 wlan_cm_disable_rso(pdev, vdev_id, roam_arg->requestor, 142 REASON_DRIVER_DISABLED); 143 } 144 145 QDF_STATUS if_mgr_disable_roaming(struct wlan_objmgr_pdev *pdev, 146 struct wlan_objmgr_vdev *vdev, 147 enum wlan_cm_rso_control_requestor requestor) 148 { 149 QDF_STATUS status = QDF_STATUS_SUCCESS; 150 struct change_roam_state_arg roam_arg; 151 uint8_t vdev_id; 152 153 vdev_id = wlan_vdev_get_id(vdev); 154 155 roam_arg.requestor = requestor; 156 roam_arg.curr_vdev_id = vdev_id; 157 158 status = wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, 159 if_mgr_disable_roaming_on_vdev, 160 &roam_arg, 0, 161 WLAN_IF_MGR_ID); 162 163 return status; 164 } 165 166 QDF_STATUS 167 if_mgr_enable_roaming_on_connected_sta(struct wlan_objmgr_pdev *pdev, 168 struct wlan_objmgr_vdev *vdev) 169 { 170 struct wlan_objmgr_psoc *psoc; 171 uint8_t vdev_id = wlan_vdev_get_id(vdev); 172 173 if (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE) 174 return QDF_STATUS_E_FAILURE; 175 176 /* 177 * When link switch is in progress, don't send RSO Enable before vdev 178 * is up. RSO Enable will be sent as part of install keys once 179 * link switch connect sequence is complete. 180 */ 181 if (mlo_mgr_is_link_switch_in_progress(vdev)) 182 return QDF_STATUS_SUCCESS; 183 184 psoc = wlan_vdev_get_psoc(vdev); 185 if (!psoc) 186 return QDF_STATUS_E_FAILURE; 187 188 if (policy_mgr_is_sta_active_connection_exists(psoc) && 189 mlo_is_enable_roaming_on_connected_sta_allowed(vdev)) { 190 wlan_cm_enable_roaming_on_connected_sta(pdev, vdev_id); 191 policy_mgr_set_pcl_for_connected_vdev(psoc, vdev_id, true); 192 } 193 194 return QDF_STATUS_SUCCESS; 195 } 196 197 QDF_STATUS if_mgr_enable_roaming_after_p2p_disconnect( 198 struct wlan_objmgr_pdev *pdev, 199 struct wlan_objmgr_vdev *vdev, 200 enum wlan_cm_rso_control_requestor requestor) 201 { 202 QDF_STATUS status = QDF_STATUS_SUCCESS; 203 struct wlan_objmgr_psoc *psoc; 204 struct change_roam_state_arg roam_arg; 205 uint8_t vdev_id; 206 207 psoc = wlan_vdev_get_psoc(vdev); 208 if (!psoc) 209 return QDF_STATUS_E_FAILURE; 210 211 vdev_id = wlan_vdev_get_id(vdev); 212 213 roam_arg.requestor = requestor; 214 roam_arg.curr_vdev_id = vdev_id; 215 216 /* 217 * Due to audio share glitch with P2P clients due 218 * to roam scan on concurrent interface, disable 219 * roaming if "p2p_disable_roam" ini is enabled. 220 * Re-enable roaming again once the p2p client 221 * gets disconnected. 222 */ 223 if (ucfg_p2p_is_roam_config_disabled(psoc) && 224 wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_CLIENT_MODE) { 225 ifmgr_debug("P2P client disconnected, enable roam"); 226 status = wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, 227 if_mgr_enable_roaming_on_vdev, 228 &roam_arg, 0, 229 WLAN_IF_MGR_ID); 230 } 231 232 return status; 233 } 234 235 /** 236 * if_mgr_calculate_mcc_beacon_interval() - Calculates the new beacon interval 237 * @sta_bi: station beacon interval 238 * @go_given_bi: P2P GO's given beacon interval 239 * 240 * This function has 3 stages. First it modifies the input go_given_bi to be 241 * within 100 to 199. Then it checks if the sta_bi and go_given_bi are multiples 242 * of each other. If they are, that means the 2 values are compatible, and just 243 * return as is, otherwise, find new compatible BI for P2P GO 244 * 245 * Return: valid beacon interval value 246 */ 247 static uint16_t if_mgr_calculate_mcc_beacon_interval(uint16_t sta_bi, 248 uint16_t go_given_bi) 249 { 250 uint8_t num_beacons, is_multiple; 251 uint16_t go_calculated_bi, go_final_bi, sta_calculated_bi; 252 253 /* ensure BI ranges between 100 and 200 */ 254 if (go_given_bi < 100) 255 go_calculated_bi = 100; 256 else 257 go_calculated_bi = 100 + (go_given_bi % 100); 258 259 if (sta_bi == 0) { 260 /* There is possibility to receive zero as value. 261 * Which will cause divide by zero. Hence initialise with 100 262 */ 263 sta_bi = 100; 264 ifmgr_warn("sta_bi 2nd parameter is zero, initialize to %d", 265 sta_bi); 266 } 267 /* check, if either one is multiple of another */ 268 if (sta_bi > go_calculated_bi) 269 is_multiple = !(sta_bi % go_calculated_bi); 270 else 271 is_multiple = !(go_calculated_bi % sta_bi); 272 273 /* if it is multiple, then accept GO's beacon interval 274 * range [100,199] as it is 275 */ 276 if (is_multiple) 277 return go_calculated_bi; 278 279 /* else , if it is not multiple, then then check for number of beacons 280 * to be inserted based on sta BI 281 */ 282 num_beacons = sta_bi / 100; 283 if (num_beacons) { 284 /* GO's final beacon interval will be aligned to sta beacon 285 * interval, but in the range of [100, 199]. 286 */ 287 sta_calculated_bi = sta_bi / num_beacons; 288 go_final_bi = sta_calculated_bi; 289 } else { 290 /* if STA beacon interval is less than 100, use GO's change 291 * beacon interval instead of updating to STA's beacon interval. 292 */ 293 go_final_bi = go_calculated_bi; 294 } 295 296 return go_final_bi; 297 } 298 299 static QDF_STATUS 300 if_mgr_send_chng_mcc_beacon_interval(struct wlan_objmgr_vdev *vdev, 301 struct beacon_interval_arg *bss_arg) 302 { 303 struct scheduler_msg msg = {0}; 304 struct wlan_change_bi *p_msg; 305 uint16_t len = 0; 306 QDF_STATUS status; 307 uint8_t *mac_addr; 308 309 if (!bss_arg->update_beacon_interval) 310 return QDF_STATUS_SUCCESS; 311 312 bss_arg->update_beacon_interval = false; 313 314 len = sizeof(*p_msg); 315 p_msg = qdf_mem_malloc(len); 316 if (!p_msg) 317 return QDF_STATUS_E_NOMEM; 318 319 p_msg->message_type = eWNI_SME_CHNG_MCC_BEACON_INTERVAL; 320 p_msg->length = len; 321 322 mac_addr = wlan_vdev_get_hw_macaddr(vdev); 323 qdf_mem_copy(&p_msg->bssid, mac_addr, QDF_MAC_ADDR_SIZE); 324 ifmgr_debug(QDF_MAC_ADDR_FMT, QDF_MAC_ADDR_REF(mac_addr)); 325 p_msg->session_id = wlan_vdev_get_id(vdev); 326 ifmgr_debug("session %d BeaconInterval %d", p_msg->session_id, 327 bss_arg->bss_beacon_interval); 328 p_msg->beacon_interval = bss_arg->bss_beacon_interval; 329 330 msg.type = eWNI_SME_CHNG_MCC_BEACON_INTERVAL; 331 msg.bodyval = 0; 332 msg.bodyptr = p_msg; 333 334 status = scheduler_post_message(QDF_MODULE_ID_PE, 335 QDF_MODULE_ID_PE, 336 QDF_MODULE_ID_PE, &msg); 337 338 if (status != QDF_STATUS_SUCCESS) 339 qdf_mem_free(p_msg); 340 341 return status; 342 } 343 344 static void if_mgr_update_beacon_interval(struct wlan_objmgr_pdev *pdev, 345 void *object, void *arg) 346 { 347 struct wlan_objmgr_psoc *psoc; 348 uint8_t allow_mcc_go_diff_bi; 349 struct wlan_objmgr_peer *peer; 350 enum wlan_peer_type bss_persona; 351 struct beacon_interval_arg *bss_arg = arg; 352 struct wlan_objmgr_vdev *vdev = object; 353 uint8_t vdev_id = wlan_vdev_get_id(vdev); 354 355 psoc = wlan_pdev_get_psoc(pdev); 356 if (!psoc) 357 return; 358 359 policy_mgr_get_allow_mcc_go_diff_bi(psoc, &allow_mcc_go_diff_bi); 360 361 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_IF_MGR_ID); 362 if (!peer) 363 return; 364 365 bss_persona = wlan_peer_get_peer_type(peer); 366 367 wlan_objmgr_peer_release_ref(peer, WLAN_IF_MGR_ID); 368 369 /* 370 * If GO in MCC support different beacon interval, 371 * change the BI of the P2P-GO 372 */ 373 if (bss_persona == WLAN_PEER_P2P_GO) 374 return; 375 /* 376 * Handle different BI scenario based on the 377 * configuration set. If Config is not set to 0x04 then 378 * Disconnect all the P2P clients associated. If config 379 * is set to 0x04 then update the BI without 380 * disconnecting all the clients 381 */ 382 if (allow_mcc_go_diff_bi == ALLOW_MCC_GO_DIFF_BI_NO_DISCONNECT && 383 bss_arg->update_beacon_interval) { 384 bss_arg->status = 385 if_mgr_send_chng_mcc_beacon_interval(vdev, bss_arg); 386 return; 387 } else if (bss_arg->update_beacon_interval) { 388 /* 389 * If the configuration of fAllowMCCGODiffBI is set to 390 * other than 0x04 391 */ 392 bss_arg->status = wlan_sap_disconnect_all_p2p_client(vdev_id); 393 return; 394 } 395 } 396 397 static QDF_STATUS 398 if_mgr_update_mcc_p2p_beacon_interval(struct wlan_objmgr_vdev *vdev, 399 struct beacon_interval_arg *bss_arg) 400 { 401 struct wlan_objmgr_psoc *psoc; 402 struct wlan_objmgr_pdev *pdev; 403 uint8_t enable_mcc_mode; 404 405 pdev = wlan_vdev_get_pdev(vdev); 406 if (!pdev) 407 return QDF_STATUS_E_FAILURE; 408 409 psoc = wlan_pdev_get_psoc(pdev); 410 if (!psoc) 411 return QDF_STATUS_E_FAILURE; 412 413 /* If MCC is not supported just break and return SUCCESS */ 414 wlan_mlme_get_mcc_feature(psoc, &enable_mcc_mode); 415 if (!enable_mcc_mode) 416 return QDF_STATUS_E_FAILURE; 417 418 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, 419 if_mgr_update_beacon_interval, 420 bss_arg, 0, WLAN_IF_MGR_ID); 421 422 return bss_arg->status; 423 } 424 425 static bool if_mgr_validate_sta_bcn_intrvl(struct wlan_objmgr_vdev *vdev, 426 struct beacon_interval_arg *bss_arg) 427 { 428 struct wlan_objmgr_psoc *psoc; 429 struct vdev_mlme_obj *vdev_mlme; 430 struct wlan_objmgr_peer *peer; 431 uint16_t new_bcn_interval; 432 uint32_t beacon_interval; 433 struct wlan_channel *chan; 434 enum QDF_OPMODE curr_persona; 435 uint8_t allow_mcc_go_diff_bi; 436 uint8_t conc_rule1 = 0, conc_rule2 = 0; 437 uint8_t vdev_id = wlan_vdev_get_id(vdev); 438 439 psoc = wlan_vdev_get_psoc(vdev); 440 if (!psoc) 441 return false; 442 443 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_IF_MGR_ID); 444 if (!peer) 445 return false; 446 447 curr_persona = wlan_vdev_mlme_get_opmode(vdev); 448 449 wlan_objmgr_peer_release_ref(peer, WLAN_IF_MGR_ID); 450 451 if (curr_persona == QDF_STA_MODE || 452 curr_persona == QDF_P2P_CLIENT_MODE) { 453 ifmgr_debug("Bcn Intrvl validation not require for STA/CLIENT"); 454 return false; 455 } 456 457 chan = wlan_vdev_get_active_channel(vdev); 458 if (!chan) { 459 ifmgr_err("failed to get active channel"); 460 return false; 461 } 462 463 vdev_mlme = 464 wlan_objmgr_vdev_get_comp_private_obj(vdev, 465 WLAN_UMAC_COMP_MLME); 466 if (!vdev_mlme) { 467 QDF_ASSERT(0); 468 return false; 469 } 470 471 wlan_util_vdev_mlme_get_param(vdev_mlme, WLAN_MLME_CFG_BEACON_INTERVAL, 472 &beacon_interval); 473 474 if (curr_persona == QDF_SAP_MODE && 475 (chan->ch_cfreq1 != bss_arg->ch_freq || 476 chan->ch_cfreq2 != bss_arg->ch_freq)) { 477 ifmgr_debug("*** MCC with SAP+STA sessions ****"); 478 bss_arg->status = QDF_STATUS_SUCCESS; 479 return true; 480 } 481 482 if (curr_persona == QDF_P2P_GO_MODE && 483 (chan->ch_cfreq1 != bss_arg->ch_freq || 484 chan->ch_cfreq2 != bss_arg->ch_freq) && 485 beacon_interval != bss_arg->bss_beacon_interval) { 486 policy_mgr_get_allow_mcc_go_diff_bi(psoc, 487 &allow_mcc_go_diff_bi); 488 489 switch (allow_mcc_go_diff_bi) { 490 case ALLOW_MCC_GO_DIFF_BI_WFA_CERT: 491 bss_arg->status = QDF_STATUS_SUCCESS; 492 return true; 493 case ALLOW_MCC_GO_DIFF_BI_WORKAROUND: 494 fallthrough; 495 case ALLOW_MCC_GO_DIFF_BI_NO_DISCONNECT: 496 policy_mgr_get_conc_rule1(psoc, &conc_rule1); 497 policy_mgr_get_conc_rule2(psoc, &conc_rule2); 498 if (conc_rule1 || conc_rule2) 499 new_bcn_interval = CUSTOM_CONC_GO_BI; 500 else 501 new_bcn_interval = 502 if_mgr_calculate_mcc_beacon_interval( 503 bss_arg->bss_beacon_interval, 504 beacon_interval); 505 506 ifmgr_debug("Peer AP BI : %d, new Beacon Interval: %d", 507 bss_arg->bss_beacon_interval, 508 new_bcn_interval); 509 510 /* Update the beacon interval */ 511 if (new_bcn_interval != beacon_interval) { 512 ifmgr_err("Beacon Interval got changed config used: %d", 513 allow_mcc_go_diff_bi); 514 bss_arg->bss_beacon_interval = new_bcn_interval; 515 bss_arg->update_beacon_interval = true; 516 bss_arg->status = 517 if_mgr_update_mcc_p2p_beacon_interval( 518 vdev, 519 bss_arg); 520 return true; 521 } 522 bss_arg->status = QDF_STATUS_SUCCESS; 523 return true; 524 case ALLOW_MCC_GO_DIFF_BI_TEAR_DOWN: 525 bss_arg->update_beacon_interval = false; 526 bss_arg->status = wlan_sap_stop_bss(vdev_id); 527 return true; 528 default: 529 ifmgr_err("BcnIntrvl is diff can't connect to preferred AP"); 530 bss_arg->status = QDF_STATUS_E_FAILURE; 531 return true; 532 } 533 } 534 return false; 535 } 536 537 static bool if_mgr_validate_p2pcli_bcn_intrvl(struct wlan_objmgr_vdev *vdev, 538 struct beacon_interval_arg *bss_arg) 539 { 540 enum QDF_OPMODE curr_persona; 541 enum wlan_peer_type bss_persona; 542 uint32_t beacon_interval; 543 struct wlan_channel *chan; 544 struct wlan_objmgr_peer *peer; 545 struct vdev_mlme_obj *vdev_mlme; 546 547 curr_persona = wlan_vdev_mlme_get_opmode(vdev); 548 549 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_IF_MGR_ID); 550 if (!peer) 551 return false; 552 553 bss_persona = wlan_peer_get_peer_type(peer); 554 555 wlan_objmgr_peer_release_ref(peer, WLAN_IF_MGR_ID); 556 557 chan = wlan_vdev_get_active_channel(vdev); 558 if (!chan) { 559 ifmgr_err("failed to get active channel"); 560 return false; 561 } 562 563 vdev_mlme = 564 wlan_objmgr_vdev_get_comp_private_obj(vdev, 565 WLAN_UMAC_COMP_MLME); 566 if (!vdev_mlme) { 567 QDF_ASSERT(0); 568 return false; 569 } 570 571 wlan_util_vdev_mlme_get_param(vdev_mlme, WLAN_MLME_CFG_BEACON_INTERVAL, 572 &beacon_interval); 573 574 if (curr_persona == QDF_STA_MODE) { 575 ifmgr_debug("Ignore Beacon Interval Validation..."); 576 } else if (bss_persona == WLAN_PEER_P2P_GO) { 577 if ((chan->ch_cfreq1 != bss_arg->ch_freq || 578 chan->ch_cfreq2 != bss_arg->ch_freq) && 579 beacon_interval != bss_arg->bss_beacon_interval) { 580 ifmgr_err("BcnIntrvl is diff can't connect to P2P_GO network"); 581 bss_arg->status = QDF_STATUS_E_FAILURE; 582 return true; 583 } 584 } 585 586 return false; 587 } 588 589 static bool 590 if_mgr_validate_p2pgo_bcn_intrvl(struct wlan_objmgr_vdev *vdev, 591 struct beacon_interval_arg *bss_arg) 592 { 593 struct wlan_objmgr_psoc *psoc; 594 struct vdev_mlme_obj *vdev_mlme; 595 enum QDF_OPMODE curr_persona; 596 uint32_t beacon_interval; 597 struct wlan_channel *chan; 598 uint8_t conc_rule1 = 0, conc_rule2 = 0; 599 uint16_t new_bcn_interval; 600 601 curr_persona = wlan_vdev_mlme_get_opmode(vdev); 602 603 chan = wlan_vdev_get_active_channel(vdev); 604 if (!chan) { 605 ifmgr_err("failed to get active channel"); 606 return false; 607 } 608 609 vdev_mlme = 610 wlan_objmgr_vdev_get_comp_private_obj(vdev, 611 WLAN_UMAC_COMP_MLME); 612 if (!vdev_mlme) { 613 QDF_ASSERT(0); 614 return false; 615 } 616 617 psoc = wlan_vdev_get_psoc(vdev); 618 if (!psoc) 619 return false; 620 621 wlan_util_vdev_mlme_get_param(vdev_mlme, WLAN_MLME_CFG_BEACON_INTERVAL, 622 &beacon_interval); 623 624 if ((curr_persona == QDF_P2P_CLIENT_MODE) || 625 (curr_persona == QDF_STA_MODE)) { 626 /* check for P2P_client scenario */ 627 if ((chan->ch_cfreq1 == 0) && (chan->ch_cfreq2 == 0) && 628 (beacon_interval == 0)) 629 return false; 630 631 if (wlan_vdev_mlme_get_state(vdev) == WLAN_VDEV_S_UP && 632 (chan->ch_cfreq1 != bss_arg->ch_freq || 633 chan->ch_cfreq2 != bss_arg->ch_freq) && 634 beacon_interval != bss_arg->bss_beacon_interval) { 635 /* 636 * Updated beaconInterval should be used only when 637 * we are starting a new BSS not incase of 638 * client or STA case 639 */ 640 policy_mgr_get_conc_rule1(psoc, &conc_rule1); 641 policy_mgr_get_conc_rule2(psoc, &conc_rule2); 642 643 /* Calculate beacon Interval for P2P-GO incase of MCC */ 644 if (conc_rule1 || conc_rule2) { 645 new_bcn_interval = CUSTOM_CONC_GO_BI; 646 } else { 647 new_bcn_interval = 648 if_mgr_calculate_mcc_beacon_interval( 649 beacon_interval, 650 bss_arg->bss_beacon_interval); 651 } 652 if (new_bcn_interval != bss_arg->bss_beacon_interval) 653 bss_arg->bss_beacon_interval = new_bcn_interval; 654 bss_arg->status = QDF_STATUS_SUCCESS; 655 return true; 656 } 657 } 658 return false; 659 } 660 661 static void if_mgr_validate_beacon_interval(struct wlan_objmgr_pdev *pdev, 662 void *object, void *arg) 663 { 664 struct beacon_interval_arg *bss_arg = arg; 665 struct wlan_objmgr_vdev *vdev = object; 666 uint8_t iter_vdev_id = wlan_vdev_get_id(vdev); 667 bool is_done = false; 668 669 if (iter_vdev_id == bss_arg->curr_vdev_id) 670 return; 671 672 if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_UP) 673 return; 674 675 if (bss_arg->is_done) 676 return; 677 678 switch (bss_arg->curr_bss_opmode) { 679 case QDF_STA_MODE: 680 is_done = if_mgr_validate_sta_bcn_intrvl(vdev, bss_arg); 681 break; 682 case QDF_P2P_CLIENT_MODE: 683 is_done = if_mgr_validate_p2pcli_bcn_intrvl(vdev, bss_arg); 684 break; 685 case QDF_SAP_MODE: 686 case QDF_IBSS_MODE: 687 break; 688 case QDF_P2P_GO_MODE: 689 is_done = if_mgr_validate_p2pgo_bcn_intrvl(vdev, bss_arg); 690 break; 691 default: 692 ifmgr_err("BSS opmode not supported: %d", 693 bss_arg->curr_bss_opmode); 694 } 695 696 if (is_done) 697 bss_arg->is_done = is_done; 698 } 699 700 bool if_mgr_is_beacon_interval_valid(struct wlan_objmgr_pdev *pdev, 701 uint8_t vdev_id, 702 struct validate_bss_data *candidate) 703 { 704 struct wlan_objmgr_psoc *psoc; 705 struct beacon_interval_arg bss_arg; 706 uint8_t enable_mcc_mode; 707 struct wlan_objmgr_vdev *vdev; 708 709 psoc = wlan_pdev_get_psoc(pdev); 710 if (!psoc) 711 return false; 712 713 wlan_mlme_get_mcc_feature(psoc, &enable_mcc_mode); 714 if (!enable_mcc_mode) 715 return false; 716 717 vdev = wlan_objmgr_get_vdev_by_id_from_pdev(pdev, vdev_id, 718 WLAN_IF_MGR_ID); 719 if (!vdev) 720 return false; 721 722 bss_arg.curr_vdev_id = vdev_id; 723 bss_arg.curr_bss_opmode = wlan_vdev_mlme_get_opmode(vdev); 724 bss_arg.ch_freq = candidate->chan_freq; 725 bss_arg.bss_beacon_interval = candidate->beacon_interval; 726 bss_arg.is_done = false; 727 728 wlan_objmgr_vdev_release_ref(vdev, WLAN_IF_MGR_ID); 729 730 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, 731 if_mgr_validate_beacon_interval, 732 &bss_arg, 0, 733 WLAN_IF_MGR_ID); 734 735 if (!bss_arg.is_done) 736 return true; 737 738 if (bss_arg.is_done && QDF_IS_STATUS_SUCCESS(bss_arg.status)) 739 return true; 740 741 return false; 742 } 743 744 static void if_mgr_get_vdev_id_from_bssid(struct wlan_objmgr_pdev *pdev, 745 void *object, void *arg) 746 { 747 struct bssid_search_arg *bssid_arg = arg; 748 struct wlan_objmgr_vdev *vdev = (struct wlan_objmgr_vdev *)object; 749 struct wlan_objmgr_peer *peer; 750 751 if (!(wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE || 752 wlan_vdev_mlme_get_opmode(vdev) == QDF_P2P_CLIENT_MODE)) 753 return; 754 755 /* Need to check the connection manager state when that becomes 756 * available 757 */ 758 if (wlan_vdev_mlme_get_state(vdev) != WLAN_VDEV_S_UP) 759 return; 760 761 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_IF_MGR_ID); 762 if (!peer) 763 return; 764 765 if (WLAN_ADDR_EQ(bssid_arg->peer_addr.bytes, 766 wlan_peer_get_macaddr(peer)) == QDF_STATUS_SUCCESS) 767 bssid_arg->vdev_id = wlan_vdev_get_id(vdev); 768 769 wlan_objmgr_peer_release_ref(peer, WLAN_IF_MGR_ID); 770 } 771 772 #ifdef WLAN_FEATURE_11BE_MLO 773 /** 774 * if_mgr_get_conc_ext_flags() - get extended flags for concurrency check 775 * @vdev: pointer to vdev on which new connection is coming up 776 * @candidate_info: interface manager validate candidate data 777 * 778 * Return: extended flags for concurrency check 779 */ 780 static inline uint32_t 781 if_mgr_get_conc_ext_flags(struct wlan_objmgr_vdev *vdev, 782 struct validate_bss_data *candidate_info) 783 { 784 struct qdf_mac_addr *mld_addr; 785 786 /* If connection is happening on non-ML VDEV 787 * force the ML AP candidate as non-MLO to 788 * downgrade connection to 11ax. 789 */ 790 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 791 if (qdf_is_macaddr_zero(mld_addr)) 792 return policy_mgr_get_conc_ext_flags(vdev, false); 793 794 return policy_mgr_get_conc_ext_flags(vdev, candidate_info->is_mlo); 795 } 796 797 static void if_mgr_update_candidate(struct wlan_objmgr_psoc *psoc, 798 struct wlan_objmgr_vdev *vdev, 799 struct validate_bss_data *candidate_info) 800 { 801 struct scan_cache_entry *scan_entry = candidate_info->scan_entry; 802 803 if (!(scan_entry->ie_list.multi_link_bv || scan_entry->ie_list.ehtcap || 804 scan_entry->ie_list.ehtop)) 805 return; 806 807 if (mlme_get_bss_11be_allowed(psoc, &candidate_info->peer_addr, 808 util_scan_entry_ie_data(scan_entry), 809 util_scan_entry_ie_len(scan_entry)) && 810 (!wlan_vdev_mlme_get_user_dis_eht_flag(vdev))) 811 return; 812 813 scan_entry->ie_list.multi_link_bv = NULL; 814 scan_entry->ie_list.ehtcap = NULL; 815 scan_entry->ie_list.ehtop = NULL; 816 qdf_mem_zero(&scan_entry->ml_info, sizeof(scan_entry->ml_info)); 817 candidate_info->is_mlo = false; 818 } 819 #else 820 static inline uint32_t 821 if_mgr_get_conc_ext_flags(struct wlan_objmgr_vdev *vdev, 822 struct validate_bss_data *candidate_info) 823 { 824 return 0; 825 } 826 827 static void if_mgr_update_candidate(struct wlan_objmgr_psoc *psoc, 828 struct wlan_objmgr_vdev *vdev, 829 struct validate_bss_data *candidate_info) 830 { 831 } 832 #endif 833 834 QDF_STATUS if_mgr_validate_candidate(struct wlan_objmgr_vdev *vdev, 835 struct if_mgr_event_data *event_data) 836 { 837 struct wlan_objmgr_psoc *psoc; 838 struct wlan_objmgr_pdev *pdev; 839 enum QDF_OPMODE op_mode; 840 enum policy_mgr_con_mode mode; 841 struct bssid_search_arg bssid_arg; 842 struct validate_bss_data *candidate_info = 843 &event_data->validate_bss_info; 844 uint32_t chan_freq = candidate_info->chan_freq; 845 uint32_t conc_freq = 0, conc_ext_flags; 846 847 op_mode = wlan_vdev_mlme_get_opmode(vdev); 848 849 pdev = wlan_vdev_get_pdev(vdev); 850 if (!pdev) 851 return QDF_STATUS_E_FAILURE; 852 853 psoc = wlan_pdev_get_psoc(pdev); 854 if (!psoc) 855 return QDF_STATUS_E_FAILURE; 856 857 if_mgr_update_candidate(psoc, vdev, candidate_info); 858 /* 859 * Do not allow STA to connect on 6Ghz or indoor channel for non dbs 860 * hardware if SAP and skip_6g_and_indoor_freq_scan ini are present 861 */ 862 if (op_mode == QDF_STA_MODE && 863 !policy_mgr_is_sta_chan_valid_for_connect_and_roam(pdev, 864 chan_freq)) { 865 ifmgr_debug("STA connection not allowed on bssid: "QDF_MAC_ADDR_FMT" with freq: %d (6Ghz or indoor(%d)), as not valid for connection", 866 QDF_MAC_ADDR_REF(candidate_info->peer_addr.bytes), 867 chan_freq, 868 wlan_reg_is_freq_indoor(pdev, chan_freq)); 869 return QDF_STATUS_E_INVAL; 870 } 871 872 /* 873 * This is a temporary check and will be removed once ll_lt_sap CSA 874 * support is added. 875 */ 876 if (policy_mgr_get_ll_lt_sap_freq(psoc) == chan_freq) { 877 ifmgr_debug("STA connection not allowed on LL_LT_SAP freq %d", 878 chan_freq); 879 return QDF_STATUS_E_INVAL; 880 } 881 /* 882 * Ignore the BSS if any other vdev is already connected to it. 883 */ 884 qdf_copy_macaddr(&bssid_arg.peer_addr, 885 &candidate_info->peer_addr); 886 bssid_arg.vdev_id = WLAN_INVALID_VDEV_ID; 887 wlan_objmgr_pdev_iterate_obj_list(pdev, WLAN_VDEV_OP, 888 if_mgr_get_vdev_id_from_bssid, 889 &bssid_arg, 0, 890 WLAN_IF_MGR_ID); 891 892 if (bssid_arg.vdev_id != WLAN_INVALID_VDEV_ID) { 893 ifmgr_info("vdev_id %d already connected to "QDF_MAC_ADDR_FMT". select next bss for vdev_id %d", 894 bssid_arg.vdev_id, 895 QDF_MAC_ADDR_REF(bssid_arg.peer_addr.bytes), 896 wlan_vdev_get_id(vdev)); 897 return QDF_STATUS_E_INVAL; 898 } 899 900 /* 901 * If concurrency enabled take the concurrent connected channel first. 902 * Valid multichannel concurrent sessions exempted 903 */ 904 mode = policy_mgr_qdf_opmode_to_pm_con_mode(psoc, op_mode, 905 wlan_vdev_get_id(vdev)); 906 907 /* If concurrency is not allowed select next bss */ 908 conc_ext_flags = if_mgr_get_conc_ext_flags(vdev, candidate_info); 909 /* 910 * Apply concurrency check only for non ML and ML assoc links only 911 * For non-assoc ML link if concurrency check fails its will be forced 912 * disabled in peer assoc. 913 */ 914 if (!wlan_vdev_mlme_is_mlo_link_vdev(vdev) && 915 !policy_mgr_is_concurrency_allowed(psoc, mode, chan_freq, 916 HW_MODE_20_MHZ, conc_ext_flags, 917 NULL)) { 918 ifmgr_info("Concurrency not allowed for this channel freq %d bssid "QDF_MAC_ADDR_FMT", selecting next", 919 chan_freq, 920 QDF_MAC_ADDR_REF(bssid_arg.peer_addr.bytes)); 921 return QDF_STATUS_E_INVAL; 922 } 923 924 /* 925 * check if channel is allowed for current hw mode, if not fetch 926 * next BSS. 927 */ 928 if (!policy_mgr_is_hwmode_set_for_given_chnl(psoc, chan_freq)) { 929 ifmgr_info("HW mode isn't properly set, freq %d BSSID "QDF_MAC_ADDR_FMT, 930 chan_freq, 931 QDF_MAC_ADDR_REF(bssid_arg.peer_addr.bytes)); 932 return QDF_STATUS_E_INVAL; 933 } 934 935 /* validate beacon interval */ 936 if (policy_mgr_concurrent_open_sessions_running(psoc) && 937 !if_mgr_is_beacon_interval_valid(pdev, wlan_vdev_get_id(vdev), 938 candidate_info)) { 939 conc_freq = wlan_get_conc_freq(); 940 ifmgr_debug("csr Conc Channel freq: %d", 941 conc_freq); 942 943 if (conc_freq) { 944 if ((conc_freq == chan_freq) || 945 (policy_mgr_is_hw_sbs_capable(psoc) && 946 policy_mgr_are_sbs_chan(psoc, conc_freq, 947 chan_freq)) || 948 (policy_mgr_is_hw_dbs_capable(psoc) && 949 !wlan_reg_is_same_band_freqs(conc_freq, 950 chan_freq))) { 951 /* 952 * make this 0 because we do not want the below 953 * check to pass as we don't want to connect on 954 * other channel 955 */ 956 ifmgr_debug("Conc chnl freq match: %d", 957 conc_freq); 958 conc_freq = 0; 959 } 960 } 961 } 962 963 if (conc_freq) 964 return QDF_STATUS_E_INVAL; 965 966 /* Check low latency SAP and STA/GC concurrency are valid or not */ 967 if (!policy_mgr_is_ll_sap_concurrency_valid(psoc, chan_freq, mode)) { 968 ifmgr_debug("STA connection not allowed on bssid: "QDF_MAC_ADDR_FMT" with freq: %d due to LL SAP present", 969 QDF_MAC_ADDR_REF(candidate_info->peer_addr.bytes), 970 chan_freq); 971 return QDF_STATUS_E_INVAL; 972 } 973 974 return QDF_STATUS_SUCCESS; 975 } 976