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