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_MLO_MULTI_CHIP 548 QDF_STATUS mlo_mgr_is_mld_has_active_link(bool *is_active) 549 { 550 qdf_list_t *ml_list; 551 uint32_t idx, count; 552 struct wlan_mlo_dev_context *mld_cur, *mld_next; 553 struct wlan_objmgr_vdev *vdev; 554 struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx(); 555 QDF_STATUS status; 556 557 if (!g_mlo_ctx || !is_active) 558 return QDF_STATUS_E_FAILURE; 559 560 ml_link_lock_acquire(g_mlo_ctx); 561 ml_list = &g_mlo_ctx->ml_dev_list; 562 if (!qdf_list_size(ml_list)) { 563 ml_link_lock_release(g_mlo_ctx); 564 return QDF_STATUS_E_FAILURE; 565 } 566 567 *is_active = false; 568 mld_cur = wlan_mlo_list_peek_head(ml_list); 569 while (mld_cur) { 570 mlo_dev_lock_acquire(mld_cur); 571 count = QDF_ARRAY_SIZE(mld_cur->wlan_vdev_list); 572 for (idx = 0; idx < count; idx++) { 573 vdev = mld_cur->wlan_vdev_list[idx]; 574 if (!vdev) 575 continue; 576 577 status = wlan_vdev_mlme_is_init_state(vdev); 578 if (QDF_STATUS_SUCCESS == status) 579 continue; 580 581 qdf_err("VDEV [vdev_id %u, pdev_id %u, psoc_id %u, state %u] is still active", 582 wlan_vdev_get_id(vdev), 583 wlan_objmgr_pdev_get_pdev_id(wlan_vdev_get_pdev(vdev)), 584 wlan_vdev_get_psoc_id(vdev), 585 wlan_vdev_mlme_get_state(vdev)); 586 *is_active = true; 587 mlo_dev_lock_release(mld_cur); 588 ml_link_lock_release(g_mlo_ctx); 589 return QDF_STATUS_SUCCESS; 590 } 591 mld_next = wlan_mlo_get_next_mld_ctx(ml_list, mld_cur); 592 mlo_dev_lock_release(mld_cur); 593 mld_cur = mld_next; 594 } 595 ml_link_lock_release(g_mlo_ctx); 596 597 return QDF_STATUS_SUCCESS; 598 } 599 600 qdf_export_symbol(mlo_mgr_is_mld_has_active_link); 601 #endif 602 603 #ifdef WLAN_FEATURE_11BE_MLO 604 bool mlo_mgr_ml_peer_exist_on_diff_ml_ctx(uint8_t *peer_addr, 605 uint8_t *peer_vdev_id) 606 { 607 qdf_list_t *ml_list; 608 uint32_t idx, count; 609 struct wlan_mlo_dev_context *mld_cur, *mld_next; 610 struct wlan_mlo_peer_list *mlo_peer_list; 611 struct wlan_objmgr_vdev *vdev; 612 bool ret_status = false, same_ml_ctx = false; 613 struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx(); 614 615 if (!g_mlo_ctx || !peer_addr || 616 qdf_is_macaddr_zero((struct qdf_mac_addr *)peer_addr)) 617 return ret_status; 618 619 ml_link_lock_acquire(g_mlo_ctx); 620 ml_list = &g_mlo_ctx->ml_dev_list; 621 if (!qdf_list_size(ml_list)) 622 goto g_ml_ref; 623 624 mld_cur = wlan_mlo_list_peek_head(ml_list); 625 while (mld_cur) { 626 mlo_dev_lock_acquire(mld_cur); 627 if (qdf_is_macaddr_equal(&mld_cur->mld_addr, 628 (struct qdf_mac_addr *)peer_addr)) { 629 /* For self peer, the address passed will match the 630 * MLD address of its own ML dev context, so allow 631 * peer creation in this scenario as both are in 632 * same ML dev context. 633 */ 634 if (peer_vdev_id) { 635 count = QDF_ARRAY_SIZE(mld_cur->wlan_vdev_list); 636 for (idx = 0; idx < count; idx++) { 637 vdev = mld_cur->wlan_vdev_list[idx]; 638 if (!vdev) 639 continue; 640 if (*peer_vdev_id == 641 wlan_vdev_get_id(vdev)) { 642 same_ml_ctx = true; 643 break; 644 } 645 } 646 } 647 mlo_dev_lock_release(mld_cur); 648 mlo_err("MLD ID %d exists with mac " QDF_MAC_ADDR_FMT, 649 mld_cur->mld_id, QDF_MAC_ADDR_REF(peer_addr)); 650 ret_status = true; 651 goto check_same_ml_ctx; 652 } 653 654 /* Check the peer list for a MAC address match */ 655 mlo_peer_list = &mld_cur->mlo_peer_list; 656 ml_peerlist_lock_acquire(mlo_peer_list); 657 if (mlo_get_mlpeer(mld_cur, (struct qdf_mac_addr *)peer_addr)) { 658 /* If peer_vdev_id is NULL, then API will treat any 659 * match as happening on another dev context 660 */ 661 if (peer_vdev_id) { 662 count = QDF_ARRAY_SIZE(mld_cur->wlan_vdev_list); 663 for (idx = 0; idx < count; idx++) { 664 vdev = mld_cur->wlan_vdev_list[idx]; 665 if (!vdev) 666 continue; 667 if (*peer_vdev_id == 668 wlan_vdev_get_id(vdev)) { 669 same_ml_ctx = true; 670 break; 671 } 672 } 673 } 674 ml_peerlist_lock_release(mlo_peer_list); 675 mlo_dev_lock_release(mld_cur); 676 mlo_err("MLD ID %d ML Peer exists with mac " QDF_MAC_ADDR_FMT, 677 mld_cur->mld_id, QDF_MAC_ADDR_REF(peer_addr)); 678 ret_status = true; 679 goto check_same_ml_ctx; 680 } 681 ml_peerlist_lock_release(mlo_peer_list); 682 683 mld_next = wlan_mlo_get_next_mld_ctx(ml_list, mld_cur); 684 mlo_dev_lock_release(mld_cur); 685 mld_cur = mld_next; 686 } 687 688 check_same_ml_ctx: 689 if (same_ml_ctx) 690 ret_status = false; 691 692 g_ml_ref: 693 ml_link_lock_release(g_mlo_ctx); 694 return ret_status; 695 } 696 697 #define WLAN_HDD_MGMT_FRAME_DA_OFFSET 4 698 #define WLAN_HDD_MGMT_FRAME_SA_OFFSET (WLAN_HDD_MGMT_FRAME_DA_OFFSET + 6) 699 #define WLAN_HDD_MGMT_FRAME_BSSID_OFFSET (WLAN_HDD_MGMT_FRAME_SA_OFFSET + 6) 700 #define WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET \ 701 (WLAN_HDD_MGMT_FRAME_BSSID_OFFSET + 6 + 2) 702 #define WLAN_HDD_MGMT_FRAME_ACTION_TYPE_OFFSET \ 703 (WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET + 1) 704 #define WLAN_HDD_ACTION_FRAME_CATEGORY_PUBLIC 0x04 705 706 /* 707 * Typical 802.11 Action Frame Format 708 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- 709 * | FC | DUR | DA | SA | BSSID |Seq.|Cat.|Act| Elements | FCS | 710 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- 711 * 2 2 6 6 6 2 1 1 Variable Len 4 712 */ 713 void wlan_mlo_update_action_frame_from_user(struct wlan_objmgr_vdev *vdev, 714 uint8_t *frame, 715 uint32_t frame_len) 716 { 717 struct wlan_objmgr_peer *peer; 718 uint8_t *da, *sa, *bssid; 719 720 if (!wlan_vdev_mlme_is_mlo_vdev(vdev) || 721 (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE)) 722 return; 723 724 if (frame_len <= WLAN_HDD_MGMT_FRAME_ACTION_TYPE_OFFSET) { 725 mlo_debug("Not a valid Action frame len: %d", frame_len); 726 return; 727 } 728 729 /* Translate address only for action frames 730 * which are not of public category. 731 * Reference: 802.11-2012, Subclause: 8.5 732 */ 733 734 if (frame[WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET] == 735 WLAN_HDD_ACTION_FRAME_CATEGORY_PUBLIC) 736 return; 737 738 da = frame + WLAN_HDD_MGMT_FRAME_DA_OFFSET; 739 sa = frame + WLAN_HDD_MGMT_FRAME_SA_OFFSET; 740 bssid = frame + WLAN_HDD_MGMT_FRAME_BSSID_OFFSET; 741 742 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_MLO_MGR_ID); 743 if (!peer) { 744 mlo_debug("Peer not found"); 745 return; 746 } 747 748 mlo_debug("Change MLD addr to link addr for non-Public action frame"); 749 /* DA = VDEV's BSS peer's link address. 750 * SA = VDEV's link address. 751 * BSSID = VDEV's BSS peer's link address. 752 */ 753 754 qdf_ether_addr_copy(da, wlan_peer_get_macaddr(peer)); 755 qdf_ether_addr_copy(sa, wlan_vdev_mlme_get_macaddr(vdev)); 756 qdf_ether_addr_copy(bssid, wlan_peer_get_macaddr(peer)); 757 758 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID); 759 } 760 761 void wlan_mlo_update_action_frame_to_user(struct wlan_objmgr_vdev *vdev, 762 uint8_t *frame, 763 uint32_t frame_len) 764 { 765 struct wlan_objmgr_peer *peer; 766 uint8_t *da, *sa, *bssid; 767 768 if (!wlan_vdev_mlme_is_mlo_vdev(vdev) || 769 (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE)) 770 return; 771 772 if (frame_len <= WLAN_HDD_MGMT_FRAME_ACTION_TYPE_OFFSET) { 773 mlo_debug("Not a valid Action frame len: %d", frame_len); 774 return; 775 } 776 777 /* Translate address only for action frames 778 * which are not of public category. 779 * Reference: 802.11-2012, Subclause: 8.5 780 */ 781 782 if (frame[WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET] == 783 WLAN_HDD_ACTION_FRAME_CATEGORY_PUBLIC) 784 return; 785 786 da = frame + WLAN_HDD_MGMT_FRAME_DA_OFFSET; 787 sa = frame + WLAN_HDD_MGMT_FRAME_SA_OFFSET; 788 bssid = frame + WLAN_HDD_MGMT_FRAME_BSSID_OFFSET; 789 790 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_MLO_MGR_ID); 791 if (!peer) { 792 mlo_debug("Peer not found"); 793 return; 794 } 795 796 mlo_debug("Change link addr to MLD addr for non-Public action frame"); 797 /* DA = VDEV's MLD address. 798 * SA = VDEV's BSS peer's MLD address. 799 * BSSID = VDEV's BSS peer's MLD address. 800 */ 801 802 qdf_ether_addr_copy(da, wlan_vdev_mlme_get_mldaddr(vdev)); 803 qdf_ether_addr_copy(sa, wlan_peer_mlme_get_mldaddr(peer)); 804 qdf_ether_addr_copy(bssid, wlan_peer_mlme_get_mldaddr(peer)); 805 806 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID); 807 } 808 #endif 809 810 static QDF_STATUS mlo_ap_ctx_deinit(struct wlan_mlo_dev_context *ml_dev) 811 { 812 wlan_mlo_vdev_aid_mgr_deinit(ml_dev); 813 mlo_ap_lock_destroy(ml_dev->ap_ctx); 814 qdf_mem_free(ml_dev->ap_ctx); 815 ml_dev->ap_ctx = NULL; 816 817 return QDF_STATUS_SUCCESS; 818 } 819 820 static QDF_STATUS mlo_ap_ctx_init(struct wlan_mlo_dev_context *ml_dev) 821 { 822 struct wlan_mlo_ap *ap_ctx; 823 824 ap_ctx = qdf_mem_malloc(sizeof(*ap_ctx)); 825 if (!ap_ctx) { 826 mlo_err("MLO AP ctx alloc failure"); 827 return QDF_STATUS_E_NOMEM; 828 } 829 830 ml_dev->ap_ctx = ap_ctx; 831 mlo_ap_lock_create(ml_dev->ap_ctx); 832 if (wlan_mlo_vdev_aid_mgr_init(ml_dev) != QDF_STATUS_SUCCESS) { 833 mlo_ap_ctx_deinit(ml_dev); 834 return QDF_STATUS_E_NOMEM; 835 } 836 837 return QDF_STATUS_SUCCESS; 838 } 839 840 #ifdef CONFIG_AP_PLATFORM 841 static inline 842 QDF_STATUS wlan_mlo_check_grp_id(uint8_t ref_id, 843 struct wlan_objmgr_vdev *vdev) 844 { 845 struct wlan_objmgr_psoc *psoc; 846 uint8_t grp_id = 0; 847 848 psoc = wlan_vdev_get_psoc(vdev); 849 if (!mlo_psoc_get_grp_id(psoc, &grp_id)) { 850 mlo_err("Unable to get mlo group id"); 851 return QDF_STATUS_E_FAILURE; 852 } 853 854 if (grp_id != ref_id) { 855 mlo_err("Error : MLD VAP Configuration with different WSI/MLD Groups"); 856 return QDF_STATUS_E_FAILURE; 857 } 858 859 return QDF_STATUS_SUCCESS; 860 } 861 862 static inline 863 QDF_STATUS wlan_mlo_pdev_check(struct wlan_objmgr_pdev *ref_pdev, 864 struct wlan_objmgr_vdev *vdev) 865 { 866 struct wlan_objmgr_pdev *pdev; 867 struct wlan_objmgr_psoc *psoc; 868 uint8_t grp_id = 0; 869 870 pdev = wlan_vdev_get_pdev(vdev); 871 872 psoc = wlan_pdev_get_psoc(ref_pdev); 873 if (!mlo_psoc_get_grp_id(psoc, &grp_id)) { 874 mlo_err("Unable to get the MLO Group ID for the vdev"); 875 return QDF_STATUS_E_FAILURE; 876 } 877 878 if (mlo_check_all_pdev_state(psoc, grp_id, MLO_LINK_SETUP_DONE)) { 879 mlo_err("Pdev link is not in ready state, initial link setup failed"); 880 return QDF_STATUS_E_FAILURE; 881 } 882 883 if (ref_pdev == pdev) { 884 mlo_err("MLD vdev for this pdev already found, investigate config"); 885 return QDF_STATUS_E_FAILURE; 886 } 887 888 if (wlan_mlo_check_grp_id(grp_id, vdev)) 889 return QDF_STATUS_E_FAILURE; 890 891 return QDF_STATUS_SUCCESS; 892 } 893 894 static inline 895 QDF_STATUS mlo_dev_config_check(struct wlan_mlo_dev_context *ml_dev, 896 struct wlan_objmgr_vdev *vdev) 897 { 898 return QDF_STATUS_SUCCESS; 899 } 900 901 #else 902 static inline 903 QDF_STATUS mlo_dev_config_check(struct wlan_mlo_dev_context *ml_dev, 904 struct wlan_objmgr_vdev *vdev) 905 { 906 enum QDF_OPMODE opmode = wlan_vdev_mlme_get_opmode(vdev); 907 908 if (wlan_mlo_check_valid_config(ml_dev, wlan_vdev_get_pdev(vdev), 909 opmode) != QDF_STATUS_SUCCESS) 910 return QDF_STATUS_E_FAILURE; 911 912 return QDF_STATUS_SUCCESS; 913 } 914 915 static inline 916 QDF_STATUS wlan_mlo_pdev_check(struct wlan_objmgr_pdev *ref_pdev, 917 struct wlan_objmgr_vdev *vdev) 918 { 919 return QDF_STATUS_SUCCESS; 920 } 921 #endif 922 923 QDF_STATUS wlan_mlo_check_valid_config(struct wlan_mlo_dev_context *ml_dev, 924 struct wlan_objmgr_pdev *pdev, 925 enum QDF_OPMODE opmode) 926 { 927 uint32_t id = 0; 928 struct wlan_objmgr_vdev *vdev; 929 930 if (!ml_dev) 931 return QDF_STATUS_E_FAILURE; 932 933 if (!pdev) 934 return QDF_STATUS_E_FAILURE; 935 936 mlo_dev_lock_acquire(ml_dev); 937 while (id < WLAN_UMAC_MLO_MAX_VDEVS) { 938 vdev = ml_dev->wlan_vdev_list[id]; 939 if (vdev) { 940 if (wlan_mlo_pdev_check(pdev, vdev)) { 941 mlo_dev_lock_release(ml_dev); 942 return QDF_STATUS_E_FAILURE; 943 } 944 945 if (wlan_vdev_mlme_get_opmode(vdev) != opmode) { 946 mlo_err("Invalid opmode %d type found expected %d, investigate config", 947 wlan_vdev_mlme_get_opmode(vdev), 948 opmode); 949 mlo_dev_lock_release(ml_dev); 950 return QDF_STATUS_E_FAILURE; 951 } 952 } 953 id++; 954 } 955 956 mlo_dev_lock_release(ml_dev); 957 return QDF_STATUS_SUCCESS; 958 } 959 960 /** 961 * mlo_t2lm_ctx_init() - API to initialize the t2lm context with the default 962 * values. 963 * @ml_dev: Pointer to ML Dev context 964 * @vdev: Pointer to vdev structure 965 * 966 * Return: None 967 */ 968 static inline void mlo_t2lm_ctx_init(struct wlan_mlo_dev_context *ml_dev, 969 struct wlan_objmgr_vdev *vdev) 970 { 971 struct wlan_t2lm_info *t2lm; 972 973 t2lm = &ml_dev->t2lm_ctx.established_t2lm.t2lm; 974 975 qdf_mem_zero(&ml_dev->t2lm_ctx, sizeof(struct wlan_t2lm_context)); 976 977 t2lm->direction = WLAN_T2LM_BIDI_DIRECTION; 978 t2lm->default_link_mapping = 1; 979 t2lm->link_mapping_size = 0; 980 981 wlan_mlo_t2lm_timer_init(vdev); 982 wlan_mlo_t2lm_register_link_update_notify_handler(ml_dev); 983 } 984 985 /** 986 * mlo_epcs_ctx_init() - API to initialize the epcs context with the 987 * default values. 988 * @ml_dev: Pointer to ML Dev context 989 * 990 * Return: None 991 */ 992 static inline void mlo_epcs_ctx_init(struct wlan_mlo_dev_context *ml_dev) 993 { 994 struct wlan_epcs_context *epcs_ctx; 995 996 epcs_ctx = &ml_dev->epcs_ctx; 997 qdf_mem_zero(epcs_ctx, sizeof(struct wlan_epcs_context)); 998 epcs_dev_lock_create(epcs_ctx); 999 } 1000 1001 #ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE 1002 /** 1003 * mlo_ptqm_migration_init() - API to initialize ptqm migration timer 1004 * @ml_dev: Pointer to ML Dev context 1005 * 1006 * Return: None 1007 */ 1008 static inline void mlo_ptqm_migration_init(struct wlan_mlo_dev_context *ml_dev) 1009 { 1010 qdf_timer_init(NULL, &ml_dev->ptqm_migrate_timer, 1011 mlo_mlme_ptqm_migrate_timer_cb, (void *)(ml_dev), 1012 QDF_TIMER_TYPE_WAKE_APPS); 1013 } 1014 #else 1015 static inline void mlo_ptqm_migration_init(struct wlan_mlo_dev_context *ml_dev) 1016 { } 1017 #endif 1018 1019 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP) 1020 static QDF_STATUS 1021 mlo_add_to_bridge_vdev_list(struct wlan_objmgr_vdev *vdev) 1022 { 1023 struct wlan_mlo_dev_context *ml_dev; 1024 struct qdf_mac_addr *mld_addr; 1025 uint8_t id = 0; 1026 1027 if (!vdev) 1028 return QDF_STATUS_E_FAILURE; 1029 1030 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 1031 ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(mld_addr); 1032 1033 if (ml_dev) { 1034 mlo_dev_lock_acquire(ml_dev); 1035 while (id < WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS) { 1036 if (ml_dev->wlan_bridge_vdev_list[id]) { 1037 id++; 1038 continue; 1039 } 1040 1041 ml_dev->wlan_bridge_vdev_list[id] = vdev; 1042 ml_dev->wlan_bridge_vdev_count++; 1043 vdev->mlo_dev_ctx = ml_dev; 1044 break; 1045 } 1046 mlo_dev_lock_release(ml_dev); 1047 1048 if (id == WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS) 1049 return QDF_STATUS_E_FAILURE; 1050 1051 return QDF_STATUS_SUCCESS; 1052 } 1053 1054 return QDF_STATUS_E_FAILURE; 1055 } 1056 1057 static QDF_STATUS 1058 mld_delete_from_bridge_vdev_list(struct wlan_objmgr_vdev *vdev) 1059 { 1060 struct wlan_mlo_dev_context *ml_dev; 1061 struct qdf_mac_addr *mld_addr; 1062 uint8_t id = 0; 1063 1064 if (!vdev) 1065 return QDF_STATUS_E_FAILURE; 1066 1067 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 1068 ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(mld_addr); 1069 1070 if (ml_dev) { 1071 mlo_dev_lock_acquire(ml_dev); 1072 while (id < WLAN_UMAC_MLO_MAX_BRIDGE_VDEVS) { 1073 if (ml_dev->wlan_bridge_vdev_list[id] == vdev) { 1074 vdev->mlo_dev_ctx = NULL; 1075 ml_dev->wlan_bridge_vdev_list[id] = NULL; 1076 ml_dev->wlan_bridge_vdev_count--; 1077 break; 1078 } 1079 id++; 1080 } 1081 mlo_dev_lock_release(ml_dev); 1082 return QDF_STATUS_SUCCESS; 1083 } 1084 1085 return QDF_STATUS_E_FAILURE; 1086 } 1087 #else 1088 static QDF_STATUS 1089 mlo_add_to_bridge_vdev_list(struct wlan_objmgr_vdev *vdev) 1090 { 1091 return QDF_STATUS_SUCCESS; 1092 } 1093 1094 static QDF_STATUS 1095 mld_delete_from_bridge_vdev_list(struct wlan_objmgr_vdev *vdev) 1096 { 1097 return QDF_STATUS_SUCCESS; 1098 } 1099 #endif 1100 1101 static QDF_STATUS mlo_dev_ctx_init(struct wlan_objmgr_vdev *vdev) 1102 { 1103 struct wlan_mlo_dev_context *ml_dev; 1104 QDF_STATUS status = QDF_STATUS_SUCCESS; 1105 struct qdf_mac_addr *mld_addr; 1106 struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx(); 1107 uint8_t id = 0; 1108 struct wlan_objmgr_psoc *psoc = NULL; 1109 1110 if (wlan_vdev_mlme_is_mlo_bridge_vdev(vdev)) { 1111 status = mlo_add_to_bridge_vdev_list(vdev); 1112 if (!QDF_IS_STATUS_SUCCESS(status)) 1113 mlo_err("Failed to init bridge vap ctx"); 1114 return status; 1115 } 1116 1117 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 1118 ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(mld_addr); 1119 psoc = wlan_vdev_get_psoc(vdev); 1120 1121 if (!psoc) { 1122 mlo_err("Failed to get psoc"); 1123 return QDF_STATUS_E_FAILURE; 1124 } 1125 1126 if (ml_dev) { 1127 if (mlo_dev_config_check(ml_dev, vdev) != QDF_STATUS_SUCCESS) 1128 return QDF_STATUS_E_FAILURE; 1129 1130 mlo_dev_lock_acquire(ml_dev); 1131 while (id < WLAN_UMAC_MLO_MAX_VDEVS) { 1132 if (ml_dev->wlan_vdev_list[id]) { 1133 id++; 1134 continue; 1135 } 1136 1137 ml_dev->wlan_vdev_list[id] = vdev; 1138 ml_dev->wlan_vdev_count++; 1139 vdev->mlo_dev_ctx = ml_dev; 1140 1141 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) 1142 wlan_mlo_vdev_alloc_aid_mgr(ml_dev, vdev); 1143 1144 break; 1145 } 1146 mlo_dev_lock_release(ml_dev); 1147 return QDF_STATUS_SUCCESS; 1148 } 1149 1150 /* Create a new ML dev context */ 1151 ml_dev = qdf_mem_malloc(sizeof(*ml_dev)); 1152 if (!ml_dev) { 1153 mlo_err("Failed to allocate memory for ML dev"); 1154 return QDF_STATUS_E_NOMEM; 1155 } 1156 1157 qdf_copy_macaddr(&ml_dev->mld_addr, mld_addr); 1158 ml_dev->wlan_vdev_list[0] = vdev; 1159 ml_dev->wlan_vdev_count++; 1160 vdev->mlo_dev_ctx = ml_dev; 1161 1162 mlo_dev_lock_create(ml_dev); 1163 tsf_recalculation_lock_create(ml_dev); 1164 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) { 1165 ml_dev->sta_ctx = qdf_mem_malloc(sizeof(struct wlan_mlo_sta)); 1166 if (!ml_dev->sta_ctx) { 1167 tsf_recalculation_lock_destroy(ml_dev); 1168 mlo_dev_lock_destroy(ml_dev); 1169 qdf_mem_free(ml_dev); 1170 return QDF_STATUS_E_NOMEM; 1171 } 1172 copied_conn_req_lock_create(ml_dev->sta_ctx); 1173 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP) 1174 ml_dev->bridge_sta_ctx = qdf_mem_malloc(sizeof(struct wlan_mlo_bridge_sta)); 1175 if (!ml_dev->bridge_sta_ctx) { 1176 tsf_recalculation_lock_destroy(ml_dev); 1177 mlo_dev_lock_destroy(ml_dev); 1178 qdf_mem_free(ml_dev->sta_ctx); 1179 qdf_mem_free(ml_dev); 1180 return QDF_STATUS_E_NOMEM; 1181 } 1182 #endif 1183 } else if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) { 1184 if (mlo_ap_ctx_init(ml_dev) != QDF_STATUS_SUCCESS) { 1185 tsf_recalculation_lock_destroy(ml_dev); 1186 mlo_dev_lock_destroy(ml_dev); 1187 qdf_mem_free(ml_dev); 1188 mlo_err("Failed to allocate memory for ap ctx"); 1189 return QDF_STATUS_E_NOMEM; 1190 } 1191 } 1192 1193 /* Create DP MLO Device Context */ 1194 if (cdp_mlo_dev_ctxt_create(wlan_psoc_get_dp_handle(psoc), 1195 (uint8_t *)mld_addr) != 1196 QDF_STATUS_SUCCESS) { 1197 tsf_recalculation_lock_destroy(ml_dev); 1198 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) { 1199 qdf_mem_free(ml_dev->sta_ctx); 1200 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP) 1201 qdf_mem_free(ml_dev->bridge_sta_ctx); 1202 #endif 1203 } else if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) { 1204 mlo_ap_ctx_deinit(ml_dev); 1205 } 1206 mlo_dev_lock_destroy(ml_dev); 1207 qdf_mem_free(ml_dev); 1208 mlo_err("Failed to create DP MLO Dev ctxt"); 1209 return QDF_STATUS_E_NOMEM; 1210 } 1211 1212 ml_dev->mlo_max_recom_simult_links = 1213 WLAN_UMAC_MLO_RECOM_MAX_SIMULT_LINKS_DEFAULT; 1214 1215 mlo_dev_mlpeer_list_init(ml_dev); 1216 1217 ml_link_lock_acquire(g_mlo_ctx); 1218 if (qdf_list_size(&g_mlo_ctx->ml_dev_list) < WLAN_UMAC_MLO_MAX_DEV) 1219 qdf_list_insert_back(&g_mlo_ctx->ml_dev_list, &ml_dev->node); 1220 ml_link_lock_release(g_mlo_ctx); 1221 1222 mlo_t2lm_ctx_init(ml_dev, vdev); 1223 mlo_epcs_ctx_init(ml_dev); 1224 mlo_ptqm_migration_init(ml_dev); 1225 mlo_mgr_link_switch_init(psoc, ml_dev); 1226 1227 return status; 1228 } 1229 1230 #ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE 1231 /** 1232 * mlo_ptqm_migration_deinit() - API to deinitialize ptqm migration timer 1233 * @ml_dev: Pointer to ML Dev context 1234 * 1235 * Return: None 1236 */ 1237 static inline void mlo_ptqm_migration_deinit( 1238 struct wlan_mlo_dev_context *ml_dev) 1239 { 1240 qdf_timer_free(&ml_dev->ptqm_migrate_timer); 1241 } 1242 #else 1243 static inline void mlo_ptqm_migration_deinit( 1244 struct wlan_mlo_dev_context *ml_dev) 1245 { } 1246 #endif 1247 1248 /** 1249 * mlo_t2lm_ctx_deinit() - API to deinitialize the t2lm context with the default 1250 * values. 1251 * @vdev: Pointer to vdev structure 1252 * @ml_dev: Pointer to mlo dev context 1253 * 1254 * Return: None 1255 */ 1256 static inline void mlo_t2lm_ctx_deinit(struct wlan_objmgr_vdev *vdev, 1257 struct wlan_mlo_dev_context *ml_dev) 1258 { 1259 wlan_mlo_t2lm_timer_deinit(vdev); 1260 wlan_unregister_t2lm_link_update_notify_handler( 1261 ml_dev, ml_dev->t2lm_ctx.link_update_callback_index); 1262 } 1263 1264 /** 1265 * mlo_epcs_ctx_deinit() - API to deinitialize the epcs context with the default 1266 * values. 1267 * @mlo_dev_ctx: MLO dev context pointer 1268 * 1269 * Return: None 1270 */ 1271 static inline void mlo_epcs_ctx_deinit(struct wlan_mlo_dev_context *mlo_dev_ctx) 1272 { 1273 epcs_dev_lock_destroy(&mlo_dev_ctx->epcs_ctx); 1274 } 1275 1276 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 1277 static void ml_free_copied_reassoc_rsp(struct wlan_mlo_sta *sta_ctx) 1278 { 1279 wlan_cm_free_connect_resp(sta_ctx->copied_reassoc_rsp); 1280 } 1281 #else 1282 static void ml_free_copied_reassoc_rsp(struct wlan_mlo_sta *sta_ctx) 1283 { 1284 return; 1285 } 1286 #endif 1287 1288 static QDF_STATUS mlo_dev_ctx_deinit(struct wlan_objmgr_vdev *vdev) 1289 { 1290 struct wlan_mlo_dev_context *ml_dev; 1291 QDF_STATUS status = QDF_STATUS_SUCCESS; 1292 struct qdf_mac_addr *mld_addr; 1293 struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx(); 1294 uint8_t id = 0; 1295 struct wlan_cm_connect_req *connect_req; 1296 struct wlan_objmgr_psoc *psoc = NULL; 1297 1298 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 1299 ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(mld_addr); 1300 psoc = wlan_vdev_get_psoc(vdev); 1301 1302 if (!psoc) { 1303 mlo_err("Failed to get psoc"); 1304 return QDF_STATUS_E_FAILURE; 1305 } 1306 1307 if (!ml_dev) { 1308 mlo_err("Failed to get MLD dev context by mld addr "QDF_MAC_ADDR_FMT, 1309 QDF_MAC_ADDR_REF(mld_addr->bytes)); 1310 if (!vdev->mlo_dev_ctx) { 1311 mlo_err("Failed to get MLD dev context from vdev"); 1312 return QDF_STATUS_SUCCESS; 1313 } 1314 ml_dev = vdev->mlo_dev_ctx; 1315 } 1316 1317 mlo_debug("deleting vdev from MLD device ctx "QDF_MAC_ADDR_FMT, 1318 QDF_MAC_ADDR_REF(mld_addr->bytes)); 1319 1320 mlo_dev_lock_acquire(ml_dev); 1321 while (id < WLAN_UMAC_MLO_MAX_VDEVS) { 1322 if (ml_dev->wlan_vdev_list[id] == vdev) { 1323 if (wlan_vdev_mlme_get_opmode(vdev) == 1324 QDF_SAP_MODE) 1325 wlan_mlo_vdev_free_aid_mgr(ml_dev, 1326 vdev); 1327 ml_dev->wlan_vdev_list[id] = NULL; 1328 ml_dev->wlan_vdev_count--; 1329 vdev->mlo_dev_ctx = NULL; 1330 break; 1331 } 1332 id++; 1333 } 1334 mlo_dev_lock_release(ml_dev); 1335 1336 if (wlan_vdev_mlme_is_mlo_bridge_vdev(vdev)) { 1337 status = mld_delete_from_bridge_vdev_list(vdev); 1338 if (!QDF_IS_STATUS_SUCCESS(status)) 1339 mlo_err("Failed to deinit bridge vap ctx"); 1340 } 1341 1342 ml_link_lock_acquire(g_mlo_ctx); 1343 if (!ml_dev->wlan_vdev_count && !ml_dev->wlan_bridge_vdev_count) { 1344 if (ml_dev->ap_ctx) 1345 mlo_ap_ctx_deinit(ml_dev); 1346 1347 mlo_dev_mlpeer_list_deinit(ml_dev); 1348 qdf_list_remove_node(&g_mlo_ctx->ml_dev_list, 1349 &ml_dev->node); 1350 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) { 1351 connect_req = ml_dev->sta_ctx->connect_req; 1352 wlan_cm_free_connect_req(connect_req); 1353 1354 if (ml_dev->sta_ctx->disconn_req) 1355 qdf_mem_free(ml_dev->sta_ctx->disconn_req); 1356 1357 if (ml_dev->sta_ctx->assoc_rsp.ptr) 1358 qdf_mem_free(ml_dev->sta_ctx->assoc_rsp.ptr); 1359 1360 ml_free_copied_reassoc_rsp(ml_dev->sta_ctx); 1361 1362 copied_conn_req_lock_destroy(ml_dev->sta_ctx); 1363 1364 qdf_mem_free(ml_dev->sta_ctx); 1365 #if defined(WLAN_FEATURE_11BE_MLO) && defined(WLAN_MLO_MULTI_CHIP) 1366 qdf_mem_free(ml_dev->bridge_sta_ctx); 1367 #endif 1368 } 1369 else if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) 1370 qdf_mem_free(ml_dev->ap_ctx); 1371 1372 mlo_ptqm_migration_deinit(ml_dev); 1373 mlo_mgr_link_switch_deinit(ml_dev); 1374 mlo_t2lm_ctx_deinit(vdev, ml_dev); 1375 mlo_epcs_ctx_deinit(ml_dev); 1376 1377 /* Destroy DP MLO Device Context */ 1378 if (cdp_mlo_dev_ctxt_destroy(wlan_psoc_get_dp_handle(psoc), 1379 (uint8_t *)mld_addr) != 1380 QDF_STATUS_SUCCESS) { 1381 mlo_err("Failed to destroy DP MLO Dev ctxt"); 1382 QDF_BUG(0); 1383 } 1384 1385 tsf_recalculation_lock_destroy(ml_dev); 1386 mlo_dev_lock_destroy(ml_dev); 1387 qdf_mem_free(ml_dev); 1388 } 1389 ml_link_lock_release(g_mlo_ctx); 1390 return status; 1391 } 1392 1393 QDF_STATUS wlan_mlo_mgr_vdev_created_notification(struct wlan_objmgr_vdev *vdev, 1394 void *arg_list) 1395 { 1396 QDF_STATUS status = QDF_STATUS_SUCCESS; 1397 struct qdf_mac_addr *mld_addr; 1398 1399 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 1400 if (qdf_is_macaddr_zero(mld_addr)) { 1401 /* It's not a ML interface*/ 1402 return QDF_STATUS_SUCCESS; 1403 } 1404 mlo_debug("MLD addr" QDF_MAC_ADDR_FMT, 1405 QDF_MAC_ADDR_REF(mld_addr->bytes)); 1406 status = mlo_dev_ctx_init(vdev); 1407 1408 wlan_vdev_set_link_id(vdev, WLAN_LINK_ID_INVALID); 1409 1410 return status; 1411 } 1412 1413 QDF_STATUS wlan_mlo_mgr_vdev_destroyed_notification(struct wlan_objmgr_vdev *vdev, 1414 void *arg_list) 1415 { 1416 QDF_STATUS status = QDF_STATUS_SUCCESS; 1417 struct qdf_mac_addr *mld_addr; 1418 1419 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 1420 if (qdf_is_macaddr_zero(mld_addr)) { 1421 /* It's not a ML interface*/ 1422 return QDF_STATUS_SUCCESS; 1423 } 1424 mlo_debug("MLD addr" QDF_MAC_ADDR_FMT, 1425 QDF_MAC_ADDR_REF(mld_addr->bytes)); 1426 1427 status = mlo_dev_ctx_deinit(vdev); 1428 1429 return status; 1430 } 1431 1432 QDF_STATUS wlan_mlo_mgr_update_mld_addr(struct qdf_mac_addr *old_mac, 1433 struct qdf_mac_addr *new_mac) 1434 { 1435 struct wlan_mlo_dev_context *ml_dev; 1436 1437 ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(old_mac); 1438 if (!ml_dev) { 1439 mlo_err("ML dev context not found for MLD:" QDF_MAC_ADDR_FMT, 1440 QDF_MAC_ADDR_REF(old_mac->bytes)); 1441 return QDF_STATUS_E_INVAL; 1442 } 1443 mlo_dev_lock_acquire(ml_dev); 1444 qdf_copy_macaddr(&ml_dev->mld_addr, new_mac); 1445 mlo_dev_lock_release(ml_dev); 1446 1447 return QDF_STATUS_SUCCESS; 1448 } 1449 1450 QDF_STATUS wlan_mlo_mgr_mld_vdev_attach(struct wlan_objmgr_vdev *vdev, 1451 struct qdf_mac_addr *mld_addr) 1452 { 1453 QDF_STATUS status = QDF_STATUS_SUCCESS; 1454 struct wlan_objmgr_psoc *psoc = NULL; 1455 1456 psoc = wlan_vdev_get_psoc(vdev); 1457 if (!psoc) { 1458 mlo_err("Failed to get psoc"); 1459 return QDF_STATUS_E_FAILURE; 1460 } 1461 1462 wlan_vdev_obj_lock(vdev); 1463 wlan_vdev_mlme_set_mldaddr(vdev, (uint8_t *)&mld_addr->bytes[0]); 1464 wlan_vdev_obj_unlock(vdev); 1465 1466 status = mlo_dev_ctx_init(vdev); 1467 1468 if (cdp_mlo_dev_ctxt_attach(wlan_psoc_get_dp_handle(psoc), 1469 wlan_vdev_get_id(vdev), 1470 (uint8_t *)mld_addr) 1471 != QDF_STATUS_SUCCESS) { 1472 mlo_err("Failed to attach DP vdev (" QDF_MAC_ADDR_FMT ") to" 1473 " MLO Dev ctxt (" QDF_MAC_ADDR_FMT ")", 1474 QDF_MAC_ADDR_REF(wlan_vdev_mlme_get_macaddr(vdev)), 1475 QDF_MAC_ADDR_REF(mld_addr->bytes)); 1476 } 1477 return status; 1478 } 1479 1480 QDF_STATUS wlan_mlo_mgr_mld_vdev_detach(struct wlan_objmgr_vdev *vdev) 1481 { 1482 QDF_STATUS status = QDF_STATUS_SUCCESS; 1483 struct qdf_mac_addr *mld_addr; 1484 struct wlan_objmgr_psoc *psoc = NULL; 1485 1486 psoc = wlan_vdev_get_psoc(vdev); 1487 if (!psoc) { 1488 mlo_err("Failed to get psoc"); 1489 return QDF_STATUS_E_FAILURE; 1490 } 1491 1492 status = mlo_dev_ctx_deinit(vdev); 1493 1494 /* Detach DP vdev from DP MLO Device Context */ 1495 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 1496 1497 if (cdp_mlo_dev_ctxt_detach(wlan_psoc_get_dp_handle(psoc), 1498 wlan_vdev_get_id(vdev), 1499 (uint8_t *)mld_addr) 1500 != QDF_STATUS_SUCCESS) { 1501 mlo_err("Failed to detach DP vdev (" QDF_MAC_ADDR_FMT ") from" 1502 " MLO Dev ctxt (" QDF_MAC_ADDR_FMT ")", 1503 QDF_MAC_ADDR_REF(wlan_vdev_mlme_get_macaddr(vdev)), 1504 QDF_MAC_ADDR_REF(mld_addr->bytes)); 1505 } 1506 1507 wlan_vdev_obj_lock(vdev); 1508 wlan_vdev_mlme_reset_mldaddr(vdev); 1509 wlan_vdev_mlme_op_flags_clear(vdev, WLAN_VDEV_OP_MLO_REMOVE_LINK_VDEV); 1510 wlan_vdev_obj_unlock(vdev); 1511 1512 return status; 1513 } 1514