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 frm_buf = qdf_nbuf_clone(peer_entry->assoc_rsp_buf); 635 break; 636 } 637 } 638 mlo_peer_lock_release(ml_peer); 639 640 return frm_buf; 641 } 642 643 void wlan_mlo_peer_free_all_link_assoc_resp_buf( 644 struct wlan_objmgr_peer *link_peer) 645 { 646 struct wlan_mlo_link_peer_entry *peer_entry; 647 struct wlan_mlo_peer_context *ml_peer; 648 uint8_t i; 649 650 ml_peer = link_peer->mlo_peer_ctx; 651 if (!ml_peer) 652 return; 653 654 mlo_peer_lock_acquire(ml_peer); 655 656 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 657 peer_entry = &ml_peer->peer_list[i]; 658 659 if (peer_entry->assoc_rsp_buf) { 660 qdf_nbuf_free(peer_entry->assoc_rsp_buf); 661 peer_entry->assoc_rsp_buf = NULL; 662 } 663 } 664 mlo_peer_lock_release(ml_peer); 665 } 666 667 static QDF_STATUS mlo_peer_detach_link_peer( 668 struct wlan_mlo_peer_context *ml_peer, 669 struct wlan_objmgr_peer *link_peer) 670 { 671 struct wlan_mlo_link_peer_entry *peer_entry; 672 QDF_STATUS status = QDF_STATUS_E_RESOURCES; 673 uint16_t i; 674 675 mlo_peer_lock_acquire(ml_peer); 676 677 if (ml_peer->mlpeer_state != ML_PEER_DISCONN_INITIATED) { 678 mlo_peer_lock_release(ml_peer); 679 return status; 680 } 681 682 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 683 peer_entry = &ml_peer->peer_list[i]; 684 if (!peer_entry->link_peer) 685 continue; 686 687 if (peer_entry->link_peer != link_peer) 688 continue; 689 690 if (peer_entry->assoc_rsp_buf) { 691 qdf_nbuf_free(peer_entry->assoc_rsp_buf); 692 peer_entry->assoc_rsp_buf = NULL; 693 } 694 695 wlan_objmgr_peer_release_ref(link_peer, WLAN_MLO_MGR_ID); 696 peer_entry->link_peer = NULL; 697 ml_peer->link_peer_cnt--; 698 status = QDF_STATUS_SUCCESS; 699 break; 700 } 701 mlo_peer_lock_release(ml_peer); 702 703 return status; 704 } 705 706 static QDF_STATUS mlo_dev_get_link_vdevs( 707 struct wlan_objmgr_vdev *vdev, 708 struct wlan_mlo_dev_context *ml_dev, 709 struct mlo_partner_info *ml_info, 710 struct wlan_objmgr_vdev *link_vdevs[]) 711 { 712 uint16_t i, j; 713 struct wlan_objmgr_vdev *vdev_link; 714 uint8_t link_id; 715 716 if (!ml_dev) { 717 mlo_err("ml_dev is null"); 718 return QDF_STATUS_E_INVAL; 719 } 720 721 if (!ml_info) { 722 mlo_err("ml_info is null"); 723 return QDF_STATUS_E_INVAL; 724 } 725 726 mlo_debug("num_partner_links %d", ml_info->num_partner_links); 727 for (i = 0; i < ml_info->num_partner_links; i++) { 728 link_id = ml_info->partner_link_info[i].link_id; 729 vdev_link = mlo_get_vdev_by_link_id(vdev, link_id); 730 if (vdev_link) { 731 link_vdevs[i] = vdev_link; 732 } else { 733 /* release ref which were taken before failure */ 734 for (j = 0; j < i; j++) { 735 vdev_link = link_vdevs[j]; 736 if (!vdev_link) 737 continue; 738 739 wlan_objmgr_vdev_release_ref(vdev_link, 740 WLAN_MLO_MGR_ID); 741 } 742 return QDF_STATUS_E_INVAL; 743 } 744 } 745 746 return QDF_STATUS_SUCCESS; 747 } 748 749 static void mlo_dev_release_link_vdevs( 750 struct wlan_objmgr_vdev *link_vdevs[]) 751 { 752 uint16_t i; 753 struct wlan_objmgr_vdev *vdev_link; 754 755 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 756 vdev_link = link_vdevs[i]; 757 if (!vdev_link) 758 continue; 759 760 wlan_objmgr_vdev_release_ref(vdev_link, WLAN_MLO_MGR_ID); 761 } 762 } 763 764 #ifdef WLAN_FEATURE_11BE 765 static void 766 wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context *ml_peer, 767 struct mlo_partner_info *ml_info) 768 { 769 ml_peer->t2lm_policy.t2lm_enable_val = ml_info->t2lm_enable_val; 770 } 771 #else 772 static void 773 wlan_mlo_peer_set_t2lm_enable_val(struct wlan_mlo_peer_context *ml_peer, 774 struct mlo_partner_info *ml_info) 775 {} 776 #endif /* WLAN_FEATURE_11BE */ 777 778 QDF_STATUS wlan_mlo_peer_create(struct wlan_objmgr_vdev *vdev, 779 struct wlan_objmgr_peer *link_peer, 780 struct mlo_partner_info *ml_info, 781 qdf_nbuf_t frm_buf, 782 uint16_t aid) 783 { 784 struct wlan_mlo_dev_context *ml_dev; 785 struct wlan_mlo_peer_context *ml_peer = NULL; 786 struct wlan_objmgr_vdev *link_vdevs[WLAN_UMAC_MLO_MAX_VDEVS] = { NULL }; 787 struct wlan_objmgr_vdev *vdev_link; 788 QDF_STATUS status; 789 uint16_t i; 790 struct wlan_objmgr_peer *assoc_peer; 791 bool is_ml_peer_attached = false; 792 793 /* get ML VDEV from VDEV */ 794 ml_dev = vdev->mlo_dev_ctx; 795 796 if (!ml_dev) { 797 mlo_err("ML dev ctx is NULL"); 798 return QDF_STATUS_E_NULL_VALUE; 799 } 800 801 /* Check resources of Partner VDEV */ 802 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) { 803 if (wlan_mlo_is_mld_ctx_exist( 804 (struct qdf_mac_addr *)&link_peer->mldaddr[0])) { 805 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " is matching with one of the MLD address in the system", 806 ml_dev->mld_id, 807 QDF_MAC_ADDR_REF(link_peer->mldaddr)); 808 return QDF_STATUS_E_FAILURE; 809 } 810 status = mlo_dev_get_link_vdevs(vdev, ml_dev, 811 ml_info, link_vdevs); 812 if (QDF_IS_STATUS_ERROR(status)) { 813 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " get link vdevs failed", 814 ml_dev->mld_id, 815 QDF_MAC_ADDR_REF(link_peer->mldaddr)); 816 return QDF_STATUS_E_FAILURE; 817 } 818 819 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 820 vdev_link = link_vdevs[i]; 821 if (!vdev_link) { 822 mlo_debug("vdev_link is null"); 823 continue; 824 } 825 826 if (wlan_vdev_is_mlo_peer_create_allowed(vdev_link) 827 != QDF_STATUS_SUCCESS) { 828 mlo_dev_release_link_vdevs(link_vdevs); 829 830 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " create not allowed on link vdev %d", 831 ml_dev->mld_id, 832 QDF_MAC_ADDR_REF 833 (link_peer->mldaddr), 834 wlan_vdev_get_id(vdev_link)); 835 return QDF_STATUS_E_INVAL; 836 } 837 } 838 839 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 840 vdev_link = link_vdevs[i]; 841 if (vdev_link && (vdev_link != vdev) && 842 (wlan_vdev_get_peer_count(vdev_link) > 843 wlan_vdev_get_max_peer_count(vdev_link))) { 844 mlo_dev_release_link_vdevs(link_vdevs); 845 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " Max peer count reached on link vdev %d", 846 ml_dev->mld_id, 847 QDF_MAC_ADDR_REF 848 (link_peer->mldaddr), 849 wlan_vdev_get_id(vdev_link)); 850 return QDF_STATUS_E_RESOURCES; 851 } 852 } 853 } 854 855 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) { 856 ml_peer = wlan_mlo_get_mlpeer(ml_dev, 857 (struct qdf_mac_addr *)&link_peer->mldaddr[0]); 858 if (ml_peer) 859 is_ml_peer_attached = true; 860 } 861 if (!ml_peer) { 862 /* Allocate MLO peer */ 863 ml_peer = qdf_mem_malloc(sizeof(*ml_peer)); 864 if (!ml_peer) { 865 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " mem alloc failed", 866 ml_dev->mld_id, 867 QDF_MAC_ADDR_REF(link_peer->mldaddr)); 868 mlo_dev_release_link_vdevs(link_vdevs); 869 return QDF_STATUS_E_NOMEM; 870 } 871 872 qdf_atomic_init(&ml_peer->ref_cnt); 873 mlo_peer_lock_create(ml_peer); 874 ml_peer->ml_dev = ml_dev; 875 ml_peer->mlpeer_state = ML_PEER_CREATED; 876 ml_peer->max_links = ml_info->num_partner_links; 877 ml_peer->primary_umac_psoc_id = ML_PRIMARY_UMAC_ID_INVAL; 878 879 ml_peer->mlo_peer_id = mlo_ap_ml_peerid_alloc(); 880 if (ml_peer->mlo_peer_id == MLO_INVALID_PEER_ID) { 881 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " invalid ml peer id", 882 ml_dev->mld_id, 883 QDF_MAC_ADDR_REF 884 (ml_peer->peer_mld_addr.bytes)); 885 mlo_peer_free(ml_peer); 886 mlo_dev_release_link_vdevs(link_vdevs); 887 return QDF_STATUS_E_RESOURCES; 888 } 889 890 qdf_copy_macaddr((struct qdf_mac_addr *)&ml_peer->peer_mld_addr, 891 (struct qdf_mac_addr *)&link_peer->mldaddr[0]); 892 wlan_mlo_peer_set_t2lm_enable_val(ml_peer, ml_info); 893 894 /* Allocate AID */ 895 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) { 896 if (aid == (uint16_t)-1) { 897 status = mlo_peer_allocate_aid(ml_dev, ml_peer); 898 if (status != QDF_STATUS_SUCCESS) { 899 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " aid alloc failed", 900 ml_dev->mld_id, 901 QDF_MAC_ADDR_REF 902 (ml_peer->peer_mld_addr.bytes)); 903 mlo_peer_free(ml_peer); 904 mlo_dev_release_link_vdevs(link_vdevs); 905 return status; 906 } 907 } else { 908 ml_peer->assoc_id = aid; 909 } 910 } 911 } 912 913 /* Populate Link peer pointer, peer MAC address, 914 * MLD address. HW link ID, update ref count 915 */ 916 status = mlo_peer_attach_link_peer(ml_peer, link_peer, NULL); 917 if (QDF_IS_STATUS_ERROR(status)) { 918 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " link peer attach failed", 919 ml_dev->mld_id, 920 QDF_MAC_ADDR_REF 921 (ml_peer->peer_mld_addr.bytes)); 922 mlo_peer_free(ml_peer); 923 mlo_dev_release_link_vdevs(link_vdevs); 924 return status; 925 } 926 927 /* Allocate Primary UMAC */ 928 mlo_peer_allocate_primary_umac(ml_dev, ml_peer, link_vdevs); 929 930 /* Store AID, MLO Peer pointer in link peer, take link peer ref count */ 931 mlo_peer_populate_link_peer(ml_peer, link_peer); 932 933 mlo_peer_populate_nawds_params(ml_peer, ml_info); 934 935 if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) || 936 ((wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) && 937 !is_ml_peer_attached)) { 938 /* Attach MLO peer to ML Peer table */ 939 status = mlo_dev_mlpeer_attach(ml_dev, ml_peer); 940 if (status != QDF_STATUS_SUCCESS) { 941 mlo_err("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " attach failed", 942 ml_dev->mld_id, 943 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes)); 944 mlo_reset_link_peer(ml_peer, link_peer); 945 wlan_objmgr_peer_release_ref(link_peer, 946 WLAN_MLO_MGR_ID); 947 mlo_peer_free(ml_peer); 948 mlo_dev_release_link_vdevs(link_vdevs); 949 return status; 950 } 951 } 952 953 wlan_mlo_peer_get_ref(ml_peer); 954 955 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) { 956 /* Notify other vdevs about link peer creation */ 957 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 958 vdev_link = link_vdevs[i]; 959 if (!vdev_link) 960 continue; 961 962 if (vdev_link == vdev) 963 continue; 964 965 mlo_partner_peer_create_post(ml_dev, vdev_link, 966 ml_peer, frm_buf, ml_info); 967 } 968 } 969 mlo_dev_release_link_vdevs(link_vdevs); 970 971 if (ml_peer->mlpeer_state == ML_PEER_DISCONN_INITIATED) { 972 mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " allocation failed", 973 ml_dev->mld_id, 974 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes)); 975 wlan_mlo_peer_release_ref(ml_peer); 976 return QDF_STATUS_E_FAILURE; 977 } 978 979 mlo_info("MLD ID %d ML Peer " QDF_MAC_ADDR_FMT " allocated %pK", 980 ml_dev->mld_id, 981 QDF_MAC_ADDR_REF(ml_peer->peer_mld_addr.bytes), 982 ml_peer); 983 984 /* 985 * wlan_mlo_peer_create() is trigggered after getting peer 986 * assoc confirm from FW. For single link MLO connection, it is 987 * OK to trigger assoc response from here. 988 */ 989 if ((wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) && 990 (!wlan_mlo_peer_is_nawds(ml_peer))) { 991 if (ml_peer->max_links == ml_peer->link_peer_cnt) { 992 assoc_peer = ml_peer->peer_list[0].link_peer; 993 if (assoc_peer) 994 mlo_mlme_peer_assoc_resp(assoc_peer); 995 } 996 } 997 998 wlan_mlo_peer_release_ref(ml_peer); 999 1000 return QDF_STATUS_SUCCESS; 1001 } 1002 1003 QDF_STATUS wlan_mlo_link_peer_attach(struct wlan_mlo_peer_context *ml_peer, 1004 struct wlan_objmgr_peer *peer, 1005 qdf_nbuf_t frm_buf) 1006 { 1007 QDF_STATUS status; 1008 struct wlan_objmgr_peer *assoc_peer; 1009 struct wlan_objmgr_vdev *vdev = NULL; 1010 1011 if (!ml_peer) 1012 return QDF_STATUS_E_FAILURE; 1013 1014 vdev = wlan_peer_get_vdev(peer); 1015 if (!vdev) 1016 return QDF_STATUS_E_FAILURE; 1017 1018 /* Populate Link peer pointer, peer MAC address, 1019 * MLD address. HW link ID, update ref count 1020 */ 1021 status = mlo_peer_attach_link_peer(ml_peer, peer, frm_buf); 1022 if (QDF_IS_STATUS_ERROR(status)) 1023 return status; 1024 1025 /* Store AID, MLO Peer pointer in link peer, take link peer ref count */ 1026 mlo_peer_populate_link_peer(ml_peer, peer); 1027 1028 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) { 1029 if (ml_peer->max_links == ml_peer->link_peer_cnt) { 1030 assoc_peer = ml_peer->peer_list[0].link_peer; 1031 if (assoc_peer) 1032 mlo_mlme_peer_assoc_resp(assoc_peer); 1033 } 1034 } 1035 1036 return status; 1037 } 1038 1039 QDF_STATUS wlan_mlo_link_peer_delete(struct wlan_objmgr_peer *peer) 1040 { 1041 struct wlan_mlo_peer_context *ml_peer; 1042 1043 ml_peer = peer->mlo_peer_ctx; 1044 1045 if (!ml_peer) 1046 return QDF_STATUS_E_NOENT; 1047 1048 mlo_reset_link_peer(ml_peer, peer); 1049 mlo_peer_detach_link_peer(ml_peer, peer); 1050 wlan_mlo_peer_release_ref(ml_peer); 1051 1052 return QDF_STATUS_SUCCESS; 1053 } 1054 1055 qdf_export_symbol(wlan_mlo_link_peer_delete); 1056 1057 qdf_nbuf_t mlo_peer_get_link_peer_assoc_req_buf( 1058 struct wlan_mlo_peer_context *ml_peer, 1059 uint8_t link_ix) 1060 { 1061 struct wlan_objmgr_peer *peer = NULL; 1062 qdf_nbuf_t assocbuf = NULL; 1063 1064 if (!ml_peer) 1065 return NULL; 1066 1067 peer = wlan_mlo_peer_get_assoc_peer(ml_peer); 1068 if (!peer) 1069 return NULL; 1070 1071 assocbuf = mlo_mlme_get_link_assoc_req(peer, link_ix); 1072 1073 return assocbuf; 1074 } 1075 1076 void wlan_mlo_peer_get_links_info(struct wlan_objmgr_peer *peer, 1077 struct mlo_tgt_partner_info *ml_links) 1078 { 1079 struct wlan_mlo_peer_context *ml_peer; 1080 struct wlan_mlo_link_peer_entry *peer_entry; 1081 struct wlan_objmgr_peer *link_peer; 1082 struct wlan_objmgr_vdev *link_vdev; 1083 uint8_t i, ix; 1084 1085 ml_peer = peer->mlo_peer_ctx; 1086 ml_links->num_partner_links = 0; 1087 1088 if (!ml_peer) 1089 return; 1090 1091 mlo_peer_lock_acquire(ml_peer); 1092 1093 if ((ml_peer->mlpeer_state != ML_PEER_CREATED) && 1094 (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) { 1095 mlo_peer_lock_release(ml_peer); 1096 return; 1097 } 1098 1099 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 1100 peer_entry = &ml_peer->peer_list[i]; 1101 link_peer = peer_entry->link_peer; 1102 1103 if (!link_peer) 1104 continue; 1105 if (link_peer == peer) 1106 continue; 1107 link_vdev = wlan_peer_get_vdev(link_peer); 1108 if (!link_vdev) 1109 continue; 1110 1111 if (ml_links->num_partner_links >= WLAN_UMAC_MLO_MAX_VDEVS) 1112 break; 1113 1114 ix = ml_links->num_partner_links; 1115 ml_links->link_info[ix].vdev_id = wlan_vdev_get_id(link_vdev); 1116 ml_links->link_info[ix].hw_mld_link_id = peer_entry->hw_link_id; 1117 ml_links->num_partner_links++; 1118 } 1119 mlo_peer_lock_release(ml_peer); 1120 } 1121 1122 qdf_export_symbol(wlan_mlo_peer_get_links_info); 1123 1124 uint8_t wlan_mlo_peer_get_primary_peer_link_id(struct wlan_objmgr_peer *peer) 1125 { 1126 struct wlan_mlo_peer_context *ml_peer; 1127 struct wlan_mlo_link_peer_entry *peer_entry; 1128 struct wlan_objmgr_peer *link_peer; 1129 struct wlan_objmgr_vdev *link_vdev; 1130 uint8_t i, vdev_link_id; 1131 1132 ml_peer = peer->mlo_peer_ctx; 1133 1134 if (!ml_peer) { 1135 mlo_err("ml_peer is null"); 1136 return WLAN_LINK_ID_INVALID; 1137 } 1138 mlo_peer_lock_acquire(ml_peer); 1139 1140 if ((ml_peer->mlpeer_state != ML_PEER_CREATED) && 1141 (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) { 1142 mlo_peer_lock_release(ml_peer); 1143 mlo_err("ml_peer is not created and association is not done"); 1144 return WLAN_LINK_ID_INVALID; 1145 } 1146 1147 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 1148 peer_entry = &ml_peer->peer_list[i]; 1149 link_peer = peer_entry->link_peer; 1150 if (!link_peer) 1151 continue; 1152 1153 if (peer_entry->is_primary) { 1154 link_vdev = wlan_peer_get_vdev(link_peer); 1155 if (!link_vdev) { 1156 mlo_peer_lock_release(ml_peer); 1157 mlo_err("link vdev not found"); 1158 return WLAN_LINK_ID_INVALID; 1159 } 1160 vdev_link_id = wlan_vdev_get_link_id(link_vdev); 1161 mlo_peer_lock_release(ml_peer); 1162 return vdev_link_id; 1163 } 1164 } 1165 mlo_peer_lock_release(ml_peer); 1166 mlo_err("None of the peer is designated as primary"); 1167 return WLAN_LINK_ID_INVALID; 1168 } 1169 1170 qdf_export_symbol(wlan_mlo_peer_get_primary_peer_link_id); 1171 1172 void wlan_mlo_peer_get_partner_links_info(struct wlan_objmgr_peer *peer, 1173 struct mlo_partner_info *ml_links) 1174 { 1175 struct wlan_mlo_peer_context *ml_peer; 1176 struct wlan_mlo_link_peer_entry *peer_entry; 1177 struct wlan_objmgr_peer *link_peer; 1178 struct wlan_objmgr_vdev *link_vdev; 1179 uint8_t i, ix; 1180 1181 ml_peer = peer->mlo_peer_ctx; 1182 ml_links->num_partner_links = 0; 1183 1184 if (!ml_peer) 1185 return; 1186 1187 mlo_peer_lock_acquire(ml_peer); 1188 1189 if ((ml_peer->mlpeer_state != ML_PEER_CREATED) && 1190 (ml_peer->mlpeer_state != ML_PEER_ASSOC_DONE)) { 1191 mlo_peer_lock_release(ml_peer); 1192 return; 1193 } 1194 1195 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 1196 peer_entry = &ml_peer->peer_list[i]; 1197 link_peer = peer_entry->link_peer; 1198 1199 if (!link_peer) 1200 continue; 1201 1202 if (link_peer == peer) 1203 continue; 1204 1205 link_vdev = wlan_peer_get_vdev(link_peer); 1206 if (!link_vdev) 1207 continue; 1208 1209 if (ml_links->num_partner_links >= WLAN_UMAC_MLO_MAX_VDEVS) 1210 break; 1211 1212 ix = ml_links->num_partner_links; 1213 ml_links->partner_link_info[ix].link_id = peer_entry->link_ix; 1214 1215 qdf_copy_macaddr(&ml_links->partner_link_info[ix].link_addr, 1216 &peer_entry->link_addr); 1217 ml_links->num_partner_links++; 1218 } 1219 mlo_peer_lock_release(ml_peer); 1220 } 1221 1222 qdf_export_symbol(wlan_mlo_peer_get_partner_links_info); 1223 1224 #ifdef UMAC_SUPPORT_MLNAWDS 1225 bool wlan_mlo_peer_is_nawds(struct wlan_mlo_peer_context *ml_peer) 1226 { 1227 bool status = false; 1228 1229 if (!ml_peer) 1230 return status; 1231 1232 mlo_peer_lock_acquire(ml_peer); 1233 if (ml_peer->is_nawds_ml_peer) 1234 status = true; 1235 mlo_peer_lock_release(ml_peer); 1236 1237 return status; 1238 } 1239 1240 qdf_export_symbol(wlan_mlo_peer_is_nawds); 1241 #endif 1242 1243 #ifdef UMAC_MLO_AUTH_DEFER 1244 void mlo_peer_free_auth_param(struct mlpeer_auth_params *auth_params) 1245 { 1246 if (auth_params->rs) 1247 qdf_mem_free(auth_params->rs); 1248 1249 if (auth_params->wbuf) 1250 qdf_nbuf_free(auth_params->wbuf); 1251 1252 qdf_mem_free(auth_params); 1253 } 1254 1255 QDF_STATUS mlo_peer_link_auth_defer(struct wlan_mlo_peer_context *ml_peer, 1256 struct qdf_mac_addr *link_mac, 1257 struct mlpeer_auth_params *auth_params) 1258 { 1259 uint8_t i; 1260 uint8_t free_entries = 0; 1261 struct mlpeer_auth_params *recv_auth; 1262 QDF_STATUS status = QDF_STATUS_E_FAILURE; 1263 1264 if (!ml_peer) 1265 return status; 1266 1267 mlo_peer_lock_acquire(ml_peer); 1268 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 1269 recv_auth = ml_peer->pending_auth[i]; 1270 if (!recv_auth) { 1271 free_entries++; 1272 continue; 1273 } 1274 /* overwrite the entry with latest entry */ 1275 if (qdf_is_macaddr_equal(link_mac, &recv_auth->link_addr)) { 1276 mlo_peer_free_auth_param(recv_auth); 1277 ml_peer->pending_auth[i] = auth_params; 1278 mlo_peer_lock_release(ml_peer); 1279 1280 return QDF_STATUS_SUCCESS; 1281 } 1282 } 1283 1284 if (!free_entries) { 1285 mlo_peer_lock_release(ml_peer); 1286 return QDF_STATUS_E_FAILURE; 1287 } 1288 1289 for (i = 0; i < MAX_MLO_LINK_PEERS; i++) { 1290 recv_auth = ml_peer->pending_auth[i]; 1291 if (!recv_auth) { 1292 ml_peer->pending_auth[i] = auth_params; 1293 status = QDF_STATUS_SUCCESS; 1294 break; 1295 } 1296 } 1297 mlo_peer_lock_release(ml_peer); 1298 1299 return status; 1300 } 1301 #endif 1302