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 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 376 void wlan_mlo_peer_delete(struct wlan_mlo_peer_context *ml_peer) 377 { 378 struct wlan_mlo_dev_context *ml_dev; 379 struct wlan_objmgr_peer *link_peer; 380 struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS]; 381 struct wlan_mlo_link_peer_entry *peer_entry; 382 uint16_t i; 383 384 if (!ml_peer) 385 return; 386 387 mlo_peer_lock_acquire(ml_peer); 388 389 if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) { 390 mlo_peer_lock_release(ml_peer); 391 return; 392 } 393 394 ml_dev = ml_peer->ml_dev; 395 396 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 397 link_peers[i] = NULL; 398 peer_entry = &ml_peer->peer_list[i]; 399 if (!peer_entry->link_peer) 400 continue; 401 402 link_peer = peer_entry->link_peer; 403 404 if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) != 405 QDF_STATUS_SUCCESS) 406 continue; 407 408 link_peers[i] = link_peer; 409 } 410 411 ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED; 412 413 mlo_peer_lock_release(ml_peer); 414 415 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 416 if (!link_peers[i]) 417 continue; 418 419 mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]); 420 } 421 } 422 423 void 424 wlan_mlo_partner_peer_create_failed_notify( 425 struct wlan_mlo_peer_context *ml_peer) 426 { 427 struct wlan_mlo_dev_context *ml_dev; 428 struct wlan_objmgr_peer *link_peer; 429 struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS]; 430 struct wlan_mlo_link_peer_entry *peer_entry; 431 uint16_t i; 432 433 if (!ml_peer) 434 return; 435 436 mlo_peer_lock_acquire(ml_peer); 437 438 if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) { 439 mlo_peer_lock_release(ml_peer); 440 return; 441 } 442 443 ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED; 444 ml_dev = ml_peer->ml_dev; 445 446 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 447 link_peers[i] = NULL; 448 peer_entry = &ml_peer->peer_list[i]; 449 if (!peer_entry->link_peer) 450 continue; 451 452 link_peer = peer_entry->link_peer; 453 if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) != 454 QDF_STATUS_SUCCESS) 455 continue; 456 457 link_peers[i] = link_peer; 458 } 459 mlo_peer_lock_release(ml_peer); 460 461 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 462 if (!link_peers[i]) 463 continue; 464 465 /* Prepare and queue message */ 466 if (i == 0) 467 mlo_link_peer_send_assoc_fail(ml_dev, link_peers[i]); 468 else 469 mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]); 470 } 471 } 472 473 void wlan_mlo_partner_peer_disconnect_notify(struct wlan_objmgr_peer *src_peer) 474 { 475 struct wlan_mlo_dev_context *ml_dev; 476 struct wlan_mlo_peer_context *ml_peer; 477 struct wlan_objmgr_peer *link_peer; 478 struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS]; 479 struct wlan_mlo_link_peer_entry *peer_entry; 480 struct wlan_objmgr_vdev *vdev = NULL; 481 uint16_t i; 482 483 ml_peer = src_peer->mlo_peer_ctx; 484 if (!ml_peer) 485 return; 486 487 vdev = wlan_peer_get_vdev(src_peer); 488 if (!vdev) 489 return; 490 491 mlo_peer_lock_acquire(ml_peer); 492 493 if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) { 494 mlo_peer_lock_release(ml_peer); 495 return; 496 } 497 498 ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED; 499 500 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) { 501 mlo_peer_lock_release(ml_peer); 502 return; 503 } 504 505 ml_dev = ml_peer->ml_dev; 506 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 507 link_peers[i] = NULL; 508 peer_entry = &ml_peer->peer_list[i]; 509 if (!peer_entry->link_peer) { 510 mlo_debug("link peer is null"); 511 continue; 512 } 513 514 if (peer_entry->link_peer == src_peer) 515 continue; 516 517 link_peer = peer_entry->link_peer; 518 if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) != 519 QDF_STATUS_SUCCESS) 520 continue; 521 522 link_peers[i] = link_peer; 523 } 524 mlo_peer_lock_release(ml_peer); 525 526 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 527 if (!link_peers[i]) 528 continue; 529 530 /* Prepare and queue message */ 531 mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]); 532 } 533 } 534 535 static void mlo_peer_populate_link_peer( 536 struct wlan_mlo_peer_context *ml_peer, 537 struct wlan_objmgr_peer *link_peer) 538 { 539 mlo_peer_lock_acquire(ml_peer); 540 wlan_mlo_peer_get_ref(ml_peer); 541 link_peer->mlo_peer_ctx = ml_peer; 542 mlo_peer_lock_release(ml_peer); 543 } 544 545 static void mlo_reset_link_peer( 546 struct wlan_mlo_peer_context *ml_peer, 547 struct wlan_objmgr_peer *link_peer) 548 { 549 mlo_peer_lock_acquire(ml_peer); 550 link_peer->mlo_peer_ctx = NULL; 551 wlan_peer_clear_mlo(link_peer); 552 mlo_peer_lock_release(ml_peer); 553 } 554 555 static void mlo_peer_free(struct wlan_mlo_peer_context *ml_peer) 556 { 557 struct wlan_mlo_dev_context *ml_dev; 558 559 ml_dev = ml_peer->ml_dev; 560 if (!ml_dev) { 561 mlo_err("ML DEV is NULL"); 562 return; 563 } 564 565 mlo_debug("ML Peer " QDF_MAC_ADDR_FMT " is freed", 566 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes)); 567 mlo_peer_lock_destroy(ml_peer); 568 mlo_ap_ml_peerid_free(ml_peer->mlo_peer_id); 569 mlo_peer_free_aid(ml_dev, ml_peer); 570 mlo_peer_free_primary_umac(ml_dev, ml_peer); 571 qdf_mem_free(ml_peer); 572 } 573 574 void mlo_peer_cleanup(struct wlan_mlo_peer_context *ml_peer) 575 { 576 struct wlan_mlo_dev_context *ml_dev; 577 578 if (!ml_peer) { 579 mlo_err("ML PEER is NULL"); 580 return; 581 } 582 ml_dev = ml_peer->ml_dev; 583 if (!ml_dev) { 584 mlo_err("ML DEV is NULL"); 585 return; 586 } 587 588 mlo_dev_mlpeer_detach(ml_dev, ml_peer); 589 /* If any Auth req is received during ML peer delete */ 590 mlo_peer_process_pending_auth(ml_dev, ml_peer); 591 mlo_peer_free(ml_peer); 592 } 593 594 static QDF_STATUS mlo_peer_attach_link_peer( 595 struct wlan_mlo_peer_context *ml_peer, 596 struct wlan_objmgr_peer *link_peer, 597 qdf_nbuf_t frm_buf) 598 { 599 struct wlan_mlo_link_peer_entry *peer_entry; 600 QDF_STATUS status = QDF_STATUS_E_RESOURCES; 601 struct wlan_objmgr_pdev *pdev; 602 struct wlan_objmgr_vdev *vdev; 603 uint16_t i; 604 605 if (!link_peer) 606 return QDF_STATUS_E_FAILURE; 607 608 vdev = wlan_peer_get_vdev(link_peer); 609 if (!vdev) 610 return QDF_STATUS_E_FAILURE; 611 612 mlo_peer_lock_acquire(ml_peer); 613 614 if (ml_peer->mlpeer_state != ML_PEER_CREATED) { 615 mlo_peer_lock_release(ml_peer); 616 mlo_err("ML Peer " QDF_MAC_ADDR_FMT " is not in created state (state %d)", 617 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 618 ml_peer->mlpeer_state); 619 return status; 620 } 621 622 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 623 peer_entry = &ml_peer->peer_list[i]; 624 if (peer_entry->link_peer) 625 continue; 626 627 if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) != 628 QDF_STATUS_SUCCESS) { 629 mlo_err("ML Peer " QDF_MAC_ADDR_FMT ", link peer " QDF_MAC_ADDR_FMT " is not in valid state", 630 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 631 QDF_MAC_ADDR_REF 632 (wlan_peer_get_macaddr(link_peer))); 633 break; 634 } 635 peer_entry->link_peer = link_peer; 636 qdf_copy_macaddr(&peer_entry->link_addr, 637 (struct qdf_mac_addr *)&link_peer->macaddr[0]); 638 639 peer_entry->link_ix = wlan_vdev_get_link_id(vdev); 640 pdev = wlan_vdev_get_pdev(wlan_peer_get_vdev(link_peer)); 641 peer_entry->hw_link_id = wlan_mlo_get_pdev_hw_link_id(pdev); 642 mlo_peer_assign_primary_umac(ml_peer, peer_entry); 643 if (frm_buf) 644 peer_entry->assoc_rsp_buf = frm_buf; 645 else 646 peer_entry->assoc_rsp_buf = NULL; 647 648 status = QDF_STATUS_SUCCESS; 649 break; 650 } 651 if (QDF_IS_STATUS_SUCCESS(status)) 652 ml_peer->link_peer_cnt++; 653 654 mlo_peer_lock_release(ml_peer); 655 656 return status; 657 } 658 659 qdf_nbuf_t mlo_peer_get_link_peer_assoc_resp_buf( 660 struct wlan_mlo_peer_context *ml_peer, 661 uint8_t link_ix) 662 { 663 struct wlan_mlo_link_peer_entry *peer_entry; 664 qdf_nbuf_t frm_buf = NULL; 665 uint8_t i; 666 667 if (!ml_peer) 668 return NULL; 669 670 if (link_ix > MAX_MLO_LINK_PEERS) 671 return NULL; 672 673 mlo_peer_lock_acquire(ml_peer); 674 if ((ml_peer->mlpeer_state != ML_PEER_CREATED) && 675 (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) { 676 mlo_peer_lock_release(ml_peer); 677 return NULL; 678 } 679 680 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 681 peer_entry = &ml_peer->peer_list[i]; 682 683 if (!peer_entry->link_peer) 684 continue; 685 686 if (peer_entry->link_ix == link_ix) { 687 if (!peer_entry->assoc_rsp_buf) 688 break; 689 690 frm_buf = qdf_nbuf_clone(peer_entry->assoc_rsp_buf); 691 break; 692 } 693 } 694 mlo_peer_lock_release(ml_peer); 695 696 return frm_buf; 697 } 698 699 void wlan_mlo_peer_free_all_link_assoc_resp_buf( 700 struct wlan_objmgr_peer *link_peer) 701 { 702 struct wlan_mlo_link_peer_entry *peer_entry; 703 struct wlan_mlo_peer_context *ml_peer; 704 uint8_t i; 705 706 ml_peer = link_peer->mlo_peer_ctx; 707 if (!ml_peer) 708 return; 709 710 mlo_peer_lock_acquire(ml_peer); 711 712 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 713 peer_entry = &ml_peer->peer_list[i]; 714 715 if (peer_entry->assoc_rsp_buf) { 716 qdf_nbuf_free(peer_entry->assoc_rsp_buf); 717 peer_entry->assoc_rsp_buf = NULL; 718 } 719 } 720 mlo_peer_lock_release(ml_peer); 721 } 722 723 static QDF_STATUS mlo_peer_detach_link_peer( 724 struct wlan_mlo_peer_context *ml_peer, 725 struct wlan_objmgr_peer *link_peer) 726 { 727 struct wlan_mlo_link_peer_entry *peer_entry; 728 QDF_STATUS status = QDF_STATUS_E_RESOURCES; 729 uint16_t i; 730 731 mlo_peer_lock_acquire(ml_peer); 732 733 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 734 peer_entry = &ml_peer->peer_list[i]; 735 if (!peer_entry->link_peer) 736 continue; 737 738 if (peer_entry->link_peer != link_peer) 739 continue; 740 741 if (peer_entry->assoc_rsp_buf) { 742 qdf_nbuf_free(peer_entry->assoc_rsp_buf); 743 peer_entry->assoc_rsp_buf = NULL; 744 } 745 746 wlan_objmgr_peer_release_ref(link_peer, WLAN_MLO_MGR_ID); 747 peer_entry->link_peer = NULL; 748 ml_peer->link_peer_cnt--; 749 status = QDF_STATUS_SUCCESS; 750 break; 751 } 752 mlo_peer_lock_release(ml_peer); 753 754 return status; 755 } 756 757 static QDF_STATUS mlo_dev_get_link_vdevs( 758 struct wlan_objmgr_vdev *vdev, 759 struct wlan_mlo_dev_context *ml_dev, 760 struct mlo_partner_info *ml_info, 761 struct wlan_objmgr_vdev *link_vdevs[]) 762 { 763 uint16_t i, j; 764 struct wlan_objmgr_vdev *vdev_link; 765 uint8_t link_id; 766 767 if (!ml_dev) { 768 mlo_err("ml_dev is null"); 769 return QDF_STATUS_E_INVAL; 770 } 771 772 if (!ml_info) { 773 mlo_err("ml_info is null"); 774 return QDF_STATUS_E_INVAL; 775 } 776 777 mlo_debug("num_partner_links %d", ml_info->num_partner_links); 778 for (i = 0; i < ml_info->num_partner_links; i++) { 779 link_id = ml_info->partner_link_info[i].link_id; 780 vdev_link = mlo_get_vdev_by_link_id(vdev, link_id); 781 if (vdev_link) { 782 link_vdevs[i] = vdev_link; 783 } else { 784 /* release ref which were taken before failure */ 785 for (j = 0; j < i; j++) { 786 vdev_link = link_vdevs[j]; 787 if (!vdev_link) 788 continue; 789 790 wlan_objmgr_vdev_release_ref(vdev_link, 791 WLAN_MLO_MGR_ID); 792 } 793 return QDF_STATUS_E_INVAL; 794 } 795 } 796 797 return QDF_STATUS_SUCCESS; 798 } 799 800 static void mlo_dev_release_link_vdevs( 801 struct wlan_objmgr_vdev *link_vdevs[]) 802 { 803 uint16_t i; 804 struct wlan_objmgr_vdev *vdev_link; 805 806 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 807 vdev_link = link_vdevs[i]; 808 if (!vdev_link) 809 continue; 810 811 wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID); 812 } 813 } 814 815 #ifdef WLAN_FEATURE_11BE 816 static void 817 wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context *ml_peer, 818 struct mlo_partner_info *ml_info) 819 { 820 ml_peer->t2lm_policy.t2lm_enable_val = ml_info->t2lm_enable_val; 821 } 822 #else 823 static void 824 wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context *ml_peer, 825 struct mlo_partner_info *ml_info) 826 {} 827 #endif /* WLAN_FEATURE_11BE */ 828 829 QDF_STATUS wlan_mlo_peer_create(struct wlan_objmgr_vdev *vdev, 830 struct wlan_objmgr_peer *link_peer, 831 struct mlo_partner_info *ml_info, 832 qdf_nbuf_t frm_buf, 833 uint16_t aid) 834 { 835 struct wlan_mlo_dev_context *ml_dev; 836 struct wlan_mlo_peer_context *ml_peer = NULL; 837 struct wlan_objmgr_vdev *link_vdevs[WLAN_UMAC_MLO_MAX_VDEVS] = { NULL }; 838 struct wlan_objmgr_vdev *vdev_link; 839 QDF_STATUS status; 840 uint16_t i; 841 struct wlan_objmgr_peer *assoc_peer; 842 bool is_ml_peer_attached = false; 843 844 /* get ML VDEV from VDEV */ 845 ml_dev = vdev->mlo_dev_ctx; 846 847 if (!ml_dev) { 848 mlo_err("ML dev ctx is NULL"); 849 return QDF_STATUS_E_NULL_VALUE; 850 } 851 852 /* Check resources of Partner VDEV */ 853 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) { 854 if (wlan_mlo_is_mld_ctx_exist( 855 (struct qdf_mac_addr *)&link_peer->mldaddr[0])) { 856 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " is matching with one of the MLD address in the system", 857 ml_dev->mld_id, 858 QDF_MAC_ADDR_REF(link_peer->mldaddr)); 859 return QDF_STATUS_E_FAILURE; 860 } 861 status = mlo_dev_get_link_vdevs(vdev, ml_dev, 862 ml_info, link_vdevs); 863 if (QDF_IS_STATUS_ERROR(status)) { 864 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " get link vdevs failed", 865 ml_dev->mld_id, 866 QDF_MAC_ADDR_REF(link_peer->mldaddr)); 867 return QDF_STATUS_E_FAILURE; 868 } 869 870 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 871 vdev_link = link_vdevs[i]; 872 if (!vdev_link) { 873 mlo_debug("vdev_link is null"); 874 continue; 875 } 876 877 if (wlan_vdev_is_mlo_peer_create_allowed(vdev_link) 878 != QDF_STATUS_SUCCESS) { 879 mlo_dev_release_link_vdevs(link_vdevs); 880 881 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " create not allowed on link vdev %d", 882 ml_dev->mld_id, 883 QDF_MAC_ADDR_REF 884 (link_peer->mldaddr), 885 wlan_vdev_get_id(vdev_link)); 886 return QDF_STATUS_E_INVAL; 887 } 888 } 889 890 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 891 vdev_link = link_vdevs[i]; 892 if (vdev_link && (vdev_link != vdev) && 893 (wlan_vdev_get_peer_count(vdev_link) > 894 wlan_vdev_get_max_peer_count(vdev_link))) { 895 mlo_dev_release_link_vdevs(link_vdevs); 896 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " Max peer count reached on link vdev %d", 897 ml_dev->mld_id, 898 QDF_MAC_ADDR_REF 899 (link_peer->mldaddr), 900 wlan_vdev_get_id(vdev_link)); 901 return QDF_STATUS_E_RESOURCES; 902 } 903 } 904 } 905 /* When roam to MLO AP, partner link vdev1 is updated first, 906 * ml peer need be created and attached for partner link peer. 907 * 908 * When roam target AP and current AP have same MLD address, don't 909 * delete old ML peer and re-create new one, just update different 910 * info. 911 */ 912 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) { 913 ml_peer = wlan_mlo_get_mlpeer(ml_dev, 914 (struct qdf_mac_addr *)&link_peer->mldaddr[0]); 915 if (ml_peer) { 916 mlo_debug("ML Peer " QDF_MAC_ADDR_FMT 917 " existed, state %d", 918 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 919 ml_peer->mlpeer_state); 920 ml_peer->mlpeer_state = ML_PEER_CREATED; 921 ml_peer->max_links = ml_info->num_partner_links; 922 wlan_mlo_peer_set_t2lm_enable_val(ml_peer, ml_info); 923 is_ml_peer_attached = true; 924 } 925 } 926 if (!ml_peer) { 927 /* Allocate MLO peer */ 928 ml_peer = qdf_mem_malloc(sizeof(*ml_peer)); 929 if (!ml_peer) { 930 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " mem alloc failed", 931 ml_dev->mld_id, 932 QDF_MAC_ADDR_REF(link_peer->mldaddr)); 933 mlo_dev_release_link_vdevs(link_vdevs); 934 return QDF_STATUS_E_NOMEM; 935 } 936 937 qdf_atomic_init(&ml_peer->ref_cnt); 938 mlo_peer_lock_create(ml_peer); 939 ml_peer->ml_dev = ml_dev; 940 ml_peer->mlpeer_state = ML_PEER_CREATED; 941 ml_peer->max_links = ml_info->num_partner_links; 942 ml_peer->primary_umac_psoc_id = ML_PRIMARY_UMAC_ID_INVAL; 943 944 ml_peer->mlo_peer_id = mlo_ap_ml_peerid_alloc(); 945 if (ml_peer->mlo_peer_id == MLO_INVALID_PEER_ID) { 946 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " invalid ml peer id", 947 ml_dev->mld_id, 948 QDF_MAC_ADDR_REF 949 (ml_peer->peer_mld_addr.bytes)); 950 mlo_peer_free(ml_peer); 951 mlo_dev_release_link_vdevs(link_vdevs); 952 return QDF_STATUS_E_RESOURCES; 953 } 954 955 qdf_copy_macaddr((struct qdf_mac_addr *)&ml_peer->peer_mld_addr, 956 (struct qdf_mac_addr *)&link_peer->mldaddr[0]); 957 wlan_mlo_peer_set_t2lm_enable_val(ml_peer, ml_info); 958 959 /* Allocate AID */ 960 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) { 961 if (aid == (uint16_t)-1) { 962 status = mlo_peer_allocate_aid(ml_dev, ml_peer); 963 if (status != QDF_STATUS_SUCCESS) { 964 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " aid alloc failed", 965 ml_dev->mld_id, 966 QDF_MAC_ADDR_REF 967 (ml_peer->peer_mld_addr.bytes)); 968 mlo_peer_free(ml_peer); 969 mlo_dev_release_link_vdevs(link_vdevs); 970 return status; 971 } 972 } else { 973 ml_peer->assoc_id = aid; 974 } 975 } 976 } 977 978 /* Populate Link peer pointer, peer MAC address, 979 * MLD address. HW link ID, update ref count 980 */ 981 status = mlo_peer_attach_link_peer(ml_peer, link_peer, NULL); 982 if (QDF_IS_STATUS_ERROR(status)) { 983 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " link peer attach failed", 984 ml_dev->mld_id, 985 QDF_MAC_ADDR_REF 986 (ml_peer->peer_mld_addr.bytes)); 987 /* If there is another link peer attached for this ML peer, 988 * ml peer can't be detached and freed. 989 */ 990 if (is_ml_peer_attached && ml_peer->link_peer_cnt) 991 return status; 992 if (is_ml_peer_attached) 993 mlo_dev_mlpeer_detach(ml_dev, ml_peer); 994 mlo_peer_free(ml_peer); 995 mlo_dev_release_link_vdevs(link_vdevs); 996 return status; 997 } 998 999 /* Allocate Primary UMAC */ 1000 mlo_peer_allocate_primary_umac(ml_dev, ml_peer, link_vdevs); 1001 1002 /* Store AID, MLO Peer pointer in link peer, take link peer ref count */ 1003 mlo_peer_populate_link_peer(ml_peer, link_peer); 1004 1005 mlo_peer_populate_nawds_params(ml_peer, ml_info); 1006 mlo_peer_populate_mesh_params(ml_peer, ml_info); 1007 1008 if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) || 1009 ((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) && 1010 !is_ml_peer_attached)) { 1011 /* Attach MLO peer to ML Peer table */ 1012 status = mlo_dev_mlpeer_attach(ml_dev, ml_peer); 1013 if (status != QDF_STATUS_SUCCESS) { 1014 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " attach failed", 1015 ml_dev->mld_id, 1016 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes)); 1017 mlo_reset_link_peer(ml_peer, link_peer); 1018 wlan_objmgr_peer_release_ref(link_peer, 1019 WLAN_MLO_MGR_ID); 1020 mlo_peer_free(ml_peer); 1021 mlo_dev_release_link_vdevs(link_vdevs); 1022 return status; 1023 } 1024 } 1025 1026 wlan_mlo_peer_get_ref(ml_peer); 1027 1028 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) { 1029 /* Notify other vdevs about link peer creation */ 1030 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 1031 vdev_link = link_vdevs[i]; 1032 if (!vdev_link) 1033 continue; 1034 1035 if (vdev_link == vdev) 1036 continue; 1037 1038 mlo_partner_peer_create_post(ml_dev, vdev_link, 1039 ml_peer, frm_buf, ml_info); 1040 } 1041 } 1042 mlo_dev_release_link_vdevs(link_vdevs); 1043 1044 if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) { 1045 mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " allocation failed", 1046 ml_dev->mld_id, 1047 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes)); 1048 wlan_mlo_peer_release_ref(ml_peer); 1049 return QDF_STATUS_E_FAILURE; 1050 } 1051 1052 mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " allocated %pK", 1053 ml_dev->mld_id, 1054 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 1055 ml_peer); 1056 1057 /* 1058 * wlan_mlo_peer_create() is trigggered after getting peer 1059 * assoc confirm from FW. For single link MLO connection, it is 1060 * OK to trigger assoc response from here. 1061 */ 1062 if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) && 1063 (!wlan_mlo_peer_is_nawds(ml_peer))) { 1064 if (ml_peer->max_links == ml_peer->link_peer_cnt) { 1065 assoc_peer = ml_peer->peer_list[0].link_peer; 1066 if (assoc_peer) 1067 mlo_mlme_peer_assoc_resp(assoc_peer); 1068 } 1069 } 1070 1071 wlan_mlo_peer_release_ref(ml_peer); 1072 1073 return QDF_STATUS_SUCCESS; 1074 } 1075 1076 QDF_STATUS wlan_mlo_link_peer_attach(struct wlan_mlo_peer_context *ml_peer, 1077 struct wlan_objmgr_peer *peer, 1078 qdf_nbuf_t frm_buf) 1079 { 1080 QDF_STATUS status; 1081 struct wlan_objmgr_peer *assoc_peer; 1082 struct wlan_objmgr_vdev *vdev = NULL; 1083 1084 if (!ml_peer) 1085 return QDF_STATUS_E_FAILURE; 1086 1087 vdev = wlan_peer_get_vdev(peer); 1088 if (!vdev) 1089 return QDF_STATUS_E_FAILURE; 1090 1091 /* Populate Link peer pointer, peer MAC address, 1092 * MLD address. HW link ID, update ref count 1093 */ 1094 status = mlo_peer_attach_link_peer(ml_peer, peer, frm_buf); 1095 if (QDF_IS_STATUS_ERROR(status)) 1096 return status; 1097 1098 /* Store AID, MLO Peer pointer in link peer, take link peer ref count */ 1099 mlo_peer_populate_link_peer(ml_peer, peer); 1100 1101 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) { 1102 if (ml_peer->max_links == ml_peer->link_peer_cnt) { 1103 assoc_peer = ml_peer->peer_list[0].link_peer; 1104 if (assoc_peer) 1105 mlo_mlme_peer_assoc_resp(assoc_peer); 1106 } 1107 } 1108 1109 return status; 1110 } 1111 1112 QDF_STATUS wlan_mlo_link_peer_delete(struct wlan_objmgr_peer *peer) 1113 { 1114 struct wlan_mlo_peer_context *ml_peer; 1115 1116 ml_peer = peer->mlo_peer_ctx; 1117 1118 if (!ml_peer) 1119 return QDF_STATUS_E_NOENT; 1120 1121 mlo_reset_link_peer(ml_peer, peer); 1122 mlo_peer_detach_link_peer(ml_peer, peer); 1123 wlan_mlo_peer_release_ref(ml_peer); 1124 1125 return QDF_STATUS_SUCCESS; 1126 } 1127 1128 qdf_export_symbol(wlan_mlo_link_peer_delete); 1129 1130 qdf_nbuf_t mlo_peer_get_link_peer_assoc_req_buf( 1131 struct wlan_mlo_peer_context *ml_peer, 1132 uint8_t link_ix) 1133 { 1134 struct wlan_objmgr_peer *peer = NULL; 1135 qdf_nbuf_t assocbuf = NULL; 1136 1137 if (!ml_peer) 1138 return NULL; 1139 1140 peer = wlan_mlo_peer_get_assoc_peer(ml_peer); 1141 if (!peer) 1142 return NULL; 1143 1144 assocbuf = mlo_mlme_get_link_assoc_req(peer, link_ix); 1145 1146 return assocbuf; 1147 } 1148 1149 void wlan_mlo_peer_get_links_info(struct wlan_objmgr_peer *peer, 1150 struct mlo_tgt_partner_info *ml_links) 1151 { 1152 struct wlan_mlo_peer_context *ml_peer; 1153 struct wlan_mlo_link_peer_entry *peer_entry; 1154 struct wlan_objmgr_peer *link_peer; 1155 struct wlan_objmgr_vdev *link_vdev; 1156 uint8_t i, ix; 1157 1158 ml_peer = peer->mlo_peer_ctx; 1159 ml_links->num_partner_links = 0; 1160 1161 if (!ml_peer) 1162 return; 1163 1164 mlo_peer_lock_acquire(ml_peer); 1165 1166 if ((ml_peer->mlpeer_state != ML_PEER_CREATED) && 1167 (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) { 1168 mlo_peer_lock_release(ml_peer); 1169 return; 1170 } 1171 1172 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 1173 peer_entry = &ml_peer->peer_list[i]; 1174 link_peer = peer_entry->link_peer; 1175 1176 if (!link_peer) 1177 continue; 1178 if (link_peer == peer) 1179 continue; 1180 link_vdev = wlan_peer_get_vdev(link_peer); 1181 if (!link_vdev) 1182 continue; 1183 1184 if (ml_links->num_partner_links >= WLAN_UMAC_MLO_MAX_VDEVS) 1185 break; 1186 1187 ix = ml_links->num_partner_links; 1188 ml_links->link_info[ix].vdev_id = wlan_vdev_get_id(link_vdev); 1189 ml_links->link_info[ix].hw_mld_link_id = peer_entry->hw_link_id; 1190 ml_links->num_partner_links++; 1191 } 1192 mlo_peer_lock_release(ml_peer); 1193 } 1194 1195 qdf_export_symbol(wlan_mlo_peer_get_links_info); 1196 1197 uint8_t wlan_mlo_peer_get_primary_peer_link_id(struct wlan_objmgr_peer *peer) 1198 { 1199 struct wlan_mlo_peer_context *ml_peer; 1200 struct wlan_mlo_link_peer_entry *peer_entry; 1201 struct wlan_objmgr_peer *link_peer; 1202 struct wlan_objmgr_vdev *link_vdev; 1203 uint8_t i, vdev_link_id; 1204 1205 ml_peer = peer->mlo_peer_ctx; 1206 1207 if (!ml_peer) { 1208 mlo_err("ml_peer is null"); 1209 return WLAN_LINK_ID_INVALID; 1210 } 1211 mlo_peer_lock_acquire(ml_peer); 1212 1213 if ((ml_peer->mlpeer_state != ML_PEER_CREATED) && 1214 (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) { 1215 mlo_peer_lock_release(ml_peer); 1216 mlo_err("ml_peer is not created and association is not done"); 1217 return WLAN_LINK_ID_INVALID; 1218 } 1219 1220 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 1221 peer_entry = &ml_peer->peer_list[i]; 1222 link_peer = peer_entry->link_peer; 1223 if (!link_peer) 1224 continue; 1225 1226 if (peer_entry->is_primary) { 1227 link_vdev = wlan_peer_get_vdev(link_peer); 1228 if (!link_vdev) { 1229 mlo_peer_lock_release(ml_peer); 1230 mlo_err("link vdev not found"); 1231 return WLAN_LINK_ID_INVALID; 1232 } 1233 vdev_link_id = wlan_vdev_get_link_id(link_vdev); 1234 mlo_peer_lock_release(ml_peer); 1235 return vdev_link_id; 1236 } 1237 } 1238 mlo_peer_lock_release(ml_peer); 1239 mlo_err("None of the peer is designated as primary"); 1240 return WLAN_LINK_ID_INVALID; 1241 } 1242 1243 qdf_export_symbol(wlan_mlo_peer_get_primary_peer_link_id); 1244 1245 void wlan_mlo_peer_get_partner_links_info(struct wlan_objmgr_peer *peer, 1246 struct mlo_partner_info *ml_links) 1247 { 1248 struct wlan_mlo_peer_context *ml_peer; 1249 struct wlan_mlo_link_peer_entry *peer_entry; 1250 struct wlan_objmgr_peer *link_peer; 1251 struct wlan_objmgr_vdev *link_vdev; 1252 uint8_t i, ix; 1253 1254 ml_peer = peer->mlo_peer_ctx; 1255 ml_links->num_partner_links = 0; 1256 1257 if (!ml_peer) 1258 return; 1259 1260 mlo_peer_lock_acquire(ml_peer); 1261 1262 if ((ml_peer->mlpeer_state != ML_PEER_CREATED) && 1263 (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) { 1264 mlo_peer_lock_release(ml_peer); 1265 return; 1266 } 1267 1268 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 1269 peer_entry = &ml_peer->peer_list[i]; 1270 link_peer = peer_entry->link_peer; 1271 1272 if (!link_peer) 1273 continue; 1274 1275 if (link_peer == peer) 1276 continue; 1277 1278 link_vdev = wlan_peer_get_vdev(link_peer); 1279 if (!link_vdev) 1280 continue; 1281 1282 if (ml_links->num_partner_links >= WLAN_UMAC_MLO_MAX_VDEVS) 1283 break; 1284 1285 ix = ml_links->num_partner_links; 1286 ml_links->partner_link_info[ix].link_id = peer_entry->link_ix; 1287 1288 qdf_copy_macaddr(&ml_links->partner_link_info[ix].link_addr, 1289 &peer_entry->link_addr); 1290 ml_links->num_partner_links++; 1291 } 1292 mlo_peer_lock_release(ml_peer); 1293 } 1294 1295 qdf_export_symbol(wlan_mlo_peer_get_partner_links_info); 1296 1297 #ifdef UMAC_SUPPORT_MLNAWDS 1298 bool wlan_mlo_peer_is_nawds(struct wlan_mlo_peer_context *ml_peer) 1299 { 1300 bool status = false; 1301 1302 if (!ml_peer) 1303 return status; 1304 1305 mlo_peer_lock_acquire(ml_peer); 1306 if (ml_peer->is_nawds_ml_peer) 1307 status = true; 1308 mlo_peer_lock_release(ml_peer); 1309 1310 return status; 1311 } 1312 1313 qdf_export_symbol(wlan_mlo_peer_is_nawds); 1314 #endif 1315 1316 #ifdef MESH_MODE_SUPPORT 1317 bool wlan_mlo_peer_is_mesh(struct wlan_mlo_peer_context *ml_peer) 1318 { 1319 bool status = false; 1320 1321 if (!ml_peer) 1322 return status; 1323 1324 mlo_peer_lock_acquire(ml_peer); 1325 if (ml_peer->is_mesh_ml_peer) 1326 status = true; 1327 mlo_peer_lock_release(ml_peer); 1328 1329 return status; 1330 } 1331 1332 qdf_export_symbol(wlan_mlo_peer_is_mesh); 1333 #endif 1334 1335 #ifdef UMAC_MLO_AUTH_DEFER 1336 void mlo_peer_free_auth_param(struct mlpeer_auth_params *auth_params) 1337 { 1338 if (auth_params->rs) 1339 qdf_mem_free(auth_params->rs); 1340 1341 if (auth_params->wbuf) 1342 qdf_nbuf_free(auth_params->wbuf); 1343 1344 qdf_mem_free(auth_params); 1345 } 1346 1347 QDF_STATUS mlo_peer_link_auth_defer(struct wlan_mlo_peer_context *ml_peer, 1348 struct qdf_mac_addr *link_mac, 1349 struct mlpeer_auth_params *auth_params) 1350 { 1351 uint8_t i; 1352 uint8_t free_entries = 0; 1353 struct mlpeer_auth_params *recv_auth; 1354 QDF_STATUS status = QDF_STATUS_E_FAILURE; 1355 1356 if (!ml_peer) 1357 return status; 1358 1359 mlo_peer_lock_acquire(ml_peer); 1360 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 1361 recv_auth = ml_peer->pending_auth[i]; 1362 if (!recv_auth) { 1363 free_entries++; 1364 continue; 1365 } 1366 /* overwrite the entry with latest entry */ 1367 if (qdf_is_macaddr_equal(link_mac, &recv_auth->link_addr)) { 1368 mlo_peer_free_auth_param(recv_auth); 1369 ml_peer->pending_auth[i] = auth_params; 1370 mlo_peer_lock_release(ml_peer); 1371 1372 return QDF_STATUS_SUCCESS; 1373 } 1374 } 1375 1376 if (!free_entries) { 1377 mlo_peer_lock_release(ml_peer); 1378 return QDF_STATUS_E_FAILURE; 1379 } 1380 1381 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 1382 recv_auth = ml_peer->pending_auth[i]; 1383 if (!recv_auth) { 1384 ml_peer->pending_auth[i] = auth_params; 1385 status = QDF_STATUS_SUCCESS; 1386 break; 1387 } 1388 } 1389 mlo_peer_lock_release(ml_peer); 1390 1391 return status; 1392 } 1393 1394 bool wlan_mlo_partner_peer_delete_is_allowed(struct wlan_objmgr_peer *src_peer) 1395 { 1396 struct wlan_objmgr_vdev *vdev = NULL; 1397 struct wlan_mlo_peer_context *ml_peer; 1398 1399 vdev = wlan_peer_get_vdev(src_peer); 1400 if (!vdev) 1401 return false; 1402 1403 ml_peer = src_peer->mlo_peer_ctx; 1404 if (!wlan_peer_is_mlo(src_peer) || !ml_peer) 1405 return false; 1406 1407 if (wlan_vdev_mlme_op_flags_get(vdev, WLAN_VDEV_OP_MLO_STOP_LINK_DEL) || 1408 wlan_vdev_mlme_op_flags_get(vdev, 1409 WLAN_VDEV_OP_MLO_LINK_TBTT_COMPLETE)) { 1410 /* Single LINK MLO connection */ 1411 if (ml_peer->link_peer_cnt == 1) 1412 return false; 1413 /* 1414 * If this link is primary TQM, then delete MLO connection till 1415 * primary umac migration is implemented 1416 */ 1417 if (wlan_mlo_peer_get_primary_peer_link_id(src_peer) != 1418 wlan_vdev_get_link_id(vdev)) 1419 return false; 1420 } 1421 1422 return true; 1423 } 1424 #endif 1425