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 /* 19 * DOC: contains MLO manager init/deinit api's 20 */ 21 #include "wlan_cmn.h" 22 #include <wlan_objmgr_cmn.h> 23 #include <wlan_objmgr_global_obj.h> 24 #include "wlan_mlo_mgr_cmn.h" 25 #include "wlan_mlo_mgr_main.h" 26 #include <wlan_mlo_mgr_ap.h> 27 #include <wlan_mlo_mgr_peer.h> 28 #include <wlan_mlo_mgr_setup.h> 29 #include <wlan_cm_public_struct.h> 30 #include "wlan_mlo_mgr_msgq.h" 31 #include <target_if_mlo_mgr.h> 32 #include <wlan_mlo_t2lm.h> 33 34 static void mlo_global_ctx_deinit(void) 35 { 36 struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx(); 37 38 if (!mlo_mgr_ctx) 39 return; 40 41 if (qdf_list_empty(&mlo_mgr_ctx->ml_dev_list)) 42 mlo_err("ML dev list is not empty"); 43 44 mlo_setup_deinit(); 45 mlo_msgq_free(); 46 ml_peerid_lock_destroy(mlo_mgr_ctx); 47 ml_link_lock_destroy(mlo_mgr_ctx); 48 ml_aid_lock_destroy(mlo_mgr_ctx); 49 qdf_list_destroy(&mlo_mgr_ctx->ml_dev_list); 50 51 qdf_mem_free(mlo_mgr_ctx); 52 wlan_objmgr_set_mlo_ctx(NULL); 53 } 54 55 static void mlo_global_ctx_init(void) 56 { 57 struct mlo_mgr_context *mlo_mgr_ctx; 58 59 /* If it is already created, ignore */ 60 if (wlan_objmgr_get_mlo_ctx()) { 61 mlo_err("Global object is already created"); 62 return; 63 } 64 65 /* Allocation of memory for Global object */ 66 mlo_mgr_ctx = (struct mlo_mgr_context *) 67 qdf_mem_malloc(sizeof(*mlo_mgr_ctx)); 68 if (!mlo_mgr_ctx) 69 return; 70 71 wlan_objmgr_set_mlo_ctx(mlo_mgr_ctx); 72 73 qdf_list_create(&mlo_mgr_ctx->ml_dev_list, WLAN_UMAC_MLO_MAX_DEV); 74 mlo_mgr_ctx->max_mlo_peer_id = MAX_MLO_PEER_ID; 75 ml_peerid_lock_create(mlo_mgr_ctx); 76 ml_link_lock_create(mlo_mgr_ctx); 77 ml_aid_lock_create(mlo_mgr_ctx); 78 mlo_mgr_ctx->mlo_is_force_primary_umac = 0; 79 mlo_msgq_init(); 80 } 81 82 QDF_STATUS wlan_mlo_mgr_psoc_enable(struct wlan_objmgr_psoc *psoc) 83 { 84 struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops; 85 86 if (!psoc) { 87 mlo_err("psoc is null"); 88 return QDF_STATUS_E_NULL_VALUE; 89 } 90 91 mlo_tx_ops = target_if_mlo_get_tx_ops(psoc); 92 if (!mlo_tx_ops) { 93 mlo_err("tx_ops is null!"); 94 return QDF_STATUS_E_NULL_VALUE; 95 } 96 97 if (!mlo_tx_ops->register_events) { 98 mlo_err("register_events function is null!"); 99 return QDF_STATUS_E_NULL_VALUE; 100 } 101 102 return mlo_tx_ops->register_events(psoc); 103 } 104 105 QDF_STATUS wlan_mlo_mgr_psoc_disable(struct wlan_objmgr_psoc *psoc) 106 { 107 struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops; 108 109 if (!psoc) { 110 mlo_err("psoc is null"); 111 return QDF_STATUS_E_NULL_VALUE; 112 } 113 114 mlo_tx_ops = target_if_mlo_get_tx_ops(psoc); 115 if (!mlo_tx_ops) { 116 mlo_err("tx_ops is null!"); 117 return QDF_STATUS_E_NULL_VALUE; 118 } 119 120 if (!mlo_tx_ops->unregister_events) { 121 mlo_err("unregister_events function is null!"); 122 return QDF_STATUS_E_NULL_VALUE; 123 } 124 125 return mlo_tx_ops->unregister_events(psoc); 126 } 127 128 QDF_STATUS wlan_mlo_mgr_init(void) 129 { 130 QDF_STATUS status; 131 132 mlo_global_ctx_init(); 133 134 status = wlan_objmgr_register_vdev_create_handler( 135 WLAN_UMAC_COMP_MLO_MGR, 136 wlan_mlo_mgr_vdev_created_notification, NULL); 137 if (QDF_IS_STATUS_ERROR(status)) { 138 mlo_err("Failed to register vdev create handler"); 139 return QDF_STATUS_E_FAILURE; 140 } 141 142 status = wlan_objmgr_register_vdev_destroy_handler(WLAN_UMAC_COMP_MLO_MGR, 143 wlan_mlo_mgr_vdev_destroyed_notification, NULL); 144 if (QDF_IS_STATUS_SUCCESS(status)) { 145 mlo_debug("MLO vdev create and delete handler registered with objmgr"); 146 return QDF_STATUS_SUCCESS; 147 } 148 wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_MLO_MGR, 149 wlan_mlo_mgr_vdev_created_notification, NULL); 150 151 return status; 152 } 153 154 QDF_STATUS wlan_mlo_mgr_deinit(void) 155 { 156 QDF_STATUS status; 157 struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx(); 158 159 if (!mlo_mgr_ctx) { 160 mlo_err("MLO global object is not allocated"); 161 return QDF_STATUS_E_FAILURE; 162 } 163 164 mlo_global_ctx_deinit(); 165 166 status = wlan_objmgr_unregister_vdev_create_handler( 167 WLAN_UMAC_COMP_MLO_MGR, 168 wlan_mlo_mgr_vdev_created_notification, NULL); 169 if (status != QDF_STATUS_SUCCESS) 170 mlo_err("Failed to unregister vdev create handler"); 171 172 status = wlan_objmgr_unregister_vdev_destroy_handler( 173 WLAN_UMAC_COMP_MLO_MGR, 174 wlan_mlo_mgr_vdev_destroyed_notification, NULL); 175 if (status != QDF_STATUS_SUCCESS) 176 mlo_err("Failed to unregister vdev delete handler"); 177 178 return status; 179 } 180 181 static inline struct wlan_mlo_dev_context *mlo_list_peek_head( 182 qdf_list_t *ml_list) 183 { 184 struct wlan_mlo_dev_context *mld_ctx; 185 qdf_list_node_t *ml_node = NULL; 186 187 /* This API is invoked with lock acquired, do not add log prints */ 188 if (qdf_list_peek_front(ml_list, &ml_node) != QDF_STATUS_SUCCESS) 189 return NULL; 190 191 mld_ctx = qdf_container_of(ml_node, struct wlan_mlo_dev_context, 192 node); 193 194 return mld_ctx; 195 } 196 197 static inline 198 struct wlan_mlo_dev_context *mlo_get_next_mld_ctx(qdf_list_t *ml_list, 199 struct wlan_mlo_dev_context *mld_cur) 200 { 201 struct wlan_mlo_dev_context *mld_next; 202 qdf_list_node_t *node = &mld_cur->node; 203 qdf_list_node_t *next_node = NULL; 204 205 /* This API is invoked with lock acquired, do not add log prints */ 206 if (!node) 207 return NULL; 208 209 if (qdf_list_peek_next(ml_list, node, &next_node) != 210 QDF_STATUS_SUCCESS) 211 return NULL; 212 213 mld_next = qdf_container_of(next_node, struct wlan_mlo_dev_context, 214 node); 215 return mld_next; 216 } 217 218 uint8_t wlan_mlo_get_sta_mld_ctx_count(void) 219 { 220 struct wlan_mlo_dev_context *mld_cur; 221 struct wlan_mlo_dev_context *mld_next; 222 qdf_list_t *ml_list; 223 struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx(); 224 uint8_t count = 0; 225 226 if (!mlo_mgr_ctx) 227 return count; 228 229 ml_link_lock_acquire(mlo_mgr_ctx); 230 ml_list = &mlo_mgr_ctx->ml_dev_list; 231 /* Get first mld context */ 232 mld_cur = mlo_list_peek_head(ml_list); 233 234 while (mld_cur) { 235 /* get next mld node */ 236 if (mld_cur->sta_ctx) 237 count++; 238 mld_next = mlo_get_next_mld_ctx(ml_list, mld_cur); 239 mld_cur = mld_next; 240 } 241 ml_link_lock_release(mlo_mgr_ctx); 242 243 return count; 244 } 245 246 struct wlan_mlo_dev_context 247 *wlan_mlo_get_mld_ctx_by_mldaddr(struct qdf_mac_addr *mldaddr) 248 { 249 struct wlan_mlo_dev_context *mld_cur; 250 struct wlan_mlo_dev_context *mld_next; 251 qdf_list_t *ml_list; 252 struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx(); 253 254 if (!mlo_mgr_ctx) 255 return NULL; 256 257 ml_link_lock_acquire(mlo_mgr_ctx); 258 ml_list = &mlo_mgr_ctx->ml_dev_list; 259 /* Get first mld context */ 260 mld_cur = mlo_list_peek_head(ml_list); 261 /** 262 * Iterate through ml list, till ml mldaddr matches with 263 * entry of list 264 */ 265 while (mld_cur) { 266 if (QDF_IS_STATUS_SUCCESS(WLAN_ADDR_EQ(&mld_cur->mld_addr, 267 mldaddr))) { 268 ml_link_lock_release(mlo_mgr_ctx); 269 return mld_cur; 270 } 271 /* get next mld node */ 272 mld_next = mlo_get_next_mld_ctx(ml_list, mld_cur); 273 mld_cur = mld_next; 274 } 275 ml_link_lock_release(mlo_mgr_ctx); 276 277 return NULL; 278 } 279 280 bool wlan_mlo_is_mld_ctx_exist(struct qdf_mac_addr *mldaddr) 281 { 282 struct wlan_mlo_dev_context *mld_ctx = NULL; 283 284 mld_ctx = wlan_mlo_get_mld_ctx_by_mldaddr(mldaddr); 285 if (mld_ctx) 286 return true; 287 288 return false; 289 } 290 291 #ifdef WLAN_FEATURE_11BE_MLO 292 bool mlo_mgr_ml_peer_exist_on_diff_ml_ctx(uint8_t *peer_addr, 293 uint8_t *peer_vdev_id) 294 { 295 qdf_list_t *ml_list; 296 uint32_t idx, count; 297 struct wlan_mlo_dev_context *mld_cur, *mld_next; 298 struct wlan_mlo_peer_list *mlo_peer_list; 299 struct wlan_objmgr_vdev *vdev; 300 bool ret_status = false, same_ml_ctx = false; 301 struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx(); 302 303 if (!g_mlo_ctx || !peer_addr || 304 qdf_is_macaddr_zero((struct qdf_mac_addr *)peer_addr)) 305 return ret_status; 306 307 ml_link_lock_acquire(g_mlo_ctx); 308 ml_list = &g_mlo_ctx->ml_dev_list; 309 if (!qdf_list_size(ml_list)) 310 goto g_ml_ref; 311 312 mld_cur = mlo_list_peek_head(ml_list); 313 while (mld_cur) { 314 mlo_dev_lock_acquire(mld_cur); 315 if (qdf_is_macaddr_equal(&mld_cur->mld_addr, 316 (struct qdf_mac_addr *)peer_addr)) { 317 /* For self peer, the address passed will match the 318 * MLD address of its own ML dev context, so allow 319 * peer creation in this scenario as both are in 320 * same ML dev context. 321 */ 322 if (peer_vdev_id) { 323 count = QDF_ARRAY_SIZE(mld_cur->wlan_vdev_list); 324 for (idx = 0; idx < count; idx++) { 325 vdev = mld_cur->wlan_vdev_list[idx]; 326 if (!vdev) 327 continue; 328 if (*peer_vdev_id == 329 wlan_vdev_get_id(vdev)) { 330 same_ml_ctx = true; 331 break; 332 } 333 } 334 } 335 mlo_dev_lock_release(mld_cur); 336 mlo_err("MLD ID %d exists with mac " QDF_MAC_ADDR_FMT, 337 mld_cur->mld_id, QDF_MAC_ADDR_REF(peer_addr)); 338 ret_status = true; 339 goto check_same_ml_ctx; 340 } 341 342 /* Check the peer list for a MAC address match */ 343 mlo_peer_list = &mld_cur->mlo_peer_list; 344 ml_peerlist_lock_acquire(mlo_peer_list); 345 if (mlo_get_mlpeer(mld_cur, (struct qdf_mac_addr *)peer_addr)) { 346 /* If peer_vdev_id is NULL, then API will treat any 347 * match as happening on another dev context 348 */ 349 if (peer_vdev_id) { 350 count = QDF_ARRAY_SIZE(mld_cur->wlan_vdev_list); 351 for (idx = 0; idx < count; idx++) { 352 vdev = mld_cur->wlan_vdev_list[idx]; 353 if (!vdev) 354 continue; 355 if (*peer_vdev_id == 356 wlan_vdev_get_id(vdev)) { 357 same_ml_ctx = true; 358 break; 359 } 360 } 361 } 362 ml_peerlist_lock_release(mlo_peer_list); 363 mlo_dev_lock_release(mld_cur); 364 mlo_err("MLD ID %d ML Peer exists with mac " QDF_MAC_ADDR_FMT, 365 mld_cur->mld_id, QDF_MAC_ADDR_REF(peer_addr)); 366 ret_status = true; 367 goto check_same_ml_ctx; 368 } 369 ml_peerlist_lock_release(mlo_peer_list); 370 371 mld_next = mlo_get_next_mld_ctx(ml_list, mld_cur); 372 mlo_dev_lock_release(mld_cur); 373 mld_cur = mld_next; 374 } 375 376 check_same_ml_ctx: 377 if (same_ml_ctx) 378 ret_status = false; 379 380 g_ml_ref: 381 ml_link_lock_release(g_mlo_ctx); 382 return ret_status; 383 } 384 #endif 385 386 static QDF_STATUS mlo_ap_ctx_deinit(struct wlan_mlo_dev_context *ml_dev) 387 { 388 wlan_mlo_vdev_aid_mgr_deinit(ml_dev); 389 mlo_ap_lock_destroy(ml_dev->ap_ctx); 390 qdf_mem_free(ml_dev->ap_ctx); 391 ml_dev->ap_ctx = NULL; 392 393 return QDF_STATUS_SUCCESS; 394 } 395 396 static QDF_STATUS mlo_ap_ctx_init(struct wlan_mlo_dev_context *ml_dev) 397 { 398 struct wlan_mlo_ap *ap_ctx; 399 400 ap_ctx = qdf_mem_malloc(sizeof(*ap_ctx)); 401 if (!ap_ctx) { 402 mlo_err("MLO AP ctx alloc failure"); 403 return QDF_STATUS_E_NOMEM; 404 } 405 406 ml_dev->ap_ctx = ap_ctx; 407 mlo_ap_lock_create(ml_dev->ap_ctx); 408 if (wlan_mlo_vdev_aid_mgr_init(ml_dev) != QDF_STATUS_SUCCESS) { 409 mlo_ap_ctx_deinit(ml_dev); 410 return QDF_STATUS_E_NOMEM; 411 } 412 413 return QDF_STATUS_SUCCESS; 414 } 415 416 #ifdef CONFIG_AP_PLATFORM 417 static inline 418 QDF_STATUS wlan_mlo_check_grp_id(uint8_t ref_id, 419 struct wlan_objmgr_vdev *vdev) 420 { 421 struct wlan_objmgr_psoc *psoc; 422 uint8_t grp_id = 0; 423 424 psoc = wlan_vdev_get_psoc(vdev); 425 if (!mlo_psoc_get_grp_id(psoc, &grp_id)) { 426 mlo_err("Unable to get mlo group id"); 427 return QDF_STATUS_E_FAILURE; 428 } 429 430 if (grp_id != ref_id) { 431 mlo_err("Error : MLD VAP Configuration with different WSI/MLD Groups"); 432 return QDF_STATUS_E_FAILURE; 433 } 434 435 return QDF_STATUS_SUCCESS; 436 } 437 438 static inline 439 QDF_STATUS wlan_mlo_pdev_check(struct wlan_objmgr_pdev *ref_pdev, 440 struct wlan_objmgr_vdev *vdev) 441 { 442 struct wlan_objmgr_pdev *pdev; 443 struct wlan_objmgr_psoc *psoc; 444 uint8_t grp_id = 0; 445 446 pdev = wlan_vdev_get_pdev(vdev); 447 448 psoc = wlan_pdev_get_psoc(ref_pdev); 449 if (!mlo_psoc_get_grp_id(psoc, &grp_id)) { 450 mlo_err("Unable to get the MLO Group ID for the vdev"); 451 return QDF_STATUS_E_FAILURE; 452 } 453 454 if (mlo_check_all_pdev_state(psoc, grp_id, MLO_LINK_SETUP_DONE)) { 455 mlo_err("Pdev link is not in ready state, initial link setup failed"); 456 return QDF_STATUS_E_FAILURE; 457 } 458 459 if (ref_pdev == pdev) { 460 mlo_err("MLD vdev for this pdev already found, investigate config"); 461 return QDF_STATUS_E_FAILURE; 462 } 463 464 if (wlan_mlo_check_grp_id(grp_id, vdev)) 465 return QDF_STATUS_E_FAILURE; 466 467 return QDF_STATUS_SUCCESS; 468 } 469 470 static inline 471 QDF_STATUS mlo_dev_config_check(struct wlan_mlo_dev_context *ml_dev, 472 struct wlan_objmgr_vdev *vdev) 473 { 474 return QDF_STATUS_SUCCESS; 475 } 476 477 #else 478 static inline 479 QDF_STATUS mlo_dev_config_check(struct wlan_mlo_dev_context *ml_dev, 480 struct wlan_objmgr_vdev *vdev) 481 { 482 enum QDF_OPMODE opmode = wlan_vdev_mlme_get_opmode(vdev); 483 484 if (wlan_mlo_check_valid_config(ml_dev, wlan_vdev_get_pdev(vdev), 485 opmode) != QDF_STATUS_SUCCESS) 486 return QDF_STATUS_E_FAILURE; 487 488 return QDF_STATUS_SUCCESS; 489 } 490 491 static inline 492 QDF_STATUS wlan_mlo_pdev_check(struct wlan_objmgr_pdev *ref_pdev, 493 struct wlan_objmgr_vdev *vdev) 494 { 495 return QDF_STATUS_SUCCESS; 496 } 497 #endif 498 499 QDF_STATUS wlan_mlo_check_valid_config(struct wlan_mlo_dev_context *ml_dev, 500 struct wlan_objmgr_pdev *pdev, 501 enum QDF_OPMODE opmode) 502 { 503 uint32_t id = 0; 504 struct wlan_objmgr_vdev *vdev; 505 506 if (!ml_dev) 507 return QDF_STATUS_E_FAILURE; 508 509 if (!pdev) 510 return QDF_STATUS_E_FAILURE; 511 512 mlo_dev_lock_acquire(ml_dev); 513 while (id < WLAN_UMAC_MLO_MAX_VDEVS) { 514 vdev = ml_dev->wlan_vdev_list[id]; 515 if (vdev) { 516 if (wlan_mlo_pdev_check(pdev, vdev)) { 517 mlo_dev_lock_release(ml_dev); 518 return QDF_STATUS_E_FAILURE; 519 } 520 521 if (wlan_vdev_mlme_get_opmode(vdev) != opmode) { 522 mlo_err("Invalid opmode %d type found expected %d, investigate config", 523 wlan_vdev_mlme_get_opmode(vdev), 524 opmode); 525 mlo_dev_lock_release(ml_dev); 526 return QDF_STATUS_E_FAILURE; 527 } 528 } 529 id++; 530 } 531 532 mlo_dev_lock_release(ml_dev); 533 return QDF_STATUS_SUCCESS; 534 } 535 536 /** 537 * mlo_t2lm_ctx_init() - API to initialize the t2lm context with the default 538 * values. 539 * @ml_dev: Pointer to ML Dev context 540 * @vdev: Pointer to vdev structure 541 * 542 * Return: None 543 */ 544 static inline void mlo_t2lm_ctx_init(struct wlan_mlo_dev_context *ml_dev, 545 struct wlan_objmgr_vdev *vdev) 546 { 547 struct wlan_t2lm_info *t2lm; 548 549 t2lm = &ml_dev->t2lm_ctx.established_t2lm.t2lm; 550 551 qdf_mem_zero(&ml_dev->t2lm_ctx, sizeof(struct wlan_t2lm_context)); 552 553 t2lm->direction = WLAN_T2LM_BIDI_DIRECTION; 554 t2lm->default_link_mapping = 1; 555 556 wlan_mlo_t2lm_timer_init(vdev); 557 } 558 559 static QDF_STATUS mlo_dev_ctx_init(struct wlan_objmgr_vdev *vdev) 560 { 561 struct wlan_mlo_dev_context *ml_dev; 562 QDF_STATUS status = QDF_STATUS_SUCCESS; 563 struct qdf_mac_addr *mld_addr; 564 struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx(); 565 uint8_t id = 0; 566 567 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 568 ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(mld_addr); 569 570 if (ml_dev) { 571 if (mlo_dev_config_check(ml_dev, vdev) != QDF_STATUS_SUCCESS) 572 return QDF_STATUS_E_FAILURE; 573 574 mlo_dev_lock_acquire(ml_dev); 575 while (id < WLAN_UMAC_MLO_MAX_VDEVS) { 576 if (ml_dev->wlan_vdev_list[id]) { 577 id++; 578 continue; 579 } 580 581 ml_dev->wlan_vdev_list[id] = vdev; 582 ml_dev->wlan_vdev_count++; 583 vdev->mlo_dev_ctx = ml_dev; 584 585 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) 586 wlan_mlo_vdev_alloc_aid_mgr(ml_dev, vdev); 587 588 break; 589 } 590 mlo_dev_lock_release(ml_dev); 591 return QDF_STATUS_SUCCESS; 592 } 593 594 /* Create a new ML dev context */ 595 ml_dev = qdf_mem_malloc(sizeof(*ml_dev)); 596 if (!ml_dev) { 597 mlo_err("Failed to allocate memory for ML dev"); 598 return QDF_STATUS_E_NOMEM; 599 } 600 601 qdf_copy_macaddr(&ml_dev->mld_addr, mld_addr); 602 ml_dev->wlan_vdev_list[0] = vdev; 603 ml_dev->wlan_vdev_count++; 604 vdev->mlo_dev_ctx = ml_dev; 605 606 mlo_dev_lock_create(ml_dev); 607 tsf_recalculation_lock_create(ml_dev); 608 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) { 609 ml_dev->sta_ctx = qdf_mem_malloc(sizeof(struct wlan_mlo_sta)); 610 if (!ml_dev->sta_ctx) { 611 tsf_recalculation_lock_destroy(ml_dev); 612 mlo_dev_lock_destroy(ml_dev); 613 qdf_mem_free(ml_dev); 614 return QDF_STATUS_E_NOMEM; 615 } 616 copied_conn_req_lock_create(ml_dev->sta_ctx); 617 } else if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) { 618 if (mlo_ap_ctx_init(ml_dev) != QDF_STATUS_SUCCESS) { 619 tsf_recalculation_lock_destroy(ml_dev); 620 mlo_dev_lock_destroy(ml_dev); 621 qdf_mem_free(ml_dev); 622 mlo_err("Failed to allocate memory for ap ctx"); 623 return QDF_STATUS_E_NOMEM; 624 } 625 } 626 627 mlo_dev_mlpeer_list_init(ml_dev); 628 629 ml_link_lock_acquire(g_mlo_ctx); 630 if (qdf_list_size(&g_mlo_ctx->ml_dev_list) < WLAN_UMAC_MLO_MAX_DEV) 631 qdf_list_insert_back(&g_mlo_ctx->ml_dev_list, &ml_dev->node); 632 ml_link_lock_release(g_mlo_ctx); 633 634 mlo_t2lm_ctx_init(ml_dev, vdev); 635 636 return status; 637 } 638 639 /** 640 * mlo_t2lm_ctx_deinit() - API to deinitialize the t2lm context with the default 641 * values. 642 * @vdev: Pointer to vdev structure 643 * 644 * Return: None 645 */ 646 static inline void mlo_t2lm_ctx_deinit(struct wlan_objmgr_vdev *vdev) 647 { 648 wlan_mlo_t2lm_timer_deinit(vdev); 649 } 650 651 static QDF_STATUS mlo_dev_ctx_deinit(struct wlan_objmgr_vdev *vdev) 652 { 653 struct wlan_mlo_dev_context *ml_dev; 654 QDF_STATUS status = QDF_STATUS_SUCCESS; 655 struct qdf_mac_addr *mld_addr; 656 struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx(); 657 uint8_t id = 0; 658 struct wlan_cm_connect_req *connect_req; 659 660 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 661 ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(mld_addr); 662 if (!ml_dev) { 663 mlo_err("Failed to get MLD dev context by mld addr "QDF_MAC_ADDR_FMT, 664 QDF_MAC_ADDR_REF(mld_addr->bytes)); 665 if (!vdev->mlo_dev_ctx) { 666 mlo_err("Failed to get MLD dev context from vdev"); 667 return QDF_STATUS_SUCCESS; 668 } 669 ml_dev = vdev->mlo_dev_ctx; 670 } 671 672 mlo_debug("deleting vdev from MLD device ctx "QDF_MAC_ADDR_FMT, 673 QDF_MAC_ADDR_REF(mld_addr->bytes)); 674 mlo_dev_lock_acquire(ml_dev); 675 while (id < WLAN_UMAC_MLO_MAX_VDEVS) { 676 if (ml_dev->wlan_vdev_list[id] == vdev) { 677 if (wlan_vdev_mlme_get_opmode(vdev) == 678 QDF_SAP_MODE) 679 wlan_mlo_vdev_free_aid_mgr(ml_dev, 680 vdev); 681 ml_dev->wlan_vdev_list[id] = NULL; 682 ml_dev->wlan_vdev_count--; 683 vdev->mlo_dev_ctx = NULL; 684 break; 685 } 686 id++; 687 } 688 mlo_dev_lock_release(ml_dev); 689 690 ml_link_lock_acquire(g_mlo_ctx); 691 if (!ml_dev->wlan_vdev_count) { 692 if (ml_dev->ap_ctx) 693 mlo_ap_ctx_deinit(ml_dev); 694 695 mlo_dev_mlpeer_list_deinit(ml_dev); 696 qdf_list_remove_node(&g_mlo_ctx->ml_dev_list, 697 &ml_dev->node); 698 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) { 699 connect_req = ml_dev->sta_ctx->connect_req; 700 if (connect_req) { 701 if (connect_req->scan_ie.ptr) { 702 qdf_mem_free(connect_req->scan_ie.ptr); 703 connect_req->scan_ie.ptr = NULL; 704 } 705 706 if (connect_req->assoc_ie.ptr) { 707 qdf_mem_free(connect_req->assoc_ie.ptr); 708 connect_req->assoc_ie.ptr = NULL; 709 } 710 qdf_mem_free(ml_dev->sta_ctx->connect_req); 711 } 712 713 if (ml_dev->sta_ctx->disconn_req) 714 qdf_mem_free(ml_dev->sta_ctx->disconn_req); 715 716 if (ml_dev->sta_ctx->assoc_rsp.ptr) 717 qdf_mem_free(ml_dev->sta_ctx->assoc_rsp.ptr); 718 719 copied_conn_req_lock_destroy(ml_dev->sta_ctx); 720 721 qdf_mem_free(ml_dev->sta_ctx); 722 } 723 else if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) 724 qdf_mem_free(ml_dev->ap_ctx); 725 726 mlo_t2lm_ctx_deinit(vdev); 727 tsf_recalculation_lock_destroy(ml_dev); 728 mlo_dev_lock_destroy(ml_dev); 729 qdf_mem_free(ml_dev); 730 } 731 ml_link_lock_release(g_mlo_ctx); 732 return status; 733 } 734 735 QDF_STATUS wlan_mlo_mgr_vdev_created_notification(struct wlan_objmgr_vdev *vdev, 736 void *arg_list) 737 { 738 QDF_STATUS status = QDF_STATUS_SUCCESS; 739 struct qdf_mac_addr *mld_addr; 740 741 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 742 if (qdf_is_macaddr_zero(mld_addr)) { 743 /* It's not a ML interface*/ 744 return QDF_STATUS_SUCCESS; 745 } 746 mlo_debug("MLD addr" QDF_MAC_ADDR_FMT, 747 QDF_MAC_ADDR_REF(mld_addr->bytes)); 748 status = mlo_dev_ctx_init(vdev); 749 750 return status; 751 } 752 753 QDF_STATUS wlan_mlo_mgr_vdev_destroyed_notification(struct wlan_objmgr_vdev *vdev, 754 void *arg_list) 755 { 756 QDF_STATUS status = QDF_STATUS_SUCCESS; 757 struct qdf_mac_addr *mld_addr; 758 759 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 760 if (qdf_is_macaddr_zero(mld_addr)) { 761 /* It's not a ML interface*/ 762 return QDF_STATUS_SUCCESS; 763 } 764 mlo_debug("MLD addr" QDF_MAC_ADDR_FMT, 765 QDF_MAC_ADDR_REF(mld_addr->bytes)); 766 767 status = mlo_dev_ctx_deinit(vdev); 768 769 return status; 770 } 771 772 QDF_STATUS wlan_mlo_mgr_update_mld_addr(struct qdf_mac_addr *old_mac, 773 struct qdf_mac_addr *new_mac) 774 { 775 struct wlan_mlo_dev_context *ml_dev; 776 777 ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(old_mac); 778 if (!ml_dev) { 779 mlo_err("ML dev context not found for MLD:" QDF_MAC_ADDR_FMT, 780 QDF_MAC_ADDR_REF(old_mac->bytes)); 781 return QDF_STATUS_E_INVAL; 782 } 783 mlo_dev_lock_acquire(ml_dev); 784 qdf_copy_macaddr(&ml_dev->mld_addr, new_mac); 785 mlo_dev_lock_release(ml_dev); 786 787 return QDF_STATUS_SUCCESS; 788 } 789