1 /* 2 * Copyright (c) 2021, The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include "wlan_mlo_mgr_main.h" 19 #include "qdf_module.h" 20 #include "qdf_types.h" 21 #include "wlan_cmn.h" 22 #include "wlan_mlo_mgr_msgq.h" 23 #include "wlan_objmgr_peer_obj.h" 24 #include "wlan_mlo_mgr_peer.h" 25 #include "wlan_mlo_mgr_ap.h" 26 #include "wlan_crypto_global_api.h" 27 #include "wlan_mlo_mgr_setup.h" 28 #include "wlan_utility.h" 29 30 static void mlo_partner_peer_create_post(struct wlan_mlo_dev_context *ml_dev, 31 struct wlan_objmgr_vdev *vdev_link, 32 struct wlan_mlo_peer_context *ml_peer, 33 qdf_nbuf_t frm_buf, 34 struct mlo_partner_info *ml_info) 35 { 36 struct peer_create_notif_s peer_create; 37 QDF_STATUS status; 38 uint8_t i; 39 uint8_t link_id; 40 41 if (wlan_objmgr_vdev_try_get_ref(vdev_link, WLAN_MLO_MGR_ID) == 42 QDF_STATUS_SUCCESS) { 43 peer_create.vdev_link = vdev_link; 44 } else { 45 mlo_err("VDEV is not in created state"); 46 return; 47 } 48 49 wlan_mlo_peer_get_ref(ml_peer); 50 peer_create.ml_peer = ml_peer; 51 link_id = wlan_vdev_get_link_id(vdev_link); 52 for (i = 0; i < ml_info->num_partner_links; i++) { 53 if (link_id != ml_info->partner_link_info[i].link_id) 54 continue; 55 56 qdf_copy_macaddr(&peer_create.addr, 57 &ml_info->partner_link_info[i].link_addr); 58 break; 59 } 60 61 status = mlo_peer_create_get_frm_buf(ml_peer, &peer_create, frm_buf); 62 63 if (QDF_IS_STATUS_ERROR(status)) { 64 wlan_mlo_peer_release_ref(ml_peer); 65 wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID); 66 mlo_err("nbuf clone is failed"); 67 return; 68 } 69 70 status = mlo_msgq_post(MLO_PEER_CREATE, ml_dev, &peer_create); 71 if (status != QDF_STATUS_SUCCESS) { 72 qdf_nbuf_free(frm_buf); 73 wlan_mlo_peer_release_ref(ml_peer); 74 wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID); 75 } 76 } 77 78 static void mlo_link_peer_assoc_notify(struct wlan_mlo_dev_context *ml_dev, 79 struct wlan_objmgr_peer *peer) 80 { 81 struct peer_assoc_notify_s peer_assoc; 82 QDF_STATUS status; 83 84 peer_assoc.peer = peer; 85 status = mlo_msgq_post(MLO_PEER_ASSOC, ml_dev, &peer_assoc); 86 if (status != QDF_STATUS_SUCCESS) 87 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID); 88 } 89 90 static void mlo_link_peer_send_assoc_fail(struct wlan_mlo_dev_context *ml_dev, 91 struct wlan_objmgr_peer *peer) 92 { 93 struct peer_assoc_fail_notify_s peer_assoc_fail; 94 QDF_STATUS status; 95 96 peer_assoc_fail.peer = peer; 97 status = mlo_msgq_post(MLO_PEER_ASSOC_FAIL, ml_dev, &peer_assoc_fail); 98 if (status != QDF_STATUS_SUCCESS) 99 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID); 100 } 101 102 static void mlo_link_peer_disconnect_notify(struct wlan_mlo_dev_context *ml_dev, 103 struct wlan_objmgr_peer *peer) 104 { 105 struct peer_discon_notify_s peer_disconn; 106 QDF_STATUS status; 107 struct wlan_objmgr_vdev *vdev; 108 enum QDF_OPMODE opmode; 109 110 vdev = wlan_peer_get_vdev(peer); 111 opmode = wlan_vdev_mlme_get_opmode(vdev); 112 113 if (opmode == QDF_SAP_MODE) { 114 peer_disconn.peer = peer; 115 status = mlo_msgq_post(MLO_PEER_DISCONNECT, ml_dev, 116 &peer_disconn); 117 if (status != QDF_STATUS_SUCCESS) 118 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID); 119 } else { 120 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID); 121 } 122 } 123 124 static void mlo_link_peer_deauth_init(struct wlan_mlo_dev_context *ml_dev, 125 struct wlan_objmgr_peer *peer, 126 uint8_t is_disassoc) 127 { 128 struct peer_deauth_notify_s peer_deauth; 129 QDF_STATUS status; 130 131 peer_deauth.peer = peer; 132 peer_deauth.is_disassoc = is_disassoc; 133 status = mlo_msgq_post(MLO_PEER_DEAUTH, ml_dev, &peer_deauth); 134 if (status != QDF_STATUS_SUCCESS) 135 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID); 136 } 137 138 #ifdef UMAC_MLO_AUTH_DEFER 139 static void mlo_peer_process_pending_auth(struct wlan_mlo_dev_context *ml_dev, 140 struct wlan_mlo_peer_context *ml_peer) 141 { 142 struct peer_auth_process_notif_s peer_auth; 143 struct mlpeer_auth_params *recv_auth; 144 uint8_t i; 145 QDF_STATUS status; 146 147 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 148 mlo_peer_lock_acquire(ml_peer); 149 recv_auth = ml_peer->pending_auth[i]; 150 if (!recv_auth) { 151 mlo_peer_lock_release(ml_peer); 152 continue; 153 } 154 peer_auth.auth_params = recv_auth; 155 ml_peer->pending_auth[i] = NULL; 156 157 mlo_peer_lock_release(ml_peer); 158 159 status = mlo_msgq_post(MLO_PEER_PENDING_AUTH, ml_dev, 160 &peer_auth); 161 if (QDF_IS_STATUS_ERROR(status)) 162 mlo_peer_free_auth_param(peer_auth.auth_params); 163 } 164 } 165 #else 166 static void mlo_peer_process_pending_auth(struct wlan_mlo_dev_context *ml_dev, 167 struct wlan_mlo_peer_context *ml_peer) 168 { 169 } 170 #endif 171 172 QDF_STATUS 173 wlan_mlo_peer_is_disconnect_progress(struct wlan_mlo_peer_context *ml_peer) 174 { 175 QDF_STATUS status; 176 177 if (!ml_peer) 178 return QDF_STATUS_E_FAILURE; 179 180 mlo_peer_lock_acquire(ml_peer); 181 182 if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) 183 status = QDF_STATUS_SUCCESS; 184 else 185 status = QDF_STATUS_E_FAILURE; 186 187 mlo_peer_lock_release(ml_peer); 188 189 return status; 190 } 191 192 QDF_STATUS wlan_mlo_peer_is_assoc_done(struct wlan_mlo_peer_context *ml_peer) 193 { 194 QDF_STATUS status; 195 196 if (!ml_peer) 197 return QDF_STATUS_E_FAILURE; 198 199 mlo_peer_lock_acquire(ml_peer); 200 201 if (ml_peer->mlpeer_state == ML_PEER_ASSOC_DONE) 202 status = QDF_STATUS_SUCCESS; 203 else 204 status = QDF_STATUS_E_FAILURE; 205 206 mlo_peer_lock_release(ml_peer); 207 208 return status; 209 } 210 211 struct wlan_objmgr_peer *wlan_mlo_peer_get_assoc_peer( 212 struct wlan_mlo_peer_context *ml_peer) 213 { 214 struct wlan_mlo_link_peer_entry *peer_entry; 215 struct wlan_objmgr_peer *assoc_peer = NULL; 216 217 if (!ml_peer) 218 return NULL; 219 220 mlo_peer_lock_acquire(ml_peer); 221 222 peer_entry = &ml_peer->peer_list[0]; 223 224 if (peer_entry->link_peer) 225 assoc_peer = peer_entry->link_peer; 226 227 mlo_peer_lock_release(ml_peer); 228 229 return assoc_peer; 230 } 231 232 qdf_export_symbol(wlan_mlo_peer_get_assoc_peer); 233 234 bool mlo_peer_is_assoc_peer(struct wlan_mlo_peer_context *ml_peer, 235 struct wlan_objmgr_peer *peer) 236 { 237 struct wlan_mlo_link_peer_entry *peer_entry; 238 bool is_assoc_peer = false; 239 240 if (!ml_peer || !peer) 241 return is_assoc_peer; 242 243 peer_entry = &ml_peer->peer_list[0]; 244 245 if (peer_entry->link_peer != peer) 246 is_assoc_peer = true; 247 248 return is_assoc_peer; 249 } 250 251 bool wlan_mlo_peer_is_assoc_peer(struct wlan_mlo_peer_context *ml_peer, 252 struct wlan_objmgr_peer *peer) 253 { 254 bool is_assoc_peer = false; 255 256 if (!ml_peer || !peer) 257 return is_assoc_peer; 258 259 mlo_peer_lock_acquire(ml_peer); 260 261 is_assoc_peer = mlo_peer_is_assoc_peer(ml_peer, peer); 262 263 mlo_peer_lock_release(ml_peer); 264 265 return is_assoc_peer; 266 } 267 268 void wlan_mlo_partner_peer_assoc_post(struct wlan_objmgr_peer *assoc_peer) 269 { 270 struct wlan_mlo_dev_context *ml_dev; 271 struct wlan_mlo_peer_context *ml_peer; 272 struct wlan_objmgr_peer *link_peer; 273 struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS]; 274 struct wlan_mlo_link_peer_entry *peer_entry; 275 uint16_t i; 276 277 ml_peer = assoc_peer->mlo_peer_ctx; 278 if (!ml_peer) 279 return; 280 281 mlo_peer_lock_acquire(ml_peer); 282 283 if (ml_peer->mlpeer_state != ML_PEER_CREATED) { 284 mlo_peer_lock_release(ml_peer); 285 return; 286 } 287 288 ml_peer->mlpeer_state = ML_PEER_ASSOC_DONE; 289 ml_dev = ml_peer->ml_dev; 290 291 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 292 link_peers[i] = NULL; 293 peer_entry = &ml_peer->peer_list[i]; 294 295 if (!peer_entry->link_peer) 296 continue; 297 298 if (peer_entry->link_peer == assoc_peer) 299 continue; 300 301 link_peer = peer_entry->link_peer; 302 303 if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) != 304 QDF_STATUS_SUCCESS) 305 continue; 306 307 link_peers[i] = link_peer; 308 } 309 mlo_peer_lock_release(ml_peer); 310 311 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 312 if (!link_peers[i]) 313 continue; 314 315 /* Prepare and queue message */ 316 mlo_link_peer_assoc_notify(ml_dev, link_peers[i]); 317 } 318 } 319 320 void 321 wlan_mlo_peer_deauth_init(struct wlan_mlo_peer_context *ml_peer, 322 struct wlan_objmgr_peer *src_peer, 323 uint8_t is_disassoc) 324 { 325 struct wlan_mlo_dev_context *ml_dev; 326 struct wlan_objmgr_peer *link_peer; 327 struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS]; 328 struct wlan_mlo_link_peer_entry *peer_entry; 329 uint16_t i; 330 uint8_t deauth_sent = 0; 331 332 if (!ml_peer) 333 return; 334 335 mlo_peer_lock_acquire(ml_peer); 336 337 if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) { 338 mlo_peer_lock_release(ml_peer); 339 return; 340 } 341 342 ml_dev = ml_peer->ml_dev; 343 344 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 345 link_peers[i] = NULL; 346 peer_entry = &ml_peer->peer_list[i]; 347 if (!peer_entry->link_peer) 348 continue; 349 350 link_peer = peer_entry->link_peer; 351 352 if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) != 353 QDF_STATUS_SUCCESS) 354 continue; 355 356 link_peers[i] = link_peer; 357 } 358 359 ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED; 360 361 mlo_peer_lock_release(ml_peer); 362 363 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 364 if (!link_peers[i]) 365 continue; 366 367 /* Prepare and queue message */ 368 /* skip sending deauth on src peer */ 369 if ((deauth_sent) || 370 (src_peer && (src_peer == link_peers[i]))) { 371 mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]); 372 } else { 373 mlo_link_peer_deauth_init(ml_dev, link_peers[i], 374 is_disassoc); 375 deauth_sent = 1; 376 } 377 } 378 } 379 380 void wlan_mlo_peer_delete(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_dev = ml_peer->ml_dev; 399 400 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 401 link_peers[i] = NULL; 402 peer_entry = &ml_peer->peer_list[i]; 403 if (!peer_entry->link_peer) 404 continue; 405 406 link_peer = peer_entry->link_peer; 407 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 415 ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED; 416 417 mlo_peer_lock_release(ml_peer); 418 419 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 420 if (!link_peers[i]) 421 continue; 422 423 mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]); 424 } 425 } 426 427 void 428 wlan_mlo_partner_peer_create_failed_notify( 429 struct wlan_mlo_peer_context *ml_peer) 430 { 431 struct wlan_mlo_dev_context *ml_dev; 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 uint16_t i; 436 437 if (!ml_peer) 438 return; 439 440 mlo_peer_lock_acquire(ml_peer); 441 442 if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) { 443 mlo_peer_lock_release(ml_peer); 444 return; 445 } 446 447 ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED; 448 ml_dev = ml_peer->ml_dev; 449 450 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 451 link_peers[i] = NULL; 452 peer_entry = &ml_peer->peer_list[i]; 453 if (!peer_entry->link_peer) 454 continue; 455 456 link_peer = peer_entry->link_peer; 457 if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) != 458 QDF_STATUS_SUCCESS) 459 continue; 460 461 link_peers[i] = link_peer; 462 } 463 mlo_peer_lock_release(ml_peer); 464 465 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 466 if (!link_peers[i]) 467 continue; 468 469 /* Prepare and queue message */ 470 if (i == 0) 471 mlo_link_peer_send_assoc_fail(ml_dev, link_peers[i]); 472 else 473 mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]); 474 } 475 } 476 477 void wlan_mlo_partner_peer_disconnect_notify(struct wlan_objmgr_peer *src_peer) 478 { 479 struct wlan_mlo_dev_context *ml_dev; 480 struct wlan_mlo_peer_context *ml_peer; 481 struct wlan_objmgr_peer *link_peer; 482 struct wlan_objmgr_peer *link_peers[MAX_MLO_LINK_PEERS]; 483 struct wlan_mlo_link_peer_entry *peer_entry; 484 struct wlan_objmgr_vdev *vdev = NULL; 485 uint16_t i; 486 487 ml_peer = src_peer->mlo_peer_ctx; 488 if (!ml_peer) 489 return; 490 491 vdev = wlan_peer_get_vdev(src_peer); 492 if (!vdev) 493 return; 494 495 mlo_peer_lock_acquire(ml_peer); 496 497 if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) { 498 mlo_peer_lock_release(ml_peer); 499 return; 500 } 501 502 ml_peer->mlpeer_state = ML_PEER_DISCONN_INITIATED; 503 504 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) { 505 mlo_peer_lock_release(ml_peer); 506 return; 507 } 508 509 ml_dev = ml_peer->ml_dev; 510 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 511 link_peers[i] = NULL; 512 peer_entry = &ml_peer->peer_list[i]; 513 if (!peer_entry->link_peer) { 514 mlo_debug("link peer is null"); 515 continue; 516 } 517 518 if (peer_entry->link_peer == src_peer) 519 continue; 520 521 link_peer = peer_entry->link_peer; 522 if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) != 523 QDF_STATUS_SUCCESS) 524 continue; 525 526 link_peers[i] = link_peer; 527 } 528 mlo_peer_lock_release(ml_peer); 529 530 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 531 if (!link_peers[i]) 532 continue; 533 534 /* Prepare and queue message */ 535 mlo_link_peer_disconnect_notify(ml_dev, link_peers[i]); 536 } 537 } 538 539 static void mlo_peer_populate_link_peer( 540 struct wlan_mlo_peer_context *ml_peer, 541 struct wlan_objmgr_peer *link_peer) 542 { 543 mlo_peer_lock_acquire(ml_peer); 544 wlan_mlo_peer_get_ref(ml_peer); 545 link_peer->mlo_peer_ctx = ml_peer; 546 mlo_peer_lock_release(ml_peer); 547 } 548 549 static void mlo_reset_link_peer( 550 struct wlan_mlo_peer_context *ml_peer, 551 struct wlan_objmgr_peer *link_peer) 552 { 553 mlo_peer_lock_acquire(ml_peer); 554 link_peer->mlo_peer_ctx = NULL; 555 wlan_peer_clear_mlo(link_peer); 556 mlo_peer_lock_release(ml_peer); 557 } 558 559 static void mlo_peer_free(struct wlan_mlo_peer_context *ml_peer) 560 { 561 struct wlan_mlo_dev_context *ml_dev; 562 563 ml_dev = ml_peer->ml_dev; 564 if (!ml_dev) { 565 mlo_err("ML DEV is NULL"); 566 return; 567 } 568 569 mlo_debug("ML Peer " QDF_MAC_ADDR_FMT " is freed", 570 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes)); 571 mlo_peer_lock_destroy(ml_peer); 572 mlo_ap_ml_peerid_free(ml_peer->mlo_peer_id); 573 mlo_peer_free_aid(ml_dev, ml_peer); 574 mlo_peer_free_primary_umac(ml_dev, ml_peer); 575 qdf_mem_free(ml_peer); 576 } 577 578 void mlo_peer_cleanup(struct wlan_mlo_peer_context *ml_peer) 579 { 580 struct wlan_mlo_dev_context *ml_dev; 581 582 if (!ml_peer) { 583 mlo_err("ML PEER is NULL"); 584 return; 585 } 586 ml_dev = ml_peer->ml_dev; 587 if (!ml_dev) { 588 mlo_err("ML DEV is NULL"); 589 return; 590 } 591 592 mlo_dev_mlpeer_detach(ml_dev, ml_peer); 593 /* If any Auth req is received during ML peer delete */ 594 mlo_peer_process_pending_auth(ml_dev, ml_peer); 595 mlo_peer_free(ml_peer); 596 } 597 598 static QDF_STATUS mlo_peer_attach_link_peer( 599 struct wlan_mlo_peer_context *ml_peer, 600 struct wlan_objmgr_peer *link_peer, 601 qdf_nbuf_t frm_buf) 602 { 603 struct wlan_mlo_link_peer_entry *peer_entry; 604 QDF_STATUS status = QDF_STATUS_E_RESOURCES; 605 struct wlan_objmgr_pdev *pdev; 606 struct wlan_objmgr_vdev *vdev; 607 uint16_t i; 608 609 if (!link_peer) 610 return QDF_STATUS_E_FAILURE; 611 612 vdev = wlan_peer_get_vdev(link_peer); 613 if (!vdev) 614 return QDF_STATUS_E_FAILURE; 615 616 mlo_peer_lock_acquire(ml_peer); 617 618 if (ml_peer->mlpeer_state != ML_PEER_CREATED) { 619 mlo_peer_lock_release(ml_peer); 620 mlo_err("ML Peer " QDF_MAC_ADDR_FMT " is not in created state (state %d)", 621 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 622 ml_peer->mlpeer_state); 623 return status; 624 } 625 626 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 627 peer_entry = &ml_peer->peer_list[i]; 628 if (peer_entry->link_peer) 629 continue; 630 631 if (wlan_objmgr_peer_try_get_ref(link_peer, WLAN_MLO_MGR_ID) != 632 QDF_STATUS_SUCCESS) { 633 mlo_err("ML Peer " QDF_MAC_ADDR_FMT ", link peer " QDF_MAC_ADDR_FMT " is not in valid state", 634 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 635 QDF_MAC_ADDR_REF 636 (wlan_peer_get_macaddr(link_peer))); 637 break; 638 } 639 peer_entry->link_peer = link_peer; 640 vdev->vdev_objmgr.wlan_ml_peer_count++; 641 qdf_copy_macaddr(&peer_entry->link_addr, 642 (struct qdf_mac_addr *)&link_peer->macaddr[0]); 643 644 peer_entry->link_ix = wlan_vdev_get_link_id(vdev); 645 pdev = wlan_vdev_get_pdev(wlan_peer_get_vdev(link_peer)); 646 peer_entry->hw_link_id = wlan_mlo_get_pdev_hw_link_id(pdev); 647 mlo_peer_assign_primary_umac(ml_peer, peer_entry); 648 if (frm_buf) 649 peer_entry->assoc_rsp_buf = frm_buf; 650 else 651 peer_entry->assoc_rsp_buf = NULL; 652 653 status = QDF_STATUS_SUCCESS; 654 break; 655 } 656 if (QDF_IS_STATUS_SUCCESS(status)) 657 ml_peer->link_peer_cnt++; 658 659 mlo_peer_lock_release(ml_peer); 660 661 return status; 662 } 663 664 qdf_nbuf_t mlo_peer_get_link_peer_assoc_resp_buf( 665 struct wlan_mlo_peer_context *ml_peer, 666 uint8_t link_ix) 667 { 668 struct wlan_mlo_link_peer_entry *peer_entry; 669 qdf_nbuf_t frm_buf = NULL; 670 uint8_t i; 671 672 if (!ml_peer) 673 return NULL; 674 675 if (link_ix > MAX_MLO_LINK_PEERS) 676 return NULL; 677 678 mlo_peer_lock_acquire(ml_peer); 679 if ((ml_peer->mlpeer_state != ML_PEER_CREATED) && 680 (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) { 681 mlo_peer_lock_release(ml_peer); 682 return NULL; 683 } 684 685 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 686 peer_entry = &ml_peer->peer_list[i]; 687 688 if (!peer_entry->link_peer) 689 continue; 690 691 if (peer_entry->link_ix == link_ix) { 692 if (!peer_entry->assoc_rsp_buf) 693 break; 694 695 frm_buf = qdf_nbuf_clone(peer_entry->assoc_rsp_buf); 696 break; 697 } 698 } 699 mlo_peer_lock_release(ml_peer); 700 701 return frm_buf; 702 } 703 704 void wlan_mlo_peer_free_all_link_assoc_resp_buf( 705 struct wlan_objmgr_peer *link_peer) 706 { 707 struct wlan_mlo_link_peer_entry *peer_entry; 708 struct wlan_mlo_peer_context *ml_peer; 709 uint8_t i; 710 711 ml_peer = link_peer->mlo_peer_ctx; 712 if (!ml_peer) 713 return; 714 715 mlo_peer_lock_acquire(ml_peer); 716 717 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 718 peer_entry = &ml_peer->peer_list[i]; 719 720 if (peer_entry->assoc_rsp_buf) { 721 qdf_nbuf_free(peer_entry->assoc_rsp_buf); 722 peer_entry->assoc_rsp_buf = NULL; 723 } 724 } 725 mlo_peer_lock_release(ml_peer); 726 } 727 728 static QDF_STATUS mlo_peer_detach_link_peer( 729 struct wlan_mlo_peer_context *ml_peer, 730 struct wlan_objmgr_peer *link_peer) 731 { 732 struct wlan_mlo_link_peer_entry *peer_entry; 733 QDF_STATUS status = QDF_STATUS_E_RESOURCES; 734 uint16_t i; 735 struct wlan_objmgr_vdev *vdev; 736 737 mlo_peer_lock_acquire(ml_peer); 738 739 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 740 peer_entry = &ml_peer->peer_list[i]; 741 if (!peer_entry->link_peer) 742 continue; 743 744 if (peer_entry->link_peer != link_peer) 745 continue; 746 747 if (peer_entry->assoc_rsp_buf) { 748 qdf_nbuf_free(peer_entry->assoc_rsp_buf); 749 peer_entry->assoc_rsp_buf = NULL; 750 } 751 vdev = wlan_peer_get_vdev(link_peer); 752 if (vdev) 753 vdev->vdev_objmgr.wlan_ml_peer_count--; 754 755 wlan_objmgr_peer_release_ref(link_peer, WLAN_MLO_MGR_ID); 756 peer_entry->link_peer = NULL; 757 ml_peer->link_peer_cnt--; 758 status = QDF_STATUS_SUCCESS; 759 break; 760 } 761 mlo_peer_lock_release(ml_peer); 762 763 return status; 764 } 765 766 static QDF_STATUS mlo_dev_get_link_vdevs( 767 struct wlan_objmgr_vdev *vdev, 768 struct wlan_mlo_dev_context *ml_dev, 769 struct mlo_partner_info *ml_info, 770 struct wlan_objmgr_vdev *link_vdevs[]) 771 { 772 uint16_t i, j; 773 struct wlan_objmgr_vdev *vdev_link; 774 uint8_t link_id; 775 776 if (!ml_dev) { 777 mlo_err("ml_dev is null"); 778 return QDF_STATUS_E_INVAL; 779 } 780 781 if (!ml_info) { 782 mlo_err("ml_info is null"); 783 return QDF_STATUS_E_INVAL; 784 } 785 786 mlo_debug("num_partner_links %d", ml_info->num_partner_links); 787 for (i = 0; i < ml_info->num_partner_links; i++) { 788 link_id = ml_info->partner_link_info[i].link_id; 789 vdev_link = mlo_get_vdev_by_link_id(vdev, link_id); 790 if (vdev_link) { 791 link_vdevs[i] = vdev_link; 792 } else { 793 /* release ref which were taken before failure */ 794 for (j = 0; j < i; j++) { 795 vdev_link = link_vdevs[j]; 796 if (!vdev_link) 797 continue; 798 799 wlan_objmgr_vdev_release_ref(vdev_link, 800 WLAN_MLO_MGR_ID); 801 } 802 return QDF_STATUS_E_INVAL; 803 } 804 } 805 806 return QDF_STATUS_SUCCESS; 807 } 808 809 static void mlo_dev_release_link_vdevs( 810 struct wlan_objmgr_vdev *link_vdevs[]) 811 { 812 uint16_t i; 813 struct wlan_objmgr_vdev *vdev_link; 814 815 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 816 vdev_link = link_vdevs[i]; 817 if (!vdev_link) 818 continue; 819 820 wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID); 821 } 822 } 823 824 #ifdef WLAN_FEATURE_11BE 825 static void 826 wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context *ml_peer, 827 struct mlo_partner_info *ml_info) 828 { 829 ml_peer->t2lm_policy.t2lm_enable_val = ml_info->t2lm_enable_val; 830 } 831 #else 832 static void 833 wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context *ml_peer, 834 struct mlo_partner_info *ml_info) 835 {} 836 #endif /* WLAN_FEATURE_11BE */ 837 838 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP) 839 static struct wlan_objmgr_vdev* 840 mlo_get_primary_umac_vdev(struct wlan_mlo_dev_context *ml_dev, 841 uint8_t psoc_id) 842 { 843 uint8_t i; 844 struct wlan_objmgr_vdev *link_vdev; 845 846 if (WLAN_OBJMGR_MAX_DEVICES <= psoc_id) 847 return NULL; 848 849 if (!ml_dev) 850 return NULL; 851 852 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 853 link_vdev = ml_dev->wlan_vdev_list[i]; 854 if (!link_vdev) 855 continue; 856 if (psoc_id == wlan_vdev_get_psoc_id(link_vdev)) 857 return link_vdev; 858 } 859 860 return NULL; 861 } 862 863 static 864 QDF_STATUS mlo_bridge_peer_create_post(struct wlan_mlo_dev_context *ml_dev, 865 struct wlan_mlo_peer_context *ml_peer, 866 uint8_t psoc_id) 867 { 868 struct peer_create_notif_s peer_create; 869 struct wlan_objmgr_vdev *vdev_link; 870 QDF_STATUS status; 871 872 vdev_link = mlo_get_primary_umac_vdev(ml_dev, psoc_id); 873 874 if (!vdev_link) { 875 mlo_err("VDEV derivation in unsuccessful"); 876 return QDF_STATUS_E_FAILURE; 877 } 878 879 if (wlan_objmgr_vdev_try_get_ref(vdev_link, WLAN_MLO_MGR_ID) != 880 QDF_STATUS_SUCCESS) { 881 mlo_err("VDEV is not in created state"); 882 return QDF_STATUS_E_FAILURE; 883 } 884 peer_create.vdev_link = vdev_link; 885 wlan_mlo_peer_get_ref(ml_peer); 886 peer_create.ml_peer = ml_peer; 887 888 qdf_copy_macaddr(&peer_create.addr, 889 &ml_peer->peer_mld_addr); 890 891 peer_create.frm_buf = NULL; 892 893 status = mlo_msgq_post(MLO_BRIDGE_PEER_CREATE, ml_dev, &peer_create); 894 if (status != QDF_STATUS_SUCCESS) { 895 wlan_mlo_peer_release_ref(ml_peer); 896 wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID); 897 } 898 899 return status; 900 } 901 902 static QDF_STATUS 903 wlan_mlo_check_and_create_bridge_peer(struct wlan_objmgr_vdev *vdev, 904 struct wlan_mlo_peer_context *ml_peer, 905 struct wlan_objmgr_vdev *link_vdevs[], 906 uint8_t num_partner_links) 907 { 908 struct wlan_mlo_dev_context *ml_dev; 909 struct wlan_objmgr_vdev *ml_vdev; 910 uint8_t psoc_ids[WLAN_NUM_TWO_LINK_PSOC]; 911 uint8_t comp_psoc_id, i, is_adjacent; 912 uint8_t bridge_peer_psoc_id = WLAN_OBJMGR_MAX_DEVICES; 913 QDF_STATUS status; 914 915 if (wlan_vdev_mlme_get_opmode(vdev) != QDF_SAP_MODE) 916 return QDF_STATUS_SUCCESS; 917 918 /* Return from here for 3 link association */ 919 if (WLAN_NUM_TWO_LINK_PSOC != num_partner_links) 920 return QDF_STATUS_SUCCESS; 921 922 ml_dev = vdev->mlo_dev_ctx; 923 if (!ml_dev) 924 return QDF_STATUS_E_FAILURE; 925 926 for (i = 0; i < WLAN_NUM_TWO_LINK_PSOC; i++) 927 psoc_ids[i] = wlan_vdev_get_psoc_id(link_vdevs[i]); 928 929 status = mlo_chip_adjacent(psoc_ids[0], psoc_ids[1], 930 &is_adjacent); 931 if (QDF_STATUS_SUCCESS != status) { 932 mlo_err("Unable to get chip adjacency for " QDF_MAC_ADDR_FMT ", psoc_0 %u, psoc_1 %u", 933 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 934 psoc_ids[0], psoc_ids[1]); 935 return status; 936 } 937 if (is_adjacent) 938 return QDF_STATUS_SUCCESS; 939 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 940 ml_vdev = ml_dev->wlan_vdev_list[i]; 941 if (!ml_vdev || (wlan_vdev_is_up(ml_vdev) != QDF_STATUS_SUCCESS)) 942 continue; 943 comp_psoc_id = wlan_vdev_get_psoc_id(ml_vdev); 944 if ((comp_psoc_id != psoc_ids[0]) && 945 (comp_psoc_id != psoc_ids[1])) { 946 bridge_peer_psoc_id = comp_psoc_id; 947 break; 948 } 949 } 950 951 if (bridge_peer_psoc_id >= WLAN_OBJMGR_MAX_DEVICES) { 952 mlo_err("Invalid psoc or psoc not found for " QDF_MAC_ADDR_FMT " psoc %u", 953 ether_sprintf(ml_peer->peer_mld_addr.bytes), 954 bridge_peer_psoc_id); 955 return QDF_STATUS_E_FAILURE; 956 } 957 958 /* Check if derived psoc is adjecent to both links */ 959 for (i = 0; i < WLAN_NUM_TWO_LINK_PSOC; i++) { 960 status = mlo_chip_adjacent(psoc_ids[i], bridge_peer_psoc_id, 961 &is_adjacent); 962 if (QDF_STATUS_SUCCESS != status) { 963 mlo_err("Unable to get chip adjacency for " QDF_MAC_ADDR_FMT ", psoc_0 %u, psoc_1 %u", 964 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 965 psoc_ids[i], bridge_peer_psoc_id); 966 return status; 967 } 968 if (!is_adjacent) { 969 mlo_err("Derived psoc is not adjecent to one of the links for " QDF_MAC_ADDR_FMT ", psoc_0 %u, psoc_1 %u psoc_2 %u", 970 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 971 psoc_ids[0], psoc_ids[1], bridge_peer_psoc_id); 972 return QDF_STATUS_E_FAILURE; 973 } 974 } 975 976 /* Assign bridge peer PSOC as primary UMAC */ 977 mlo_peer_overwrite_primary_umac(bridge_peer_psoc_id, ml_peer); 978 mlo_debug("Creating bridge peer for " QDF_MAC_ADDR_FMT " on psoc %u, is_adjacent %u", 979 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 980 bridge_peer_psoc_id, is_adjacent); 981 /* Create bridge peer */ 982 status = mlo_bridge_peer_create_post(ml_dev, ml_peer, 983 bridge_peer_psoc_id); 984 return status; 985 } 986 #else 987 static QDF_STATUS 988 wlan_mlo_check_and_create_bridge_peer(struct wlan_objmgr_vdev *vdev, 989 struct wlan_mlo_peer_context *ml_peer, 990 struct wlan_objmgr_vdev *link_vdevs[], 991 uint8_t num_partner_links) 992 { 993 return QDF_STATUS_SUCCESS; 994 } 995 #endif 996 997 QDF_STATUS wlan_mlo_peer_create(struct wlan_objmgr_vdev *vdev, 998 struct wlan_objmgr_peer *link_peer, 999 struct mlo_partner_info *ml_info, 1000 qdf_nbuf_t frm_buf, 1001 uint16_t aid) 1002 { 1003 struct wlan_mlo_dev_context *ml_dev; 1004 struct wlan_mlo_peer_context *ml_peer = NULL; 1005 struct wlan_objmgr_vdev *link_vdevs[WLAN_UMAC_MLO_MAX_VDEVS] = { NULL }; 1006 struct wlan_objmgr_vdev *vdev_link; 1007 QDF_STATUS status; 1008 uint16_t i; 1009 struct wlan_objmgr_peer *assoc_peer; 1010 bool is_ml_peer_attached = false; 1011 1012 /* get ML VDEV from VDEV */ 1013 ml_dev = vdev->mlo_dev_ctx; 1014 1015 if (!ml_dev) { 1016 mlo_err("ML dev ctx is NULL"); 1017 return QDF_STATUS_E_NULL_VALUE; 1018 } 1019 1020 /* Check resources of Partner VDEV */ 1021 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) { 1022 if (wlan_mlo_is_mld_ctx_exist( 1023 (struct qdf_mac_addr *)&link_peer->mldaddr[0])) { 1024 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " is matching with one of the MLD address in the system", 1025 ml_dev->mld_id, 1026 QDF_MAC_ADDR_REF(link_peer->mldaddr)); 1027 return QDF_STATUS_E_FAILURE; 1028 } 1029 /* Limit max assoc links */ 1030 if (ml_info->num_partner_links > WLAN_UMAC_MLO_ASSOC_MAX_SUPPORTED_LINKS) { 1031 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " exceeds MAX assoc limit of %d", 1032 ml_dev->mld_id, 1033 QDF_MAC_ADDR_REF(link_peer->mldaddr), 1034 WLAN_UMAC_MLO_ASSOC_MAX_SUPPORTED_LINKS); 1035 return QDF_STATUS_E_RESOURCES; 1036 } 1037 1038 status = mlo_dev_get_link_vdevs(vdev, ml_dev, 1039 ml_info, link_vdevs); 1040 if (QDF_IS_STATUS_ERROR(status)) { 1041 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " get link vdevs failed", 1042 ml_dev->mld_id, 1043 QDF_MAC_ADDR_REF(link_peer->mldaddr)); 1044 return QDF_STATUS_E_FAILURE; 1045 } 1046 1047 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 1048 vdev_link = link_vdevs[i]; 1049 if (!vdev_link) { 1050 mlo_debug("vdev_link is null"); 1051 continue; 1052 } 1053 1054 if (wlan_vdev_is_mlo_peer_create_allowed(vdev_link) 1055 != QDF_STATUS_SUCCESS) { 1056 mlo_dev_release_link_vdevs(link_vdevs); 1057 1058 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " create not allowed on link vdev %d", 1059 ml_dev->mld_id, 1060 QDF_MAC_ADDR_REF 1061 (link_peer->mldaddr), 1062 wlan_vdev_get_id(vdev_link)); 1063 return QDF_STATUS_E_INVAL; 1064 } 1065 } 1066 1067 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 1068 vdev_link = link_vdevs[i]; 1069 if (vdev_link && (vdev_link != vdev) && 1070 (wlan_vdev_get_peer_count(vdev_link) > 1071 wlan_vdev_get_max_peer_count(vdev_link))) { 1072 mlo_dev_release_link_vdevs(link_vdevs); 1073 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " Max peer count reached on link vdev %d", 1074 ml_dev->mld_id, 1075 QDF_MAC_ADDR_REF 1076 (link_peer->mldaddr), 1077 wlan_vdev_get_id(vdev_link)); 1078 return QDF_STATUS_E_RESOURCES; 1079 } 1080 } 1081 } 1082 /* When roam to MLO AP, partner link vdev1 is updated first, 1083 * ml peer need be created and attached for partner link peer. 1084 * 1085 * When roam target AP and current AP have same MLD address, don't 1086 * delete old ML peer and re-create new one, just update different 1087 * info. 1088 */ 1089 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) { 1090 ml_peer = wlan_mlo_get_mlpeer(ml_dev, 1091 (struct qdf_mac_addr *)&link_peer->mldaddr[0]); 1092 if (ml_peer) { 1093 mlo_debug("ML Peer " QDF_MAC_ADDR_FMT 1094 " existed, state %d", 1095 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 1096 ml_peer->mlpeer_state); 1097 ml_peer->mlpeer_state = ML_PEER_CREATED; 1098 ml_peer->max_links = ml_info->num_partner_links; 1099 wlan_mlo_peer_set_t2lm_enable_val(ml_peer, ml_info); 1100 is_ml_peer_attached = true; 1101 } 1102 } 1103 if (!ml_peer) { 1104 /* Allocate MLO peer */ 1105 ml_peer = qdf_mem_malloc(sizeof(*ml_peer)); 1106 if (!ml_peer) { 1107 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " mem alloc failed", 1108 ml_dev->mld_id, 1109 QDF_MAC_ADDR_REF(link_peer->mldaddr)); 1110 mlo_dev_release_link_vdevs(link_vdevs); 1111 return QDF_STATUS_E_NOMEM; 1112 } 1113 1114 qdf_atomic_init(&ml_peer->ref_cnt); 1115 mlo_peer_lock_create(ml_peer); 1116 ml_peer->ml_dev = ml_dev; 1117 ml_peer->mlpeer_state = ML_PEER_CREATED; 1118 ml_peer->max_links = ml_info->num_partner_links; 1119 ml_peer->primary_umac_psoc_id = ML_PRIMARY_UMAC_ID_INVAL; 1120 1121 ml_peer->mlo_peer_id = mlo_ap_ml_peerid_alloc(); 1122 if (ml_peer->mlo_peer_id == MLO_INVALID_PEER_ID) { 1123 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " invalid ml peer id", 1124 ml_dev->mld_id, 1125 QDF_MAC_ADDR_REF 1126 (ml_peer->peer_mld_addr.bytes)); 1127 mlo_peer_free(ml_peer); 1128 mlo_dev_release_link_vdevs(link_vdevs); 1129 return QDF_STATUS_E_RESOURCES; 1130 } 1131 1132 qdf_copy_macaddr((struct qdf_mac_addr *)&ml_peer->peer_mld_addr, 1133 (struct qdf_mac_addr *)&link_peer->mldaddr[0]); 1134 wlan_mlo_peer_set_t2lm_enable_val(ml_peer, ml_info); 1135 1136 /* Allocate AID */ 1137 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) { 1138 if (aid == (uint16_t)-1) { 1139 status = mlo_peer_allocate_aid(ml_dev, ml_peer); 1140 if (status != QDF_STATUS_SUCCESS) { 1141 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " aid alloc failed", 1142 ml_dev->mld_id, 1143 QDF_MAC_ADDR_REF 1144 (ml_peer->peer_mld_addr.bytes)); 1145 mlo_peer_free(ml_peer); 1146 mlo_dev_release_link_vdevs(link_vdevs); 1147 return status; 1148 } 1149 } else { 1150 ml_peer->assoc_id = aid; 1151 } 1152 } 1153 } 1154 1155 /* Populate Link peer pointer, peer MAC address, 1156 * MLD address. HW link ID, update ref count 1157 */ 1158 status = mlo_peer_attach_link_peer(ml_peer, link_peer, NULL); 1159 if (QDF_IS_STATUS_ERROR(status)) { 1160 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " link peer attach failed", 1161 ml_dev->mld_id, 1162 QDF_MAC_ADDR_REF 1163 (ml_peer->peer_mld_addr.bytes)); 1164 /* If there is another link peer attached for this ML peer, 1165 * ml peer can't be detached and freed. 1166 */ 1167 if (is_ml_peer_attached && ml_peer->link_peer_cnt) 1168 return status; 1169 if (is_ml_peer_attached) 1170 mlo_dev_mlpeer_detach(ml_dev, ml_peer); 1171 mlo_peer_free(ml_peer); 1172 mlo_dev_release_link_vdevs(link_vdevs); 1173 return status; 1174 } 1175 1176 /* Allocate Primary UMAC */ 1177 mlo_peer_allocate_primary_umac(ml_dev, ml_peer, link_vdevs); 1178 1179 /* Store AID, MLO Peer pointer in link peer, take link peer ref count */ 1180 mlo_peer_populate_link_peer(ml_peer, link_peer); 1181 1182 mlo_peer_populate_nawds_params(ml_peer, ml_info); 1183 mlo_peer_populate_mesh_params(ml_peer, ml_info); 1184 1185 if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) || 1186 ((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) && 1187 !is_ml_peer_attached)) { 1188 /* Reject creation for AP mode, If ML peer is present with 1189 * MLD MAC address, For PSTA case, all MLD STAs are connected 1190 * to same MLD AP, it can have duplicate MLD address entries 1191 * for STA MLDs 1192 */ 1193 if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) && 1194 mlo_mgr_ml_peer_exist_on_diff_ml_ctx(&link_peer->mldaddr[0], 1195 NULL)) { 1196 mlo_reset_link_peer(ml_peer, link_peer); 1197 mlo_peer_free(ml_peer); 1198 mlo_dev_release_link_vdevs(link_vdevs); 1199 wlan_objmgr_peer_release_ref(link_peer, 1200 WLAN_MLO_MGR_ID); 1201 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " is exists, creation failed", 1202 ml_dev->mld_id, 1203 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes)); 1204 return QDF_STATUS_E_EXISTS; 1205 } 1206 1207 /* Attach MLO peer to ML Peer table */ 1208 status = mlo_dev_mlpeer_attach(ml_dev, ml_peer); 1209 if (status != QDF_STATUS_SUCCESS) { 1210 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " attach failed", 1211 ml_dev->mld_id, 1212 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes)); 1213 mlo_reset_link_peer(ml_peer, link_peer); 1214 wlan_objmgr_peer_release_ref(link_peer, 1215 WLAN_MLO_MGR_ID); 1216 mlo_peer_free(ml_peer); 1217 mlo_dev_release_link_vdevs(link_vdevs); 1218 return status; 1219 } 1220 } 1221 1222 wlan_mlo_peer_get_ref(ml_peer); 1223 1224 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) { 1225 /* Notify other vdevs about link peer creation */ 1226 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 1227 vdev_link = link_vdevs[i]; 1228 if (!vdev_link) 1229 continue; 1230 1231 if (vdev_link == vdev) 1232 continue; 1233 1234 mlo_partner_peer_create_post(ml_dev, vdev_link, 1235 ml_peer, frm_buf, ml_info); 1236 } 1237 status = wlan_mlo_check_and_create_bridge_peer(vdev, ml_peer, 1238 link_vdevs, 1239 ml_info->num_partner_links); 1240 if (QDF_STATUS_SUCCESS != status) { 1241 mlo_err("MLD ID %d: Bridge peer creation failed", 1242 ml_dev->mld_id); 1243 wlan_mlo_partner_peer_create_failed_notify(ml_peer); 1244 mlo_dev_release_link_vdevs(link_vdevs); 1245 wlan_mlo_peer_release_ref(ml_peer); 1246 return QDF_STATUS_E_FAILURE; 1247 } 1248 } 1249 mlo_dev_release_link_vdevs(link_vdevs); 1250 1251 if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) { 1252 mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " allocation failed", 1253 ml_dev->mld_id, 1254 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes)); 1255 wlan_mlo_peer_release_ref(ml_peer); 1256 return QDF_STATUS_E_FAILURE; 1257 } 1258 1259 mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " allocated %pK", 1260 ml_dev->mld_id, 1261 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 1262 ml_peer); 1263 1264 /* 1265 * wlan_mlo_peer_create() is trigggered after getting peer 1266 * assoc confirm from FW. For single link MLO connection, it is 1267 * OK to trigger assoc response from here. 1268 */ 1269 if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) && 1270 (!wlan_mlo_peer_is_nawds(ml_peer))) { 1271 if ((ml_peer->max_links == 1) && 1272 (ml_peer->link_peer_cnt == 1)) { 1273 assoc_peer = ml_peer->peer_list[0].link_peer; 1274 if (assoc_peer) 1275 mlo_mlme_peer_assoc_resp(assoc_peer); 1276 } 1277 } 1278 1279 wlan_mlo_peer_release_ref(ml_peer); 1280 1281 return QDF_STATUS_SUCCESS; 1282 } 1283 1284 QDF_STATUS wlan_mlo_link_peer_attach(struct wlan_mlo_peer_context *ml_peer, 1285 struct wlan_objmgr_peer *peer, 1286 qdf_nbuf_t frm_buf) 1287 { 1288 QDF_STATUS status; 1289 struct wlan_objmgr_peer *assoc_peer; 1290 struct wlan_objmgr_vdev *vdev = NULL; 1291 1292 if (!ml_peer) 1293 return QDF_STATUS_E_FAILURE; 1294 1295 vdev = wlan_peer_get_vdev(peer); 1296 if (!vdev) 1297 return QDF_STATUS_E_FAILURE; 1298 1299 /* Populate Link peer pointer, peer MAC address, 1300 * MLD address. HW link ID, update ref count 1301 */ 1302 status = mlo_peer_attach_link_peer(ml_peer, peer, frm_buf); 1303 if (QDF_IS_STATUS_ERROR(status)) 1304 return status; 1305 1306 /* Store AID, MLO Peer pointer in link peer, take link peer ref count */ 1307 mlo_peer_populate_link_peer(ml_peer, peer); 1308 1309 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) { 1310 if (ml_peer->max_links == ml_peer->link_peer_cnt) { 1311 assoc_peer = ml_peer->peer_list[0].link_peer; 1312 if (assoc_peer) 1313 mlo_mlme_peer_assoc_resp(assoc_peer); 1314 } 1315 } 1316 1317 return status; 1318 } 1319 1320 QDF_STATUS wlan_mlo_link_peer_delete(struct wlan_objmgr_peer *peer) 1321 { 1322 struct wlan_mlo_peer_context *ml_peer; 1323 1324 ml_peer = peer->mlo_peer_ctx; 1325 1326 if (!ml_peer) 1327 return QDF_STATUS_E_NOENT; 1328 1329 mlo_reset_link_peer(ml_peer, peer); 1330 mlo_peer_detach_link_peer(ml_peer, peer); 1331 wlan_mlo_peer_release_ref(ml_peer); 1332 1333 return QDF_STATUS_SUCCESS; 1334 } 1335 1336 qdf_export_symbol(wlan_mlo_link_peer_delete); 1337 1338 qdf_nbuf_t mlo_peer_get_link_peer_assoc_req_buf( 1339 struct wlan_mlo_peer_context *ml_peer, 1340 uint8_t link_ix) 1341 { 1342 struct wlan_objmgr_peer *peer = NULL; 1343 qdf_nbuf_t assocbuf = NULL; 1344 1345 if (!ml_peer) 1346 return NULL; 1347 1348 peer = wlan_mlo_peer_get_assoc_peer(ml_peer); 1349 if (!peer) 1350 return NULL; 1351 1352 assocbuf = mlo_mlme_get_link_assoc_req(peer, link_ix); 1353 1354 return assocbuf; 1355 } 1356 1357 void wlan_mlo_peer_get_links_info(struct wlan_objmgr_peer *peer, 1358 struct mlo_tgt_partner_info *ml_links) 1359 { 1360 struct wlan_mlo_peer_context *ml_peer; 1361 struct wlan_mlo_link_peer_entry *peer_entry; 1362 struct wlan_objmgr_peer *link_peer; 1363 struct wlan_objmgr_vdev *link_vdev; 1364 uint8_t i, ix, idx = 0; 1365 struct wlan_mlo_eml_cap *ml_emlcap; 1366 1367 ml_peer = peer->mlo_peer_ctx; 1368 ml_links->num_partner_links = 0; 1369 1370 if (!ml_peer) 1371 return; 1372 1373 ml_emlcap = &ml_peer->mlpeer_emlcap; 1374 1375 mlo_peer_lock_acquire(ml_peer); 1376 1377 if ((ml_peer->mlpeer_state != ML_PEER_CREATED) && 1378 (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) { 1379 mlo_peer_lock_release(ml_peer); 1380 return; 1381 } 1382 1383 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 1384 peer_entry = &ml_peer->peer_list[i]; 1385 link_peer = peer_entry->link_peer; 1386 1387 if (!link_peer) 1388 continue; 1389 idx++; 1390 if (link_peer == peer) 1391 continue; 1392 link_vdev = wlan_peer_get_vdev(link_peer); 1393 if (!link_vdev) 1394 continue; 1395 1396 if (ml_links->num_partner_links >= WLAN_UMAC_MLO_MAX_VDEVS) 1397 break; 1398 1399 ix = ml_links->num_partner_links; 1400 ml_links->link_info[ix].vdev_id = wlan_vdev_get_id(link_vdev); 1401 ml_links->link_info[ix].hw_mld_link_id = peer_entry->hw_link_id; 1402 ml_links->link_info[ix].mlo_enabled = 1; 1403 ml_links->link_info[ix].mlo_assoc_link = 1404 wlan_peer_mlme_is_assoc_peer(link_peer); 1405 ml_links->link_info[ix].mlo_primary_umac = 1406 peer_entry->is_primary; 1407 ml_links->link_info[ix].mlo_logical_link_index_valid = 1; 1408 ml_links->link_info[ix].emlsr_support = ml_emlcap->emlsr_supp; 1409 ml_links->link_info[ix].logical_link_index = idx - 1; 1410 ml_links->num_partner_links++; 1411 } 1412 mlo_peer_lock_release(ml_peer); 1413 } 1414 1415 qdf_export_symbol(wlan_mlo_peer_get_links_info); 1416 1417 uint8_t wlan_mlo_peer_get_primary_peer_link_id(struct wlan_objmgr_peer *peer) 1418 { 1419 struct wlan_mlo_peer_context *ml_peer; 1420 struct wlan_mlo_link_peer_entry *peer_entry; 1421 struct wlan_objmgr_peer *link_peer; 1422 struct wlan_objmgr_vdev *link_vdev; 1423 uint8_t i, vdev_link_id; 1424 1425 ml_peer = peer->mlo_peer_ctx; 1426 1427 if (!ml_peer) { 1428 mlo_err("ml_peer is null"); 1429 return WLAN_LINK_ID_INVALID; 1430 } 1431 mlo_peer_lock_acquire(ml_peer); 1432 1433 if ((ml_peer->mlpeer_state != ML_PEER_CREATED) && 1434 (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) { 1435 mlo_peer_lock_release(ml_peer); 1436 mlo_err("ml_peer is not created and association is not done"); 1437 return WLAN_LINK_ID_INVALID; 1438 } 1439 1440 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 1441 peer_entry = &ml_peer->peer_list[i]; 1442 link_peer = peer_entry->link_peer; 1443 if (!link_peer) 1444 continue; 1445 1446 if (peer_entry->is_primary) { 1447 link_vdev = wlan_peer_get_vdev(link_peer); 1448 if (!link_vdev) { 1449 mlo_peer_lock_release(ml_peer); 1450 mlo_err("link vdev not found"); 1451 return WLAN_LINK_ID_INVALID; 1452 } 1453 vdev_link_id = wlan_vdev_get_link_id(link_vdev); 1454 mlo_peer_lock_release(ml_peer); 1455 return vdev_link_id; 1456 } 1457 } 1458 mlo_peer_lock_release(ml_peer); 1459 mlo_err("None of the peer is designated as primary"); 1460 return WLAN_LINK_ID_INVALID; 1461 } 1462 1463 qdf_export_symbol(wlan_mlo_peer_get_primary_peer_link_id); 1464 1465 void wlan_mlo_peer_get_partner_links_info(struct wlan_objmgr_peer *peer, 1466 struct mlo_partner_info *ml_links) 1467 { 1468 struct wlan_mlo_peer_context *ml_peer; 1469 struct wlan_mlo_link_peer_entry *peer_entry; 1470 struct wlan_objmgr_peer *link_peer; 1471 struct wlan_objmgr_vdev *link_vdev; 1472 uint8_t i, ix; 1473 1474 ml_peer = peer->mlo_peer_ctx; 1475 ml_links->num_partner_links = 0; 1476 1477 if (!ml_peer) 1478 return; 1479 1480 mlo_peer_lock_acquire(ml_peer); 1481 1482 if ((ml_peer->mlpeer_state != ML_PEER_CREATED) && 1483 (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) { 1484 mlo_peer_lock_release(ml_peer); 1485 return; 1486 } 1487 1488 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 1489 peer_entry = &ml_peer->peer_list[i]; 1490 link_peer = peer_entry->link_peer; 1491 1492 if (!link_peer) 1493 continue; 1494 1495 if (link_peer == peer) 1496 continue; 1497 1498 link_vdev = wlan_peer_get_vdev(link_peer); 1499 if (!link_vdev) 1500 continue; 1501 1502 if (ml_links->num_partner_links >= WLAN_UMAC_MLO_MAX_VDEVS) 1503 break; 1504 1505 ix = ml_links->num_partner_links; 1506 ml_links->partner_link_info[ix].link_id = peer_entry->link_ix; 1507 ml_links->partner_link_info[ix].is_bridge = 1508 (wlan_peer_get_peer_type(link_peer) == WLAN_PEER_MLO_BRIDGE); 1509 1510 qdf_copy_macaddr(&ml_links->partner_link_info[ix].link_addr, 1511 &peer_entry->link_addr); 1512 ml_links->num_partner_links++; 1513 } 1514 mlo_peer_lock_release(ml_peer); 1515 } 1516 1517 qdf_export_symbol(wlan_mlo_peer_get_partner_links_info); 1518 1519 #ifdef UMAC_SUPPORT_MLNAWDS 1520 bool wlan_mlo_peer_is_nawds(struct wlan_mlo_peer_context *ml_peer) 1521 { 1522 bool status = false; 1523 1524 if (!ml_peer) 1525 return status; 1526 1527 mlo_peer_lock_acquire(ml_peer); 1528 if (ml_peer->is_nawds_ml_peer) 1529 status = true; 1530 mlo_peer_lock_release(ml_peer); 1531 1532 return status; 1533 } 1534 1535 qdf_export_symbol(wlan_mlo_peer_is_nawds); 1536 #endif 1537 1538 #ifdef MESH_MODE_SUPPORT 1539 bool wlan_mlo_peer_is_mesh(struct wlan_mlo_peer_context *ml_peer) 1540 { 1541 bool status = false; 1542 1543 if (!ml_peer) 1544 return status; 1545 1546 mlo_peer_lock_acquire(ml_peer); 1547 if (ml_peer->is_mesh_ml_peer) 1548 status = true; 1549 mlo_peer_lock_release(ml_peer); 1550 1551 return status; 1552 } 1553 1554 qdf_export_symbol(wlan_mlo_peer_is_mesh); 1555 #endif 1556 1557 #ifdef UMAC_MLO_AUTH_DEFER 1558 void mlo_peer_free_auth_param(struct mlpeer_auth_params *auth_params) 1559 { 1560 if (auth_params->rs) 1561 qdf_mem_free(auth_params->rs); 1562 1563 if (auth_params->wbuf) 1564 qdf_nbuf_free(auth_params->wbuf); 1565 1566 qdf_mem_free(auth_params); 1567 } 1568 1569 QDF_STATUS mlo_peer_link_auth_defer(struct wlan_mlo_peer_context *ml_peer, 1570 struct qdf_mac_addr *link_mac, 1571 struct mlpeer_auth_params *auth_params) 1572 { 1573 uint8_t i; 1574 uint8_t free_entries = 0; 1575 struct mlpeer_auth_params *recv_auth; 1576 QDF_STATUS status = QDF_STATUS_E_FAILURE; 1577 1578 if (!ml_peer) 1579 return status; 1580 1581 mlo_peer_lock_acquire(ml_peer); 1582 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 1583 recv_auth = ml_peer->pending_auth[i]; 1584 if (!recv_auth) { 1585 free_entries++; 1586 continue; 1587 } 1588 /* overwrite the entry with latest entry */ 1589 if (qdf_is_macaddr_equal(link_mac, &recv_auth->link_addr)) { 1590 mlo_peer_free_auth_param(recv_auth); 1591 ml_peer->pending_auth[i] = auth_params; 1592 mlo_peer_lock_release(ml_peer); 1593 1594 return QDF_STATUS_SUCCESS; 1595 } 1596 } 1597 1598 if (!free_entries) { 1599 mlo_peer_lock_release(ml_peer); 1600 return QDF_STATUS_E_FAILURE; 1601 } 1602 1603 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 1604 recv_auth = ml_peer->pending_auth[i]; 1605 if (!recv_auth) { 1606 ml_peer->pending_auth[i] = auth_params; 1607 status = QDF_STATUS_SUCCESS; 1608 break; 1609 } 1610 } 1611 mlo_peer_lock_release(ml_peer); 1612 1613 return status; 1614 } 1615 1616 bool wlan_mlo_partner_peer_delete_is_allowed(struct wlan_objmgr_peer *src_peer) 1617 { 1618 struct wlan_objmgr_vdev *vdev = NULL; 1619 struct wlan_mlo_peer_context *ml_peer; 1620 1621 vdev = wlan_peer_get_vdev(src_peer); 1622 if (!vdev) 1623 return false; 1624 1625 ml_peer = src_peer->mlo_peer_ctx; 1626 if (!wlan_peer_is_mlo(src_peer) || !ml_peer) 1627 return false; 1628 1629 if (wlan_vdev_mlme_op_flags_get(vdev, WLAN_VDEV_OP_MLO_STOP_LINK_DEL) || 1630 wlan_vdev_mlme_op_flags_get(vdev, 1631 WLAN_VDEV_OP_MLO_LINK_TBTT_COMPLETE)) { 1632 /* Single LINK MLO connection */ 1633 if (ml_peer->link_peer_cnt == 1) 1634 return false; 1635 /* 1636 * If this link is primary TQM, then delete MLO connection till 1637 * primary umac migration is implemented 1638 */ 1639 if (wlan_mlo_peer_get_primary_peer_link_id(src_peer) != 1640 wlan_vdev_get_link_id(vdev)) 1641 return false; 1642 } 1643 1644 return true; 1645 } 1646 #endif 1647