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 #include <wlan_cm_api.h> 34 #include <wlan_mlo_mgr_public_api.h> 35 #include "cdp_txrx_cmn.h" 36 37 #ifdef WLAN_WSI_STATS_SUPPORT 38 /* 39 * wlan_mlo_wsi_get_num_psocs() - Get the number of attached PSOCs 40 * @psoc: Pointer to psoc 41 * @arg: Pointer to variable to store count 42 * @index: Index for iteration function 43 */ 44 static void wlan_mlo_wsi_get_num_psocs(struct wlan_objmgr_psoc *psoc, 45 void *arg, uint8_t index) 46 { 47 /* If arg is NULL then skip increment */ 48 if (!arg) 49 return; 50 51 (*(uint32_t *)arg)++; 52 } 53 54 static void mlo_wsi_link_info_deinit(struct mlo_mgr_context *mlo_mgr) 55 { 56 if (!mlo_mgr) 57 return; 58 59 if (mlo_mgr->wsi_info) { 60 qdf_mem_free(mlo_mgr->wsi_info); 61 mlo_mgr->wsi_info = NULL; 62 } 63 } 64 65 #ifdef WLAN_MLO_MULTI_CHIP 66 void mlo_wsi_link_info_update_soc(struct wlan_objmgr_psoc *psoc, 67 uint8_t grp_id) 68 { 69 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 70 struct mlo_wsi_psoc_grp *mlo_grp_info; 71 uint8_t i, j; 72 73 if (!mlo_ctx) { 74 mlo_err("Invalid mlo_mgr_ctx"); 75 return; 76 } 77 78 mlo_grp_info = &mlo_ctx->wsi_info->mlo_psoc_grp[grp_id]; 79 if (!mlo_grp_info) { 80 mlo_err("mlo_grp_info is invalid for ix %d", i); 81 return; 82 } 83 84 mlo_ctx->wsi_info->num_psoc++; 85 86 /* Set the PSOC order for the MLO group */ 87 for (j = 0; j < WLAN_OBJMGR_MAX_DEVICES; j++) { 88 if (mlo_grp_info->psoc_order[j] == MLO_WSI_PSOC_ID_MAX) { 89 mlo_grp_info->psoc_order[j] = wlan_psoc_get_id(psoc); 90 mlo_grp_info->num_psoc++; 91 break; 92 } 93 } 94 } 95 #endif 96 97 static void 98 mlo_wsi_link_info_setup_mlo_grps(struct mlo_mgr_context *mlo_mgr) 99 { 100 struct mlo_wsi_psoc_grp *mlo_grp_info; 101 uint8_t i, j; 102 103 if (!mlo_mgr) { 104 mlo_err("Invalid mlo_mgr"); 105 return; 106 } 107 108 if (!mlo_mgr->wsi_info) { 109 mlo_err("Invalid wsi_info"); 110 return; 111 } 112 113 wlan_objmgr_iterate_psoc_list(wlan_mlo_wsi_get_num_psocs, 114 &mlo_mgr->wsi_info->num_psoc, 115 WLAN_MLO_MGR_ID); 116 if (!mlo_mgr->wsi_info->num_psoc) 117 mlo_info("Could not find active PSOCs"); 118 119 for (i = 0; i < MLO_WSI_MAX_MLO_GRPS; i++) { 120 mlo_grp_info = 121 &mlo_mgr->wsi_info->mlo_psoc_grp[i]; 122 if (!mlo_grp_info) { 123 mlo_err("mlo_grp_info is invalid for ix %d", i); 124 continue; 125 } 126 127 /* Set the PSOC order for the MLO group */ 128 for (j = 0; j < WLAN_OBJMGR_MAX_DEVICES; j++) { 129 /* 130 * NOTE: Inclusion of more MLO groups will require 131 * changes to this block where rvalue will need 132 * to be checked against the group they need to 133 * be assigned to. 134 */ 135 if (j < mlo_mgr->wsi_info->num_psoc) { 136 mlo_grp_info->psoc_order[j] = j; 137 mlo_grp_info->num_psoc++; 138 } else { 139 mlo_grp_info->psoc_order[j] = 140 MLO_WSI_PSOC_ID_MAX; 141 } 142 mlo_err("PSOC order %d, index %d", 143 mlo_grp_info->psoc_order[j], j); 144 } 145 } 146 } 147 148 static void mlo_wsi_link_info_init(struct mlo_mgr_context *mlo_mgr) 149 { 150 uint8_t i; 151 152 if (!mlo_mgr) 153 return; 154 155 /* Initialize the mlo_wsi_link_info structure */ 156 mlo_mgr->wsi_info = qdf_mem_malloc( 157 sizeof(struct mlo_wsi_info)); 158 if (!mlo_mgr->wsi_info) { 159 mlo_err("Could not allocate memory for wsi_link_info"); 160 return; 161 } 162 163 /* Initialize the MLO group context in the WSI stats */ 164 for (i = 0; i < MLO_WSI_MAX_MLO_GRPS; i++) 165 mlo_wsi_link_info_setup_mlo_grps(mlo_mgr); 166 } 167 #else 168 static void mlo_wsi_link_info_init(struct mlo_mgr_context *mlo_mgr) 169 { 170 } 171 172 static void mlo_wsi_link_info_deinit(struct mlo_mgr_context *mlo_mgr) 173 { 174 } 175 #endif 176 177 static void mlo_global_ctx_deinit(void) 178 { 179 struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx(); 180 181 if (!mlo_mgr_ctx) 182 return; 183 184 if (qdf_list_empty(&mlo_mgr_ctx->ml_dev_list)) 185 mlo_debug("ML dev list is not empty"); 186 187 /* Deallocation of the WSI link information */ 188 mlo_wsi_link_info_deinit(mlo_mgr_ctx); 189 190 mlo_setup_deinit(); 191 mlo_msgq_free(); 192 ml_peerid_lock_destroy(mlo_mgr_ctx); 193 ml_link_lock_destroy(mlo_mgr_ctx); 194 ml_aid_lock_destroy(mlo_mgr_ctx); 195 qdf_list_destroy(&mlo_mgr_ctx->ml_dev_list); 196 197 qdf_mem_free(mlo_mgr_ctx); 198 wlan_objmgr_set_mlo_ctx(NULL); 199 } 200 201 static void mlo_global_ctx_init(void) 202 { 203 struct mlo_mgr_context *mlo_mgr_ctx; 204 205 /* If it is already created, ignore */ 206 if (wlan_objmgr_get_mlo_ctx()) { 207 mlo_err("Global object is already created"); 208 return; 209 } 210 211 /* Allocation of memory for Global object */ 212 mlo_mgr_ctx = (struct mlo_mgr_context *) 213 qdf_mem_malloc(sizeof(*mlo_mgr_ctx)); 214 if (!mlo_mgr_ctx) 215 return; 216 217 wlan_objmgr_set_mlo_ctx(mlo_mgr_ctx); 218 219 qdf_list_create(&mlo_mgr_ctx->ml_dev_list, WLAN_UMAC_MLO_MAX_DEV); 220 mlo_mgr_ctx->max_mlo_peer_id = MAX_MLO_PEER_ID; 221 mlo_mgr_ctx->last_mlo_peer_id = 0; 222 ml_peerid_lock_create(mlo_mgr_ctx); 223 ml_link_lock_create(mlo_mgr_ctx); 224 ml_aid_lock_create(mlo_mgr_ctx); 225 mlo_mgr_ctx->mlo_is_force_primary_umac = 0; 226 mlo_mgr_ctx->force_non_assoc_prim_umac = 0; 227 mlo_msgq_init(); 228 229 /* Allocation of the WSI link information */ 230 mlo_wsi_link_info_init(mlo_mgr_ctx); 231 } 232 233 /** 234 * wlan_mlo_check_psoc_capable() - Check if psoc is mlo capable 235 * @psoc: psoc pointer 236 * 237 * API to check if psoc is mlo capable 238 * 239 * Return: bool, true if capable else false 240 */ 241 #ifdef WLAN_MLO_MULTI_CHIP 242 static bool wlan_mlo_check_psoc_capable(struct wlan_objmgr_psoc *psoc) 243 { 244 return wlan_mlo_get_psoc_capable(psoc); 245 } 246 #else 247 static bool wlan_mlo_check_psoc_capable(struct wlan_objmgr_psoc *psoc) 248 { 249 return true; 250 } 251 #endif 252 253 QDF_STATUS wlan_mlo_mgr_psoc_enable(struct wlan_objmgr_psoc *psoc) 254 { 255 struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops; 256 257 if (!psoc) { 258 mlo_err("psoc is null"); 259 return QDF_STATUS_E_NULL_VALUE; 260 } 261 262 if (!wlan_mlo_check_psoc_capable(psoc)) 263 return QDF_STATUS_SUCCESS; 264 265 mlo_tx_ops = target_if_mlo_get_tx_ops(psoc); 266 if (!mlo_tx_ops) { 267 mlo_err("tx_ops is null!"); 268 return QDF_STATUS_E_NULL_VALUE; 269 } 270 271 if (!mlo_tx_ops->register_events) { 272 mlo_err("register_events function is null!"); 273 return QDF_STATUS_E_NULL_VALUE; 274 } 275 276 return mlo_tx_ops->register_events(psoc); 277 } 278 279 QDF_STATUS wlan_mlo_mgr_psoc_disable(struct wlan_objmgr_psoc *psoc) 280 { 281 struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops; 282 283 if (!psoc) { 284 mlo_err("psoc is null"); 285 return QDF_STATUS_E_NULL_VALUE; 286 } 287 288 mlo_tx_ops = target_if_mlo_get_tx_ops(psoc); 289 if (!mlo_tx_ops) { 290 mlo_err("tx_ops is null!"); 291 return QDF_STATUS_E_NULL_VALUE; 292 } 293 294 if (!mlo_tx_ops->unregister_events) { 295 mlo_err("unregister_events function is null!"); 296 return QDF_STATUS_E_NULL_VALUE; 297 } 298 299 return mlo_tx_ops->unregister_events(psoc); 300 } 301 302 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE 303 QDF_STATUS 304 mlo_mgr_register_link_switch_notifier(enum wlan_umac_comp_id comp_id, 305 mlo_mgr_link_switch_notifier_cb cb) 306 { 307 struct mlo_mgr_context *g_mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx(); 308 309 if (!g_mlo_mgr_ctx) { 310 mlo_err("global mlo mgr not initialized"); 311 return QDF_STATUS_E_INVAL; 312 } 313 314 if (!cb || comp_id >= WLAN_UMAC_COMP_ID_MAX) { 315 mlo_err("Invalid component"); 316 QDF_ASSERT(0); 317 return QDF_STATUS_E_INVAL; 318 } 319 320 if (g_mlo_mgr_ctx->lswitch_notifier[comp_id].in_use) 321 return QDF_STATUS_E_ALREADY; 322 323 g_mlo_mgr_ctx->lswitch_notifier[comp_id].in_use = true; 324 g_mlo_mgr_ctx->lswitch_notifier[comp_id].cb = cb; 325 return QDF_STATUS_SUCCESS; 326 } 327 328 QDF_STATUS 329 mlo_mgr_unregister_link_switch_notifier(enum wlan_umac_comp_id comp_id) 330 { 331 struct mlo_mgr_context *g_mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx(); 332 333 if (!g_mlo_mgr_ctx) { 334 mlo_err("global mlo mgr not initialized"); 335 return QDF_STATUS_E_INVAL; 336 } 337 338 if (comp_id >= WLAN_UMAC_COMP_ID_MAX) { 339 mlo_err("Invalid component"); 340 QDF_ASSERT(0); 341 return QDF_STATUS_E_INVAL; 342 } 343 344 if (!g_mlo_mgr_ctx->lswitch_notifier[comp_id].in_use) 345 return QDF_STATUS_E_INVAL; 346 347 g_mlo_mgr_ctx->lswitch_notifier[comp_id].in_use = false; 348 g_mlo_mgr_ctx->lswitch_notifier[comp_id].cb = NULL; 349 return QDF_STATUS_SUCCESS; 350 } 351 352 static QDF_STATUS mlo_mgr_init_link_switch_notifier(void) 353 { 354 int i; 355 struct mlo_mgr_context *g_mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx(); 356 357 if (!g_mlo_mgr_ctx) 358 return QDF_STATUS_E_INVAL; 359 360 for (i = 0; i < WLAN_UMAC_COMP_ID_MAX; i++) { 361 g_mlo_mgr_ctx->lswitch_notifier[i].in_use = false; 362 g_mlo_mgr_ctx->lswitch_notifier[i].cb = NULL; 363 } 364 365 return QDF_STATUS_SUCCESS; 366 } 367 #else 368 static inline QDF_STATUS mlo_mgr_init_link_switch_notifier(void) 369 { 370 return QDF_STATUS_E_NOSUPPORT; 371 } 372 #endif /* WLAN_FEATURE_11BE_MLO_ADV_FEATURE */ 373 374 QDF_STATUS wlan_mlo_mgr_init(void) 375 { 376 QDF_STATUS status; 377 378 mlo_global_ctx_init(); 379 380 status = wlan_objmgr_register_vdev_create_handler( 381 WLAN_UMAC_COMP_MLO_MGR, 382 wlan_mlo_mgr_vdev_created_notification, NULL); 383 if (QDF_IS_STATUS_ERROR(status)) { 384 mlo_err("Failed to register vdev create handler"); 385 return QDF_STATUS_E_FAILURE; 386 } 387 388 status = wlan_objmgr_register_vdev_destroy_handler(WLAN_UMAC_COMP_MLO_MGR, 389 wlan_mlo_mgr_vdev_destroyed_notification, NULL); 390 if (QDF_IS_STATUS_ERROR(status)) { 391 mlo_debug("Failed to register VDEV destroy handler"); 392 wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_MLO_MGR, 393 wlan_mlo_mgr_vdev_created_notification, NULL); 394 return status; 395 } 396 397 status = mlo_mgr_init_link_switch_notifier(); 398 if (QDF_IS_STATUS_SUCCESS(status)) { 399 status = mlo_mgr_register_link_switch_notifier(WLAN_UMAC_COMP_MLO_MGR, 400 mlo_mgr_link_switch_notification); 401 return status; 402 } 403 if (status == QDF_STATUS_E_NOSUPPORT) 404 status = QDF_STATUS_SUCCESS; 405 406 return status; 407 } 408 409 QDF_STATUS wlan_mlo_mgr_deinit(void) 410 { 411 QDF_STATUS status; 412 struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx(); 413 414 if (!mlo_mgr_ctx) { 415 mlo_err("MLO global object is not allocated"); 416 return QDF_STATUS_E_FAILURE; 417 } 418 419 wlan_mlo_mgr_unregister_link_switch_notifier(WLAN_UMAC_COMP_MLO_MGR); 420 421 mlo_global_ctx_deinit(); 422 423 status = wlan_objmgr_unregister_vdev_create_handler( 424 WLAN_UMAC_COMP_MLO_MGR, 425 wlan_mlo_mgr_vdev_created_notification, NULL); 426 if (status != QDF_STATUS_SUCCESS) 427 mlo_err("Failed to unregister vdev create handler"); 428 429 status = wlan_objmgr_unregister_vdev_destroy_handler( 430 WLAN_UMAC_COMP_MLO_MGR, 431 wlan_mlo_mgr_vdev_destroyed_notification, NULL); 432 if (status != QDF_STATUS_SUCCESS) 433 mlo_err("Failed to unregister vdev delete handler"); 434 435 return status; 436 } 437 438 struct wlan_mlo_dev_context *wlan_mlo_list_peek_head( 439 qdf_list_t *ml_list) 440 { 441 struct wlan_mlo_dev_context *mld_ctx; 442 qdf_list_node_t *ml_node = NULL; 443 444 /* This API is invoked with lock acquired, do not add log prints */ 445 if (qdf_list_peek_front(ml_list, &ml_node) != QDF_STATUS_SUCCESS) 446 return NULL; 447 448 mld_ctx = qdf_container_of(ml_node, struct wlan_mlo_dev_context, 449 node); 450 451 return mld_ctx; 452 } 453 454 struct wlan_mlo_dev_context *wlan_mlo_get_next_mld_ctx(qdf_list_t *ml_list, 455 struct wlan_mlo_dev_context *mld_cur) 456 { 457 struct wlan_mlo_dev_context *mld_next; 458 qdf_list_node_t *node = &mld_cur->node; 459 qdf_list_node_t *next_node = NULL; 460 461 /* This API is invoked with lock acquired, do not add log prints */ 462 if (!node) 463 return NULL; 464 465 if (qdf_list_peek_next(ml_list, node, &next_node) != 466 QDF_STATUS_SUCCESS) 467 return NULL; 468 469 mld_next = qdf_container_of(next_node, struct wlan_mlo_dev_context, 470 node); 471 return mld_next; 472 } 473 474 uint8_t wlan_mlo_get_sta_mld_ctx_count(void) 475 { 476 struct wlan_mlo_dev_context *mld_cur; 477 struct wlan_mlo_dev_context *mld_next; 478 qdf_list_t *ml_list; 479 struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx(); 480 uint8_t count = 0; 481 482 if (!mlo_mgr_ctx) 483 return count; 484 485 ml_link_lock_acquire(mlo_mgr_ctx); 486 ml_list = &mlo_mgr_ctx->ml_dev_list; 487 /* Get first mld context */ 488 mld_cur = wlan_mlo_list_peek_head(ml_list); 489 490 while (mld_cur) { 491 /* get next mld node */ 492 if (mld_cur->sta_ctx) 493 count++; 494 mld_next = wlan_mlo_get_next_mld_ctx(ml_list, mld_cur); 495 mld_cur = mld_next; 496 } 497 ml_link_lock_release(mlo_mgr_ctx); 498 499 return count; 500 } 501 502 struct wlan_mlo_dev_context 503 *wlan_mlo_get_mld_ctx_by_mldaddr(struct qdf_mac_addr *mldaddr) 504 { 505 struct wlan_mlo_dev_context *mld_cur; 506 struct wlan_mlo_dev_context *mld_next; 507 qdf_list_t *ml_list; 508 struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx(); 509 510 if (!mlo_mgr_ctx) 511 return NULL; 512 513 ml_link_lock_acquire(mlo_mgr_ctx); 514 ml_list = &mlo_mgr_ctx->ml_dev_list; 515 /* Get first mld context */ 516 mld_cur = wlan_mlo_list_peek_head(ml_list); 517 /** 518 * Iterate through ml list, till ml mldaddr matches with 519 * entry of list 520 */ 521 while (mld_cur) { 522 if (QDF_IS_STATUS_SUCCESS(WLAN_ADDR_EQ(&mld_cur->mld_addr, 523 mldaddr))) { 524 ml_link_lock_release(mlo_mgr_ctx); 525 return mld_cur; 526 } 527 /* get next mld node */ 528 mld_next = wlan_mlo_get_next_mld_ctx(ml_list, mld_cur); 529 mld_cur = mld_next; 530 } 531 ml_link_lock_release(mlo_mgr_ctx); 532 533 return NULL; 534 } 535 536 bool wlan_mlo_is_mld_ctx_exist(struct qdf_mac_addr *mldaddr) 537 { 538 struct wlan_mlo_dev_context *mld_ctx = NULL; 539 540 mld_ctx = wlan_mlo_get_mld_ctx_by_mldaddr(mldaddr); 541 if (mld_ctx) 542 return true; 543 544 return false; 545 } 546 547 #ifdef WLAN_FEATURE_11BE_MLO 548 bool mlo_mgr_ml_peer_exist_on_diff_ml_ctx(uint8_t *peer_addr, 549 uint8_t *peer_vdev_id) 550 { 551 qdf_list_t *ml_list; 552 uint32_t idx, count; 553 struct wlan_mlo_dev_context *mld_cur, *mld_next; 554 struct wlan_mlo_peer_list *mlo_peer_list; 555 struct wlan_objmgr_vdev *vdev; 556 bool ret_status = false, same_ml_ctx = false; 557 struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx(); 558 559 if (!g_mlo_ctx || !peer_addr || 560 qdf_is_macaddr_zero((struct qdf_mac_addr *)peer_addr)) 561 return ret_status; 562 563 ml_link_lock_acquire(g_mlo_ctx); 564 ml_list = &g_mlo_ctx->ml_dev_list; 565 if (!qdf_list_size(ml_list)) 566 goto g_ml_ref; 567 568 mld_cur = wlan_mlo_list_peek_head(ml_list); 569 while (mld_cur) { 570 mlo_dev_lock_acquire(mld_cur); 571 if (qdf_is_macaddr_equal(&mld_cur->mld_addr, 572 (struct qdf_mac_addr *)peer_addr)) { 573 /* For self peer, the address passed will match the 574 * MLD address of its own ML dev context, so allow 575 * peer creation in this scenario as both are in 576 * same ML dev context. 577 */ 578 if (peer_vdev_id) { 579 count = QDF_ARRAY_SIZE(mld_cur->wlan_vdev_list); 580 for (idx = 0; idx < count; idx++) { 581 vdev = mld_cur->wlan_vdev_list[idx]; 582 if (!vdev) 583 continue; 584 if (*peer_vdev_id == 585 wlan_vdev_get_id(vdev)) { 586 same_ml_ctx = true; 587 break; 588 } 589 } 590 } 591 mlo_dev_lock_release(mld_cur); 592 mlo_err("MLD ID %d exists with mac " QDF_MAC_ADDR_FMT, 593 mld_cur->mld_id, QDF_MAC_ADDR_REF(peer_addr)); 594 ret_status = true; 595 goto check_same_ml_ctx; 596 } 597 598 /* Check the peer list for a MAC address match */ 599 mlo_peer_list = &mld_cur->mlo_peer_list; 600 ml_peerlist_lock_acquire(mlo_peer_list); 601 if (mlo_get_mlpeer(mld_cur, (struct qdf_mac_addr *)peer_addr)) { 602 /* If peer_vdev_id is NULL, then API will treat any 603 * match as happening on another dev context 604 */ 605 if (peer_vdev_id) { 606 count = QDF_ARRAY_SIZE(mld_cur->wlan_vdev_list); 607 for (idx = 0; idx < count; idx++) { 608 vdev = mld_cur->wlan_vdev_list[idx]; 609 if (!vdev) 610 continue; 611 if (*peer_vdev_id == 612 wlan_vdev_get_id(vdev)) { 613 same_ml_ctx = true; 614 break; 615 } 616 } 617 } 618 ml_peerlist_lock_release(mlo_peer_list); 619 mlo_dev_lock_release(mld_cur); 620 mlo_err("MLD ID %d ML Peer exists with mac " QDF_MAC_ADDR_FMT, 621 mld_cur->mld_id, QDF_MAC_ADDR_REF(peer_addr)); 622 ret_status = true; 623 goto check_same_ml_ctx; 624 } 625 ml_peerlist_lock_release(mlo_peer_list); 626 627 mld_next = wlan_mlo_get_next_mld_ctx(ml_list, mld_cur); 628 mlo_dev_lock_release(mld_cur); 629 mld_cur = mld_next; 630 } 631 632 check_same_ml_ctx: 633 if (same_ml_ctx) 634 ret_status = false; 635 636 g_ml_ref: 637 ml_link_lock_release(g_mlo_ctx); 638 return ret_status; 639 } 640 641 #define WLAN_HDD_MGMT_FRAME_DA_OFFSET 4 642 #define WLAN_HDD_MGMT_FRAME_SA_OFFSET (WLAN_HDD_MGMT_FRAME_DA_OFFSET + 6) 643 #define WLAN_HDD_MGMT_FRAME_BSSID_OFFSET (WLAN_HDD_MGMT_FRAME_SA_OFFSET + 6) 644 #define WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET \ 645 (WLAN_HDD_MGMT_FRAME_BSSID_OFFSET + 6 + 2) 646 #define WLAN_HDD_MGMT_FRAME_ACTION_TYPE_OFFSET \ 647 (WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET + 1) 648 #define WLAN_HDD_ACTION_FRAME_CATEGORY_PUBLIC 0x04 649 650 /* 651 * Typical 802.11 Action Frame Format 652 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- 653 * | FC | DUR | DA | SA | BSSID |Seq.|Cat.|Act| Elements | FCS | 654 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- 655 * 2 2 6 6 6 2 1 1 Variable Len 4 656 */ 657 void wlan_mlo_update_action_frame_from_user(struct wlan_objmgr_vdev *vdev, 658 uint8_t *frame, 659 uint32_t frame_len) 660 { 661 struct wlan_objmgr_peer *peer; 662 uint8_t *da, *sa, *bssid; 663 664 if (!wlan_vdev_mlme_is_mlo_vdev(vdev) || 665 (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE)) 666 return; 667 668 if (frame_len <= WLAN_HDD_MGMT_FRAME_ACTION_TYPE_OFFSET) { 669 mlo_debug("Not a valid Action frame len: %d", frame_len); 670 return; 671 } 672 673 /* Translate address only for action frames 674 * which are not of public category. 675 * Reference: 802.11-2012, Subclause: 8.5 676 */ 677 678 if (frame[WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET] == 679 WLAN_HDD_ACTION_FRAME_CATEGORY_PUBLIC) 680 return; 681 682 da = frame + WLAN_HDD_MGMT_FRAME_DA_OFFSET; 683 sa = frame + WLAN_HDD_MGMT_FRAME_SA_OFFSET; 684 bssid = frame + WLAN_HDD_MGMT_FRAME_BSSID_OFFSET; 685 686 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_MLO_MGR_ID); 687 if (!peer) { 688 mlo_debug("Peer not found"); 689 return; 690 } 691 692 mlo_debug("Change MLD addr to link addr for non-Public action frame"); 693 /* DA = VDEV's BSS peer's link address. 694 * SA = VDEV's link address. 695 * BSSID = VDEV's BSS peer's link address. 696 */ 697 698 qdf_ether_addr_copy(da, wlan_peer_get_macaddr(peer)); 699 qdf_ether_addr_copy(sa, wlan_vdev_mlme_get_macaddr(vdev)); 700 qdf_ether_addr_copy(bssid, wlan_peer_get_macaddr(peer)); 701 702 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID); 703 } 704 705 void wlan_mlo_update_action_frame_to_user(struct wlan_objmgr_vdev *vdev, 706 uint8_t *frame, 707 uint32_t frame_len) 708 { 709 struct wlan_objmgr_peer *peer; 710 uint8_t *da, *sa, *bssid; 711 712 if (!wlan_vdev_mlme_is_mlo_vdev(vdev) || 713 (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE)) 714 return; 715 716 if (frame_len <= WLAN_HDD_MGMT_FRAME_ACTION_TYPE_OFFSET) { 717 mlo_debug("Not a valid Action frame len: %d", frame_len); 718 return; 719 } 720 721 /* Translate address only for action frames 722 * which are not of public category. 723 * Reference: 802.11-2012, Subclause: 8.5 724 */ 725 726 if (frame[WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET] == 727 WLAN_HDD_ACTION_FRAME_CATEGORY_PUBLIC) 728 return; 729 730 da = frame + WLAN_HDD_MGMT_FRAME_DA_OFFSET; 731 sa = frame + WLAN_HDD_MGMT_FRAME_SA_OFFSET; 732 bssid = frame + WLAN_HDD_MGMT_FRAME_BSSID_OFFSET; 733 734 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_MLO_MGR_ID); 735 if (!peer) { 736 mlo_debug("Peer not found"); 737 return; 738 } 739 740 mlo_debug("Change link addr to MLD addr for non-Public action frame"); 741 /* DA = VDEV's MLD address. 742 * SA = VDEV's BSS peer's MLD address. 743 * BSSID = VDEV's BSS peer's MLD address. 744 */ 745 746 qdf_ether_addr_copy(da, wlan_vdev_mlme_get_mldaddr(vdev)); 747 qdf_ether_addr_copy(sa, wlan_peer_mlme_get_mldaddr(peer)); 748 qdf_ether_addr_copy(bssid, wlan_peer_mlme_get_mldaddr(peer)); 749 750 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID); 751 } 752 #endif 753 754 static QDF_STATUS mlo_ap_ctx_deinit(struct wlan_mlo_dev_context *ml_dev) 755 { 756 wlan_mlo_vdev_aid_mgr_deinit(ml_dev); 757 mlo_ap_lock_destroy(ml_dev->ap_ctx); 758 qdf_mem_free(ml_dev->ap_ctx); 759 ml_dev->ap_ctx = NULL; 760 761 return QDF_STATUS_SUCCESS; 762 } 763 764 static QDF_STATUS mlo_ap_ctx_init(struct wlan_mlo_dev_context *ml_dev) 765 { 766 struct wlan_mlo_ap *ap_ctx; 767 768 ap_ctx = qdf_mem_malloc(sizeof(*ap_ctx)); 769 if (!ap_ctx) { 770 mlo_err("MLO AP ctx alloc failure"); 771 return QDF_STATUS_E_NOMEM; 772 } 773 774 ml_dev->ap_ctx = ap_ctx; 775 mlo_ap_lock_create(ml_dev->ap_ctx); 776 if (wlan_mlo_vdev_aid_mgr_init(ml_dev) != QDF_STATUS_SUCCESS) { 777 mlo_ap_ctx_deinit(ml_dev); 778 return QDF_STATUS_E_NOMEM; 779 } 780 781 return QDF_STATUS_SUCCESS; 782 } 783 784 #ifdef CONFIG_AP_PLATFORM 785 static inline 786 QDF_STATUS wlan_mlo_check_grp_id(uint8_t ref_id, 787 struct wlan_objmgr_vdev *vdev) 788 { 789 struct wlan_objmgr_psoc *psoc; 790 uint8_t grp_id = 0; 791 792 psoc = wlan_vdev_get_psoc(vdev); 793 if (!mlo_psoc_get_grp_id(psoc, &grp_id)) { 794 mlo_err("Unable to get mlo group id"); 795 return QDF_STATUS_E_FAILURE; 796 } 797 798 if (grp_id != ref_id) { 799 mlo_err("Error : MLD VAP Configuration with different WSI/MLD Groups"); 800 return QDF_STATUS_E_FAILURE; 801 } 802 803 return QDF_STATUS_SUCCESS; 804 } 805 806 static inline 807 QDF_STATUS wlan_mlo_pdev_check(struct wlan_objmgr_pdev *ref_pdev, 808 struct wlan_objmgr_vdev *vdev) 809 { 810 struct wlan_objmgr_pdev *pdev; 811 struct wlan_objmgr_psoc *psoc; 812 uint8_t grp_id = 0; 813 814 pdev = wlan_vdev_get_pdev(vdev); 815 816 psoc = wlan_pdev_get_psoc(ref_pdev); 817 if (!mlo_psoc_get_grp_id(psoc, &grp_id)) { 818 mlo_err("Unable to get the MLO Group ID for the vdev"); 819 return QDF_STATUS_E_FAILURE; 820 } 821 822 if (mlo_check_all_pdev_state(psoc, grp_id, MLO_LINK_SETUP_DONE)) { 823 mlo_err("Pdev link is not in ready state, initial link setup failed"); 824 return QDF_STATUS_E_FAILURE; 825 } 826 827 if (ref_pdev == pdev) { 828 mlo_err("MLD vdev for this pdev already found, investigate config"); 829 return QDF_STATUS_E_FAILURE; 830 } 831 832 if (wlan_mlo_check_grp_id(grp_id, vdev)) 833 return QDF_STATUS_E_FAILURE; 834 835 return QDF_STATUS_SUCCESS; 836 } 837 838 static inline 839 QDF_STATUS mlo_dev_config_check(struct wlan_mlo_dev_context *ml_dev, 840 struct wlan_objmgr_vdev *vdev) 841 { 842 return QDF_STATUS_SUCCESS; 843 } 844 845 #else 846 static inline 847 QDF_STATUS mlo_dev_config_check(struct wlan_mlo_dev_context *ml_dev, 848 struct wlan_objmgr_vdev *vdev) 849 { 850 enum QDF_OPMODE opmode = wlan_vdev_mlme_get_opmode(vdev); 851 852 if (wlan_mlo_check_valid_config(ml_dev, wlan_vdev_get_pdev(vdev), 853 opmode) != QDF_STATUS_SUCCESS) 854 return QDF_STATUS_E_FAILURE; 855 856 return QDF_STATUS_SUCCESS; 857 } 858 859 static inline 860 QDF_STATUS wlan_mlo_pdev_check(struct wlan_objmgr_pdev *ref_pdev, 861 struct wlan_objmgr_vdev *vdev) 862 { 863 return QDF_STATUS_SUCCESS; 864 } 865 #endif 866 867 QDF_STATUS wlan_mlo_check_valid_config(struct wlan_mlo_dev_context *ml_dev, 868 struct wlan_objmgr_pdev *pdev, 869 enum QDF_OPMODE opmode) 870 { 871 uint32_t id = 0; 872 struct wlan_objmgr_vdev *vdev; 873 874 if (!ml_dev) 875 return QDF_STATUS_E_FAILURE; 876 877 if (!pdev) 878 return QDF_STATUS_E_FAILURE; 879 880 mlo_dev_lock_acquire(ml_dev); 881 while (id < WLAN_UMAC_MLO_MAX_VDEVS) { 882 vdev = ml_dev->wlan_vdev_list[id]; 883 if (vdev) { 884 if (wlan_mlo_pdev_check(pdev, vdev)) { 885 mlo_dev_lock_release(ml_dev); 886 return QDF_STATUS_E_FAILURE; 887 } 888 889 if (wlan_vdev_mlme_get_opmode(vdev) != opmode) { 890 mlo_err("Invalid opmode %d type found expected %d, investigate config", 891 wlan_vdev_mlme_get_opmode(vdev), 892 opmode); 893 mlo_dev_lock_release(ml_dev); 894 return QDF_STATUS_E_FAILURE; 895 } 896 } 897 id++; 898 } 899 900 mlo_dev_lock_release(ml_dev); 901 return QDF_STATUS_SUCCESS; 902 } 903 904 /** 905 * mlo_t2lm_ctx_init() - API to initialize the t2lm context with the default 906 * values. 907 * @ml_dev: Pointer to ML Dev context 908 * @vdev: Pointer to vdev structure 909 * 910 * Return: None 911 */ 912 static inline void mlo_t2lm_ctx_init(struct wlan_mlo_dev_context *ml_dev, 913 struct wlan_objmgr_vdev *vdev) 914 { 915 struct wlan_t2lm_info *t2lm; 916 917 t2lm = &ml_dev->t2lm_ctx.established_t2lm.t2lm; 918 919 qdf_mem_zero(&ml_dev->t2lm_ctx, sizeof(struct wlan_t2lm_context)); 920 921 t2lm->direction = WLAN_T2LM_BIDI_DIRECTION; 922 t2lm->default_link_mapping = 1; 923 t2lm->link_mapping_size = 0; 924 925 wlan_mlo_t2lm_timer_init(vdev); 926 } 927 928 /** 929 * mlo_epcs_ctx_init() - API to initialize the epcs context with the 930 * default values. 931 * @ml_dev: Pointer to ML Dev context 932 * 933 * Return: None 934 */ 935 static inline void mlo_epcs_ctx_init(struct wlan_mlo_dev_context *ml_dev) 936 { 937 struct wlan_epcs_context *epcs_ctx; 938 939 epcs_ctx = &ml_dev->epcs_ctx; 940 qdf_mem_zero(epcs_ctx, sizeof(struct wlan_epcs_context)); 941 epcs_dev_lock_create(epcs_ctx); 942 } 943 944 #ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE 945 /** 946 * mlo_ptqm_migration_init() - API to initialize ptqm migration timer 947 * @ml_dev: Pointer to ML Dev context 948 * 949 * Return: None 950 */ 951 static inline void mlo_ptqm_migration_init(struct wlan_mlo_dev_context *ml_dev) 952 { 953 qdf_timer_init(NULL, &ml_dev->ptqm_migrate_timer, 954 mlo_mlme_ptqm_migrate_timer_cb, (void *)(ml_dev), 955 QDF_TIMER_TYPE_WAKE_APPS); 956 } 957 #else 958 static inline void mlo_ptqm_migration_init(struct wlan_mlo_dev_context *ml_dev) 959 { } 960 #endif 961 962 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP) 963 static QDF_STATUS 964 mlo_add_to_bridge_vdev_list(struct wlan_objmgr_vdev *vdev) 965 { 966 struct wlan_mlo_dev_context *ml_dev; 967 struct qdf_mac_addr *mld_addr; 968 uint8_t id = 0; 969 970 if (!vdev) 971 return QDF_STATUS_E_FAILURE; 972 973 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 974 ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(mld_addr); 975 976 if (ml_dev) { 977 mlo_dev_lock_acquire(ml_dev); 978 while (id < WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS) { 979 if (ml_dev->wlan_bridge_vdev_list[id]) { 980 id++; 981 continue; 982 } 983 984 ml_dev->wlan_bridge_vdev_list[id] = vdev; 985 ml_dev->wlan_bridge_vdev_count++; 986 vdev->mlo_dev_ctx = ml_dev; 987 break; 988 } 989 mlo_dev_lock_release(ml_dev); 990 991 if (id == WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS) 992 return QDF_STATUS_E_FAILURE; 993 994 return QDF_STATUS_SUCCESS; 995 } 996 997 return QDF_STATUS_E_FAILURE; 998 } 999 1000 static QDF_STATUS 1001 mld_delete_from_bridge_vdev_list(struct wlan_objmgr_vdev *vdev) 1002 { 1003 struct wlan_mlo_dev_context *ml_dev; 1004 struct qdf_mac_addr *mld_addr; 1005 uint8_t id = 0; 1006 1007 if (!vdev) 1008 return QDF_STATUS_E_FAILURE; 1009 1010 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 1011 ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(mld_addr); 1012 1013 if (ml_dev) { 1014 mlo_dev_lock_acquire(ml_dev); 1015 while (id < WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS) { 1016 if (ml_dev->wlan_bridge_vdev_list[id] == vdev) { 1017 vdev->mlo_dev_ctx = NULL; 1018 ml_dev->wlan_bridge_vdev_list[id] = NULL; 1019 ml_dev->wlan_bridge_vdev_count--; 1020 break; 1021 } 1022 id++; 1023 } 1024 mlo_dev_lock_release(ml_dev); 1025 return QDF_STATUS_SUCCESS; 1026 } 1027 1028 return QDF_STATUS_E_FAILURE; 1029 } 1030 #else 1031 static QDF_STATUS 1032 mlo_add_to_bridge_vdev_list(struct wlan_objmgr_vdev *vdev) 1033 { 1034 return QDF_STATUS_SUCCESS; 1035 } 1036 1037 static QDF_STATUS 1038 mld_delete_from_bridge_vdev_list(struct wlan_objmgr_vdev *vdev) 1039 { 1040 return QDF_STATUS_SUCCESS; 1041 } 1042 #endif 1043 1044 static QDF_STATUS mlo_dev_ctx_init(struct wlan_objmgr_vdev *vdev) 1045 { 1046 struct wlan_mlo_dev_context *ml_dev; 1047 QDF_STATUS status = QDF_STATUS_SUCCESS; 1048 struct qdf_mac_addr *mld_addr; 1049 struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx(); 1050 uint8_t id = 0; 1051 struct wlan_objmgr_psoc *psoc = NULL; 1052 1053 if (wlan_vdev_mlme_is_mlo_bridge_vdev(vdev)) { 1054 status = mlo_add_to_bridge_vdev_list(vdev); 1055 if (!QDF_IS_STATUS_SUCCESS(status)) 1056 mlo_err("Failed to init bridge vap ctx"); 1057 return status; 1058 } 1059 1060 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 1061 ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(mld_addr); 1062 psoc = wlan_vdev_get_psoc(vdev); 1063 1064 if (!psoc) { 1065 mlo_err("Failed to get psoc"); 1066 return QDF_STATUS_E_FAILURE; 1067 } 1068 1069 if (ml_dev) { 1070 if (mlo_dev_config_check(ml_dev, vdev) != QDF_STATUS_SUCCESS) 1071 return QDF_STATUS_E_FAILURE; 1072 1073 mlo_dev_lock_acquire(ml_dev); 1074 while (id < WLAN_UMAC_MLO_MAX_VDEVS) { 1075 if (ml_dev->wlan_vdev_list[id]) { 1076 id++; 1077 continue; 1078 } 1079 1080 ml_dev->wlan_vdev_list[id] = vdev; 1081 ml_dev->wlan_vdev_count++; 1082 vdev->mlo_dev_ctx = ml_dev; 1083 1084 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) 1085 wlan_mlo_vdev_alloc_aid_mgr(ml_dev, vdev); 1086 1087 break; 1088 } 1089 mlo_dev_lock_release(ml_dev); 1090 return QDF_STATUS_SUCCESS; 1091 } 1092 1093 /* Create a new ML dev context */ 1094 ml_dev = qdf_mem_malloc(sizeof(*ml_dev)); 1095 if (!ml_dev) { 1096 mlo_err("Failed to allocate memory for ML dev"); 1097 return QDF_STATUS_E_NOMEM; 1098 } 1099 1100 qdf_copy_macaddr(&ml_dev->mld_addr, mld_addr); 1101 ml_dev->wlan_vdev_list[0] = vdev; 1102 ml_dev->wlan_vdev_count++; 1103 vdev->mlo_dev_ctx = ml_dev; 1104 1105 mlo_dev_lock_create(ml_dev); 1106 tsf_recalculation_lock_create(ml_dev); 1107 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) { 1108 ml_dev->sta_ctx = qdf_mem_malloc(sizeof(struct wlan_mlo_sta)); 1109 if (!ml_dev->sta_ctx) { 1110 tsf_recalculation_lock_destroy(ml_dev); 1111 mlo_dev_lock_destroy(ml_dev); 1112 qdf_mem_free(ml_dev); 1113 return QDF_STATUS_E_NOMEM; 1114 } 1115 copied_conn_req_lock_create(ml_dev->sta_ctx); 1116 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP) 1117 ml_dev->bridge_sta_ctx = qdf_mem_malloc(sizeof(struct wlan_mlo_bridge_sta)); 1118 if (!ml_dev->bridge_sta_ctx) { 1119 tsf_recalculation_lock_destroy(ml_dev); 1120 mlo_dev_lock_destroy(ml_dev); 1121 qdf_mem_free(ml_dev->sta_ctx); 1122 qdf_mem_free(ml_dev); 1123 return QDF_STATUS_E_NOMEM; 1124 } 1125 #endif 1126 } else if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) { 1127 if (mlo_ap_ctx_init(ml_dev) != QDF_STATUS_SUCCESS) { 1128 tsf_recalculation_lock_destroy(ml_dev); 1129 mlo_dev_lock_destroy(ml_dev); 1130 qdf_mem_free(ml_dev); 1131 mlo_err("Failed to allocate memory for ap ctx"); 1132 return QDF_STATUS_E_NOMEM; 1133 } 1134 } 1135 1136 /* Create DP MLO Device Context */ 1137 if (cdp_mlo_dev_ctxt_create(wlan_psoc_get_dp_handle(psoc), 1138 (uint8_t *)mld_addr) != 1139 QDF_STATUS_SUCCESS) { 1140 tsf_recalculation_lock_destroy(ml_dev); 1141 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) { 1142 qdf_mem_free(ml_dev->sta_ctx); 1143 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP) 1144 qdf_mem_free(ml_dev->bridge_sta_ctx); 1145 #endif 1146 } else if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) { 1147 mlo_ap_ctx_deinit(ml_dev); 1148 } 1149 mlo_dev_lock_destroy(ml_dev); 1150 qdf_mem_free(ml_dev); 1151 mlo_err("Failed to create DP MLO Dev ctxt"); 1152 return QDF_STATUS_E_NOMEM; 1153 } 1154 1155 ml_dev->mlo_max_recom_simult_links = 1156 WLAN_UMAC_MLO_RECOM_MAX_SIMULT_LINKS_DEFAULT; 1157 1158 mlo_dev_mlpeer_list_init(ml_dev); 1159 1160 ml_link_lock_acquire(g_mlo_ctx); 1161 if (qdf_list_size(&g_mlo_ctx->ml_dev_list) < WLAN_UMAC_MLO_MAX_DEV) 1162 qdf_list_insert_back(&g_mlo_ctx->ml_dev_list, &ml_dev->node); 1163 ml_link_lock_release(g_mlo_ctx); 1164 1165 mlo_t2lm_ctx_init(ml_dev, vdev); 1166 mlo_epcs_ctx_init(ml_dev); 1167 mlo_ptqm_migration_init(ml_dev); 1168 mlo_mgr_link_switch_init(ml_dev); 1169 1170 return status; 1171 } 1172 1173 #ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE 1174 /** 1175 * mlo_ptqm_migration_deinit() - API to deinitialize ptqm migration timer 1176 * @ml_dev: Pointer to ML Dev context 1177 * 1178 * Return: None 1179 */ 1180 static inline void mlo_ptqm_migration_deinit( 1181 struct wlan_mlo_dev_context *ml_dev) 1182 { 1183 qdf_timer_free(&ml_dev->ptqm_migrate_timer); 1184 } 1185 #else 1186 static inline void mlo_ptqm_migration_deinit( 1187 struct wlan_mlo_dev_context *ml_dev) 1188 { } 1189 #endif 1190 1191 /** 1192 * mlo_t2lm_ctx_deinit() - API to deinitialize the t2lm context with the default 1193 * values. 1194 * @vdev: Pointer to vdev structure 1195 * 1196 * Return: None 1197 */ 1198 static inline void mlo_t2lm_ctx_deinit(struct wlan_objmgr_vdev *vdev) 1199 { 1200 wlan_mlo_t2lm_timer_deinit(vdev); 1201 } 1202 1203 /** 1204 * mlo_epcs_ctx_deinit() - API to deinitialize the epcs context with the default 1205 * values. 1206 * @mlo_dev_ctx: MLO dev context pointer 1207 * 1208 * Return: None 1209 */ 1210 static inline void mlo_epcs_ctx_deinit(struct wlan_mlo_dev_context *mlo_dev_ctx) 1211 { 1212 epcs_dev_lock_destroy(&mlo_dev_ctx->epcs_ctx); 1213 } 1214 1215 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 1216 static void ml_free_copied_reassoc_rsp(struct wlan_mlo_sta *sta_ctx) 1217 { 1218 wlan_cm_free_connect_resp(sta_ctx->copied_reassoc_rsp); 1219 } 1220 #else 1221 static void ml_free_copied_reassoc_rsp(struct wlan_mlo_sta *sta_ctx) 1222 { 1223 return; 1224 } 1225 #endif 1226 1227 static QDF_STATUS mlo_dev_ctx_deinit(struct wlan_objmgr_vdev *vdev) 1228 { 1229 struct wlan_mlo_dev_context *ml_dev; 1230 QDF_STATUS status = QDF_STATUS_SUCCESS; 1231 struct qdf_mac_addr *mld_addr; 1232 struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx(); 1233 uint8_t id = 0; 1234 struct wlan_cm_connect_req *connect_req; 1235 struct wlan_objmgr_psoc *psoc = NULL; 1236 1237 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 1238 ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(mld_addr); 1239 psoc = wlan_vdev_get_psoc(vdev); 1240 1241 if (!psoc) { 1242 mlo_err("Failed to get psoc"); 1243 return QDF_STATUS_E_FAILURE; 1244 } 1245 1246 if (!ml_dev) { 1247 mlo_err("Failed to get MLD dev context by mld addr "QDF_MAC_ADDR_FMT, 1248 QDF_MAC_ADDR_REF(mld_addr->bytes)); 1249 if (!vdev->mlo_dev_ctx) { 1250 mlo_err("Failed to get MLD dev context from vdev"); 1251 return QDF_STATUS_SUCCESS; 1252 } 1253 ml_dev = vdev->mlo_dev_ctx; 1254 } 1255 1256 mlo_debug("deleting vdev from MLD device ctx "QDF_MAC_ADDR_FMT, 1257 QDF_MAC_ADDR_REF(mld_addr->bytes)); 1258 1259 mlo_dev_lock_acquire(ml_dev); 1260 while (id < WLAN_UMAC_MLO_MAX_VDEVS) { 1261 if (ml_dev->wlan_vdev_list[id] == vdev) { 1262 if (wlan_vdev_mlme_get_opmode(vdev) == 1263 QDF_SAP_MODE) 1264 wlan_mlo_vdev_free_aid_mgr(ml_dev, 1265 vdev); 1266 ml_dev->wlan_vdev_list[id] = NULL; 1267 ml_dev->wlan_vdev_count--; 1268 vdev->mlo_dev_ctx = NULL; 1269 break; 1270 } 1271 id++; 1272 } 1273 mlo_dev_lock_release(ml_dev); 1274 1275 if (wlan_vdev_mlme_is_mlo_bridge_vdev(vdev)) { 1276 status = mld_delete_from_bridge_vdev_list(vdev); 1277 if (!QDF_IS_STATUS_SUCCESS(status)) 1278 mlo_err("Failed to deinit bridge vap ctx"); 1279 } 1280 1281 ml_link_lock_acquire(g_mlo_ctx); 1282 if (!ml_dev->wlan_vdev_count && !ml_dev->wlan_bridge_vdev_count) { 1283 if (ml_dev->ap_ctx) 1284 mlo_ap_ctx_deinit(ml_dev); 1285 1286 mlo_dev_mlpeer_list_deinit(ml_dev); 1287 qdf_list_remove_node(&g_mlo_ctx->ml_dev_list, 1288 &ml_dev->node); 1289 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) { 1290 connect_req = ml_dev->sta_ctx->connect_req; 1291 wlan_cm_free_connect_req(connect_req); 1292 1293 if (ml_dev->sta_ctx->disconn_req) 1294 qdf_mem_free(ml_dev->sta_ctx->disconn_req); 1295 1296 if (ml_dev->sta_ctx->assoc_rsp.ptr) 1297 qdf_mem_free(ml_dev->sta_ctx->assoc_rsp.ptr); 1298 1299 ml_free_copied_reassoc_rsp(ml_dev->sta_ctx); 1300 1301 copied_conn_req_lock_destroy(ml_dev->sta_ctx); 1302 1303 qdf_mem_free(ml_dev->sta_ctx); 1304 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP) 1305 qdf_mem_free(ml_dev->bridge_sta_ctx); 1306 #endif 1307 } 1308 else if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) 1309 qdf_mem_free(ml_dev->ap_ctx); 1310 1311 mlo_ptqm_migration_deinit(ml_dev); 1312 mlo_mgr_link_switch_deinit(ml_dev); 1313 mlo_t2lm_ctx_deinit(vdev); 1314 mlo_epcs_ctx_deinit(ml_dev); 1315 1316 /* Destroy DP MLO Device Context */ 1317 if (cdp_mlo_dev_ctxt_destroy(wlan_psoc_get_dp_handle(psoc), 1318 (uint8_t *)mld_addr) != 1319 QDF_STATUS_SUCCESS) { 1320 mlo_err("Failed to destroy DP MLO Dev ctxt"); 1321 QDF_BUG(0); 1322 } 1323 1324 tsf_recalculation_lock_destroy(ml_dev); 1325 mlo_dev_lock_destroy(ml_dev); 1326 qdf_mem_free(ml_dev); 1327 } 1328 ml_link_lock_release(g_mlo_ctx); 1329 return status; 1330 } 1331 1332 QDF_STATUS wlan_mlo_mgr_vdev_created_notification(struct wlan_objmgr_vdev *vdev, 1333 void *arg_list) 1334 { 1335 QDF_STATUS status = QDF_STATUS_SUCCESS; 1336 struct qdf_mac_addr *mld_addr; 1337 1338 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 1339 if (qdf_is_macaddr_zero(mld_addr)) { 1340 /* It's not a ML interface*/ 1341 return QDF_STATUS_SUCCESS; 1342 } 1343 mlo_debug("MLD addr" QDF_MAC_ADDR_FMT, 1344 QDF_MAC_ADDR_REF(mld_addr->bytes)); 1345 status = mlo_dev_ctx_init(vdev); 1346 1347 wlan_vdev_set_link_id(vdev, WLAN_LINK_ID_INVALID); 1348 1349 return status; 1350 } 1351 1352 QDF_STATUS wlan_mlo_mgr_vdev_destroyed_notification(struct wlan_objmgr_vdev *vdev, 1353 void *arg_list) 1354 { 1355 QDF_STATUS status = QDF_STATUS_SUCCESS; 1356 struct qdf_mac_addr *mld_addr; 1357 1358 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 1359 if (qdf_is_macaddr_zero(mld_addr)) { 1360 /* It's not a ML interface*/ 1361 return QDF_STATUS_SUCCESS; 1362 } 1363 mlo_debug("MLD addr" QDF_MAC_ADDR_FMT, 1364 QDF_MAC_ADDR_REF(mld_addr->bytes)); 1365 1366 status = mlo_dev_ctx_deinit(vdev); 1367 1368 return status; 1369 } 1370 1371 QDF_STATUS wlan_mlo_mgr_update_mld_addr(struct qdf_mac_addr *old_mac, 1372 struct qdf_mac_addr *new_mac) 1373 { 1374 struct wlan_mlo_dev_context *ml_dev; 1375 1376 ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(old_mac); 1377 if (!ml_dev) { 1378 mlo_err("ML dev context not found for MLD:" QDF_MAC_ADDR_FMT, 1379 QDF_MAC_ADDR_REF(old_mac->bytes)); 1380 return QDF_STATUS_E_INVAL; 1381 } 1382 mlo_dev_lock_acquire(ml_dev); 1383 qdf_copy_macaddr(&ml_dev->mld_addr, new_mac); 1384 mlo_dev_lock_release(ml_dev); 1385 1386 return QDF_STATUS_SUCCESS; 1387 } 1388 1389 QDF_STATUS wlan_mlo_mgr_mld_vdev_attach(struct wlan_objmgr_vdev *vdev, 1390 struct qdf_mac_addr *mld_addr) 1391 { 1392 QDF_STATUS status = QDF_STATUS_SUCCESS; 1393 struct wlan_objmgr_psoc *psoc = NULL; 1394 1395 psoc = wlan_vdev_get_psoc(vdev); 1396 if (!psoc) { 1397 mlo_err("Failed to get psoc"); 1398 return QDF_STATUS_E_FAILURE; 1399 } 1400 1401 wlan_vdev_obj_lock(vdev); 1402 wlan_vdev_mlme_set_mldaddr(vdev, (uint8_t *)&mld_addr->bytes[0]); 1403 wlan_vdev_obj_unlock(vdev); 1404 1405 status = mlo_dev_ctx_init(vdev); 1406 1407 if (cdp_mlo_dev_ctxt_attach(wlan_psoc_get_dp_handle(psoc), 1408 wlan_vdev_get_id(vdev), 1409 (uint8_t *)mld_addr) 1410 != QDF_STATUS_SUCCESS) { 1411 mlo_err("Failed to attach DP vdev (" QDF_MAC_ADDR_FMT ") to" 1412 " MLO Dev ctxt (" QDF_MAC_ADDR_FMT ")", 1413 QDF_MAC_ADDR_REF(wlan_vdev_mlme_get_macaddr(vdev)), 1414 QDF_MAC_ADDR_REF(mld_addr->bytes)); 1415 } 1416 return status; 1417 } 1418 1419 QDF_STATUS wlan_mlo_mgr_mld_vdev_detach(struct wlan_objmgr_vdev *vdev) 1420 { 1421 QDF_STATUS status = QDF_STATUS_SUCCESS; 1422 struct qdf_mac_addr *mld_addr; 1423 struct wlan_objmgr_psoc *psoc = NULL; 1424 1425 psoc = wlan_vdev_get_psoc(vdev); 1426 if (!psoc) { 1427 mlo_err("Failed to get psoc"); 1428 return QDF_STATUS_E_FAILURE; 1429 } 1430 1431 status = mlo_dev_ctx_deinit(vdev); 1432 1433 /* Detach DP vdev from DP MLO Device Context */ 1434 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 1435 1436 if (cdp_mlo_dev_ctxt_detach(wlan_psoc_get_dp_handle(psoc), 1437 wlan_vdev_get_id(vdev), 1438 (uint8_t *)mld_addr) 1439 != QDF_STATUS_SUCCESS) { 1440 mlo_err("Failed to detach DP vdev (" QDF_MAC_ADDR_FMT ") from" 1441 " MLO Dev ctxt (" QDF_MAC_ADDR_FMT ")", 1442 QDF_MAC_ADDR_REF(wlan_vdev_mlme_get_macaddr(vdev)), 1443 QDF_MAC_ADDR_REF(mld_addr->bytes)); 1444 } 1445 1446 wlan_vdev_obj_lock(vdev); 1447 wlan_vdev_mlme_reset_mldaddr(vdev); 1448 wlan_vdev_mlme_op_flags_clear(vdev, WLAN_VDEV_OP_MLO_REMOVE_LINK_VDEV); 1449 wlan_vdev_obj_unlock(vdev); 1450 1451 return status; 1452 } 1453