1 /* 2 * Copyright (c) 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 #include "wlan_mlo_mgr_main.h" 19 #include "qdf_module.h" 20 #include "qdf_types.h" 21 #include "wlan_cmn.h" 22 #include "wlan_mlo_mgr_msgq.h" 23 #include "wlan_objmgr_peer_obj.h" 24 #include "wlan_mlo_mgr_peer.h" 25 #include "wlan_mlo_mgr_ap.h" 26 #include "wlan_crypto_global_api.h" 27 #include "wlan_mlo_mgr_setup.h" 28 #include "wlan_utility.h" 29 #include "wlan_mlo_epcs.h" 30 31 static void mlo_partner_peer_create_post(struct wlan_mlo_dev_context *ml_dev, 32 struct wlan_objmgr_vdev *vdev_link, 33 struct wlan_mlo_peer_context *ml_peer, 34 qdf_nbuf_t frm_buf, 35 struct mlo_partner_info *ml_info) 36 { 37 struct peer_create_notif_s peer_create; 38 QDF_STATUS status; 39 uint8_t i; 40 uint8_t link_id; 41 42 if (wlan_objmgr_vdev_try_get_ref(vdev_link, WLAN_MLO_MGR_ID) == 43 QDF_STATUS_SUCCESS) { 44 peer_create.vdev_link = vdev_link; 45 } else { 46 mlo_err("VDEV is not in created state"); 47 return; 48 } 49 50 wlan_mlo_peer_get_ref(ml_peer); 51 peer_create.ml_peer = ml_peer; 52 link_id = wlan_vdev_get_link_id(vdev_link); 53 for (i = 0; i < ml_info->num_partner_links; i++) { 54 if (link_id != ml_info->partner_link_info[i].link_id) 55 continue; 56 57 qdf_copy_macaddr(&peer_create.addr, 58 &ml_info->partner_link_info[i].link_addr); 59 break; 60 } 61 62 status = mlo_peer_create_get_frm_buf(ml_peer, &peer_create, frm_buf); 63 64 if (QDF_IS_STATUS_ERROR(status)) { 65 wlan_mlo_peer_release_ref(ml_peer); 66 wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID); 67 mlo_err("nbuf clone is failed"); 68 return; 69 } 70 71 status = mlo_msgq_post(MLO_PEER_CREATE, ml_dev, &peer_create); 72 if (status != QDF_STATUS_SUCCESS) { 73 qdf_nbuf_free(frm_buf); 74 wlan_mlo_peer_release_ref(ml_peer); 75 wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID); 76 } 77 } 78 79 static void mlo_partner_peer_reassoc_post(struct wlan_mlo_dev_context *ml_dev, 80 struct wlan_objmgr_vdev *vdev_link, 81 struct wlan_mlo_peer_context *ml_peer, 82 qdf_nbuf_t frm_buf, 83 struct mlo_partner_info *ml_info) 84 { 85 struct peer_create_notif_s peer_create; 86 QDF_STATUS status; 87 uint8_t i; 88 uint8_t link_id; 89 90 if (wlan_objmgr_vdev_try_get_ref(vdev_link, WLAN_MLO_MGR_ID) == 91 QDF_STATUS_SUCCESS) { 92 peer_create.vdev_link = vdev_link; 93 } else { 94 mlo_err("VDEV is not in created state"); 95 return; 96 } 97 98 wlan_mlo_peer_get_ref(ml_peer); 99 peer_create.ml_peer = ml_peer; 100 link_id = wlan_vdev_get_link_id(vdev_link); 101 for (i = 0; i < ml_info->num_partner_links; i++) { 102 if (link_id != ml_info->partner_link_info[i].link_id) 103 continue; 104 105 qdf_copy_macaddr(&peer_create.addr, 106 &ml_info->partner_link_info[i].link_addr); 107 break; 108 } 109 110 status = mlo_peer_create_get_frm_buf(ml_peer, &peer_create, frm_buf); 111 112 if (QDF_IS_STATUS_ERROR(status)) { 113 wlan_mlo_peer_release_ref(ml_peer); 114 wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID); 115 mlo_err("nbuf clone is failed"); 116 return; 117 } 118 119 status = mlo_msgq_post(MLO_PEER_REASSOC, ml_dev, &peer_create); 120 if (status != QDF_STATUS_SUCCESS) { 121 qdf_nbuf_free(frm_buf); 122 wlan_mlo_peer_release_ref(ml_peer); 123 wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID); 124 } 125 } 126 127 static void mlo_link_peer_assoc_notify(struct wlan_mlo_dev_context *ml_dev, 128 struct wlan_objmgr_peer *peer) 129 { 130 struct peer_assoc_notify_s peer_assoc; 131 QDF_STATUS status; 132 133 peer_assoc.peer = peer; 134 status = mlo_msgq_post(MLO_PEER_ASSOC, ml_dev, &peer_assoc); 135 if (status != QDF_STATUS_SUCCESS) 136 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID); 137 } 138 139 static void mlo_link_peer_send_assoc_fail(struct wlan_mlo_dev_context *ml_dev, 140 struct wlan_objmgr_peer *peer) 141 { 142 struct peer_assoc_fail_notify_s peer_assoc_fail; 143 QDF_STATUS status; 144 145 peer_assoc_fail.peer = peer; 146 status = mlo_msgq_post(MLO_PEER_ASSOC_FAIL, ml_dev, &peer_assoc_fail); 147 if (status != QDF_STATUS_SUCCESS) 148 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID); 149 } 150 151 static void mlo_link_peer_disconnect_notify(struct wlan_mlo_dev_context *ml_dev, 152 struct wlan_objmgr_peer *peer) 153 { 154 struct peer_discon_notify_s peer_disconn; 155 QDF_STATUS status; 156 struct wlan_objmgr_vdev *vdev; 157 enum QDF_OPMODE opmode; 158 159 vdev = wlan_peer_get_vdev(peer); 160 opmode = wlan_vdev_mlme_get_opmode(vdev); 161 162 if (opmode == QDF_SAP_MODE) { 163 peer_disconn.peer = peer; 164 status = mlo_msgq_post(MLO_PEER_DISCONNECT, ml_dev, 165 &peer_disconn); 166 if (status != QDF_STATUS_SUCCESS) 167 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID); 168 } else { 169 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID); 170 } 171 } 172 173 static void mlo_link_peer_deauth_init(struct wlan_mlo_dev_context *ml_dev, 174 struct wlan_objmgr_peer *peer, 175 uint8_t is_disassoc) 176 { 177 struct peer_deauth_notify_s peer_deauth; 178 QDF_STATUS status; 179 180 peer_deauth.peer = peer; 181 peer_deauth.is_disassoc = is_disassoc; 182 status = mlo_msgq_post(MLO_PEER_DEAUTH, ml_dev, &peer_deauth); 183 if (status != QDF_STATUS_SUCCESS) 184 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID); 185 } 186 187 #ifdef UMAC_MLO_AUTH_DEFER 188 static void mlo_peer_process_pending_auth(struct wlan_mlo_dev_context *ml_dev, 189 struct wlan_mlo_peer_context *ml_peer) 190 { 191 struct peer_auth_process_notif_s peer_auth; 192 struct mlpeer_auth_params *recv_auth; 193 uint8_t i; 194 QDF_STATUS status; 195 196 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 197 mlo_peer_lock_acquire(ml_peer); 198 recv_auth = ml_peer->pending_auth[i]; 199 if (!recv_auth) { 200 mlo_peer_lock_release(ml_peer); 201 continue; 202 } 203 peer_auth.auth_params = recv_auth; 204 ml_peer->pending_auth[i] = NULL; 205 206 mlo_peer_lock_release(ml_peer); 207 208 status = mlo_msgq_post(MLO_PEER_PENDING_AUTH, ml_dev, 209 &peer_auth); 210 if (QDF_IS_STATUS_ERROR(status)) 211 mlo_peer_free_auth_param(peer_auth.auth_params); 212 } 213 } 214 #else 215 static void mlo_peer_process_pending_auth(struct wlan_mlo_dev_context *ml_dev, 216 struct wlan_mlo_peer_context *ml_peer) 217 { 218 } 219 #endif 220 221 QDF_STATUS 222 wlan_mlo_peer_is_disconnect_progress(struct wlan_mlo_peer_context *ml_peer) 223 { 224 QDF_STATUS status; 225 226 if (!ml_peer) 227 return QDF_STATUS_E_FAILURE; 228 229 mlo_peer_lock_acquire(ml_peer); 230 231 if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) 232 status = QDF_STATUS_SUCCESS; 233 else 234 status = QDF_STATUS_E_FAILURE; 235 236 mlo_peer_lock_release(ml_peer); 237 238 return status; 239 } 240 241 QDF_STATUS wlan_mlo_peer_is_assoc_done(struct wlan_mlo_peer_context *ml_peer) 242 { 243 QDF_STATUS status; 244 245 if (!ml_peer) 246 return QDF_STATUS_E_FAILURE; 247 248 mlo_peer_lock_acquire(ml_peer); 249 250 if (ml_peer->mlpeer_state == ML_PEER_ASSOC_DONE) 251 status = QDF_STATUS_SUCCESS; 252 else 253 status = QDF_STATUS_E_FAILURE; 254 255 mlo_peer_lock_release(ml_peer); 256 257 return status; 258 } 259 260 qdf_export_symbol(wlan_mlo_peer_is_assoc_done); 261 262 struct wlan_objmgr_peer *wlan_mlo_peer_get_assoc_peer( 263 struct wlan_mlo_peer_context *ml_peer) 264 { 265 struct wlan_mlo_link_peer_entry *peer_entry; 266 struct wlan_objmgr_peer *assoc_peer = NULL; 267 268 if (!ml_peer) 269 return NULL; 270 271 mlo_peer_lock_acquire(ml_peer); 272 273 peer_entry = &ml_peer->peer_list[0]; 274 275 if (peer_entry->link_peer) 276 assoc_peer = peer_entry->link_peer; 277 278 mlo_peer_lock_release(ml_peer); 279 280 return assoc_peer; 281 } 282 283 qdf_export_symbol(wlan_mlo_peer_get_assoc_peer); 284 285 struct wlan_objmgr_peer *wlan_mlo_peer_get_bridge_peer( 286 struct wlan_mlo_peer_context *ml_peer) 287 { 288 struct wlan_mlo_link_peer_entry *peer_entry = NULL; 289 struct wlan_objmgr_peer *bridge_peer = NULL; 290 struct wlan_objmgr_peer *link_peer = NULL; 291 int i = 0; 292 293 if (!ml_peer) 294 return NULL; 295 296 mlo_peer_lock_acquire(ml_peer); 297 298 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 299 peer_entry = &ml_peer->peer_list[i]; 300 if (!peer_entry) 301 continue; 302 303 link_peer = peer_entry->link_peer; 304 if (!link_peer) 305 continue; 306 307 if (wlan_peer_get_peer_type(link_peer) == 308 WLAN_PEER_MLO_BRIDGE) { 309 if (peer_entry->is_primary) 310 bridge_peer = link_peer; 311 else 312 mlo_err("Bridge peer is not primary"); 313 314 break; 315 } 316 } 317 mlo_peer_lock_release(ml_peer); 318 319 return bridge_peer; 320 } 321 322 qdf_export_symbol(wlan_mlo_peer_get_bridge_peer); 323 324 struct wlan_objmgr_vdev * 325 wlan_mlo_peer_get_primary_link_vdev(struct wlan_mlo_peer_context *ml_peer) 326 { 327 struct wlan_mlo_link_peer_entry *peer_entry = NULL; 328 struct wlan_objmgr_peer *link_peer; 329 struct wlan_objmgr_vdev *link_vdev; 330 uint8_t i; 331 332 if (!ml_peer) { 333 mlo_err("ml_peer is null"); 334 return NULL; 335 } 336 mlo_peer_lock_acquire(ml_peer); 337 338 if ((ml_peer->mlpeer_state != ML_PEER_CREATED) && 339 (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) { 340 mlo_peer_lock_release(ml_peer); 341 mlo_err("ml_peer is not created and association is not done"); 342 return NULL; 343 } 344 345 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 346 peer_entry = &ml_peer->peer_list[i]; 347 link_peer = peer_entry->link_peer; 348 if (!link_peer) 349 continue; 350 351 if (peer_entry->is_primary) { 352 link_vdev = wlan_peer_get_vdev(link_peer); 353 if (!link_vdev) { 354 mlo_peer_lock_release(ml_peer); 355 mlo_err("link vdev not found"); 356 return NULL; 357 } 358 if (wlan_objmgr_vdev_try_get_ref(link_vdev, WLAN_MLO_MGR_ID) != 359 QDF_STATUS_SUCCESS) { 360 mlo_peer_lock_release(ml_peer); 361 mlo_err("taking ref failed"); 362 return NULL; 363 } 364 mlo_peer_lock_release(ml_peer); 365 return link_vdev; 366 } 367 } 368 mlo_peer_lock_release(ml_peer); 369 mlo_err("None of the peer is designated as primary"); 370 371 return NULL; 372 } 373 374 bool mlo_peer_is_assoc_peer(struct wlan_mlo_peer_context *ml_peer, 375 struct wlan_objmgr_peer *peer) 376 { 377 struct wlan_mlo_link_peer_entry *peer_entry; 378 bool is_assoc_peer = false; 379 380 if (!ml_peer || !peer) 381 return is_assoc_peer; 382 383 peer_entry = &ml_peer->peer_list[0]; 384 385 if (peer_entry->link_peer == peer) 386 is_assoc_peer = true; 387 388 return is_assoc_peer; 389 } 390 391 bool wlan_mlo_peer_is_assoc_peer(struct wlan_mlo_peer_context *ml_peer, 392 struct wlan_objmgr_peer *peer) 393 { 394 bool is_assoc_peer = false; 395 396 if (!ml_peer || !peer) 397 return is_assoc_peer; 398 399 mlo_peer_lock_acquire(ml_peer); 400 401 is_assoc_peer = mlo_peer_is_assoc_peer(ml_peer, peer); 402 403 mlo_peer_lock_release(ml_peer); 404 405 return is_assoc_peer; 406 } 407 408 bool wlan_mlo_peer_is_link_peer(struct wlan_mlo_peer_context *ml_peer, 409 struct wlan_objmgr_peer *peer) 410 { 411 struct wlan_mlo_link_peer_entry *peer_entry; 412 bool is_link_peer = false; 413 uint16_t i; 414 415 if (!ml_peer || !peer) 416 return is_link_peer; 417 418 mlo_peer_lock_acquire(ml_peer); 419 420 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 421 peer_entry = &ml_peer->peer_list[i]; 422 if (!peer_entry->link_peer) 423 continue; 424 425 if (peer == peer_entry->link_peer) { 426 is_link_peer = true; 427 break; 428 } 429 } 430 431 mlo_peer_lock_release(ml_peer); 432 433 return is_link_peer; 434 } 435 436 void wlan_mlo_partner_peer_assoc_post(struct wlan_objmgr_peer *assoc_peer) 437 { 438 struct wlan_mlo_dev_context *ml_dev; 439 struct wlan_mlo_peer_context *ml_peer; 440 struct wlan_objmgr_peer *link_peer; 441 struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS]; 442 struct wlan_mlo_link_peer_entry *peer_entry; 443 uint16_t i; 444 445 ml_peer = assoc_peer->mlo_peer_ctx; 446 if (!ml_peer) 447 return; 448 449 mlo_peer_lock_acquire(ml_peer); 450 451 if (ml_peer->mlpeer_state != ML_PEER_CREATED) { 452 mlo_peer_lock_release(ml_peer); 453 return; 454 } 455 456 ml_peer->mlpeer_state = ML_PEER_ASSOC_DONE; 457 ml_dev = ml_peer->ml_dev; 458 459 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 460 link_peers[i] = NULL; 461 peer_entry = &ml_peer->peer_list[i]; 462 463 if (!peer_entry->link_peer) 464 continue; 465 466 if (peer_entry->link_peer == assoc_peer) 467 continue; 468 469 link_peer = peer_entry->link_peer; 470 471 if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) != 472 QDF_STATUS_SUCCESS) 473 continue; 474 475 link_peers[i] = link_peer; 476 } 477 wlan_mlo_peer_wsi_link_add(ml_peer); 478 mlo_peer_lock_release(ml_peer); 479 480 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 481 if (!link_peers[i]) 482 continue; 483 484 /* Prepare and queue message */ 485 mlo_link_peer_assoc_notify(ml_dev, link_peers[i]); 486 } 487 } 488 489 void wlan_mlo_link_peer_assoc_set(struct wlan_objmgr_peer *peer, bool is_sent) 490 { 491 struct wlan_mlo_peer_context *ml_peer; 492 struct wlan_mlo_link_peer_entry *peer_entry; 493 uint16_t i; 494 495 ml_peer = peer->mlo_peer_ctx; 496 if (!ml_peer) 497 return; 498 499 mlo_peer_lock_acquire(ml_peer); 500 501 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 502 peer_entry = &ml_peer->peer_list[i]; 503 504 if (!peer_entry->link_peer) 505 continue; 506 507 if (peer_entry->link_peer == peer) { 508 peer_entry->peer_assoc_sent = is_sent; 509 break; 510 } 511 } 512 mlo_peer_lock_release(ml_peer); 513 } 514 515 qdf_export_symbol(wlan_mlo_link_peer_assoc_set); 516 517 void wlan_mlo_peer_get_del_hw_bitmap(struct wlan_objmgr_peer *peer, 518 uint32_t *hw_link_id_bitmap) 519 { 520 struct wlan_mlo_peer_context *ml_peer; 521 struct wlan_mlo_link_peer_entry *peer_entry; 522 uint16_t i; 523 524 ml_peer = peer->mlo_peer_ctx; 525 if (!ml_peer) 526 return; 527 528 mlo_peer_lock_acquire(ml_peer); 529 530 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 531 peer_entry = &ml_peer->peer_list[i]; 532 533 if (!peer_entry->link_peer) 534 continue; 535 536 if (peer_entry->link_peer == peer) { 537 /* Peer assoc is not sent, no need to send bitmap */ 538 if (!peer_entry->peer_assoc_sent) 539 break; 540 541 continue; 542 } 543 if (!peer_entry->peer_assoc_sent) 544 *hw_link_id_bitmap |= 1 << peer_entry->hw_link_id; 545 } 546 mlo_peer_lock_release(ml_peer); 547 } 548 549 qdf_export_symbol(wlan_mlo_peer_get_del_hw_bitmap); 550 551 void 552 wlan_mlo_peer_deauth_init(struct wlan_mlo_peer_context *ml_peer, 553 struct wlan_objmgr_peer *src_peer, 554 uint8_t is_disassoc) 555 { 556 struct wlan_mlo_dev_context *ml_dev; 557 struct wlan_objmgr_peer *link_peer; 558 struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS]; 559 struct wlan_mlo_link_peer_entry *peer_entry; 560 uint16_t i; 561 uint8_t deauth_sent = 0; 562 563 if (!ml_peer) 564 return; 565 566 mlo_peer_lock_acquire(ml_peer); 567 568 if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) { 569 mlo_peer_lock_release(ml_peer); 570 return; 571 } 572 573 ml_dev = ml_peer->ml_dev; 574 575 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 576 link_peers[i] = NULL; 577 peer_entry = &ml_peer->peer_list[i]; 578 if (!peer_entry->link_peer) 579 continue; 580 581 link_peer = peer_entry->link_peer; 582 583 if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) != 584 QDF_STATUS_SUCCESS) 585 continue; 586 587 link_peers[i] = link_peer; 588 } 589 590 ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED; 591 592 mlo_peer_lock_release(ml_peer); 593 594 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 595 if (!link_peers[i]) 596 continue; 597 598 /* Prepare and queue message */ 599 /* skip sending deauth on src peer */ 600 if ((deauth_sent) || 601 (src_peer && (src_peer == link_peers[i]))) { 602 mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]); 603 } else { 604 mlo_link_peer_deauth_init(ml_dev, link_peers[i], 605 is_disassoc); 606 deauth_sent = 1; 607 } 608 } 609 } 610 611 qdf_export_symbol(wlan_mlo_peer_deauth_init); 612 613 void wlan_mlo_peer_delete(struct wlan_mlo_peer_context *ml_peer) 614 { 615 struct wlan_mlo_dev_context *ml_dev; 616 struct wlan_objmgr_peer *link_peer; 617 struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS]; 618 struct wlan_mlo_link_peer_entry *peer_entry; 619 uint16_t i; 620 621 if (!ml_peer) 622 return; 623 624 mlo_peer_lock_acquire(ml_peer); 625 626 if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) { 627 mlo_peer_lock_release(ml_peer); 628 return; 629 } 630 631 ml_dev = ml_peer->ml_dev; 632 633 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 634 link_peers[i] = NULL; 635 peer_entry = &ml_peer->peer_list[i]; 636 if (!peer_entry->link_peer) 637 continue; 638 639 link_peer = peer_entry->link_peer; 640 641 if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) != 642 QDF_STATUS_SUCCESS) 643 continue; 644 645 link_peers[i] = link_peer; 646 } 647 648 ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED; 649 650 mlo_peer_lock_release(ml_peer); 651 652 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 653 if (!link_peers[i]) 654 continue; 655 656 mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]); 657 } 658 } 659 660 void 661 wlan_mlo_partner_peer_create_failed_notify( 662 struct wlan_mlo_peer_context *ml_peer) 663 { 664 struct wlan_mlo_dev_context *ml_dev; 665 struct wlan_objmgr_peer *link_peer; 666 struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS]; 667 struct wlan_mlo_link_peer_entry *peer_entry; 668 uint16_t i; 669 670 if (!ml_peer) 671 return; 672 673 mlo_peer_lock_acquire(ml_peer); 674 675 if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) { 676 mlo_peer_lock_release(ml_peer); 677 return; 678 } 679 680 ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED; 681 ml_dev = ml_peer->ml_dev; 682 683 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 684 link_peers[i] = NULL; 685 peer_entry = &ml_peer->peer_list[i]; 686 if (!peer_entry->link_peer) 687 continue; 688 689 link_peer = peer_entry->link_peer; 690 if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) != 691 QDF_STATUS_SUCCESS) 692 continue; 693 694 link_peers[i] = link_peer; 695 } 696 mlo_peer_lock_release(ml_peer); 697 698 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 699 if (!link_peers[i]) 700 continue; 701 702 /* Prepare and queue message */ 703 if (i == 0) 704 mlo_link_peer_send_assoc_fail(ml_dev, link_peers[i]); 705 else 706 mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]); 707 } 708 } 709 710 void wlan_mlo_partner_peer_disconnect_notify(struct wlan_objmgr_peer *src_peer) 711 { 712 struct wlan_mlo_dev_context *ml_dev; 713 struct wlan_mlo_peer_context *ml_peer; 714 struct wlan_objmgr_peer *link_peer; 715 struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS]; 716 struct wlan_mlo_link_peer_entry *peer_entry; 717 struct wlan_objmgr_vdev *vdev = NULL; 718 uint16_t i; 719 720 ml_peer = src_peer->mlo_peer_ctx; 721 if (!ml_peer) 722 return; 723 724 vdev = wlan_peer_get_vdev(src_peer); 725 if (!vdev) 726 return; 727 728 /* Do not change peer state to disconnect initiated for 729 * link switch case, this can lead to not sending deauth frame 730 * incase of actual disconnect and AP might drop the next connect 731 * request as it might think STA is still in connected state. 732 */ 733 if (wlan_vdev_mlme_is_mlo_link_switch_in_progress(vdev)) 734 return; 735 736 mlo_peer_lock_acquire(ml_peer); 737 738 if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) { 739 mlo_peer_lock_release(ml_peer); 740 return; 741 } 742 743 wlan_mlo_peer_wsi_link_delete(ml_peer); 744 745 ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED; 746 747 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) { 748 mlo_peer_lock_release(ml_peer); 749 return; 750 } 751 752 ml_dev = ml_peer->ml_dev; 753 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 754 link_peers[i] = NULL; 755 peer_entry = &ml_peer->peer_list[i]; 756 if (!peer_entry->link_peer) { 757 mlo_debug("link peer is null"); 758 continue; 759 } 760 761 if (peer_entry->link_peer == src_peer) 762 continue; 763 764 link_peer = peer_entry->link_peer; 765 if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) != 766 QDF_STATUS_SUCCESS) 767 continue; 768 769 link_peers[i] = link_peer; 770 } 771 mlo_peer_lock_release(ml_peer); 772 773 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 774 if (!link_peers[i]) 775 continue; 776 777 /* Prepare and queue message */ 778 mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]); 779 } 780 } 781 782 qdf_export_symbol(wlan_mlo_partner_peer_disconnect_notify); 783 784 static void mlo_peer_populate_link_peer( 785 struct wlan_mlo_peer_context *ml_peer, 786 struct wlan_objmgr_peer *link_peer) 787 { 788 mlo_peer_lock_acquire(ml_peer); 789 wlan_mlo_peer_get_ref(ml_peer); 790 link_peer->mlo_peer_ctx = ml_peer; 791 mlo_peer_lock_release(ml_peer); 792 } 793 794 static void mlo_reset_link_peer( 795 struct wlan_mlo_peer_context *ml_peer, 796 struct wlan_objmgr_peer *link_peer) 797 { 798 mlo_peer_lock_acquire(ml_peer); 799 link_peer->mlo_peer_ctx = NULL; 800 wlan_peer_clear_mlo(link_peer); 801 mlo_peer_lock_release(ml_peer); 802 } 803 804 static void mlo_peer_free(struct wlan_mlo_peer_context *ml_peer) 805 { 806 struct wlan_mlo_dev_context *ml_dev; 807 808 ml_dev = ml_peer->ml_dev; 809 if (!ml_dev) { 810 mlo_err("ML DEV is NULL"); 811 return; 812 } 813 814 mlo_debug("ML Peer " QDF_MAC_ADDR_FMT " is freed", 815 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes)); 816 mlo_peer_lock_destroy(ml_peer); 817 epcs_dev_peer_lock_destroy(&ml_peer->epcs_info); 818 mlo_ap_ml_ptqm_peerid_free(ml_dev, ml_peer->mlo_peer_id); 819 mlo_ap_ml_peerid_free(ml_peer->mlo_peer_id); 820 mlo_peer_free_aid(ml_dev, ml_peer); 821 mlo_peer_free_primary_umac(ml_dev, ml_peer); 822 qdf_mem_free(ml_peer); 823 } 824 825 void mlo_peer_cleanup(struct wlan_mlo_peer_context *ml_peer) 826 { 827 struct wlan_mlo_dev_context *ml_dev; 828 829 if (!ml_peer) { 830 mlo_err("ML PEER is NULL"); 831 return; 832 } 833 ml_dev = ml_peer->ml_dev; 834 if (!ml_dev) { 835 mlo_err("ML DEV is NULL"); 836 return; 837 } 838 839 mlo_dev_mlpeer_detach(ml_dev, ml_peer); 840 /* If any Auth req is received during ML peer delete */ 841 mlo_peer_process_pending_auth(ml_dev, ml_peer); 842 mlo_peer_free(ml_peer); 843 } 844 845 static QDF_STATUS mlo_peer_attach_link_peer( 846 struct wlan_mlo_peer_context *ml_peer, 847 struct wlan_objmgr_peer *link_peer, 848 qdf_nbuf_t frm_buf) 849 { 850 struct wlan_mlo_link_peer_entry *peer_entry; 851 QDF_STATUS status = QDF_STATUS_E_RESOURCES; 852 struct wlan_objmgr_pdev *pdev; 853 struct wlan_objmgr_vdev *vdev; 854 uint16_t i; 855 856 if (!link_peer) 857 return QDF_STATUS_E_FAILURE; 858 859 vdev = wlan_peer_get_vdev(link_peer); 860 if (!vdev) 861 return QDF_STATUS_E_FAILURE; 862 863 mlo_peer_lock_acquire(ml_peer); 864 865 if (ml_peer->mlpeer_state != ML_PEER_CREATED) { 866 mlo_peer_lock_release(ml_peer); 867 mlo_err("ML Peer " QDF_MAC_ADDR_FMT " is not in created state (state %d)", 868 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 869 ml_peer->mlpeer_state); 870 return status; 871 } 872 873 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 874 peer_entry = &ml_peer->peer_list[i]; 875 if (peer_entry->link_peer) 876 continue; 877 878 if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) != 879 QDF_STATUS_SUCCESS) { 880 mlo_err("ML Peer " QDF_MAC_ADDR_FMT ", link peer " QDF_MAC_ADDR_FMT " is not in valid state", 881 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 882 QDF_MAC_ADDR_REF 883 (wlan_peer_get_macaddr(link_peer))); 884 break; 885 } 886 peer_entry->link_peer = link_peer; 887 qdf_atomic_inc(&vdev->vdev_objmgr.wlan_ml_peer_count); 888 qdf_copy_macaddr(&peer_entry->link_addr, 889 (struct qdf_mac_addr *)&link_peer->macaddr[0]); 890 891 peer_entry->link_ix = wlan_vdev_get_link_id(vdev); 892 pdev = wlan_vdev_get_pdev(wlan_peer_get_vdev(link_peer)); 893 peer_entry->hw_link_id = wlan_mlo_get_pdev_hw_link_id(pdev); 894 mlo_peer_assign_primary_umac(ml_peer, peer_entry); 895 if (frm_buf) 896 peer_entry->assoc_rsp_buf = frm_buf; 897 else 898 peer_entry->assoc_rsp_buf = NULL; 899 900 status = QDF_STATUS_SUCCESS; 901 break; 902 } 903 if (QDF_IS_STATUS_SUCCESS(status)) 904 ml_peer->link_peer_cnt++; 905 906 mlo_peer_lock_release(ml_peer); 907 908 return status; 909 } 910 911 qdf_nbuf_t mlo_peer_get_link_peer_assoc_resp_buf( 912 struct wlan_mlo_peer_context *ml_peer, 913 uint8_t link_ix) 914 { 915 struct wlan_mlo_link_peer_entry *peer_entry; 916 qdf_nbuf_t frm_buf = NULL; 917 uint8_t i; 918 919 if (!ml_peer) 920 return NULL; 921 922 if (link_ix > MAX_MLO_LINK_PEERS) 923 return NULL; 924 925 mlo_peer_lock_acquire(ml_peer); 926 if ((ml_peer->mlpeer_state != ML_PEER_CREATED) && 927 (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) { 928 mlo_peer_lock_release(ml_peer); 929 return NULL; 930 } 931 932 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 933 peer_entry = &ml_peer->peer_list[i]; 934 935 if (!peer_entry->link_peer) 936 continue; 937 938 if (peer_entry->link_ix == link_ix) { 939 if (!peer_entry->assoc_rsp_buf) 940 break; 941 942 frm_buf = qdf_nbuf_clone(peer_entry->assoc_rsp_buf); 943 break; 944 } 945 } 946 mlo_peer_lock_release(ml_peer); 947 948 return frm_buf; 949 } 950 951 void wlan_mlo_peer_free_all_link_assoc_resp_buf( 952 struct wlan_objmgr_peer *link_peer) 953 { 954 struct wlan_mlo_link_peer_entry *peer_entry; 955 struct wlan_mlo_peer_context *ml_peer; 956 uint8_t i; 957 958 ml_peer = link_peer->mlo_peer_ctx; 959 if (!ml_peer) 960 return; 961 962 mlo_peer_lock_acquire(ml_peer); 963 964 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 965 peer_entry = &ml_peer->peer_list[i]; 966 967 if (peer_entry->assoc_rsp_buf) { 968 qdf_nbuf_free(peer_entry->assoc_rsp_buf); 969 peer_entry->assoc_rsp_buf = NULL; 970 } 971 } 972 mlo_peer_lock_release(ml_peer); 973 } 974 975 static QDF_STATUS mlo_peer_detach_link_peer( 976 struct wlan_mlo_peer_context *ml_peer, 977 struct wlan_objmgr_peer *link_peer) 978 { 979 struct wlan_mlo_link_peer_entry *peer_entry; 980 QDF_STATUS status = QDF_STATUS_E_RESOURCES; 981 uint16_t i; 982 struct wlan_objmgr_vdev *vdev; 983 984 mlo_peer_lock_acquire(ml_peer); 985 986 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 987 peer_entry = &ml_peer->peer_list[i]; 988 if (!peer_entry->link_peer) 989 continue; 990 991 if (peer_entry->link_peer != link_peer) 992 continue; 993 994 if (peer_entry->assoc_rsp_buf) { 995 qdf_nbuf_free(peer_entry->assoc_rsp_buf); 996 peer_entry->assoc_rsp_buf = NULL; 997 } 998 vdev = wlan_peer_get_vdev(link_peer); 999 if (vdev) { 1000 qdf_atomic_dec(&vdev->vdev_objmgr.wlan_ml_peer_count); 1001 } else { 1002 mlo_err("vdev is null for ml_peer: " QDF_MAC_ADDR_FMT 1003 "mld mac addr: " QDF_MAC_ADDR_FMT, 1004 QDF_MAC_ADDR_REF(link_peer->macaddr), 1005 QDF_MAC_ADDR_REF(link_peer->mldaddr)); 1006 qdf_assert_always(vdev); 1007 } 1008 wlan_objmgr_peer_release_ref(link_peer, WLAN_MLO_MGR_ID); 1009 peer_entry->link_peer = NULL; 1010 ml_peer->link_peer_cnt--; 1011 status = QDF_STATUS_SUCCESS; 1012 break; 1013 } 1014 mlo_peer_lock_release(ml_peer); 1015 1016 return status; 1017 } 1018 1019 static QDF_STATUS mlo_dev_get_link_vdevs( 1020 struct wlan_objmgr_vdev *vdev, 1021 struct wlan_mlo_dev_context *ml_dev, 1022 struct mlo_partner_info *ml_info, 1023 struct wlan_objmgr_vdev *link_vdevs[]) 1024 { 1025 uint16_t i, j; 1026 struct wlan_objmgr_vdev *vdev_link; 1027 uint8_t link_id; 1028 1029 if (!ml_dev) { 1030 mlo_err("ml_dev is null"); 1031 return QDF_STATUS_E_INVAL; 1032 } 1033 1034 if (!ml_info) { 1035 mlo_err("ml_info is null"); 1036 return QDF_STATUS_E_INVAL; 1037 } 1038 1039 mlo_debug("num_partner_links %d", ml_info->num_partner_links); 1040 for (i = 0; i < ml_info->num_partner_links; i++) { 1041 link_id = ml_info->partner_link_info[i].link_id; 1042 vdev_link = mlo_get_vdev_by_link_id(vdev, link_id); 1043 if (vdev_link) { 1044 link_vdevs[i] = vdev_link; 1045 } else { 1046 /* release ref which were taken before failure */ 1047 for (j = 0; j < i; j++) { 1048 vdev_link = link_vdevs[j]; 1049 if (!vdev_link) 1050 continue; 1051 1052 wlan_objmgr_vdev_release_ref(vdev_link, 1053 WLAN_MLO_MGR_ID); 1054 } 1055 return QDF_STATUS_E_INVAL; 1056 } 1057 } 1058 1059 return QDF_STATUS_SUCCESS; 1060 } 1061 1062 static void mlo_dev_release_link_vdevs( 1063 struct wlan_objmgr_vdev *link_vdevs[]) 1064 { 1065 uint16_t i; 1066 struct wlan_objmgr_vdev *vdev_link; 1067 1068 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 1069 vdev_link = link_vdevs[i]; 1070 if (!vdev_link) 1071 continue; 1072 1073 wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID); 1074 } 1075 } 1076 1077 #ifdef WLAN_FEATURE_11BE 1078 static void 1079 wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context *ml_peer, 1080 struct mlo_partner_info *ml_info) 1081 { 1082 ml_peer->t2lm_policy.t2lm_enable_val = ml_info->t2lm_enable_val; 1083 } 1084 1085 static void 1086 wlan_mlo_peer_initialize_epcs_info(struct wlan_mlo_peer_context *ml_peer) 1087 { 1088 ml_peer->epcs_info.state = EPCS_DOWN; 1089 ml_peer->epcs_info.self_gen_dialog_token = 0; 1090 } 1091 1092 #else 1093 static void 1094 wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context *ml_peer, 1095 struct mlo_partner_info *ml_info) 1096 {} 1097 1098 static void 1099 wlan_mlo_peer_initialize_epcs_info(struct wlan_mlo_peer_context *ml_peer) 1100 {} 1101 #endif /* WLAN_FEATURE_11BE */ 1102 1103 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP) 1104 struct wlan_objmgr_vdev* 1105 mlo_get_link_vdev_from_psoc_id(struct wlan_mlo_dev_context *ml_dev, 1106 uint8_t psoc_id, bool get_bridge_vdev) 1107 { 1108 uint8_t i; 1109 uint16_t num_bridge_vdev = 0; 1110 uint8_t max_vdevs = WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS; 1111 struct wlan_objmgr_vdev *link_vdev; 1112 QDF_STATUS status; 1113 1114 if (WLAN_OBJMGR_MAX_DEVICES <= psoc_id) 1115 return NULL; 1116 1117 if (!ml_dev) 1118 return NULL; 1119 1120 /* if there are no bridge vdevs available, 1121 * fall back to actual link vdevs 1122 */ 1123 status = mlo_ap_get_bridge_vdev_count(ml_dev, &num_bridge_vdev); 1124 if (!get_bridge_vdev || (status != QDF_STATUS_SUCCESS) || 1125 !num_bridge_vdev) 1126 max_vdevs = WLAN_UMAC_MLO_MAX_VDEVS; 1127 1128 for (i = 0; i < max_vdevs; i++) { 1129 if (max_vdevs == WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS) 1130 link_vdev = ml_dev->wlan_bridge_vdev_list[i]; 1131 else 1132 link_vdev = ml_dev->wlan_vdev_list[i]; 1133 if (!link_vdev) 1134 continue; 1135 if (psoc_id != wlan_vdev_get_psoc_id(link_vdev)) 1136 continue; 1137 if (wlan_objmgr_vdev_try_get_ref(link_vdev, WLAN_MLO_MGR_ID) != 1138 QDF_STATUS_SUCCESS) { 1139 mlo_err("VDEV is not in created state"); 1140 return NULL; 1141 } 1142 return link_vdev; 1143 } 1144 1145 return NULL; 1146 } 1147 1148 static 1149 QDF_STATUS mlo_bridge_peer_create_post(struct wlan_mlo_dev_context *ml_dev, 1150 struct wlan_mlo_peer_context *ml_peer, 1151 uint8_t psoc_id) 1152 { 1153 struct peer_create_notif_s peer_create; 1154 struct wlan_objmgr_vdev *vdev_link; 1155 QDF_STATUS status; 1156 1157 /* Bridge peer not required */ 1158 if (psoc_id >= WLAN_OBJMGR_MAX_DEVICES) 1159 return QDF_STATUS_SUCCESS; 1160 1161 vdev_link = mlo_get_link_vdev_from_psoc_id(ml_dev, psoc_id, true); 1162 1163 if (!vdev_link) { 1164 mlo_err("VDEV derivation in unsuccessful for %u psoc", 1165 psoc_id); 1166 return QDF_STATUS_E_FAILURE; 1167 } 1168 1169 peer_create.vdev_link = vdev_link; 1170 wlan_mlo_peer_get_ref(ml_peer); 1171 peer_create.ml_peer = ml_peer; 1172 1173 qdf_copy_macaddr(&peer_create.addr, 1174 &ml_peer->peer_mld_addr); 1175 1176 peer_create.frm_buf = NULL; 1177 1178 status = mlo_msgq_post(MLO_BRIDGE_PEER_CREATE, ml_dev, &peer_create); 1179 if (status != QDF_STATUS_SUCCESS) { 1180 wlan_mlo_peer_release_ref(ml_peer); 1181 wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID); 1182 } 1183 1184 return status; 1185 } 1186 1187 static QDF_STATUS 1188 wlan_mlo_get_bridge_peer_psoc_id(struct wlan_objmgr_vdev *vdev, 1189 struct wlan_mlo_peer_context *ml_peer, 1190 struct wlan_objmgr_vdev *link_vdevs[], 1191 uint8_t num_partner_links, 1192 uint8_t *bridge_psoc_id) 1193 { 1194 struct wlan_mlo_dev_context *ml_dev; 1195 struct wlan_objmgr_vdev *ml_vdev; 1196 uint8_t psoc_ids[WLAN_NUM_TWO_LINK_PSOC]; 1197 uint8_t comp_psoc_id, i, is_adjacent; 1198 uint8_t bridge_peer_psoc_id = WLAN_OBJMGR_MAX_DEVICES; 1199 uint16_t num_bridge_vdev = 0; 1200 uint8_t max_vdevs = WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS; 1201 QDF_STATUS status; 1202 1203 if (wlan_vdev_mlme_get_opmode(vdev) != QDF_SAP_MODE) 1204 return QDF_STATUS_SUCCESS; 1205 1206 /* Return from here for 3 link association */ 1207 if (WLAN_NUM_TWO_LINK_PSOC != num_partner_links) 1208 return QDF_STATUS_SUCCESS; 1209 1210 ml_dev = vdev->mlo_dev_ctx; 1211 if (!ml_dev) 1212 return QDF_STATUS_E_FAILURE; 1213 1214 for (i = 0; i < WLAN_NUM_TWO_LINK_PSOC; i++) 1215 psoc_ids[i] = wlan_vdev_get_psoc_id(link_vdevs[i]); 1216 1217 status = mlo_chip_adjacent(psoc_ids[0], psoc_ids[1], 1218 &is_adjacent); 1219 if (QDF_STATUS_SUCCESS != status) { 1220 mlo_err("Unable to get chip adjacency for " QDF_MAC_ADDR_FMT ", psoc_0 %u, psoc_1 %u", 1221 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 1222 psoc_ids[0], psoc_ids[1]); 1223 return status; 1224 } 1225 1226 if (is_adjacent) 1227 return QDF_STATUS_SUCCESS; 1228 1229 /* if there are no bridge vdevs available, 1230 * fall back to actual link vdevs 1231 */ 1232 status = mlo_ap_get_bridge_vdev_count(ml_dev, &num_bridge_vdev); 1233 if ((status != QDF_STATUS_SUCCESS) || !num_bridge_vdev) { 1234 mlo_err_rl("Using actual vdev as bridge vdev"); 1235 max_vdevs = WLAN_UMAC_MLO_MAX_VDEVS; 1236 } 1237 1238 for (i = 0; i < max_vdevs; i++) { 1239 if (max_vdevs == WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS) 1240 ml_vdev = ml_dev->wlan_bridge_vdev_list[i]; 1241 else 1242 ml_vdev = ml_dev->wlan_vdev_list[i]; 1243 if (!ml_vdev || (wlan_vdev_is_up(ml_vdev) != QDF_STATUS_SUCCESS)) 1244 continue; 1245 comp_psoc_id = wlan_vdev_get_psoc_id(ml_vdev); 1246 if ((comp_psoc_id != psoc_ids[0]) && 1247 (comp_psoc_id != psoc_ids[1])) { 1248 bridge_peer_psoc_id = comp_psoc_id; 1249 break; 1250 } 1251 } 1252 1253 if (bridge_peer_psoc_id >= WLAN_OBJMGR_MAX_DEVICES) { 1254 mlo_err("Invalid psoc or psoc not found for " QDF_MAC_ADDR_FMT " psoc %u", 1255 ether_sprintf(ml_peer->peer_mld_addr.bytes), 1256 bridge_peer_psoc_id); 1257 return QDF_STATUS_E_FAILURE; 1258 } 1259 1260 /* Check if derived psoc is adjecent to both links */ 1261 for (i = 0; i < WLAN_NUM_TWO_LINK_PSOC; i++) { 1262 status = mlo_chip_adjacent(psoc_ids[i], bridge_peer_psoc_id, 1263 &is_adjacent); 1264 if (QDF_STATUS_SUCCESS != status) { 1265 mlo_err("Unable to get chip adjacency for " QDF_MAC_ADDR_FMT ", psoc_0 %u, psoc_1 %u", 1266 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 1267 psoc_ids[i], bridge_peer_psoc_id); 1268 return status; 1269 } 1270 if (!is_adjacent) { 1271 mlo_err("Derived psoc is not adjecent to one of the links for " QDF_MAC_ADDR_FMT ", psoc_0 %u, psoc_1 %u psoc_2 %u", 1272 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 1273 psoc_ids[0], psoc_ids[1], bridge_peer_psoc_id); 1274 return QDF_STATUS_E_FAILURE; 1275 } 1276 } 1277 1278 /* Add vdev corresponds to bridge link to link_vdevs so 1279 * that primary UMAC derivation follows 3-link assoc. 1280 */ 1281 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 1282 if (link_vdevs[i]) 1283 continue; 1284 1285 link_vdevs[i] = mlo_get_link_vdev_from_psoc_id(ml_dev, 1286 bridge_peer_psoc_id, 1287 true); 1288 if (!link_vdevs[i]) 1289 return QDF_STATUS_E_FAILURE; 1290 1291 ml_peer->max_links++; 1292 *bridge_psoc_id = bridge_peer_psoc_id; 1293 break; 1294 } 1295 1296 if (i == WLAN_UMAC_MLO_MAX_VDEVS) { 1297 mlo_err("Unable to append bridge peer vdev to link vdev list"); 1298 return QDF_STATUS_E_FAILURE; 1299 } 1300 1301 mlo_debug("%u is adjecent psoc for " QDF_MAC_ADDR_FMT " is_adjacent %u", 1302 bridge_peer_psoc_id, 1303 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 1304 is_adjacent); 1305 1306 return status; 1307 } 1308 #else 1309 static 1310 QDF_STATUS mlo_bridge_peer_create_post(struct wlan_mlo_dev_context *ml_dev, 1311 struct wlan_mlo_peer_context *ml_peer, 1312 uint8_t psoc_id) 1313 { 1314 return QDF_STATUS_SUCCESS; 1315 } 1316 1317 static QDF_STATUS 1318 wlan_mlo_get_bridge_peer_psoc_id(struct wlan_objmgr_vdev *vdev, 1319 struct wlan_mlo_peer_context *ml_peer, 1320 struct wlan_objmgr_vdev *link_vdevs[], 1321 uint8_t num_partner_links, 1322 uint8_t *bridge_psoc_id) 1323 { 1324 return QDF_STATUS_SUCCESS; 1325 } 1326 #endif 1327 1328 QDF_STATUS wlan_mlo_peer_asreq(struct wlan_objmgr_vdev *vdev, 1329 struct wlan_objmgr_peer *link_peer, 1330 struct mlo_partner_info *ml_info, 1331 qdf_nbuf_t frm_buf) 1332 { 1333 struct wlan_mlo_dev_context *ml_dev; 1334 struct wlan_mlo_peer_context *ml_peer = NULL; 1335 struct wlan_objmgr_vdev *link_vdevs[WLAN_UMAC_MLO_MAX_VDEVS] = { NULL }; 1336 struct wlan_objmgr_vdev *vdev_link; 1337 QDF_STATUS status; 1338 uint16_t i; 1339 uint16_t j; 1340 uint16_t link_count; 1341 struct wlan_mlo_link_peer_entry *peer_entry; 1342 struct wlan_objmgr_peer *iter_peer; 1343 1344 /* get ML VDEV from VDEV */ 1345 ml_dev = vdev->mlo_dev_ctx; 1346 if (!ml_dev) { 1347 mlo_err("ML dev ctx is NULL"); 1348 return QDF_STATUS_E_NULL_VALUE; 1349 } 1350 1351 ml_peer = link_peer->mlo_peer_ctx; 1352 if (!ml_peer) { 1353 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " ML peer is NULL", 1354 ml_dev->mld_id, 1355 QDF_MAC_ADDR_REF(link_peer->mldaddr)); 1356 1357 return QDF_STATUS_E_FAILURE; 1358 } 1359 1360 if (!wlan_mlo_peer_is_assoc_peer(ml_peer, link_peer)) { 1361 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT "Assoc req received on non-assoc peer" QDF_MAC_ADDR_FMT, 1362 ml_dev->mld_id, 1363 QDF_MAC_ADDR_REF(link_peer->mldaddr), 1364 QDF_MAC_ADDR_REF(link_peer->macaddr)); 1365 1366 return QDF_STATUS_E_FAILURE; 1367 } 1368 1369 status = mlo_dev_get_link_vdevs(vdev, ml_dev, 1370 ml_info, link_vdevs); 1371 if (QDF_IS_STATUS_ERROR(status)) { 1372 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " get link vdevs failed", 1373 ml_dev->mld_id, 1374 QDF_MAC_ADDR_REF(link_peer->mldaddr)); 1375 return QDF_STATUS_E_FAILURE; 1376 } 1377 1378 /* If ML peer state is not in Assoc done state, drop REASSOC req */ 1379 if (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE) { 1380 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " invalid state %d", 1381 ml_dev->mld_id, 1382 QDF_MAC_ADDR_REF(link_peer->mldaddr), 1383 ml_peer->mlpeer_state); 1384 1385 mlo_dev_release_link_vdevs(link_vdevs); 1386 1387 return QDF_STATUS_E_FAILURE; 1388 } 1389 1390 link_count = 0; 1391 for (j = 0; j < ml_peer->max_links; j++) { 1392 peer_entry = &ml_peer->peer_list[j]; 1393 iter_peer = peer_entry->link_peer; 1394 if (!iter_peer) 1395 continue; 1396 1397 if (wlan_peer_get_peer_type(iter_peer) == 1398 WLAN_PEER_MLO_BRIDGE) { 1399 link_count++; 1400 continue; 1401 } 1402 1403 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 1404 vdev_link = link_vdevs[i]; 1405 if (!vdev_link) 1406 continue; 1407 1408 if (vdev_link != wlan_peer_get_vdev(iter_peer)) 1409 continue; 1410 1411 link_count++; 1412 break; 1413 } 1414 } 1415 if (link_count != ml_peer->link_peer_cnt) { 1416 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " incorrect link peers", 1417 ml_dev->mld_id, 1418 QDF_MAC_ADDR_REF(link_peer->mldaddr)); 1419 mlo_dev_release_link_vdevs(link_vdevs); 1420 1421 return QDF_STATUS_E_INVAL; 1422 } 1423 1424 /* Notify other vdevs about assoc req */ 1425 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 1426 vdev_link = link_vdevs[i]; 1427 if (!vdev_link) 1428 continue; 1429 1430 if (vdev_link == vdev) 1431 continue; 1432 1433 mlo_partner_peer_reassoc_post(ml_dev, vdev_link, 1434 ml_peer, frm_buf, ml_info); 1435 } 1436 1437 mlo_dev_release_link_vdevs(link_vdevs); 1438 1439 if (QDF_IS_STATUS_ERROR(wlan_mlo_validate_reassocreq(ml_peer))) { 1440 mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " reassoc proc is failed %pK", 1441 ml_dev->mld_id, 1442 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 1443 ml_peer); 1444 1445 return QDF_STATUS_E_FAILURE; 1446 } 1447 1448 mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " reassoc handled %pK", 1449 ml_dev->mld_id, 1450 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 1451 ml_peer); 1452 1453 return QDF_STATUS_SUCCESS; 1454 } 1455 1456 QDF_STATUS wlan_mlo_peer_create(struct wlan_objmgr_vdev *vdev, 1457 struct wlan_objmgr_peer *link_peer, 1458 struct mlo_partner_info *ml_info, 1459 qdf_nbuf_t frm_buf, 1460 uint16_t aid) 1461 { 1462 struct wlan_mlo_dev_context *ml_dev; 1463 struct wlan_mlo_peer_context *ml_peer = NULL; 1464 struct wlan_objmgr_vdev *link_vdevs[WLAN_UMAC_MLO_MAX_VDEVS] = { NULL }; 1465 struct wlan_objmgr_vdev *tmp_link_vdevs[WLAN_UMAC_MLO_MAX_VDEVS] = { NULL }; 1466 struct wlan_objmgr_vdev *vdev_link; 1467 QDF_STATUS status; 1468 uint16_t i, j; 1469 struct wlan_objmgr_peer *assoc_peer; 1470 uint8_t bridge_peer_psoc_id = WLAN_OBJMGR_MAX_DEVICES; 1471 bool is_ml_peer_attached = false; 1472 1473 /* get ML VDEV from VDEV */ 1474 ml_dev = vdev->mlo_dev_ctx; 1475 1476 if (!ml_dev) { 1477 mlo_err("ML dev ctx is NULL"); 1478 return QDF_STATUS_E_NULL_VALUE; 1479 } 1480 1481 /* Check resources of Partner VDEV */ 1482 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) { 1483 if (wlan_mlo_is_mld_ctx_exist( 1484 (struct qdf_mac_addr *)&link_peer->mldaddr[0])) { 1485 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " is matching with one of the MLD address in the system", 1486 ml_dev->mld_id, 1487 QDF_MAC_ADDR_REF(link_peer->mldaddr)); 1488 return QDF_STATUS_E_FAILURE; 1489 } 1490 /* Limit max assoc links */ 1491 if (ml_info->num_partner_links > WLAN_UMAC_MLO_ASSOC_MAX_SUPPORTED_LINKS) { 1492 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " exceeds MAX assoc limit of %d", 1493 ml_dev->mld_id, 1494 QDF_MAC_ADDR_REF(link_peer->mldaddr), 1495 WLAN_UMAC_MLO_ASSOC_MAX_SUPPORTED_LINKS); 1496 return QDF_STATUS_E_RESOURCES; 1497 } 1498 1499 status = mlo_dev_get_link_vdevs(vdev, ml_dev, 1500 ml_info, link_vdevs); 1501 if (QDF_IS_STATUS_ERROR(status)) { 1502 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " get link vdevs failed", 1503 ml_dev->mld_id, 1504 QDF_MAC_ADDR_REF(link_peer->mldaddr)); 1505 return QDF_STATUS_E_FAILURE; 1506 } 1507 1508 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 1509 vdev_link = link_vdevs[i]; 1510 if (!vdev_link) { 1511 mlo_debug("vdev_link is null"); 1512 continue; 1513 } 1514 1515 if (wlan_vdev_is_mlo_peer_create_allowed(vdev_link) 1516 != QDF_STATUS_SUCCESS) { 1517 mlo_dev_release_link_vdevs(link_vdevs); 1518 1519 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " create not allowed on link vdev %d", 1520 ml_dev->mld_id, 1521 QDF_MAC_ADDR_REF 1522 (link_peer->mldaddr), 1523 wlan_vdev_get_id(vdev_link)); 1524 return QDF_STATUS_E_INVAL; 1525 } 1526 } 1527 1528 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 1529 vdev_link = link_vdevs[i]; 1530 if (vdev_link && (vdev_link != vdev) && 1531 (wlan_vdev_get_peer_count(vdev_link) > 1532 wlan_vdev_get_max_peer_count(vdev_link))) { 1533 mlo_dev_release_link_vdevs(link_vdevs); 1534 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " Max peer count reached on link vdev %d", 1535 ml_dev->mld_id, 1536 QDF_MAC_ADDR_REF 1537 (link_peer->mldaddr), 1538 wlan_vdev_get_id(vdev_link)); 1539 return QDF_STATUS_E_RESOURCES; 1540 } 1541 } 1542 } 1543 /* When roam to MLO AP, partner link vdev1 is updated first, 1544 * ml peer need be created and attached for partner link peer. 1545 * 1546 * When roam target AP and current AP have same MLD address, don't 1547 * delete old ML peer and re-create new one, just update different 1548 * info. 1549 */ 1550 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) { 1551 ml_peer = wlan_mlo_get_mlpeer(ml_dev, 1552 (struct qdf_mac_addr *)&link_peer->mldaddr[0]); 1553 if (ml_peer) { 1554 mlo_debug("ML Peer " QDF_MAC_ADDR_FMT 1555 " existed, state %d", 1556 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 1557 ml_peer->mlpeer_state); 1558 ml_peer->mlpeer_state = ML_PEER_CREATED; 1559 ml_peer->max_links = ml_info->num_partner_links; 1560 wlan_mlo_peer_set_t2lm_enable_val(ml_peer, ml_info); 1561 is_ml_peer_attached = true; 1562 } 1563 } 1564 if (!ml_peer) { 1565 /* Allocate MLO peer */ 1566 ml_peer = qdf_mem_malloc(sizeof(*ml_peer)); 1567 if (!ml_peer) { 1568 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " mem alloc failed", 1569 ml_dev->mld_id, 1570 QDF_MAC_ADDR_REF(link_peer->mldaddr)); 1571 mlo_dev_release_link_vdevs(link_vdevs); 1572 return QDF_STATUS_E_NOMEM; 1573 } 1574 1575 qdf_atomic_init(&ml_peer->ref_cnt); 1576 mlo_peer_lock_create(ml_peer); 1577 ml_peer->ml_dev = ml_dev; 1578 ml_peer->mlpeer_state = ML_PEER_CREATED; 1579 ml_peer->max_links = ml_info->num_partner_links; 1580 ml_peer->primary_umac_psoc_id = ML_PRIMARY_UMAC_ID_INVAL; 1581 ml_peer->migrate_primary_umac_psoc_id = 1582 ML_PRIMARY_UMAC_ID_INVAL; 1583 ml_peer->primary_umac_migration_in_progress = false; 1584 1585 ml_peer->mlo_peer_id = mlo_ap_ml_peerid_alloc(); 1586 if (ml_peer->mlo_peer_id == MLO_INVALID_PEER_ID) { 1587 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " invalid ml peer id", 1588 ml_dev->mld_id, 1589 QDF_MAC_ADDR_REF 1590 (ml_peer->peer_mld_addr.bytes)); 1591 mlo_peer_free(ml_peer); 1592 mlo_dev_release_link_vdevs(link_vdevs); 1593 return QDF_STATUS_E_RESOURCES; 1594 } 1595 1596 qdf_copy_macaddr((struct qdf_mac_addr *)&ml_peer->peer_mld_addr, 1597 (struct qdf_mac_addr *)&link_peer->mldaddr[0]); 1598 wlan_mlo_peer_set_t2lm_enable_val(ml_peer, ml_info); 1599 epcs_dev_peer_lock_create(&ml_peer->epcs_info); 1600 wlan_mlo_peer_initialize_epcs_info(ml_peer); 1601 1602 /* Allocate AID */ 1603 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) { 1604 if (aid == (uint16_t)-1) { 1605 status = mlo_peer_allocate_aid(ml_dev, ml_peer); 1606 if (status != QDF_STATUS_SUCCESS) { 1607 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " aid alloc failed", 1608 ml_dev->mld_id, 1609 QDF_MAC_ADDR_REF 1610 (ml_peer->peer_mld_addr.bytes)); 1611 mlo_peer_free(ml_peer); 1612 mlo_dev_release_link_vdevs(link_vdevs); 1613 return status; 1614 } 1615 } else { 1616 ml_peer->assoc_id = aid; 1617 } 1618 } 1619 } 1620 1621 /* Populate Link peer pointer, peer MAC address, 1622 * MLD address. HW link ID, update ref count 1623 */ 1624 status = mlo_peer_attach_link_peer(ml_peer, link_peer, NULL); 1625 if (QDF_IS_STATUS_ERROR(status)) { 1626 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " link peer attach failed", 1627 ml_dev->mld_id, 1628 QDF_MAC_ADDR_REF 1629 (ml_peer->peer_mld_addr.bytes)); 1630 /* If there is another link peer attached for this ML peer, 1631 * ml peer can't be detached and freed. 1632 */ 1633 if (is_ml_peer_attached && ml_peer->link_peer_cnt) 1634 return status; 1635 if (is_ml_peer_attached) 1636 mlo_dev_mlpeer_detach(ml_dev, ml_peer); 1637 mlo_peer_free(ml_peer); 1638 mlo_dev_release_link_vdevs(link_vdevs); 1639 return status; 1640 } 1641 1642 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) { 1643 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 1644 if (!link_vdevs[i]) { 1645 mlo_debug("vdev_link is null"); 1646 continue; 1647 } 1648 1649 if (wlan_objmgr_vdev_try_get_ref(link_vdevs[i], WLAN_MLO_MGR_ID) != 1650 QDF_STATUS_SUCCESS) { 1651 mlo_err("VDEV is not in created state"); 1652 /* release ref which were taken before failure */ 1653 for (j = 0; j < i; j++) { 1654 if (!link_vdevs[i]) 1655 continue; 1656 1657 wlan_objmgr_vdev_release_ref(link_vdevs[i], 1658 WLAN_MLO_MGR_ID); 1659 } 1660 mlo_reset_link_peer(ml_peer, link_peer); 1661 mlo_peer_free(ml_peer); 1662 mlo_dev_release_link_vdevs(link_vdevs); 1663 1664 return QDF_STATUS_E_FAILURE; 1665 } 1666 tmp_link_vdevs[i] = link_vdevs[i]; 1667 } 1668 1669 status = wlan_mlo_get_bridge_peer_psoc_id(vdev, ml_peer, 1670 tmp_link_vdevs, 1671 ml_info->num_partner_links, 1672 &bridge_peer_psoc_id); 1673 if (QDF_STATUS_SUCCESS != status) { 1674 mlo_err("MLD ID %d: Failed to derive bridge peer psoc id", 1675 ml_dev->mld_id); 1676 mlo_reset_link_peer(ml_peer, link_peer); 1677 mlo_peer_free(ml_peer); 1678 mlo_dev_release_link_vdevs(link_vdevs); 1679 mlo_dev_release_link_vdevs(tmp_link_vdevs); 1680 wlan_objmgr_peer_release_ref(link_peer, 1681 WLAN_MLO_MGR_ID); 1682 return QDF_STATUS_E_FAILURE; 1683 } 1684 } 1685 1686 /* Allocate Primary UMAC */ 1687 mlo_peer_allocate_primary_umac(ml_dev, ml_peer, tmp_link_vdevs); 1688 1689 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) 1690 mlo_dev_release_link_vdevs(tmp_link_vdevs); 1691 1692 /* Store AID, MLO Peer pointer in link peer, take link peer ref count */ 1693 mlo_peer_populate_link_peer(ml_peer, link_peer); 1694 1695 mlo_peer_populate_nawds_params(ml_peer, ml_info); 1696 mlo_peer_populate_mesh_params(ml_peer, ml_info); 1697 1698 if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) || 1699 ((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) && 1700 !is_ml_peer_attached)) { 1701 /* Reject creation for AP mode, If ML peer is present with 1702 * MLD MAC address, For PSTA case, all MLD STAs are connected 1703 * to same MLD AP, it can have duplicate MLD address entries 1704 * for STA MLDs 1705 */ 1706 if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) && 1707 mlo_mgr_ml_peer_exist_on_diff_ml_ctx(&link_peer->mldaddr[0], 1708 NULL)) { 1709 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " is exists, creation failed", 1710 ml_dev->mld_id, 1711 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes)); 1712 mlo_reset_link_peer(ml_peer, link_peer); 1713 mlo_peer_free(ml_peer); 1714 mlo_dev_release_link_vdevs(link_vdevs); 1715 wlan_objmgr_peer_release_ref(link_peer, 1716 WLAN_MLO_MGR_ID); 1717 return QDF_STATUS_E_EXISTS; 1718 } 1719 1720 /* Attach MLO peer to ML Peer table */ 1721 status = mlo_dev_mlpeer_attach(ml_dev, ml_peer); 1722 if (status != QDF_STATUS_SUCCESS) { 1723 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " attach failed", 1724 ml_dev->mld_id, 1725 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes)); 1726 mlo_reset_link_peer(ml_peer, link_peer); 1727 wlan_objmgr_peer_release_ref(link_peer, 1728 WLAN_MLO_MGR_ID); 1729 mlo_peer_free(ml_peer); 1730 mlo_dev_release_link_vdevs(link_vdevs); 1731 return status; 1732 } 1733 } 1734 1735 wlan_mlo_peer_get_ref(ml_peer); 1736 1737 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) { 1738 /* Notify other vdevs about link peer creation */ 1739 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 1740 vdev_link = link_vdevs[i]; 1741 if (!vdev_link) 1742 continue; 1743 1744 if (vdev_link == vdev) 1745 continue; 1746 1747 mlo_partner_peer_create_post(ml_dev, vdev_link, 1748 ml_peer, frm_buf, ml_info); 1749 } 1750 /* Create bridge peer */ 1751 status = mlo_bridge_peer_create_post(ml_dev, ml_peer, 1752 bridge_peer_psoc_id); 1753 if (QDF_STATUS_SUCCESS != status) { 1754 mlo_err("MLD ID %d: Bridge peer creation failed", 1755 ml_dev->mld_id); 1756 wlan_mlo_partner_peer_create_failed_notify(ml_peer); 1757 mlo_dev_release_link_vdevs(link_vdevs); 1758 wlan_mlo_peer_release_ref(ml_peer); 1759 return QDF_STATUS_E_FAILURE; 1760 } 1761 } 1762 mlo_dev_release_link_vdevs(link_vdevs); 1763 1764 if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) { 1765 mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " allocation failed", 1766 ml_dev->mld_id, 1767 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes)); 1768 wlan_mlo_peer_release_ref(ml_peer); 1769 return QDF_STATUS_E_FAILURE; 1770 } 1771 1772 mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " allocated %pK", 1773 ml_dev->mld_id, 1774 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 1775 ml_peer); 1776 1777 /* 1778 * wlan_mlo_peer_create() is trigggered after getting peer 1779 * assoc confirm from FW. For single link MLO connection, it is 1780 * OK to trigger assoc response from here. 1781 */ 1782 if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) && 1783 (!wlan_mlo_peer_is_nawds(ml_peer))) { 1784 if ((ml_peer->max_links == 1) && 1785 (ml_peer->link_peer_cnt == 1)) { 1786 assoc_peer = ml_peer->peer_list[0].link_peer; 1787 if (assoc_peer) 1788 mlo_mlme_peer_assoc_resp(assoc_peer); 1789 } 1790 } 1791 1792 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) 1793 wlan_clear_peer_level_tid_to_link_mapping(vdev); 1794 1795 wlan_mlo_peer_release_ref(ml_peer); 1796 1797 return QDF_STATUS_SUCCESS; 1798 } 1799 1800 QDF_STATUS wlan_mlo_link_peer_attach(struct wlan_mlo_peer_context *ml_peer, 1801 struct wlan_objmgr_peer *peer, 1802 qdf_nbuf_t frm_buf) 1803 { 1804 QDF_STATUS status; 1805 struct wlan_objmgr_peer *assoc_peer; 1806 struct wlan_objmgr_vdev *vdev = NULL; 1807 1808 if (!ml_peer) 1809 return QDF_STATUS_E_FAILURE; 1810 1811 vdev = wlan_peer_get_vdev(peer); 1812 if (!vdev) 1813 return QDF_STATUS_E_FAILURE; 1814 1815 /* Populate Link peer pointer, peer MAC address, 1816 * MLD address. HW link ID, update ref count 1817 */ 1818 status = mlo_peer_attach_link_peer(ml_peer, peer, frm_buf); 1819 if (QDF_IS_STATUS_ERROR(status)) 1820 return status; 1821 1822 /* Store AID, MLO Peer pointer in link peer, take link peer ref count */ 1823 mlo_peer_populate_link_peer(ml_peer, peer); 1824 1825 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) { 1826 if (ml_peer->max_links == ml_peer->link_peer_cnt) { 1827 assoc_peer = ml_peer->peer_list[0].link_peer; 1828 if (assoc_peer) 1829 mlo_mlme_peer_assoc_resp(assoc_peer); 1830 } 1831 } 1832 1833 return status; 1834 } 1835 1836 QDF_STATUS wlan_mlo_link_asresp_attach(struct wlan_mlo_peer_context *ml_peer, 1837 struct wlan_objmgr_peer *peer, 1838 qdf_nbuf_t frm_buf) 1839 { 1840 uint16_t i; 1841 struct wlan_mlo_link_peer_entry *peer_entry; 1842 1843 if (!ml_peer) { 1844 mlo_err(" ml peer is NULL"); 1845 return QDF_STATUS_E_FAILURE; 1846 } 1847 1848 if (!peer) { 1849 ml_peer->link_asresp_cnt++; 1850 mlo_err(" ml peer or link peer pointer is NULL"); 1851 return QDF_STATUS_E_FAILURE; 1852 } 1853 mlo_peer_lock_acquire(ml_peer); 1854 1855 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 1856 peer_entry = &ml_peer->peer_list[i]; 1857 if (!peer_entry->link_peer) 1858 continue; 1859 1860 if (peer == peer_entry->link_peer) { 1861 ml_peer->link_asresp_cnt++; 1862 /* Free previous assoc resp buffer */ 1863 if (peer_entry->assoc_rsp_buf) { 1864 qdf_nbuf_free(peer_entry->assoc_rsp_buf); 1865 peer_entry->assoc_rsp_buf = NULL; 1866 } 1867 1868 if (frm_buf) 1869 peer_entry->assoc_rsp_buf = frm_buf; 1870 else 1871 peer_entry->assoc_rsp_buf = NULL; 1872 1873 break; 1874 } 1875 } 1876 1877 mlo_peer_lock_release(ml_peer); 1878 1879 return QDF_STATUS_SUCCESS; 1880 } 1881 1882 QDF_STATUS wlan_mlo_link_peer_delete(struct wlan_objmgr_peer *peer) 1883 { 1884 struct wlan_mlo_peer_context *ml_peer; 1885 1886 ml_peer = peer->mlo_peer_ctx; 1887 1888 if (!ml_peer) 1889 return QDF_STATUS_E_NOENT; 1890 1891 if (ml_peer->mlpeer_state != ML_PEER_DISCONN_INITIATED) 1892 wlan_mlo_peer_wsi_link_delete(ml_peer); 1893 1894 mlo_reset_link_peer(ml_peer, peer); 1895 mlo_peer_detach_link_peer(ml_peer, peer); 1896 1897 if (ml_peer->mlpeer_state != ML_PEER_DISCONN_INITIATED) 1898 wlan_mlo_peer_wsi_link_add(ml_peer); 1899 1900 wlan_mlo_peer_release_ref(ml_peer); 1901 1902 return QDF_STATUS_SUCCESS; 1903 } 1904 1905 qdf_export_symbol(wlan_mlo_link_peer_delete); 1906 1907 qdf_nbuf_t mlo_peer_get_link_peer_assoc_req_buf( 1908 struct wlan_mlo_peer_context *ml_peer, 1909 uint8_t link_ix) 1910 { 1911 struct wlan_objmgr_peer *peer = NULL; 1912 qdf_nbuf_t assocbuf = NULL; 1913 1914 if (!ml_peer) 1915 return NULL; 1916 1917 peer = wlan_mlo_peer_get_assoc_peer(ml_peer); 1918 if (!peer) 1919 return NULL; 1920 1921 assocbuf = mlo_mlme_get_link_assoc_req(peer, link_ix); 1922 1923 return assocbuf; 1924 } 1925 1926 void wlan_mlo_peer_get_links_info(struct wlan_objmgr_peer *peer, 1927 struct mlo_tgt_partner_info *ml_links) 1928 { 1929 struct wlan_mlo_peer_context *ml_peer; 1930 struct wlan_mlo_link_peer_entry *peer_entry; 1931 struct wlan_objmgr_peer *link_peer; 1932 struct wlan_objmgr_vdev *link_vdev; 1933 uint8_t i, ix, idx = 0; 1934 struct wlan_mlo_eml_cap *ml_emlcap; 1935 1936 ml_peer = peer->mlo_peer_ctx; 1937 ml_links->num_partner_links = 0; 1938 1939 if (!ml_peer) 1940 return; 1941 1942 ml_emlcap = &ml_peer->mlpeer_emlcap; 1943 1944 mlo_peer_lock_acquire(ml_peer); 1945 1946 if ((ml_peer->mlpeer_state != ML_PEER_CREATED) && 1947 (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) { 1948 mlo_peer_lock_release(ml_peer); 1949 return; 1950 } 1951 1952 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 1953 peer_entry = &ml_peer->peer_list[i]; 1954 link_peer = peer_entry->link_peer; 1955 1956 if (!link_peer) 1957 continue; 1958 idx++; 1959 if (link_peer == peer) 1960 continue; 1961 link_vdev = wlan_peer_get_vdev(link_peer); 1962 if (!link_vdev) 1963 continue; 1964 1965 if (ml_links->num_partner_links >= WLAN_UMAC_MLO_MAX_VDEVS) 1966 break; 1967 1968 ix = ml_links->num_partner_links; 1969 ml_links->link_info[ix].vdev_id = wlan_vdev_get_id(link_vdev); 1970 ml_links->link_info[ix].hw_mld_link_id = peer_entry->hw_link_id; 1971 ml_links->link_info[ix].mlo_enabled = 1; 1972 ml_links->link_info[ix].mlo_assoc_link = 1973 wlan_peer_mlme_is_assoc_peer(link_peer); 1974 ml_links->link_info[ix].mlo_primary_umac = 1975 peer_entry->is_primary; 1976 ml_links->link_info[ix].mlo_logical_link_index_valid = 1; 1977 ml_links->link_info[ix].emlsr_support = ml_emlcap->emlsr_supp; 1978 ml_links->link_info[ix].logical_link_index = idx - 1; 1979 ml_links->link_info[ix].mlo_bridge_peer = link_peer->mlo_bridge_peer; 1980 ml_links->num_partner_links++; 1981 } 1982 mlo_peer_lock_release(ml_peer); 1983 } 1984 1985 qdf_export_symbol(wlan_mlo_peer_get_links_info); 1986 1987 uint8_t wlan_mlo_peer_get_primary_peer_link_id(struct wlan_objmgr_peer *peer) 1988 { 1989 struct wlan_mlo_peer_context *ml_peer; 1990 1991 ml_peer = peer->mlo_peer_ctx; 1992 1993 if (!ml_peer) { 1994 mlo_err("ml_peer is null"); 1995 return WLAN_LINK_ID_INVALID; 1996 } 1997 1998 return wlan_mlo_peer_get_primary_peer_link_id_by_ml_peer(ml_peer); 1999 } 2000 2001 qdf_export_symbol(wlan_mlo_peer_get_primary_peer_link_id); 2002 2003 uint8_t wlan_mlo_peer_get_primary_peer_link_id_by_ml_peer( 2004 struct wlan_mlo_peer_context *ml_peer) 2005 { 2006 struct wlan_mlo_link_peer_entry *peer_entry; 2007 struct wlan_objmgr_peer *link_peer; 2008 struct wlan_objmgr_vdev *link_vdev; 2009 uint8_t i, vdev_link_id; 2010 2011 if (!ml_peer) { 2012 mlo_err("ml_peer is null"); 2013 return WLAN_LINK_ID_INVALID; 2014 } 2015 mlo_peer_lock_acquire(ml_peer); 2016 2017 if ((ml_peer->mlpeer_state != ML_PEER_CREATED) && 2018 (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) { 2019 mlo_peer_lock_release(ml_peer); 2020 mlo_err("ml_peer is not created and association is not done"); 2021 return WLAN_LINK_ID_INVALID; 2022 } 2023 2024 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 2025 peer_entry = &ml_peer->peer_list[i]; 2026 link_peer = peer_entry->link_peer; 2027 if (!link_peer) 2028 continue; 2029 2030 if (peer_entry->is_primary) { 2031 link_vdev = wlan_peer_get_vdev(link_peer); 2032 if (!link_vdev) { 2033 mlo_peer_lock_release(ml_peer); 2034 mlo_err("link vdev not found"); 2035 return WLAN_LINK_ID_INVALID; 2036 } 2037 vdev_link_id = wlan_vdev_get_link_id(link_vdev); 2038 mlo_peer_lock_release(ml_peer); 2039 return vdev_link_id; 2040 } 2041 } 2042 mlo_peer_lock_release(ml_peer); 2043 mlo_err("None of the peer is designated as primary"); 2044 return WLAN_LINK_ID_INVALID; 2045 } 2046 2047 qdf_export_symbol(wlan_mlo_peer_get_primary_peer_link_id_by_ml_peer); 2048 2049 #ifdef WLAN_MLO_MULTI_CHIP 2050 void wlan_mlo_peer_get_str_capability(struct wlan_objmgr_peer *peer, 2051 uint8_t *str_capability) 2052 { 2053 struct wlan_mlo_peer_context *ml_peer; 2054 uint8_t i; 2055 2056 if (!str_capability) 2057 return; 2058 2059 *str_capability = 1; 2060 if (!peer) 2061 return; 2062 ml_peer = peer->mlo_peer_ctx; 2063 if (!ml_peer) 2064 return; 2065 2066 mlo_peer_lock_acquire(ml_peer); 2067 if ((ml_peer->mlpeer_state != ML_PEER_CREATED) && 2068 (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) { 2069 mlo_peer_lock_release(ml_peer); 2070 return; 2071 } 2072 2073 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 2074 if (ml_peer->mlpeer_nstrinfo[i].link_id >= MAX_MLO_LINKS) 2075 continue; 2076 if (ml_peer->mlpeer_nstrinfo[i].nstr_lp_present) { 2077 *str_capability = 0; 2078 break; 2079 } 2080 } 2081 mlo_peer_lock_release(ml_peer); 2082 } 2083 2084 void wlan_mlo_peer_get_eml_capability(struct wlan_objmgr_peer *peer, 2085 uint8_t *is_emlsr_capable, 2086 uint8_t *is_emlmr_capable) 2087 { 2088 struct wlan_mlo_peer_context *ml_peer; 2089 2090 if (!is_emlsr_capable || !is_emlmr_capable) 2091 return; 2092 2093 *is_emlsr_capable = 0; 2094 *is_emlmr_capable = 0; 2095 if (!peer) 2096 return; 2097 ml_peer = peer->mlo_peer_ctx; 2098 if (!ml_peer) 2099 return; 2100 2101 mlo_peer_lock_acquire(ml_peer); 2102 if ((ml_peer->mlpeer_state != ML_PEER_CREATED) && 2103 (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) { 2104 mlo_peer_lock_release(ml_peer); 2105 return; 2106 } 2107 *is_emlsr_capable = ml_peer->mlpeer_emlcap.emlsr_supp; 2108 *is_emlmr_capable = ml_peer->mlpeer_emlcap.emlmr_supp; 2109 mlo_peer_lock_release(ml_peer); 2110 } 2111 #endif 2112 2113 void wlan_mlo_peer_get_partner_links_info(struct wlan_objmgr_peer *peer, 2114 struct mlo_partner_info *ml_links) 2115 { 2116 struct wlan_mlo_peer_context *ml_peer; 2117 struct wlan_mlo_link_peer_entry *peer_entry; 2118 struct wlan_objmgr_peer *link_peer; 2119 struct wlan_objmgr_vdev *link_vdev; 2120 uint8_t i, ix; 2121 2122 ml_peer = peer->mlo_peer_ctx; 2123 ml_links->num_partner_links = 0; 2124 2125 if (!ml_peer) 2126 return; 2127 2128 mlo_peer_lock_acquire(ml_peer); 2129 2130 if ((ml_peer->mlpeer_state != ML_PEER_CREATED) && 2131 (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) { 2132 mlo_peer_lock_release(ml_peer); 2133 return; 2134 } 2135 2136 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 2137 peer_entry = &ml_peer->peer_list[i]; 2138 link_peer = peer_entry->link_peer; 2139 2140 if (!link_peer) 2141 continue; 2142 2143 if (link_peer == peer) 2144 continue; 2145 2146 link_vdev = wlan_peer_get_vdev(link_peer); 2147 if (!link_vdev) 2148 continue; 2149 2150 if (ml_links->num_partner_links >= WLAN_UMAC_MLO_MAX_VDEVS) 2151 break; 2152 2153 ix = ml_links->num_partner_links; 2154 ml_links->partner_link_info[ix].link_id = peer_entry->link_ix; 2155 ml_links->partner_link_info[ix].is_bridge = 2156 (wlan_peer_get_peer_type(link_peer) == WLAN_PEER_MLO_BRIDGE); 2157 2158 qdf_copy_macaddr(&ml_links->partner_link_info[ix].link_addr, 2159 &peer_entry->link_addr); 2160 ml_links->num_partner_links++; 2161 } 2162 mlo_peer_lock_release(ml_peer); 2163 } 2164 2165 qdf_export_symbol(wlan_mlo_peer_get_partner_links_info); 2166 2167 #ifdef UMAC_SUPPORT_MLNAWDS 2168 bool wlan_mlo_peer_is_nawds(struct wlan_mlo_peer_context *ml_peer) 2169 { 2170 bool status = false; 2171 2172 if (!ml_peer) 2173 return status; 2174 2175 mlo_peer_lock_acquire(ml_peer); 2176 if (ml_peer->is_nawds_ml_peer) 2177 status = true; 2178 mlo_peer_lock_release(ml_peer); 2179 2180 return status; 2181 } 2182 2183 qdf_export_symbol(wlan_mlo_peer_is_nawds); 2184 #endif 2185 2186 #ifdef MESH_MODE_SUPPORT 2187 bool wlan_mlo_peer_is_mesh(struct wlan_mlo_peer_context *ml_peer) 2188 { 2189 bool status = false; 2190 2191 if (!ml_peer) 2192 return status; 2193 2194 mlo_peer_lock_acquire(ml_peer); 2195 if (ml_peer->is_mesh_ml_peer) 2196 status = true; 2197 mlo_peer_lock_release(ml_peer); 2198 2199 return status; 2200 } 2201 2202 qdf_export_symbol(wlan_mlo_peer_is_mesh); 2203 #endif 2204 2205 #ifdef UMAC_MLO_AUTH_DEFER 2206 void mlo_peer_free_auth_param(struct mlpeer_auth_params *auth_params) 2207 { 2208 if (auth_params->rs) 2209 qdf_mem_free(auth_params->rs); 2210 2211 if (auth_params->wbuf) 2212 qdf_nbuf_free(auth_params->wbuf); 2213 2214 qdf_mem_free(auth_params); 2215 } 2216 2217 QDF_STATUS mlo_peer_link_auth_defer(struct wlan_mlo_peer_context *ml_peer, 2218 struct qdf_mac_addr *link_mac, 2219 struct mlpeer_auth_params *auth_params) 2220 { 2221 uint8_t i; 2222 uint8_t free_entries = 0; 2223 struct mlpeer_auth_params *recv_auth; 2224 QDF_STATUS status = QDF_STATUS_E_FAILURE; 2225 2226 if (!ml_peer) 2227 return status; 2228 2229 mlo_peer_lock_acquire(ml_peer); 2230 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 2231 recv_auth = ml_peer->pending_auth[i]; 2232 if (!recv_auth) { 2233 free_entries++; 2234 continue; 2235 } 2236 /* overwrite the entry with latest entry */ 2237 if (qdf_is_macaddr_equal(link_mac, &recv_auth->link_addr)) { 2238 mlo_peer_free_auth_param(recv_auth); 2239 ml_peer->pending_auth[i] = auth_params; 2240 mlo_peer_lock_release(ml_peer); 2241 2242 return QDF_STATUS_SUCCESS; 2243 } 2244 } 2245 2246 if (!free_entries) { 2247 mlo_peer_lock_release(ml_peer); 2248 return QDF_STATUS_E_FAILURE; 2249 } 2250 2251 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 2252 recv_auth = ml_peer->pending_auth[i]; 2253 if (!recv_auth) { 2254 ml_peer->pending_auth[i] = auth_params; 2255 status = QDF_STATUS_SUCCESS; 2256 break; 2257 } 2258 } 2259 mlo_peer_lock_release(ml_peer); 2260 2261 return status; 2262 } 2263 2264 bool wlan_mlo_partner_peer_delete_is_allowed(struct wlan_objmgr_peer *src_peer) 2265 { 2266 struct wlan_objmgr_vdev *vdev = NULL; 2267 struct wlan_mlo_peer_context *ml_peer; 2268 2269 vdev = wlan_peer_get_vdev(src_peer); 2270 if (!vdev) 2271 return false; 2272 2273 ml_peer = src_peer->mlo_peer_ctx; 2274 if (!wlan_peer_is_mlo(src_peer) || !ml_peer) 2275 return false; 2276 2277 if (wlan_vdev_mlme_op_flags_get(vdev, WLAN_VDEV_OP_MLO_STOP_LINK_DEL) || 2278 wlan_vdev_mlme_op_flags_get(vdev, 2279 WLAN_VDEV_OP_MLO_LINK_TBTT_COMPLETE)) { 2280 /* Single LINK MLO connection */ 2281 if (ml_peer->link_peer_cnt == 1) 2282 return false; 2283 2284 /* 2285 * If this link is primary TQM and there is no ongoing migration 2286 * from this link, then issue full disconnect. 2287 */ 2288 if ((wlan_mlo_peer_get_primary_peer_link_id(src_peer) != 2289 wlan_vdev_get_link_id(vdev)) || 2290 ml_peer->primary_umac_migration_in_progress) 2291 return false; 2292 } 2293 2294 return true; 2295 } 2296 2297 qdf_export_symbol(wlan_mlo_partner_peer_delete_is_allowed); 2298 #endif 2299 2300 QDF_STATUS wlan_mlo_validate_reassocreq(struct wlan_mlo_peer_context *ml_peer) 2301 { 2302 uint16_t i; 2303 struct wlan_mlo_link_peer_entry *peer_entry; 2304 QDF_STATUS status = QDF_STATUS_SUCCESS; 2305 2306 if (!ml_peer) { 2307 mlo_err(" ml peer is NULL"); 2308 return QDF_STATUS_E_FAILURE; 2309 } 2310 2311 mlo_peer_lock_acquire(ml_peer); 2312 2313 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 2314 peer_entry = &ml_peer->peer_list[i]; 2315 if (!peer_entry->link_peer) 2316 continue; 2317 2318 /* Check non-assoc link peer Assoc resp buf is valid 2319 * (exclude bridge peer) 2320 */ 2321 if (i && !peer_entry->assoc_rsp_buf && 2322 (wlan_peer_get_peer_type(peer_entry->link_peer) != 2323 WLAN_PEER_MLO_BRIDGE)) { 2324 status = QDF_STATUS_E_FAILURE; 2325 break; 2326 } 2327 } 2328 2329 mlo_peer_lock_release(ml_peer); 2330 2331 return status; 2332 } 2333 2334 #ifdef WLAN_WSI_STATS_SUPPORT 2335 static uint32_t 2336 wlan_mlo_psoc_get_mlo_grp_idx(struct mlo_mgr_context *mlo_mgr, 2337 uint32_t psoc_id) 2338 { 2339 struct mlo_wsi_info *wsi_info = NULL; 2340 struct mlo_wsi_psoc_grp *mlo_psoc_grp; 2341 uint8_t grp_id, i; 2342 2343 if (!mlo_mgr) 2344 return MLO_WSI_MAX_MLO_GRPS; 2345 2346 /* Retrieve the WSI link info structure */ 2347 wsi_info = mlo_mgr->wsi_info; 2348 if (!wsi_info) 2349 return MLO_WSI_MAX_MLO_GRPS; 2350 2351 for (grp_id = 0; grp_id < MLO_WSI_MAX_MLO_GRPS; grp_id++) { 2352 mlo_psoc_grp = &wsi_info->mlo_psoc_grp[grp_id]; 2353 for (i = 0; i < mlo_psoc_grp->num_psoc; i++) { 2354 if (mlo_psoc_grp->psoc_order[i] == psoc_id) 2355 return grp_id; 2356 } 2357 } 2358 2359 return MLO_WSI_MAX_MLO_GRPS; 2360 } 2361 2362 QDF_STATUS wlan_mlo_wsi_link_info_send_cmd(void) 2363 { 2364 struct mlo_mgr_context *mlo_mgr = NULL; 2365 struct mlo_wsi_info *wsi_info = NULL; 2366 struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops = NULL; 2367 struct wlan_objmgr_psoc *psoc_objmgr = NULL; 2368 struct wlan_objmgr_pdev *pdev = NULL; 2369 QDF_STATUS error = QDF_STATUS_SUCCESS; 2370 int i, j; 2371 2372 /* Retrieve the MLO manager context */ 2373 mlo_mgr = wlan_objmgr_get_mlo_ctx(); 2374 if (!mlo_mgr) 2375 return QDF_STATUS_E_INVAL; 2376 2377 /* Retrieve the WSI link info structure */ 2378 wsi_info = mlo_mgr->wsi_info; 2379 if (!wsi_info) 2380 return QDF_STATUS_E_INVAL; 2381 2382 if (wsi_info->block_wmi_cmd) { 2383 mlo_debug("WMI command is blocked"); 2384 return error; 2385 } 2386 /* 2387 * Check each PSOC if the WMI command needs to be sent 2388 * and send it for each PDEV in that PSOC 2389 */ 2390 for (i = 0; i < WLAN_OBJMGR_MAX_DEVICES; i++) { 2391 if (!wsi_info->link_stats[i].send_wmi_cmd) 2392 continue; 2393 2394 psoc_objmgr = wlan_objmgr_get_psoc_by_id(i, WLAN_MLO_MGR_ID); 2395 if (!psoc_objmgr) { 2396 mlo_err("Could not get PSOC obj for index %d", i); 2397 continue; 2398 } 2399 2400 mlo_tx_ops = &psoc_objmgr->soc_cb.tx_ops->mlo_ops; 2401 if (!mlo_tx_ops || !mlo_tx_ops->send_wsi_link_info_cmd) { 2402 mlo_err("mlo_tx_ops is null"); 2403 wlan_objmgr_psoc_release_ref(psoc_objmgr, 2404 WLAN_MLO_MGR_ID); 2405 return QDF_STATUS_E_NULL_VALUE; 2406 } 2407 2408 for (j = 0; j < psoc_objmgr->soc_objmgr.wlan_pdev_count; j++) { 2409 pdev = psoc_objmgr->soc_objmgr.wlan_pdev_list[j]; 2410 if (!pdev) 2411 continue; 2412 2413 if (mlo_tx_ops->send_wsi_link_info_cmd( 2414 pdev, &wsi_info->link_stats[i]) != 2415 QDF_STATUS_SUCCESS) { 2416 mlo_err("Could not send WMI command for PDEV %d in PSOC %d", 2417 j, i); 2418 error = QDF_STATUS_E_FAILURE; 2419 } else { 2420 wsi_info->link_stats[i].send_wmi_cmd = false; 2421 } 2422 } 2423 wlan_objmgr_psoc_release_ref(psoc_objmgr, WLAN_MLO_MGR_ID); 2424 } 2425 2426 return error; 2427 } 2428 2429 static uint32_t wlan_mlo_psoc_get_ix_in_grp(struct mlo_mgr_context *mlo_mgr, 2430 uint32_t grp_id, 2431 uint32_t prim_psoc_id) 2432 { 2433 uint32_t i; 2434 2435 if (!mlo_mgr) { 2436 mlo_err("NULL mlo_mgr"); 2437 return 0xFF; 2438 } 2439 2440 /* Iterate through the PSOC order and find the ID */ 2441 for (i = 0; i < mlo_mgr->wsi_info->mlo_psoc_grp[grp_id].num_psoc; i++) { 2442 if (mlo_mgr->wsi_info->mlo_psoc_grp[grp_id].psoc_order[i] == 2443 prim_psoc_id) { 2444 return i; 2445 } 2446 } 2447 2448 return 0xFF; 2449 } 2450 2451 static QDF_STATUS 2452 wlan_mlo_peer_wsi_link_update(struct wlan_mlo_peer_context *ml_peer, bool add) 2453 { 2454 struct mlo_mgr_context *mlo_mgr = NULL; 2455 struct mlo_wsi_info *wsi_info = NULL; 2456 struct wlan_mlo_link_peer_entry *peer_entry = NULL; 2457 uint32_t prim_psoc_id = 0xFF; 2458 uint32_t sec_psoc_id[MAX_MLO_LINK_PEERS] = {0xFF}; 2459 uint32_t hops, hop_id; 2460 uint32_t prim_grp_idx, sec_grp_idx; 2461 uint32_t prim_psoc_ix_grp, sec_psoc_ix_grp; 2462 uint32_t i, j; 2463 struct mlo_wsi_psoc_grp *mlo_psoc_grp; 2464 struct wlan_objmgr_psoc *psoc; 2465 2466 /* Check if ml_peer is valid */ 2467 if (!ml_peer) { 2468 mlo_err("ML peer is null"); 2469 return QDF_STATUS_E_INVAL; 2470 } 2471 2472 /* Retrieve the MLO manager context */ 2473 mlo_mgr = wlan_objmgr_get_mlo_ctx(); 2474 if (!mlo_mgr) { 2475 mlo_err("ML MGR is NULL for ML peer" QDF_MAC_ADDR_FMT, 2476 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes)); 2477 return QDF_STATUS_E_INVAL; 2478 } 2479 2480 /* Retrieve the WSI link info structure */ 2481 wsi_info = mlo_mgr->wsi_info; 2482 if (!wsi_info) { 2483 mlo_err("WSI Info is NULL for ML peer" QDF_MAC_ADDR_FMT, 2484 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes)); 2485 return QDF_STATUS_E_INVAL; 2486 } 2487 2488 prim_psoc_id = ml_peer->primary_umac_psoc_id; 2489 /* Populate the primary PSOC ID of the respective group */ 2490 prim_grp_idx = wlan_mlo_psoc_get_mlo_grp_idx(mlo_mgr, prim_psoc_id); 2491 if (prim_grp_idx == MLO_WSI_MAX_MLO_GRPS) { 2492 mlo_err("Group index is invalid for ML peer" QDF_MAC_ADDR_FMT, 2493 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes)); 2494 return QDF_STATUS_E_INVAL; 2495 } 2496 2497 /* Populate MLO primary and secondary link */ 2498 for (i = 0, j = 0; i < MAX_MLO_LINK_PEERS; i++) { 2499 peer_entry = &ml_peer->peer_list[i]; 2500 if (!peer_entry->link_peer) { 2501 mlo_err("link peer is null"); 2502 continue; 2503 } 2504 2505 psoc = wlan_peer_get_psoc(peer_entry->link_peer); 2506 if (!mlo_get_wsi_stats_info_support(psoc)) { 2507 mlo_info("WSI stats support is not enabled on psoc %d", 2508 wlan_psoc_get_id(psoc)); 2509 return QDF_STATUS_E_INVAL; 2510 } 2511 2512 /* 2513 * Consider all non-primary peers as secondary links. 2514 * Additionally, consider all active peers as secondary link if 2515 * the TQM is on another PSOC with bridge peer. 2516 */ 2517 if (!peer_entry->is_primary) { 2518 sec_psoc_id[j] = wlan_vdev_get_psoc_id( 2519 wlan_peer_get_vdev( 2520 peer_entry->link_peer)); 2521 2522 sec_grp_idx = wlan_mlo_psoc_get_mlo_grp_idx 2523 (mlo_mgr, 2524 sec_psoc_id[j]); 2525 if (sec_grp_idx != prim_grp_idx) { 2526 mlo_err("Secondary link is not part of same MLO group as primary link"); 2527 continue; 2528 } 2529 j++; 2530 } 2531 } 2532 2533 /* 2534 * Logic for finding ingress and egress stats: 2535 * For a given MLO group, there is a PSOC order 2536 * (1) Iterate through each secondary link 2537 * (1.1) Set the WMI command to true for that PSOC 2538 * (1.2) Increment the ingress count for that PSOC 2539 * (1.3) Calculate the number of hops from the secondary link 2540 * to that primary link within the group. 2541 * (1.4) Iterate through a decrement sequence from the hop_count 2542 * (1.4.1) Increment the egress count for that PSOC index 2543 */ 2544 prim_psoc_ix_grp = wlan_mlo_psoc_get_ix_in_grp(mlo_mgr, prim_grp_idx, 2545 prim_psoc_id); 2546 2547 wsi_info->link_stats[prim_psoc_id].send_wmi_cmd = true; 2548 mlo_psoc_grp = &wsi_info->mlo_psoc_grp[prim_grp_idx]; 2549 for (i = 0; i < j; i++) { 2550 sec_psoc_ix_grp = wlan_mlo_psoc_get_ix_in_grp(mlo_mgr, 2551 prim_grp_idx, 2552 sec_psoc_id[i]); 2553 hops = qdf_min(mlo_psoc_grp->num_psoc - 2554 (prim_psoc_ix_grp - sec_psoc_ix_grp), 2555 (sec_psoc_ix_grp - prim_psoc_ix_grp)); 2556 2557 wsi_info->link_stats[sec_psoc_id[i]].send_wmi_cmd = true; 2558 if (add) 2559 wsi_info->link_stats[sec_psoc_id[i]].ingress_cnt++; 2560 else 2561 wsi_info->link_stats[sec_psoc_id[i]].ingress_cnt--; 2562 2563 while (hops > 1) { 2564 hops--; 2565 hop_id = mlo_psoc_grp->psoc_order[hops]; 2566 wsi_info->link_stats[hop_id].send_wmi_cmd = true; 2567 if (add) 2568 wsi_info->link_stats[hop_id].egress_cnt++; 2569 else 2570 wsi_info->link_stats[hop_id].egress_cnt--; 2571 } 2572 } 2573 2574 /* Check if WMI bit is set, if yes, then send the command */ 2575 if (wlan_mlo_wsi_link_info_send_cmd() != QDF_STATUS_SUCCESS) { 2576 mlo_err("WSI link info not sent for ML peer" QDF_MAC_ADDR_FMT, 2577 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes)); 2578 return QDF_STATUS_E_FAILURE; 2579 } 2580 2581 return QDF_STATUS_SUCCESS; 2582 } 2583 2584 QDF_STATUS wlan_mlo_peer_wsi_link_add(struct wlan_mlo_peer_context *ml_peer) 2585 { 2586 if (!ml_peer) { 2587 mlo_err("Invalid peer"); 2588 return QDF_STATUS_E_INVAL; 2589 } 2590 2591 return wlan_mlo_peer_wsi_link_update(ml_peer, 1); 2592 } 2593 2594 QDF_STATUS wlan_mlo_peer_wsi_link_delete(struct wlan_mlo_peer_context *ml_peer) 2595 { 2596 if (!ml_peer) { 2597 mlo_err("Invalid peer"); 2598 return QDF_STATUS_E_INVAL; 2599 } 2600 2601 return wlan_mlo_peer_wsi_link_update(ml_peer, 0); 2602 } 2603 2604 void wlan_mlo_wsi_stats_block_cmd(void) 2605 { 2606 struct mlo_mgr_context *mlo_mgr = NULL; 2607 struct mlo_wsi_info *wsi_info = NULL; 2608 2609 /* Retrieve the MLO manager context */ 2610 mlo_mgr = wlan_objmgr_get_mlo_ctx(); 2611 if (!mlo_mgr) 2612 return; 2613 2614 /* Retrieve the WSI link info structure */ 2615 wsi_info = mlo_mgr->wsi_info; 2616 if (!wsi_info) 2617 return; 2618 2619 wsi_info->block_wmi_cmd++; 2620 } 2621 2622 void wlan_mlo_wsi_stats_allow_cmd(void) 2623 { 2624 struct mlo_mgr_context *mlo_mgr = NULL; 2625 struct mlo_wsi_info *wsi_info = NULL; 2626 2627 /* Retrieve the MLO manager context */ 2628 mlo_mgr = wlan_objmgr_get_mlo_ctx(); 2629 if (!mlo_mgr) 2630 return; 2631 2632 /* Retrieve the WSI link info structure */ 2633 wsi_info = mlo_mgr->wsi_info; 2634 if (!wsi_info) 2635 return; 2636 2637 if (wsi_info->block_wmi_cmd) 2638 wsi_info->block_wmi_cmd--; 2639 } 2640 2641 #else 2642 void wlan_mlo_wsi_stats_block_cmd(void) 2643 { 2644 } 2645 2646 void wlan_mlo_wsi_stats_allow_cmd(void) 2647 { 2648 } 2649 2650 QDF_STATUS wlan_mlo_wsi_link_info_send_cmd(void) 2651 { 2652 return QDF_STATUS_SUCCESS; 2653 } 2654 2655 QDF_STATUS wlan_mlo_peer_wsi_link_add(struct wlan_mlo_peer_context *ml_peer) 2656 { 2657 return QDF_STATUS_SUCCESS; 2658 } 2659 2660 QDF_STATUS wlan_mlo_peer_wsi_link_delete(struct wlan_mlo_peer_context *ml_peer) 2661 { 2662 return QDF_STATUS_SUCCESS; 2663 } 2664 #endif 2665