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(uint8_t *peer_addr) 293 { 294 qdf_list_t *ml_list; 295 struct wlan_mlo_dev_context *mld_cur, *mld_next; 296 struct wlan_mlo_peer_list *mlo_peer_list; 297 bool ret_status = false; 298 struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx(); 299 300 if (!g_mlo_ctx || !peer_addr || 301 qdf_is_macaddr_zero((struct qdf_mac_addr *)peer_addr)) 302 return ret_status; 303 304 ml_link_lock_acquire(g_mlo_ctx); 305 ml_list = &g_mlo_ctx->ml_dev_list; 306 if (!qdf_list_size(ml_list)) 307 goto g_ml_ref; 308 309 mld_cur = mlo_list_peek_head(ml_list); 310 while (mld_cur) { 311 mlo_dev_lock_acquire(mld_cur); 312 if (qdf_is_macaddr_equal(&mld_cur->mld_addr, 313 (struct qdf_mac_addr *)peer_addr)) { 314 mlo_dev_lock_release(mld_cur); 315 mlo_err("MLD ID %d exists with mac " QDF_MAC_ADDR_FMT, 316 mld_cur->mld_id, QDF_MAC_ADDR_REF(peer_addr)); 317 ret_status = true; 318 goto g_ml_ref; 319 } 320 321 /* Check the peer list for a MAC address match */ 322 mlo_peer_list = &mld_cur->mlo_peer_list; 323 ml_peerlist_lock_acquire(mlo_peer_list); 324 if (mlo_get_mlpeer(mld_cur, (struct qdf_mac_addr *)peer_addr)) { 325 ml_peerlist_lock_release(mlo_peer_list); 326 mlo_dev_lock_release(mld_cur); 327 mlo_err("MLD ID %d ML Peer exists with mac " QDF_MAC_ADDR_FMT, 328 mld_cur->mld_id, QDF_MAC_ADDR_REF(peer_addr)); 329 ret_status = true; 330 goto g_ml_ref; 331 } 332 ml_peerlist_lock_release(mlo_peer_list); 333 334 mld_next = mlo_get_next_mld_ctx(ml_list, mld_cur); 335 mlo_dev_lock_release(mld_cur); 336 mld_cur = mld_next; 337 } 338 339 g_ml_ref: 340 ml_link_lock_release(g_mlo_ctx); 341 return ret_status; 342 } 343 #endif 344 345 static QDF_STATUS mlo_ap_ctx_deinit(struct wlan_mlo_dev_context *ml_dev) 346 { 347 wlan_mlo_vdev_aid_mgr_deinit(ml_dev); 348 mlo_ap_lock_destroy(ml_dev->ap_ctx); 349 qdf_mem_free(ml_dev->ap_ctx); 350 ml_dev->ap_ctx = NULL; 351 352 return QDF_STATUS_SUCCESS; 353 } 354 355 static QDF_STATUS mlo_ap_ctx_init(struct wlan_mlo_dev_context *ml_dev) 356 { 357 struct wlan_mlo_ap *ap_ctx; 358 359 ap_ctx = qdf_mem_malloc(sizeof(*ap_ctx)); 360 if (!ap_ctx) { 361 mlo_err("MLO AP ctx alloc failure"); 362 return QDF_STATUS_E_NOMEM; 363 } 364 365 ml_dev->ap_ctx = ap_ctx; 366 mlo_ap_lock_create(ml_dev->ap_ctx); 367 if (wlan_mlo_vdev_aid_mgr_init(ml_dev) != QDF_STATUS_SUCCESS) { 368 mlo_ap_ctx_deinit(ml_dev); 369 return QDF_STATUS_E_NOMEM; 370 } 371 372 return QDF_STATUS_SUCCESS; 373 } 374 375 #ifdef CONFIG_AP_PLATFORM 376 static inline 377 QDF_STATUS wlan_mlo_check_grp_id(uint8_t ref_id, 378 struct wlan_objmgr_vdev *vdev) 379 { 380 struct wlan_objmgr_psoc *psoc; 381 uint8_t grp_id = 0; 382 383 psoc = wlan_vdev_get_psoc(vdev); 384 if (!mlo_psoc_get_grp_id(psoc, &grp_id)) { 385 mlo_err("Unable to get mlo group id"); 386 return QDF_STATUS_E_FAILURE; 387 } 388 389 if (grp_id != ref_id) { 390 mlo_err("Error : MLD VAP Configuration with different WSI/MLD Groups"); 391 return QDF_STATUS_E_FAILURE; 392 } 393 394 return QDF_STATUS_SUCCESS; 395 } 396 397 static inline 398 QDF_STATUS wlan_mlo_pdev_check(struct wlan_objmgr_pdev *ref_pdev, 399 struct wlan_objmgr_vdev *vdev) 400 { 401 struct wlan_objmgr_pdev *pdev; 402 struct wlan_objmgr_psoc *psoc; 403 uint8_t grp_id = 0; 404 405 pdev = wlan_vdev_get_pdev(vdev); 406 407 psoc = wlan_pdev_get_psoc(ref_pdev); 408 if (!mlo_psoc_get_grp_id(psoc, &grp_id)) { 409 mlo_err("Unable to get the MLO Group ID for the vdev"); 410 return QDF_STATUS_E_FAILURE; 411 } 412 413 if (mlo_check_all_pdev_state(psoc, grp_id, MLO_LINK_SETUP_DONE)) { 414 mlo_err("Pdev link is not in ready state, initial link setup failed"); 415 return QDF_STATUS_E_FAILURE; 416 } 417 418 if (ref_pdev == pdev) { 419 mlo_err("MLD vdev for this pdev already found, investigate config"); 420 return QDF_STATUS_E_FAILURE; 421 } 422 423 if (wlan_mlo_check_grp_id(grp_id, vdev)) 424 return QDF_STATUS_E_FAILURE; 425 426 return QDF_STATUS_SUCCESS; 427 } 428 429 static inline 430 QDF_STATUS mlo_dev_config_check(struct wlan_mlo_dev_context *ml_dev, 431 struct wlan_objmgr_vdev *vdev) 432 { 433 return QDF_STATUS_SUCCESS; 434 } 435 436 #else 437 static inline 438 QDF_STATUS mlo_dev_config_check(struct wlan_mlo_dev_context *ml_dev, 439 struct wlan_objmgr_vdev *vdev) 440 { 441 enum QDF_OPMODE opmode = wlan_vdev_mlme_get_opmode(vdev); 442 443 if (wlan_mlo_check_valid_config(ml_dev, wlan_vdev_get_pdev(vdev), 444 opmode) != QDF_STATUS_SUCCESS) 445 return QDF_STATUS_E_FAILURE; 446 447 return QDF_STATUS_SUCCESS; 448 } 449 450 static inline 451 QDF_STATUS wlan_mlo_pdev_check(struct wlan_objmgr_pdev *ref_pdev, 452 struct wlan_objmgr_vdev *vdev) 453 { 454 return QDF_STATUS_SUCCESS; 455 } 456 #endif 457 458 QDF_STATUS wlan_mlo_check_valid_config(struct wlan_mlo_dev_context *ml_dev, 459 struct wlan_objmgr_pdev *pdev, 460 enum QDF_OPMODE opmode) 461 { 462 uint32_t id = 0; 463 struct wlan_objmgr_vdev *vdev; 464 465 if (!ml_dev) 466 return QDF_STATUS_E_FAILURE; 467 468 if (!pdev) 469 return QDF_STATUS_E_FAILURE; 470 471 mlo_dev_lock_acquire(ml_dev); 472 while (id < WLAN_UMAC_MLO_MAX_VDEVS) { 473 vdev = ml_dev->wlan_vdev_list[id]; 474 if (vdev) { 475 if (wlan_mlo_pdev_check(pdev, vdev)) { 476 mlo_dev_lock_release(ml_dev); 477 return QDF_STATUS_E_FAILURE; 478 } 479 480 if (wlan_vdev_mlme_get_opmode(vdev) != opmode) { 481 mlo_err("Invalid opmode %d type found expected %d, investigate config", 482 wlan_vdev_mlme_get_opmode(vdev), 483 opmode); 484 mlo_dev_lock_release(ml_dev); 485 return QDF_STATUS_E_FAILURE; 486 } 487 } 488 id++; 489 } 490 491 mlo_dev_lock_release(ml_dev); 492 return QDF_STATUS_SUCCESS; 493 } 494 495 /** 496 * mlo_t2lm_ctx_init() - API to initialize the t2lm context with the default 497 * values. 498 * @ml_dev: Pointer to ML Dev context 499 * @vdev: Pointer to vdev structure 500 * 501 * Return: None 502 */ 503 static inline void mlo_t2lm_ctx_init(struct wlan_mlo_dev_context *ml_dev, 504 struct wlan_objmgr_vdev *vdev) 505 { 506 struct wlan_t2lm_info *t2lm; 507 508 t2lm = &ml_dev->t2lm_ctx.established_t2lm.t2lm; 509 510 qdf_mem_zero(&ml_dev->t2lm_ctx, sizeof(struct wlan_t2lm_context)); 511 512 t2lm->direction = WLAN_T2LM_BIDI_DIRECTION; 513 t2lm->default_link_mapping = 1; 514 515 wlan_mlo_t2lm_timer_init(vdev); 516 } 517 518 static QDF_STATUS mlo_dev_ctx_init(struct wlan_objmgr_vdev *vdev) 519 { 520 struct wlan_mlo_dev_context *ml_dev; 521 QDF_STATUS status = QDF_STATUS_SUCCESS; 522 struct qdf_mac_addr *mld_addr; 523 struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx(); 524 uint8_t id = 0; 525 526 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 527 ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(mld_addr); 528 529 if (ml_dev) { 530 if (mlo_dev_config_check(ml_dev, vdev) != QDF_STATUS_SUCCESS) 531 return QDF_STATUS_E_FAILURE; 532 533 mlo_dev_lock_acquire(ml_dev); 534 while (id < WLAN_UMAC_MLO_MAX_VDEVS) { 535 if (ml_dev->wlan_vdev_list[id]) { 536 id++; 537 continue; 538 } 539 540 ml_dev->wlan_vdev_list[id] = vdev; 541 ml_dev->wlan_vdev_count++; 542 vdev->mlo_dev_ctx = ml_dev; 543 544 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) 545 wlan_mlo_vdev_alloc_aid_mgr(ml_dev, vdev); 546 547 break; 548 } 549 mlo_dev_lock_release(ml_dev); 550 return QDF_STATUS_SUCCESS; 551 } 552 553 /* Create a new ML dev context */ 554 ml_dev = qdf_mem_malloc(sizeof(*ml_dev)); 555 if (!ml_dev) { 556 mlo_err("Failed to allocate memory for ML dev"); 557 return QDF_STATUS_E_NOMEM; 558 } 559 560 qdf_copy_macaddr(&ml_dev->mld_addr, mld_addr); 561 ml_dev->wlan_vdev_list[0] = vdev; 562 ml_dev->wlan_vdev_count++; 563 vdev->mlo_dev_ctx = ml_dev; 564 565 mlo_dev_lock_create(ml_dev); 566 tsf_recalculation_lock_create(ml_dev); 567 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) { 568 ml_dev->sta_ctx = qdf_mem_malloc(sizeof(struct wlan_mlo_sta)); 569 if (!ml_dev->sta_ctx) { 570 tsf_recalculation_lock_destroy(ml_dev); 571 mlo_dev_lock_destroy(ml_dev); 572 qdf_mem_free(ml_dev); 573 return QDF_STATUS_E_NOMEM; 574 } 575 copied_conn_req_lock_create(ml_dev->sta_ctx); 576 } else if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) { 577 if (mlo_ap_ctx_init(ml_dev) != QDF_STATUS_SUCCESS) { 578 tsf_recalculation_lock_destroy(ml_dev); 579 mlo_dev_lock_destroy(ml_dev); 580 qdf_mem_free(ml_dev); 581 mlo_err("Failed to allocate memory for ap ctx"); 582 return QDF_STATUS_E_NOMEM; 583 } 584 } 585 586 mlo_dev_mlpeer_list_init(ml_dev); 587 588 ml_link_lock_acquire(g_mlo_ctx); 589 if (qdf_list_size(&g_mlo_ctx->ml_dev_list) < WLAN_UMAC_MLO_MAX_DEV) 590 qdf_list_insert_back(&g_mlo_ctx->ml_dev_list, &ml_dev->node); 591 ml_link_lock_release(g_mlo_ctx); 592 593 mlo_t2lm_ctx_init(ml_dev, vdev); 594 595 return status; 596 } 597 598 /** 599 * mlo_t2lm_ctx_deinit() - API to deinitialize the t2lm context with the default 600 * values. 601 * @vdev: Pointer to vdev structure 602 * 603 * Return: None 604 */ 605 static inline void mlo_t2lm_ctx_deinit(struct wlan_objmgr_vdev *vdev) 606 { 607 wlan_mlo_t2lm_timer_deinit(vdev); 608 } 609 610 static QDF_STATUS mlo_dev_ctx_deinit(struct wlan_objmgr_vdev *vdev) 611 { 612 struct wlan_mlo_dev_context *ml_dev; 613 QDF_STATUS status = QDF_STATUS_SUCCESS; 614 struct qdf_mac_addr *mld_addr; 615 struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx(); 616 uint8_t id = 0; 617 struct wlan_cm_connect_req *connect_req; 618 619 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 620 ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(mld_addr); 621 if (!ml_dev) { 622 mlo_err("Failed to get MLD dev context by mld addr "QDF_MAC_ADDR_FMT, 623 QDF_MAC_ADDR_REF(mld_addr->bytes)); 624 if (!vdev->mlo_dev_ctx) { 625 mlo_err("Failed to get MLD dev context from vdev"); 626 return QDF_STATUS_SUCCESS; 627 } 628 ml_dev = vdev->mlo_dev_ctx; 629 } 630 631 mlo_debug("deleting vdev from MLD device ctx "QDF_MAC_ADDR_FMT, 632 QDF_MAC_ADDR_REF(mld_addr->bytes)); 633 mlo_dev_lock_acquire(ml_dev); 634 while (id < WLAN_UMAC_MLO_MAX_VDEVS) { 635 if (ml_dev->wlan_vdev_list[id] == vdev) { 636 if (wlan_vdev_mlme_get_opmode(vdev) == 637 QDF_SAP_MODE) 638 wlan_mlo_vdev_free_aid_mgr(ml_dev, 639 vdev); 640 ml_dev->wlan_vdev_list[id] = NULL; 641 ml_dev->wlan_vdev_count--; 642 vdev->mlo_dev_ctx = NULL; 643 break; 644 } 645 id++; 646 } 647 mlo_dev_lock_release(ml_dev); 648 649 ml_link_lock_acquire(g_mlo_ctx); 650 if (!ml_dev->wlan_vdev_count) { 651 if (ml_dev->ap_ctx) 652 mlo_ap_ctx_deinit(ml_dev); 653 654 mlo_dev_mlpeer_list_deinit(ml_dev); 655 qdf_list_remove_node(&g_mlo_ctx->ml_dev_list, 656 &ml_dev->node); 657 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) { 658 connect_req = ml_dev->sta_ctx->connect_req; 659 if (connect_req) { 660 if (connect_req->scan_ie.ptr) { 661 qdf_mem_free(connect_req->scan_ie.ptr); 662 connect_req->scan_ie.ptr = NULL; 663 } 664 665 if (connect_req->assoc_ie.ptr) { 666 qdf_mem_free(connect_req->assoc_ie.ptr); 667 connect_req->assoc_ie.ptr = NULL; 668 } 669 qdf_mem_free(ml_dev->sta_ctx->connect_req); 670 } 671 672 if (ml_dev->sta_ctx->disconn_req) 673 qdf_mem_free(ml_dev->sta_ctx->disconn_req); 674 675 if (ml_dev->sta_ctx->assoc_rsp.ptr) 676 qdf_mem_free(ml_dev->sta_ctx->assoc_rsp.ptr); 677 678 copied_conn_req_lock_destroy(ml_dev->sta_ctx); 679 680 qdf_mem_free(ml_dev->sta_ctx); 681 } 682 else if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) 683 qdf_mem_free(ml_dev->ap_ctx); 684 685 mlo_t2lm_ctx_deinit(vdev); 686 tsf_recalculation_lock_destroy(ml_dev); 687 mlo_dev_lock_destroy(ml_dev); 688 qdf_mem_free(ml_dev); 689 } 690 ml_link_lock_release(g_mlo_ctx); 691 return status; 692 } 693 694 QDF_STATUS wlan_mlo_mgr_vdev_created_notification(struct wlan_objmgr_vdev *vdev, 695 void *arg_list) 696 { 697 QDF_STATUS status = QDF_STATUS_SUCCESS; 698 struct qdf_mac_addr *mld_addr; 699 700 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 701 if (qdf_is_macaddr_zero(mld_addr)) { 702 /* It's not a ML interface*/ 703 return QDF_STATUS_SUCCESS; 704 } 705 mlo_debug("MLD addr" QDF_MAC_ADDR_FMT, 706 QDF_MAC_ADDR_REF(mld_addr->bytes)); 707 status = mlo_dev_ctx_init(vdev); 708 709 return status; 710 } 711 712 QDF_STATUS wlan_mlo_mgr_vdev_destroyed_notification(struct wlan_objmgr_vdev *vdev, 713 void *arg_list) 714 { 715 QDF_STATUS status = QDF_STATUS_SUCCESS; 716 struct qdf_mac_addr *mld_addr; 717 718 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 719 if (qdf_is_macaddr_zero(mld_addr)) { 720 /* It's not a ML interface*/ 721 return QDF_STATUS_SUCCESS; 722 } 723 mlo_debug("MLD addr" QDF_MAC_ADDR_FMT, 724 QDF_MAC_ADDR_REF(mld_addr->bytes)); 725 726 status = mlo_dev_ctx_deinit(vdev); 727 728 return status; 729 } 730 731 QDF_STATUS wlan_mlo_mgr_update_mld_addr(struct qdf_mac_addr *old_mac, 732 struct qdf_mac_addr *new_mac) 733 { 734 struct wlan_mlo_dev_context *ml_dev; 735 736 ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(old_mac); 737 if (!ml_dev) { 738 mlo_err("ML dev context not found for MLD:" QDF_MAC_ADDR_FMT, 739 QDF_MAC_ADDR_REF(old_mac->bytes)); 740 return QDF_STATUS_E_INVAL; 741 } 742 mlo_dev_lock_acquire(ml_dev); 743 qdf_copy_macaddr(&ml_dev->mld_addr, new_mac); 744 mlo_dev_lock_release(ml_dev); 745 746 return QDF_STATUS_SUCCESS; 747 } 748