1 /* 2 * Copyright (c) 2021, The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 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 28 static void mlo_partner_peer_create_post(struct wlan_mlo_dev_context *ml_dev, 29 struct wlan_objmgr_vdev *vdev_link, 30 struct wlan_mlo_peer_context *ml_peer, 31 qdf_nbuf_t frm_buf, 32 struct mlo_partner_info *ml_info) 33 { 34 struct peer_create_notif_s peer_create; 35 QDF_STATUS status; 36 uint8_t i; 37 uint8_t link_id; 38 39 if (wlan_objmgr_vdev_try_get_ref(vdev_link, WLAN_MLO_MGR_ID) == 40 QDF_STATUS_SUCCESS) { 41 peer_create.vdev_link = vdev_link; 42 } else { 43 mlo_err("VDEV is not in created state"); 44 return; 45 } 46 47 wlan_mlo_peer_get_ref(ml_peer); 48 peer_create.ml_peer = ml_peer; 49 link_id = wlan_vdev_get_link_id(vdev_link); 50 for (i = 0; i < ml_info->num_partner_links; i++) { 51 if (link_id != ml_info->partner_link_info[i].link_id) 52 continue; 53 54 qdf_copy_macaddr(&peer_create.addr, 55 &ml_info->partner_link_info[i].link_addr); 56 break; 57 } 58 59 status = mlo_peer_create_get_frm_buf(ml_peer, &peer_create, frm_buf); 60 61 if (QDF_IS_STATUS_ERROR(status)) { 62 wlan_mlo_peer_release_ref(ml_peer); 63 wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID); 64 mlo_err("nbuf clone is failed"); 65 return; 66 } 67 68 status = mlo_msgq_post(MLO_PEER_CREATE, ml_dev, &peer_create); 69 if (status != QDF_STATUS_SUCCESS) { 70 qdf_nbuf_free(frm_buf); 71 wlan_mlo_peer_release_ref(ml_peer); 72 wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID); 73 } 74 } 75 76 static void mlo_link_peer_assoc_notify(struct wlan_mlo_dev_context *ml_dev, 77 struct wlan_objmgr_peer *peer) 78 { 79 struct peer_assoc_notify_s peer_assoc; 80 QDF_STATUS status; 81 82 peer_assoc.peer = peer; 83 status = mlo_msgq_post(MLO_PEER_ASSOC, ml_dev, &peer_assoc); 84 if (status != QDF_STATUS_SUCCESS) 85 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID); 86 } 87 88 static void mlo_link_peer_send_assoc_fail(struct wlan_mlo_dev_context *ml_dev, 89 struct wlan_objmgr_peer *peer) 90 { 91 struct peer_assoc_fail_notify_s peer_assoc_fail; 92 QDF_STATUS status; 93 94 peer_assoc_fail.peer = peer; 95 status = mlo_msgq_post(MLO_PEER_ASSOC_FAIL, ml_dev, &peer_assoc_fail); 96 if (status != QDF_STATUS_SUCCESS) 97 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID); 98 } 99 100 static void mlo_link_peer_disconnect_notify(struct wlan_mlo_dev_context *ml_dev, 101 struct wlan_objmgr_peer *peer) 102 { 103 struct peer_discon_notify_s peer_disconn; 104 QDF_STATUS status; 105 struct wlan_objmgr_vdev *vdev; 106 enum QDF_OPMODE opmode; 107 108 vdev = wlan_peer_get_vdev(peer); 109 opmode = wlan_vdev_mlme_get_opmode(vdev); 110 111 if (opmode == QDF_SAP_MODE) { 112 peer_disconn.peer = peer; 113 status = mlo_msgq_post(MLO_PEER_DISCONNECT, ml_dev, 114 &peer_disconn); 115 if (status != QDF_STATUS_SUCCESS) 116 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID); 117 } else { 118 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID); 119 } 120 } 121 122 static void mlo_link_peer_deauth_init(struct wlan_mlo_dev_context *ml_dev, 123 struct wlan_objmgr_peer *peer, 124 uint8_t is_disassoc) 125 { 126 struct peer_deauth_notify_s peer_deauth; 127 QDF_STATUS status; 128 129 peer_deauth.peer = peer; 130 peer_deauth.is_disassoc = is_disassoc; 131 status = mlo_msgq_post(MLO_PEER_DEAUTH, ml_dev, &peer_deauth); 132 if (status != QDF_STATUS_SUCCESS) 133 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID); 134 } 135 136 #ifdef UMAC_MLO_AUTH_DEFER 137 static void mlo_peer_process_pending_auth(struct wlan_mlo_dev_context *ml_dev, 138 struct wlan_mlo_peer_context *ml_peer) 139 { 140 struct peer_auth_process_notif_s peer_auth; 141 struct mlpeer_auth_params *recv_auth; 142 uint8_t i; 143 QDF_STATUS status; 144 145 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 146 mlo_peer_lock_acquire(ml_peer); 147 recv_auth = ml_peer->pending_auth[i]; 148 if (!recv_auth) { 149 mlo_peer_lock_release(ml_peer); 150 continue; 151 } 152 peer_auth.auth_params = recv_auth; 153 ml_peer->pending_auth[i] = NULL; 154 155 mlo_peer_lock_release(ml_peer); 156 157 status = mlo_msgq_post(MLO_PEER_PENDING_AUTH, ml_dev, 158 &peer_auth); 159 if (QDF_IS_STATUS_ERROR(status)) 160 mlo_peer_free_auth_param(peer_auth.auth_params); 161 } 162 } 163 #else 164 static void mlo_peer_process_pending_auth(struct wlan_mlo_dev_context *ml_dev, 165 struct wlan_mlo_peer_context *ml_peer) 166 { 167 } 168 #endif 169 170 QDF_STATUS 171 wlan_mlo_peer_is_disconnect_progress(struct wlan_mlo_peer_context *ml_peer) 172 { 173 QDF_STATUS status; 174 175 if (!ml_peer) 176 return QDF_STATUS_E_FAILURE; 177 178 mlo_peer_lock_acquire(ml_peer); 179 180 if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) 181 status = QDF_STATUS_SUCCESS; 182 else 183 status = QDF_STATUS_E_FAILURE; 184 185 mlo_peer_lock_release(ml_peer); 186 187 return status; 188 } 189 190 QDF_STATUS wlan_mlo_peer_is_assoc_done(struct wlan_mlo_peer_context *ml_peer) 191 { 192 QDF_STATUS status; 193 194 if (!ml_peer) 195 return QDF_STATUS_E_FAILURE; 196 197 mlo_peer_lock_acquire(ml_peer); 198 199 if (ml_peer->mlpeer_state == ML_PEER_ASSOC_DONE) 200 status = QDF_STATUS_SUCCESS; 201 else 202 status = QDF_STATUS_E_FAILURE; 203 204 mlo_peer_lock_release(ml_peer); 205 206 return status; 207 } 208 209 struct wlan_objmgr_peer *wlan_mlo_peer_get_assoc_peer( 210 struct wlan_mlo_peer_context *ml_peer) 211 { 212 struct wlan_mlo_link_peer_entry *peer_entry; 213 struct wlan_objmgr_peer *assoc_peer = NULL; 214 215 if (!ml_peer) 216 return NULL; 217 218 mlo_peer_lock_acquire(ml_peer); 219 220 peer_entry = &ml_peer->peer_list[0]; 221 222 if (peer_entry->link_peer) 223 assoc_peer = peer_entry->link_peer; 224 225 mlo_peer_lock_release(ml_peer); 226 227 return assoc_peer; 228 } 229 230 bool mlo_peer_is_assoc_peer(struct wlan_mlo_peer_context *ml_peer, 231 struct wlan_objmgr_peer *peer) 232 { 233 struct wlan_mlo_link_peer_entry *peer_entry; 234 bool is_assoc_peer = false; 235 236 if (!ml_peer || !peer) 237 return is_assoc_peer; 238 239 peer_entry = &ml_peer->peer_list[0]; 240 241 if (peer_entry->link_peer != peer) 242 is_assoc_peer = true; 243 244 return is_assoc_peer; 245 } 246 247 bool wlan_mlo_peer_is_assoc_peer(struct wlan_mlo_peer_context *ml_peer, 248 struct wlan_objmgr_peer *peer) 249 { 250 bool is_assoc_peer = false; 251 252 if (!ml_peer || !peer) 253 return is_assoc_peer; 254 255 mlo_peer_lock_acquire(ml_peer); 256 257 is_assoc_peer = mlo_peer_is_assoc_peer(ml_peer, peer); 258 259 mlo_peer_lock_release(ml_peer); 260 261 return is_assoc_peer; 262 } 263 264 void wlan_mlo_partner_peer_assoc_post(struct wlan_objmgr_peer *assoc_peer) 265 { 266 struct wlan_mlo_dev_context *ml_dev; 267 struct wlan_mlo_peer_context *ml_peer; 268 struct wlan_objmgr_peer *link_peer; 269 struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS]; 270 struct wlan_mlo_link_peer_entry *peer_entry; 271 uint16_t i; 272 273 ml_peer = assoc_peer->mlo_peer_ctx; 274 if (!ml_peer) 275 return; 276 277 mlo_peer_lock_acquire(ml_peer); 278 279 if (ml_peer->mlpeer_state != ML_PEER_CREATED) { 280 mlo_peer_lock_release(ml_peer); 281 return; 282 } 283 284 ml_peer->mlpeer_state = ML_PEER_ASSOC_DONE; 285 ml_dev = ml_peer->ml_dev; 286 287 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 288 link_peers[i] = NULL; 289 peer_entry = &ml_peer->peer_list[i]; 290 291 if (!peer_entry->link_peer) 292 continue; 293 294 if (peer_entry->link_peer == assoc_peer) 295 continue; 296 297 link_peer = peer_entry->link_peer; 298 299 if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) != 300 QDF_STATUS_SUCCESS) 301 continue; 302 303 link_peers[i] = link_peer; 304 } 305 mlo_peer_lock_release(ml_peer); 306 307 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 308 if (!link_peers[i]) 309 continue; 310 311 /* Prepare and queue message */ 312 mlo_link_peer_assoc_notify(ml_dev, link_peers[i]); 313 } 314 } 315 316 void 317 wlan_mlo_peer_deauth_init(struct wlan_mlo_peer_context *ml_peer, 318 struct wlan_objmgr_peer *src_peer, 319 uint8_t is_disassoc) 320 { 321 struct wlan_mlo_dev_context *ml_dev; 322 struct wlan_objmgr_peer *link_peer; 323 struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS]; 324 struct wlan_mlo_link_peer_entry *peer_entry; 325 uint16_t i; 326 uint8_t deauth_sent = 0; 327 328 if (!ml_peer) 329 return; 330 331 mlo_peer_lock_acquire(ml_peer); 332 333 if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) { 334 mlo_peer_lock_release(ml_peer); 335 return; 336 } 337 338 ml_dev = ml_peer->ml_dev; 339 340 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 341 link_peers[i] = NULL; 342 peer_entry = &ml_peer->peer_list[i]; 343 if (!peer_entry->link_peer) 344 continue; 345 346 link_peer = peer_entry->link_peer; 347 348 if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) != 349 QDF_STATUS_SUCCESS) 350 continue; 351 352 link_peers[i] = link_peer; 353 } 354 355 ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED; 356 357 mlo_peer_lock_release(ml_peer); 358 359 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 360 if (!link_peers[i]) 361 continue; 362 363 /* Prepare and queue message */ 364 /* skip sending deauth on src peer */ 365 if ((deauth_sent) || 366 (src_peer && (src_peer == link_peers[i]))) { 367 mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]); 368 } else { 369 mlo_link_peer_deauth_init(ml_dev, link_peers[i], 370 is_disassoc); 371 deauth_sent = 1; 372 } 373 } 374 375 return; 376 } 377 378 void 379 wlan_mlo_partner_peer_create_failed_notify( 380 struct wlan_mlo_peer_context *ml_peer) 381 { 382 struct wlan_mlo_dev_context *ml_dev; 383 struct wlan_objmgr_peer *link_peer; 384 struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS]; 385 struct wlan_mlo_link_peer_entry *peer_entry; 386 uint16_t i; 387 388 if (!ml_peer) 389 return; 390 391 mlo_peer_lock_acquire(ml_peer); 392 393 if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) { 394 mlo_peer_lock_release(ml_peer); 395 return; 396 } 397 398 ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED; 399 ml_dev = ml_peer->ml_dev; 400 401 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 402 link_peers[i] = NULL; 403 peer_entry = &ml_peer->peer_list[i]; 404 if (!peer_entry->link_peer) 405 continue; 406 407 link_peer = peer_entry->link_peer; 408 if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) != 409 QDF_STATUS_SUCCESS) 410 continue; 411 412 link_peers[i] = link_peer; 413 } 414 mlo_peer_lock_release(ml_peer); 415 416 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 417 if (!link_peers[i]) 418 continue; 419 420 /* Prepare and queue message */ 421 if (i == 0) 422 mlo_link_peer_send_assoc_fail(ml_dev, link_peers[i]); 423 else 424 mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]); 425 } 426 } 427 428 void wlan_mlo_partner_peer_disconnect_notify(struct wlan_objmgr_peer *src_peer) 429 { 430 struct wlan_mlo_dev_context *ml_dev; 431 struct wlan_mlo_peer_context *ml_peer; 432 struct wlan_objmgr_peer *link_peer; 433 struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS]; 434 struct wlan_mlo_link_peer_entry *peer_entry; 435 struct wlan_objmgr_vdev *vdev = NULL; 436 uint16_t i; 437 438 ml_peer = src_peer->mlo_peer_ctx; 439 if (!ml_peer) 440 return; 441 442 vdev = wlan_peer_get_vdev(src_peer); 443 if (!vdev) 444 return; 445 446 mlo_peer_lock_acquire(ml_peer); 447 448 if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) { 449 mlo_peer_lock_release(ml_peer); 450 return; 451 } 452 453 ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED; 454 455 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) { 456 mlo_peer_lock_release(ml_peer); 457 return; 458 } 459 460 ml_dev = ml_peer->ml_dev; 461 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 462 link_peers[i] = NULL; 463 peer_entry = &ml_peer->peer_list[i]; 464 if (!peer_entry->link_peer) { 465 mlo_debug("link peer is null"); 466 continue; 467 } 468 469 if (peer_entry->link_peer == src_peer) 470 continue; 471 472 link_peer = peer_entry->link_peer; 473 if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) != 474 QDF_STATUS_SUCCESS) 475 continue; 476 477 link_peers[i] = link_peer; 478 } 479 mlo_peer_lock_release(ml_peer); 480 481 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 482 if (!link_peers[i]) 483 continue; 484 485 /* Prepare and queue message */ 486 mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]); 487 } 488 } 489 490 static void mlo_peer_populate_link_peer( 491 struct wlan_mlo_peer_context *ml_peer, 492 struct wlan_objmgr_peer *link_peer) 493 { 494 mlo_peer_lock_acquire(ml_peer); 495 wlan_mlo_peer_get_ref(ml_peer); 496 link_peer->mlo_peer_ctx = ml_peer; 497 mlo_peer_lock_release(ml_peer); 498 } 499 500 static void mlo_reset_link_peer( 501 struct wlan_mlo_peer_context *ml_peer, 502 struct wlan_objmgr_peer *link_peer) 503 { 504 mlo_peer_lock_acquire(ml_peer); 505 link_peer->mlo_peer_ctx = NULL; 506 wlan_peer_clear_mlo(link_peer); 507 mlo_peer_lock_release(ml_peer); 508 } 509 510 static void mlo_peer_free(struct wlan_mlo_peer_context *ml_peer) 511 { 512 struct wlan_mlo_dev_context *ml_dev; 513 514 ml_dev = ml_peer->ml_dev; 515 if (!ml_dev) { 516 mlo_err("ML DEV is NULL"); 517 return; 518 } 519 520 mlo_debug("ML Peer " QDF_MAC_ADDR_FMT " is freed", 521 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes)); 522 mlo_peer_lock_destroy(ml_peer); 523 mlo_ap_ml_peerid_free(ml_peer->mlo_peer_id); 524 mlo_peer_free_aid(ml_dev, ml_peer); 525 mlo_peer_free_primary_umac(ml_dev, ml_peer); 526 qdf_mem_free(ml_peer); 527 } 528 529 void mlo_peer_cleanup(struct wlan_mlo_peer_context *ml_peer) 530 { 531 struct wlan_mlo_dev_context *ml_dev; 532 533 if (!ml_peer) { 534 mlo_err("ML PEER is NULL"); 535 return; 536 } 537 ml_dev = ml_peer->ml_dev; 538 if (!ml_dev) { 539 mlo_err("ML DEV is NULL"); 540 return; 541 } 542 543 mlo_dev_mlpeer_detach(ml_dev, ml_peer); 544 /* If any Auth req is received during ML peer delete */ 545 mlo_peer_process_pending_auth(ml_dev, ml_peer); 546 mlo_peer_free(ml_peer); 547 } 548 549 static QDF_STATUS mlo_peer_attach_link_peer( 550 struct wlan_mlo_peer_context *ml_peer, 551 struct wlan_objmgr_peer *link_peer, 552 qdf_nbuf_t frm_buf) 553 { 554 struct wlan_mlo_link_peer_entry *peer_entry; 555 QDF_STATUS status = QDF_STATUS_E_RESOURCES; 556 struct wlan_objmgr_pdev *pdev; 557 struct wlan_objmgr_vdev *vdev; 558 uint16_t i; 559 560 if (!link_peer) 561 return QDF_STATUS_E_FAILURE; 562 563 vdev = wlan_peer_get_vdev(link_peer); 564 if (!vdev) 565 return QDF_STATUS_E_FAILURE; 566 567 mlo_peer_lock_acquire(ml_peer); 568 569 if (ml_peer->mlpeer_state != ML_PEER_CREATED) { 570 mlo_peer_lock_release(ml_peer); 571 mlo_err("ML Peer " QDF_MAC_ADDR_FMT " is not in created state (state %d)", 572 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 573 ml_peer->mlpeer_state); 574 return status; 575 } 576 577 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 578 peer_entry = &ml_peer->peer_list[i]; 579 if (peer_entry->link_peer) 580 continue; 581 582 if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) != 583 QDF_STATUS_SUCCESS) { 584 mlo_err("ML Peer " QDF_MAC_ADDR_FMT ", link peer " QDF_MAC_ADDR_FMT " is not in valid state", 585 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 586 QDF_MAC_ADDR_REF 587 (wlan_peer_get_macaddr(link_peer))); 588 break; 589 } 590 peer_entry->link_peer = link_peer; 591 qdf_copy_macaddr(&peer_entry->link_addr, 592 (struct qdf_mac_addr *)&link_peer->macaddr[0]); 593 594 peer_entry->link_ix = wlan_vdev_get_link_id(vdev); 595 pdev = wlan_vdev_get_pdev(wlan_peer_get_vdev(link_peer)); 596 peer_entry->hw_link_id = wlan_mlo_get_pdev_hw_link_id(pdev); 597 mlo_peer_assign_primary_umac(ml_peer, peer_entry); 598 if (frm_buf) 599 peer_entry->assoc_rsp_buf = frm_buf; 600 else 601 peer_entry->assoc_rsp_buf = NULL; 602 603 status = QDF_STATUS_SUCCESS; 604 break; 605 } 606 if (QDF_IS_STATUS_SUCCESS(status)) 607 ml_peer->link_peer_cnt++; 608 609 mlo_peer_lock_release(ml_peer); 610 611 return status; 612 } 613 614 qdf_nbuf_t mlo_peer_get_link_peer_assoc_resp_buf( 615 struct wlan_mlo_peer_context *ml_peer, 616 uint8_t link_ix) 617 { 618 struct wlan_mlo_link_peer_entry *peer_entry; 619 qdf_nbuf_t frm_buf = NULL; 620 uint8_t i; 621 622 if (!ml_peer) 623 return NULL; 624 625 if (link_ix > MAX_MLO_LINK_PEERS) 626 return NULL; 627 628 mlo_peer_lock_acquire(ml_peer); 629 if ((ml_peer->mlpeer_state != ML_PEER_CREATED) && 630 (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) { 631 mlo_peer_lock_release(ml_peer); 632 return NULL; 633 } 634 635 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 636 peer_entry = &ml_peer->peer_list[i]; 637 638 if (!peer_entry->link_peer) 639 continue; 640 641 if (peer_entry->link_ix == link_ix) { 642 if (!peer_entry->assoc_rsp_buf) 643 break; 644 645 frm_buf = qdf_nbuf_clone(peer_entry->assoc_rsp_buf); 646 break; 647 } 648 } 649 mlo_peer_lock_release(ml_peer); 650 651 return frm_buf; 652 } 653 654 void wlan_mlo_peer_free_all_link_assoc_resp_buf( 655 struct wlan_objmgr_peer *link_peer) 656 { 657 struct wlan_mlo_link_peer_entry *peer_entry; 658 struct wlan_mlo_peer_context *ml_peer; 659 uint8_t i; 660 661 ml_peer = link_peer->mlo_peer_ctx; 662 if (!ml_peer) 663 return; 664 665 mlo_peer_lock_acquire(ml_peer); 666 667 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 668 peer_entry = &ml_peer->peer_list[i]; 669 670 if (peer_entry->assoc_rsp_buf) { 671 qdf_nbuf_free(peer_entry->assoc_rsp_buf); 672 peer_entry->assoc_rsp_buf = NULL; 673 } 674 } 675 mlo_peer_lock_release(ml_peer); 676 } 677 678 static QDF_STATUS mlo_peer_detach_link_peer( 679 struct wlan_mlo_peer_context *ml_peer, 680 struct wlan_objmgr_peer *link_peer) 681 { 682 struct wlan_mlo_link_peer_entry *peer_entry; 683 QDF_STATUS status = QDF_STATUS_E_RESOURCES; 684 uint16_t i; 685 686 mlo_peer_lock_acquire(ml_peer); 687 688 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 689 peer_entry = &ml_peer->peer_list[i]; 690 if (!peer_entry->link_peer) 691 continue; 692 693 if (peer_entry->link_peer != link_peer) 694 continue; 695 696 if (peer_entry->assoc_rsp_buf) { 697 qdf_nbuf_free(peer_entry->assoc_rsp_buf); 698 peer_entry->assoc_rsp_buf = NULL; 699 } 700 701 wlan_objmgr_peer_release_ref(link_peer, WLAN_MLO_MGR_ID); 702 peer_entry->link_peer = NULL; 703 ml_peer->link_peer_cnt--; 704 status = QDF_STATUS_SUCCESS; 705 break; 706 } 707 mlo_peer_lock_release(ml_peer); 708 709 return status; 710 } 711 712 static QDF_STATUS mlo_dev_get_link_vdevs( 713 struct wlan_objmgr_vdev *vdev, 714 struct wlan_mlo_dev_context *ml_dev, 715 struct mlo_partner_info *ml_info, 716 struct wlan_objmgr_vdev *link_vdevs[]) 717 { 718 uint16_t i, j; 719 struct wlan_objmgr_vdev *vdev_link; 720 uint8_t link_id; 721 722 if (!ml_dev) { 723 mlo_err("ml_dev is null"); 724 return QDF_STATUS_E_INVAL; 725 } 726 727 if (!ml_info) { 728 mlo_err("ml_info is null"); 729 return QDF_STATUS_E_INVAL; 730 } 731 732 mlo_debug("num_partner_links %d", ml_info->num_partner_links); 733 for (i = 0; i < ml_info->num_partner_links; i++) { 734 link_id = ml_info->partner_link_info[i].link_id; 735 vdev_link = mlo_get_vdev_by_link_id(vdev, link_id); 736 if (vdev_link) { 737 link_vdevs[i] = vdev_link; 738 } else { 739 /* release ref which were taken before failure */ 740 for (j = 0; j < i; j++) { 741 vdev_link = link_vdevs[j]; 742 if (!vdev_link) 743 continue; 744 745 wlan_objmgr_vdev_release_ref(vdev_link, 746 WLAN_MLO_MGR_ID); 747 } 748 return QDF_STATUS_E_INVAL; 749 } 750 } 751 752 return QDF_STATUS_SUCCESS; 753 } 754 755 static void mlo_dev_release_link_vdevs( 756 struct wlan_objmgr_vdev *link_vdevs[]) 757 { 758 uint16_t i; 759 struct wlan_objmgr_vdev *vdev_link; 760 761 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 762 vdev_link = link_vdevs[i]; 763 if (!vdev_link) 764 continue; 765 766 wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID); 767 } 768 } 769 770 #ifdef WLAN_FEATURE_11BE 771 static void 772 wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context *ml_peer, 773 struct mlo_partner_info *ml_info) 774 { 775 ml_peer->t2lm_policy.t2lm_enable_val = ml_info->t2lm_enable_val; 776 } 777 #else 778 static void 779 wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context *ml_peer, 780 struct mlo_partner_info *ml_info) 781 {} 782 #endif /* WLAN_FEATURE_11BE */ 783 784 QDF_STATUS wlan_mlo_peer_create(struct wlan_objmgr_vdev *vdev, 785 struct wlan_objmgr_peer *link_peer, 786 struct mlo_partner_info *ml_info, 787 qdf_nbuf_t frm_buf, 788 uint16_t aid) 789 { 790 struct wlan_mlo_dev_context *ml_dev; 791 struct wlan_mlo_peer_context *ml_peer = NULL; 792 struct wlan_objmgr_vdev *link_vdevs[WLAN_UMAC_MLO_MAX_VDEVS] = { NULL }; 793 struct wlan_objmgr_vdev *vdev_link; 794 QDF_STATUS status; 795 uint16_t i; 796 struct wlan_objmgr_peer *assoc_peer; 797 bool is_ml_peer_attached = false; 798 799 /* get ML VDEV from VDEV */ 800 ml_dev = vdev->mlo_dev_ctx; 801 802 if (!ml_dev) { 803 mlo_err("ML dev ctx is NULL"); 804 return QDF_STATUS_E_NULL_VALUE; 805 } 806 807 /* Check resources of Partner VDEV */ 808 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) { 809 if (wlan_mlo_is_mld_ctx_exist( 810 (struct qdf_mac_addr *)&link_peer->mldaddr[0])) { 811 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " is matching with one of the MLD address in the system", 812 ml_dev->mld_id, 813 QDF_MAC_ADDR_REF(link_peer->mldaddr)); 814 return QDF_STATUS_E_FAILURE; 815 } 816 status = mlo_dev_get_link_vdevs(vdev, ml_dev, 817 ml_info, link_vdevs); 818 if (QDF_IS_STATUS_ERROR(status)) { 819 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " get link vdevs failed", 820 ml_dev->mld_id, 821 QDF_MAC_ADDR_REF(link_peer->mldaddr)); 822 return QDF_STATUS_E_FAILURE; 823 } 824 825 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 826 vdev_link = link_vdevs[i]; 827 if (!vdev_link) { 828 mlo_debug("vdev_link is null"); 829 continue; 830 } 831 832 if (wlan_vdev_is_mlo_peer_create_allowed(vdev_link) 833 != QDF_STATUS_SUCCESS) { 834 mlo_dev_release_link_vdevs(link_vdevs); 835 836 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " create not allowed on link vdev %d", 837 ml_dev->mld_id, 838 QDF_MAC_ADDR_REF 839 (link_peer->mldaddr), 840 wlan_vdev_get_id(vdev_link)); 841 return QDF_STATUS_E_INVAL; 842 } 843 } 844 845 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 846 vdev_link = link_vdevs[i]; 847 if (vdev_link && (vdev_link != vdev) && 848 (wlan_vdev_get_peer_count(vdev_link) > 849 wlan_vdev_get_max_peer_count(vdev_link))) { 850 mlo_dev_release_link_vdevs(link_vdevs); 851 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " Max peer count reached on link vdev %d", 852 ml_dev->mld_id, 853 QDF_MAC_ADDR_REF 854 (link_peer->mldaddr), 855 wlan_vdev_get_id(vdev_link)); 856 return QDF_STATUS_E_RESOURCES; 857 } 858 } 859 } 860 /* When roam to MLO AP, partner link vdev1 is updated first, 861 * ml peer need be created and attached for partner link peer. 862 * 863 * When roam target AP and current AP have same MLD address, don't 864 * delete old ML peer and re-create new one, just update different 865 * info. 866 */ 867 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) { 868 ml_peer = wlan_mlo_get_mlpeer(ml_dev, 869 (struct qdf_mac_addr *)&link_peer->mldaddr[0]); 870 if (ml_peer) { 871 mlo_debug("ML Peer " QDF_MAC_ADDR_FMT 872 " existed, state %d", 873 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 874 ml_peer->mlpeer_state); 875 ml_peer->mlpeer_state = ML_PEER_CREATED; 876 ml_peer->max_links = ml_info->num_partner_links; 877 wlan_mlo_peer_set_t2lm_enable_val(ml_peer, ml_info); 878 is_ml_peer_attached = true; 879 } 880 } 881 if (!ml_peer) { 882 /* Allocate MLO peer */ 883 ml_peer = qdf_mem_malloc(sizeof(*ml_peer)); 884 if (!ml_peer) { 885 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " mem alloc failed", 886 ml_dev->mld_id, 887 QDF_MAC_ADDR_REF(link_peer->mldaddr)); 888 mlo_dev_release_link_vdevs(link_vdevs); 889 return QDF_STATUS_E_NOMEM; 890 } 891 892 qdf_atomic_init(&ml_peer->ref_cnt); 893 mlo_peer_lock_create(ml_peer); 894 ml_peer->ml_dev = ml_dev; 895 ml_peer->mlpeer_state = ML_PEER_CREATED; 896 ml_peer->max_links = ml_info->num_partner_links; 897 ml_peer->primary_umac_psoc_id = ML_PRIMARY_UMAC_ID_INVAL; 898 899 ml_peer->mlo_peer_id = mlo_ap_ml_peerid_alloc(); 900 if (ml_peer->mlo_peer_id == MLO_INVALID_PEER_ID) { 901 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " invalid ml peer id", 902 ml_dev->mld_id, 903 QDF_MAC_ADDR_REF 904 (ml_peer->peer_mld_addr.bytes)); 905 mlo_peer_free(ml_peer); 906 mlo_dev_release_link_vdevs(link_vdevs); 907 return QDF_STATUS_E_RESOURCES; 908 } 909 910 qdf_copy_macaddr((struct qdf_mac_addr *)&ml_peer->peer_mld_addr, 911 (struct qdf_mac_addr *)&link_peer->mldaddr[0]); 912 wlan_mlo_peer_set_t2lm_enable_val(ml_peer, ml_info); 913 914 /* Allocate AID */ 915 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) { 916 if (aid == (uint16_t)-1) { 917 status = mlo_peer_allocate_aid(ml_dev, ml_peer); 918 if (status != QDF_STATUS_SUCCESS) { 919 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " aid alloc failed", 920 ml_dev->mld_id, 921 QDF_MAC_ADDR_REF 922 (ml_peer->peer_mld_addr.bytes)); 923 mlo_peer_free(ml_peer); 924 mlo_dev_release_link_vdevs(link_vdevs); 925 return status; 926 } 927 } else { 928 ml_peer->assoc_id = aid; 929 } 930 } 931 } 932 933 /* Populate Link peer pointer, peer MAC address, 934 * MLD address. HW link ID, update ref count 935 */ 936 status = mlo_peer_attach_link_peer(ml_peer, link_peer, NULL); 937 if (QDF_IS_STATUS_ERROR(status)) { 938 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " link peer attach failed", 939 ml_dev->mld_id, 940 QDF_MAC_ADDR_REF 941 (ml_peer->peer_mld_addr.bytes)); 942 /* If there is another link peer attached for this ML peer, 943 * ml peer can't be detached and freed. 944 */ 945 if (is_ml_peer_attached && ml_peer->link_peer_cnt) 946 return status; 947 if (is_ml_peer_attached) 948 mlo_dev_mlpeer_detach(ml_dev, ml_peer); 949 mlo_peer_free(ml_peer); 950 mlo_dev_release_link_vdevs(link_vdevs); 951 return status; 952 } 953 954 /* Allocate Primary UMAC */ 955 mlo_peer_allocate_primary_umac(ml_dev, ml_peer, link_vdevs); 956 957 /* Store AID, MLO Peer pointer in link peer, take link peer ref count */ 958 mlo_peer_populate_link_peer(ml_peer, link_peer); 959 960 mlo_peer_populate_nawds_params(ml_peer, ml_info); 961 mlo_peer_populate_mesh_params(ml_peer, ml_info); 962 963 if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) || 964 ((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) && 965 !is_ml_peer_attached)) { 966 /* Attach MLO peer to ML Peer table */ 967 status = mlo_dev_mlpeer_attach(ml_dev, ml_peer); 968 if (status != QDF_STATUS_SUCCESS) { 969 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " attach failed", 970 ml_dev->mld_id, 971 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes)); 972 mlo_reset_link_peer(ml_peer, link_peer); 973 wlan_objmgr_peer_release_ref(link_peer, 974 WLAN_MLO_MGR_ID); 975 mlo_peer_free(ml_peer); 976 mlo_dev_release_link_vdevs(link_vdevs); 977 return status; 978 } 979 } 980 981 wlan_mlo_peer_get_ref(ml_peer); 982 983 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) { 984 /* Notify other vdevs about link peer creation */ 985 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 986 vdev_link = link_vdevs[i]; 987 if (!vdev_link) 988 continue; 989 990 if (vdev_link == vdev) 991 continue; 992 993 mlo_partner_peer_create_post(ml_dev, vdev_link, 994 ml_peer, frm_buf, ml_info); 995 } 996 } 997 mlo_dev_release_link_vdevs(link_vdevs); 998 999 if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) { 1000 mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " allocation failed", 1001 ml_dev->mld_id, 1002 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes)); 1003 wlan_mlo_peer_release_ref(ml_peer); 1004 return QDF_STATUS_E_FAILURE; 1005 } 1006 1007 mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " allocated %pK", 1008 ml_dev->mld_id, 1009 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 1010 ml_peer); 1011 1012 /* 1013 * wlan_mlo_peer_create() is trigggered after getting peer 1014 * assoc confirm from FW. For single link MLO connection, it is 1015 * OK to trigger assoc response from here. 1016 */ 1017 if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) && 1018 (!wlan_mlo_peer_is_nawds(ml_peer))) { 1019 if (ml_peer->max_links == ml_peer->link_peer_cnt) { 1020 assoc_peer = ml_peer->peer_list[0].link_peer; 1021 if (assoc_peer) 1022 mlo_mlme_peer_assoc_resp(assoc_peer); 1023 } 1024 } 1025 1026 wlan_mlo_peer_release_ref(ml_peer); 1027 1028 return QDF_STATUS_SUCCESS; 1029 } 1030 1031 QDF_STATUS wlan_mlo_link_peer_attach(struct wlan_mlo_peer_context *ml_peer, 1032 struct wlan_objmgr_peer *peer, 1033 qdf_nbuf_t frm_buf) 1034 { 1035 QDF_STATUS status; 1036 struct wlan_objmgr_peer *assoc_peer; 1037 struct wlan_objmgr_vdev *vdev = NULL; 1038 1039 if (!ml_peer) 1040 return QDF_STATUS_E_FAILURE; 1041 1042 vdev = wlan_peer_get_vdev(peer); 1043 if (!vdev) 1044 return QDF_STATUS_E_FAILURE; 1045 1046 /* Populate Link peer pointer, peer MAC address, 1047 * MLD address. HW link ID, update ref count 1048 */ 1049 status = mlo_peer_attach_link_peer(ml_peer, peer, frm_buf); 1050 if (QDF_IS_STATUS_ERROR(status)) 1051 return status; 1052 1053 /* Store AID, MLO Peer pointer in link peer, take link peer ref count */ 1054 mlo_peer_populate_link_peer(ml_peer, peer); 1055 1056 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) { 1057 if (ml_peer->max_links == ml_peer->link_peer_cnt) { 1058 assoc_peer = ml_peer->peer_list[0].link_peer; 1059 if (assoc_peer) 1060 mlo_mlme_peer_assoc_resp(assoc_peer); 1061 } 1062 } 1063 1064 return status; 1065 } 1066 1067 QDF_STATUS wlan_mlo_link_peer_delete(struct wlan_objmgr_peer *peer) 1068 { 1069 struct wlan_mlo_peer_context *ml_peer; 1070 1071 ml_peer = peer->mlo_peer_ctx; 1072 1073 if (!ml_peer) 1074 return QDF_STATUS_E_NOENT; 1075 1076 mlo_reset_link_peer(ml_peer, peer); 1077 mlo_peer_detach_link_peer(ml_peer, peer); 1078 wlan_mlo_peer_release_ref(ml_peer); 1079 1080 return QDF_STATUS_SUCCESS; 1081 } 1082 1083 qdf_export_symbol(wlan_mlo_link_peer_delete); 1084 1085 qdf_nbuf_t mlo_peer_get_link_peer_assoc_req_buf( 1086 struct wlan_mlo_peer_context *ml_peer, 1087 uint8_t link_ix) 1088 { 1089 struct wlan_objmgr_peer *peer = NULL; 1090 qdf_nbuf_t assocbuf = NULL; 1091 1092 if (!ml_peer) 1093 return NULL; 1094 1095 peer = wlan_mlo_peer_get_assoc_peer(ml_peer); 1096 if (!peer) 1097 return NULL; 1098 1099 assocbuf = mlo_mlme_get_link_assoc_req(peer, link_ix); 1100 1101 return assocbuf; 1102 } 1103 1104 void wlan_mlo_peer_get_links_info(struct wlan_objmgr_peer *peer, 1105 struct mlo_tgt_partner_info *ml_links) 1106 { 1107 struct wlan_mlo_peer_context *ml_peer; 1108 struct wlan_mlo_link_peer_entry *peer_entry; 1109 struct wlan_objmgr_peer *link_peer; 1110 struct wlan_objmgr_vdev *link_vdev; 1111 uint8_t i, ix; 1112 1113 ml_peer = peer->mlo_peer_ctx; 1114 ml_links->num_partner_links = 0; 1115 1116 if (!ml_peer) 1117 return; 1118 1119 mlo_peer_lock_acquire(ml_peer); 1120 1121 if ((ml_peer->mlpeer_state != ML_PEER_CREATED) && 1122 (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) { 1123 mlo_peer_lock_release(ml_peer); 1124 return; 1125 } 1126 1127 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 1128 peer_entry = &ml_peer->peer_list[i]; 1129 link_peer = peer_entry->link_peer; 1130 1131 if (!link_peer) 1132 continue; 1133 if (link_peer == peer) 1134 continue; 1135 link_vdev = wlan_peer_get_vdev(link_peer); 1136 if (!link_vdev) 1137 continue; 1138 1139 if (ml_links->num_partner_links >= WLAN_UMAC_MLO_MAX_VDEVS) 1140 break; 1141 1142 ix = ml_links->num_partner_links; 1143 ml_links->link_info[ix].vdev_id = wlan_vdev_get_id(link_vdev); 1144 ml_links->link_info[ix].hw_mld_link_id = peer_entry->hw_link_id; 1145 ml_links->num_partner_links++; 1146 } 1147 mlo_peer_lock_release(ml_peer); 1148 } 1149 1150 qdf_export_symbol(wlan_mlo_peer_get_links_info); 1151 1152 uint8_t wlan_mlo_peer_get_primary_peer_link_id(struct wlan_objmgr_peer *peer) 1153 { 1154 struct wlan_mlo_peer_context *ml_peer; 1155 struct wlan_mlo_link_peer_entry *peer_entry; 1156 struct wlan_objmgr_peer *link_peer; 1157 struct wlan_objmgr_vdev *link_vdev; 1158 uint8_t i, vdev_link_id; 1159 1160 ml_peer = peer->mlo_peer_ctx; 1161 1162 if (!ml_peer) { 1163 mlo_err("ml_peer is null"); 1164 return WLAN_LINK_ID_INVALID; 1165 } 1166 mlo_peer_lock_acquire(ml_peer); 1167 1168 if ((ml_peer->mlpeer_state != ML_PEER_CREATED) && 1169 (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) { 1170 mlo_peer_lock_release(ml_peer); 1171 mlo_err("ml_peer is not created and association is not done"); 1172 return WLAN_LINK_ID_INVALID; 1173 } 1174 1175 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 1176 peer_entry = &ml_peer->peer_list[i]; 1177 link_peer = peer_entry->link_peer; 1178 if (!link_peer) 1179 continue; 1180 1181 if (peer_entry->is_primary) { 1182 link_vdev = wlan_peer_get_vdev(link_peer); 1183 if (!link_vdev) { 1184 mlo_peer_lock_release(ml_peer); 1185 mlo_err("link vdev not found"); 1186 return WLAN_LINK_ID_INVALID; 1187 } 1188 vdev_link_id = wlan_vdev_get_link_id(link_vdev); 1189 mlo_peer_lock_release(ml_peer); 1190 return vdev_link_id; 1191 } 1192 } 1193 mlo_peer_lock_release(ml_peer); 1194 mlo_err("None of the peer is designated as primary"); 1195 return WLAN_LINK_ID_INVALID; 1196 } 1197 1198 qdf_export_symbol(wlan_mlo_peer_get_primary_peer_link_id); 1199 1200 void wlan_mlo_peer_get_partner_links_info(struct wlan_objmgr_peer *peer, 1201 struct mlo_partner_info *ml_links) 1202 { 1203 struct wlan_mlo_peer_context *ml_peer; 1204 struct wlan_mlo_link_peer_entry *peer_entry; 1205 struct wlan_objmgr_peer *link_peer; 1206 struct wlan_objmgr_vdev *link_vdev; 1207 uint8_t i, ix; 1208 1209 ml_peer = peer->mlo_peer_ctx; 1210 ml_links->num_partner_links = 0; 1211 1212 if (!ml_peer) 1213 return; 1214 1215 mlo_peer_lock_acquire(ml_peer); 1216 1217 if ((ml_peer->mlpeer_state != ML_PEER_CREATED) && 1218 (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) { 1219 mlo_peer_lock_release(ml_peer); 1220 return; 1221 } 1222 1223 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 1224 peer_entry = &ml_peer->peer_list[i]; 1225 link_peer = peer_entry->link_peer; 1226 1227 if (!link_peer) 1228 continue; 1229 1230 if (link_peer == peer) 1231 continue; 1232 1233 link_vdev = wlan_peer_get_vdev(link_peer); 1234 if (!link_vdev) 1235 continue; 1236 1237 if (ml_links->num_partner_links >= WLAN_UMAC_MLO_MAX_VDEVS) 1238 break; 1239 1240 ix = ml_links->num_partner_links; 1241 ml_links->partner_link_info[ix].link_id = peer_entry->link_ix; 1242 1243 qdf_copy_macaddr(&ml_links->partner_link_info[ix].link_addr, 1244 &peer_entry->link_addr); 1245 ml_links->num_partner_links++; 1246 } 1247 mlo_peer_lock_release(ml_peer); 1248 } 1249 1250 qdf_export_symbol(wlan_mlo_peer_get_partner_links_info); 1251 1252 #ifdef UMAC_SUPPORT_MLNAWDS 1253 bool wlan_mlo_peer_is_nawds(struct wlan_mlo_peer_context *ml_peer) 1254 { 1255 bool status = false; 1256 1257 if (!ml_peer) 1258 return status; 1259 1260 mlo_peer_lock_acquire(ml_peer); 1261 if (ml_peer->is_nawds_ml_peer) 1262 status = true; 1263 mlo_peer_lock_release(ml_peer); 1264 1265 return status; 1266 } 1267 1268 qdf_export_symbol(wlan_mlo_peer_is_nawds); 1269 #endif 1270 1271 #ifdef MESH_MODE_SUPPORT 1272 bool wlan_mlo_peer_is_mesh(struct wlan_mlo_peer_context *ml_peer) 1273 { 1274 bool status = false; 1275 1276 if (!ml_peer) 1277 return status; 1278 1279 mlo_peer_lock_acquire(ml_peer); 1280 if (ml_peer->is_mesh_ml_peer) 1281 status = true; 1282 mlo_peer_lock_release(ml_peer); 1283 1284 return status; 1285 } 1286 1287 qdf_export_symbol(wlan_mlo_peer_is_mesh); 1288 #endif 1289 1290 #ifdef UMAC_MLO_AUTH_DEFER 1291 void mlo_peer_free_auth_param(struct mlpeer_auth_params *auth_params) 1292 { 1293 if (auth_params->rs) 1294 qdf_mem_free(auth_params->rs); 1295 1296 if (auth_params->wbuf) 1297 qdf_nbuf_free(auth_params->wbuf); 1298 1299 qdf_mem_free(auth_params); 1300 } 1301 1302 QDF_STATUS mlo_peer_link_auth_defer(struct wlan_mlo_peer_context *ml_peer, 1303 struct qdf_mac_addr *link_mac, 1304 struct mlpeer_auth_params *auth_params) 1305 { 1306 uint8_t i; 1307 uint8_t free_entries = 0; 1308 struct mlpeer_auth_params *recv_auth; 1309 QDF_STATUS status = QDF_STATUS_E_FAILURE; 1310 1311 if (!ml_peer) 1312 return status; 1313 1314 mlo_peer_lock_acquire(ml_peer); 1315 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 1316 recv_auth = ml_peer->pending_auth[i]; 1317 if (!recv_auth) { 1318 free_entries++; 1319 continue; 1320 } 1321 /* overwrite the entry with latest entry */ 1322 if (qdf_is_macaddr_equal(link_mac, &recv_auth->link_addr)) { 1323 mlo_peer_free_auth_param(recv_auth); 1324 ml_peer->pending_auth[i] = auth_params; 1325 mlo_peer_lock_release(ml_peer); 1326 1327 return QDF_STATUS_SUCCESS; 1328 } 1329 } 1330 1331 if (!free_entries) { 1332 mlo_peer_lock_release(ml_peer); 1333 return QDF_STATUS_E_FAILURE; 1334 } 1335 1336 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 1337 recv_auth = ml_peer->pending_auth[i]; 1338 if (!recv_auth) { 1339 ml_peer->pending_auth[i] = auth_params; 1340 status = QDF_STATUS_SUCCESS; 1341 break; 1342 } 1343 } 1344 mlo_peer_lock_release(ml_peer); 1345 1346 return status; 1347 } 1348 1349 bool wlan_mlo_partner_peer_delete_is_allowed(struct wlan_objmgr_peer *src_peer) 1350 { 1351 struct wlan_objmgr_vdev *vdev = NULL; 1352 struct wlan_mlo_peer_context *ml_peer; 1353 1354 vdev = wlan_peer_get_vdev(src_peer); 1355 if (!vdev) 1356 return false; 1357 1358 ml_peer = src_peer->mlo_peer_ctx; 1359 if (!wlan_peer_is_mlo(src_peer) || !ml_peer) 1360 return false; 1361 1362 if (wlan_vdev_mlme_op_flags_get(vdev, WLAN_VDEV_OP_MLO_STOP_LINK_DEL) || 1363 wlan_vdev_mlme_op_flags_get(vdev, 1364 WLAN_VDEV_OP_MLO_LINK_TBTT_COMPLETE)) { 1365 /* Single LINK MLO connection */ 1366 if (ml_peer->link_peer_cnt == 1) 1367 return false; 1368 /* 1369 * If this link is primary TQM, then delete MLO connection till 1370 * primary umac migration is implemented 1371 */ 1372 if (wlan_mlo_peer_get_primary_peer_link_id(src_peer) != 1373 wlan_vdev_get_link_id(vdev)) 1374 return false; 1375 } 1376 1377 return true; 1378 } 1379 #endif 1380