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 mlo_mgr_ctx->last_mlo_peer_id = 0; 76 ml_peerid_lock_create(mlo_mgr_ctx); 77 ml_link_lock_create(mlo_mgr_ctx); 78 ml_aid_lock_create(mlo_mgr_ctx); 79 mlo_mgr_ctx->mlo_is_force_primary_umac = 0; 80 mlo_msgq_init(); 81 } 82 83 QDF_STATUS wlan_mlo_mgr_psoc_enable(struct wlan_objmgr_psoc *psoc) 84 { 85 struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops; 86 87 if (!psoc) { 88 mlo_err("psoc is null"); 89 return QDF_STATUS_E_NULL_VALUE; 90 } 91 92 mlo_tx_ops = target_if_mlo_get_tx_ops(psoc); 93 if (!mlo_tx_ops) { 94 mlo_err("tx_ops is null!"); 95 return QDF_STATUS_E_NULL_VALUE; 96 } 97 98 if (!mlo_tx_ops->register_events) { 99 mlo_err("register_events function is null!"); 100 return QDF_STATUS_E_NULL_VALUE; 101 } 102 103 return mlo_tx_ops->register_events(psoc); 104 } 105 106 QDF_STATUS wlan_mlo_mgr_psoc_disable(struct wlan_objmgr_psoc *psoc) 107 { 108 struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops; 109 110 if (!psoc) { 111 mlo_err("psoc is null"); 112 return QDF_STATUS_E_NULL_VALUE; 113 } 114 115 mlo_tx_ops = target_if_mlo_get_tx_ops(psoc); 116 if (!mlo_tx_ops) { 117 mlo_err("tx_ops is null!"); 118 return QDF_STATUS_E_NULL_VALUE; 119 } 120 121 if (!mlo_tx_ops->unregister_events) { 122 mlo_err("unregister_events function is null!"); 123 return QDF_STATUS_E_NULL_VALUE; 124 } 125 126 return mlo_tx_ops->unregister_events(psoc); 127 } 128 129 QDF_STATUS wlan_mlo_mgr_init(void) 130 { 131 QDF_STATUS status; 132 133 mlo_global_ctx_init(); 134 135 status = wlan_objmgr_register_vdev_create_handler( 136 WLAN_UMAC_COMP_MLO_MGR, 137 wlan_mlo_mgr_vdev_created_notification, NULL); 138 if (QDF_IS_STATUS_ERROR(status)) { 139 mlo_err("Failed to register vdev create handler"); 140 return QDF_STATUS_E_FAILURE; 141 } 142 143 status = wlan_objmgr_register_vdev_destroy_handler(WLAN_UMAC_COMP_MLO_MGR, 144 wlan_mlo_mgr_vdev_destroyed_notification, NULL); 145 if (QDF_IS_STATUS_SUCCESS(status)) { 146 mlo_debug("MLO vdev create and delete handler registered with objmgr"); 147 return QDF_STATUS_SUCCESS; 148 } 149 wlan_objmgr_unregister_vdev_create_handler(WLAN_UMAC_COMP_MLO_MGR, 150 wlan_mlo_mgr_vdev_created_notification, NULL); 151 152 return status; 153 } 154 155 QDF_STATUS wlan_mlo_mgr_deinit(void) 156 { 157 QDF_STATUS status; 158 struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx(); 159 160 if (!mlo_mgr_ctx) { 161 mlo_err("MLO global object is not allocated"); 162 return QDF_STATUS_E_FAILURE; 163 } 164 165 mlo_global_ctx_deinit(); 166 167 status = wlan_objmgr_unregister_vdev_create_handler( 168 WLAN_UMAC_COMP_MLO_MGR, 169 wlan_mlo_mgr_vdev_created_notification, NULL); 170 if (status != QDF_STATUS_SUCCESS) 171 mlo_err("Failed to unregister vdev create handler"); 172 173 status = wlan_objmgr_unregister_vdev_destroy_handler( 174 WLAN_UMAC_COMP_MLO_MGR, 175 wlan_mlo_mgr_vdev_destroyed_notification, NULL); 176 if (status != QDF_STATUS_SUCCESS) 177 mlo_err("Failed to unregister vdev delete handler"); 178 179 return status; 180 } 181 182 struct wlan_mlo_dev_context *wlan_mlo_list_peek_head( 183 qdf_list_t *ml_list) 184 { 185 struct wlan_mlo_dev_context *mld_ctx; 186 qdf_list_node_t *ml_node = NULL; 187 188 /* This API is invoked with lock acquired, do not add log prints */ 189 if (qdf_list_peek_front(ml_list, &ml_node) != QDF_STATUS_SUCCESS) 190 return NULL; 191 192 mld_ctx = qdf_container_of(ml_node, struct wlan_mlo_dev_context, 193 node); 194 195 return mld_ctx; 196 } 197 198 struct wlan_mlo_dev_context *wlan_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 = wlan_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 = wlan_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 = wlan_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 = wlan_mlo_get_next_mld_ctx(ml_list, mld_cur); 273 mld_cur = mld_next; 274 } 275 ml_link_lock_release(mlo_mgr_ctx); 276 277 return NULL; 278 } 279 280 bool wlan_mlo_is_mld_ctx_exist(struct qdf_mac_addr *mldaddr) 281 { 282 struct wlan_mlo_dev_context *mld_ctx = NULL; 283 284 mld_ctx = wlan_mlo_get_mld_ctx_by_mldaddr(mldaddr); 285 if (mld_ctx) 286 return true; 287 288 return false; 289 } 290 291 #ifdef WLAN_FEATURE_11BE_MLO 292 bool mlo_mgr_ml_peer_exist_on_diff_ml_ctx(uint8_t *peer_addr, 293 uint8_t *peer_vdev_id) 294 { 295 qdf_list_t *ml_list; 296 uint32_t idx, count; 297 struct wlan_mlo_dev_context *mld_cur, *mld_next; 298 struct wlan_mlo_peer_list *mlo_peer_list; 299 struct wlan_objmgr_vdev *vdev; 300 bool ret_status = false, same_ml_ctx = false; 301 struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx(); 302 303 if (!g_mlo_ctx || !peer_addr || 304 qdf_is_macaddr_zero((struct qdf_mac_addr *)peer_addr)) 305 return ret_status; 306 307 ml_link_lock_acquire(g_mlo_ctx); 308 ml_list = &g_mlo_ctx->ml_dev_list; 309 if (!qdf_list_size(ml_list)) 310 goto g_ml_ref; 311 312 mld_cur = wlan_mlo_list_peek_head(ml_list); 313 while (mld_cur) { 314 mlo_dev_lock_acquire(mld_cur); 315 if (qdf_is_macaddr_equal(&mld_cur->mld_addr, 316 (struct qdf_mac_addr *)peer_addr)) { 317 /* For self peer, the address passed will match the 318 * MLD address of its own ML dev context, so allow 319 * peer creation in this scenario as both are in 320 * same ML dev context. 321 */ 322 if (peer_vdev_id) { 323 count = QDF_ARRAY_SIZE(mld_cur->wlan_vdev_list); 324 for (idx = 0; idx < count; idx++) { 325 vdev = mld_cur->wlan_vdev_list[idx]; 326 if (!vdev) 327 continue; 328 if (*peer_vdev_id == 329 wlan_vdev_get_id(vdev)) { 330 same_ml_ctx = true; 331 break; 332 } 333 } 334 } 335 mlo_dev_lock_release(mld_cur); 336 mlo_err("MLD ID %d exists with mac " QDF_MAC_ADDR_FMT, 337 mld_cur->mld_id, QDF_MAC_ADDR_REF(peer_addr)); 338 ret_status = true; 339 goto check_same_ml_ctx; 340 } 341 342 /* Check the peer list for a MAC address match */ 343 mlo_peer_list = &mld_cur->mlo_peer_list; 344 ml_peerlist_lock_acquire(mlo_peer_list); 345 if (mlo_get_mlpeer(mld_cur, (struct qdf_mac_addr *)peer_addr)) { 346 /* If peer_vdev_id is NULL, then API will treat any 347 * match as happening on another dev context 348 */ 349 if (peer_vdev_id) { 350 count = QDF_ARRAY_SIZE(mld_cur->wlan_vdev_list); 351 for (idx = 0; idx < count; idx++) { 352 vdev = mld_cur->wlan_vdev_list[idx]; 353 if (!vdev) 354 continue; 355 if (*peer_vdev_id == 356 wlan_vdev_get_id(vdev)) { 357 same_ml_ctx = true; 358 break; 359 } 360 } 361 } 362 ml_peerlist_lock_release(mlo_peer_list); 363 mlo_dev_lock_release(mld_cur); 364 mlo_err("MLD ID %d ML Peer exists with mac " QDF_MAC_ADDR_FMT, 365 mld_cur->mld_id, QDF_MAC_ADDR_REF(peer_addr)); 366 ret_status = true; 367 goto check_same_ml_ctx; 368 } 369 ml_peerlist_lock_release(mlo_peer_list); 370 371 mld_next = wlan_mlo_get_next_mld_ctx(ml_list, mld_cur); 372 mlo_dev_lock_release(mld_cur); 373 mld_cur = mld_next; 374 } 375 376 check_same_ml_ctx: 377 if (same_ml_ctx) 378 ret_status = false; 379 380 g_ml_ref: 381 ml_link_lock_release(g_mlo_ctx); 382 return ret_status; 383 } 384 385 #define WLAN_HDD_MGMT_FRAME_DA_OFFSET 4 386 #define WLAN_HDD_MGMT_FRAME_SA_OFFSET (WLAN_HDD_MGMT_FRAME_DA_OFFSET + 6) 387 #define WLAN_HDD_MGMT_FRAME_BSSID_OFFSET (WLAN_HDD_MGMT_FRAME_SA_OFFSET + 6) 388 #define WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET \ 389 (WLAN_HDD_MGMT_FRAME_BSSID_OFFSET + 6 + 2) 390 #define WLAN_HDD_MGMT_FRAME_ACTION_TYPE_OFFSET \ 391 (WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET + 1) 392 #define WLAN_HDD_ACTION_FRAME_CATEGORY_PUBLIC 0x04 393 394 /* 395 * Typical 802.11 Action Frame Format 396 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- 397 * | FC | DUR | DA | SA | BSSID |Seq.|Cat.|Act| Elements | FCS | 398 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- 399 * 2 2 6 6 6 2 1 1 Variable Len 4 400 */ 401 void wlan_mlo_update_action_frame_from_user(struct wlan_objmgr_vdev *vdev, 402 uint8_t *frame, 403 uint32_t frame_len) 404 { 405 struct wlan_objmgr_peer *peer; 406 uint8_t *da, *sa, *bssid; 407 408 if (!wlan_vdev_mlme_is_mlo_vdev(vdev) || 409 (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE)) 410 return; 411 412 if (frame_len <= WLAN_HDD_MGMT_FRAME_ACTION_TYPE_OFFSET) { 413 mlo_debug("Not a valid Action frame len: %d", frame_len); 414 return; 415 } 416 417 /* Translate address only for action frames 418 * which are not of public category. 419 * Reference: 802.11-2012, Subclause: 8.5 420 */ 421 422 if (frame[WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET] == 423 WLAN_HDD_ACTION_FRAME_CATEGORY_PUBLIC) 424 return; 425 426 da = frame + WLAN_HDD_MGMT_FRAME_DA_OFFSET; 427 sa = frame + WLAN_HDD_MGMT_FRAME_SA_OFFSET; 428 bssid = frame + WLAN_HDD_MGMT_FRAME_BSSID_OFFSET; 429 430 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_MLO_MGR_ID); 431 if (!peer) { 432 mlo_debug("Peer not found"); 433 return; 434 } 435 436 mlo_debug("Change MLD addr to link addr for non-Public action frame"); 437 /* DA = VDEV's BSS peer's link address. 438 * SA = VDEV's link address. 439 * BSSID = VDEV's BSS peer's link address. 440 */ 441 442 qdf_ether_addr_copy(da, wlan_peer_get_macaddr(peer)); 443 qdf_ether_addr_copy(sa, wlan_vdev_mlme_get_macaddr(vdev)); 444 qdf_ether_addr_copy(bssid, wlan_peer_get_macaddr(peer)); 445 446 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID); 447 } 448 449 void wlan_mlo_update_action_frame_to_user(struct wlan_objmgr_vdev *vdev, 450 uint8_t *frame, 451 uint32_t frame_len) 452 { 453 struct wlan_objmgr_peer *peer; 454 uint8_t *da, *sa, *bssid; 455 456 if (!wlan_vdev_mlme_is_mlo_vdev(vdev) || 457 (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE)) 458 return; 459 460 if (frame_len <= WLAN_HDD_MGMT_FRAME_ACTION_TYPE_OFFSET) { 461 mlo_debug("Not a valid Action frame len: %d", frame_len); 462 return; 463 } 464 465 /* Translate address only for action frames 466 * which are not of public category. 467 * Reference: 802.11-2012, Subclause: 8.5 468 */ 469 470 if (frame[WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET] == 471 WLAN_HDD_ACTION_FRAME_CATEGORY_PUBLIC) 472 return; 473 474 da = frame + WLAN_HDD_MGMT_FRAME_DA_OFFSET; 475 sa = frame + WLAN_HDD_MGMT_FRAME_SA_OFFSET; 476 bssid = frame + WLAN_HDD_MGMT_FRAME_BSSID_OFFSET; 477 478 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_MLO_MGR_ID); 479 if (!peer) { 480 mlo_debug("Peer not found"); 481 return; 482 } 483 484 mlo_debug("Change link addr to MLD addr for non-Public action frame"); 485 /* DA = VDEV's MLD address. 486 * SA = VDEV's BSS peer's MLD address. 487 * BSSID = VDEV's BSS peer's MLD address. 488 */ 489 490 qdf_ether_addr_copy(da, wlan_vdev_mlme_get_mldaddr(vdev)); 491 qdf_ether_addr_copy(sa, wlan_peer_mlme_get_mldaddr(peer)); 492 qdf_ether_addr_copy(bssid, wlan_peer_mlme_get_mldaddr(peer)); 493 494 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID); 495 } 496 #endif 497 498 static QDF_STATUS mlo_ap_ctx_deinit(struct wlan_mlo_dev_context *ml_dev) 499 { 500 wlan_mlo_vdev_aid_mgr_deinit(ml_dev); 501 mlo_ap_lock_destroy(ml_dev->ap_ctx); 502 qdf_mem_free(ml_dev->ap_ctx); 503 ml_dev->ap_ctx = NULL; 504 505 return QDF_STATUS_SUCCESS; 506 } 507 508 static QDF_STATUS mlo_ap_ctx_init(struct wlan_mlo_dev_context *ml_dev) 509 { 510 struct wlan_mlo_ap *ap_ctx; 511 512 ap_ctx = qdf_mem_malloc(sizeof(*ap_ctx)); 513 if (!ap_ctx) { 514 mlo_err("MLO AP ctx alloc failure"); 515 return QDF_STATUS_E_NOMEM; 516 } 517 518 ml_dev->ap_ctx = ap_ctx; 519 mlo_ap_lock_create(ml_dev->ap_ctx); 520 if (wlan_mlo_vdev_aid_mgr_init(ml_dev) != QDF_STATUS_SUCCESS) { 521 mlo_ap_ctx_deinit(ml_dev); 522 return QDF_STATUS_E_NOMEM; 523 } 524 525 return QDF_STATUS_SUCCESS; 526 } 527 528 #ifdef CONFIG_AP_PLATFORM 529 static inline 530 QDF_STATUS wlan_mlo_check_grp_id(uint8_t ref_id, 531 struct wlan_objmgr_vdev *vdev) 532 { 533 struct wlan_objmgr_psoc *psoc; 534 uint8_t grp_id = 0; 535 536 psoc = wlan_vdev_get_psoc(vdev); 537 if (!mlo_psoc_get_grp_id(psoc, &grp_id)) { 538 mlo_err("Unable to get mlo group id"); 539 return QDF_STATUS_E_FAILURE; 540 } 541 542 if (grp_id != ref_id) { 543 mlo_err("Error : MLD VAP Configuration with different WSI/MLD Groups"); 544 return QDF_STATUS_E_FAILURE; 545 } 546 547 return QDF_STATUS_SUCCESS; 548 } 549 550 static inline 551 QDF_STATUS wlan_mlo_pdev_check(struct wlan_objmgr_pdev *ref_pdev, 552 struct wlan_objmgr_vdev *vdev) 553 { 554 struct wlan_objmgr_pdev *pdev; 555 struct wlan_objmgr_psoc *psoc; 556 uint8_t grp_id = 0; 557 558 pdev = wlan_vdev_get_pdev(vdev); 559 560 psoc = wlan_pdev_get_psoc(ref_pdev); 561 if (!mlo_psoc_get_grp_id(psoc, &grp_id)) { 562 mlo_err("Unable to get the MLO Group ID for the vdev"); 563 return QDF_STATUS_E_FAILURE; 564 } 565 566 if (mlo_check_all_pdev_state(psoc, grp_id, MLO_LINK_SETUP_DONE)) { 567 mlo_err("Pdev link is not in ready state, initial link setup failed"); 568 return QDF_STATUS_E_FAILURE; 569 } 570 571 if (ref_pdev == pdev) { 572 mlo_err("MLD vdev for this pdev already found, investigate config"); 573 return QDF_STATUS_E_FAILURE; 574 } 575 576 if (wlan_mlo_check_grp_id(grp_id, vdev)) 577 return QDF_STATUS_E_FAILURE; 578 579 return QDF_STATUS_SUCCESS; 580 } 581 582 static inline 583 QDF_STATUS mlo_dev_config_check(struct wlan_mlo_dev_context *ml_dev, 584 struct wlan_objmgr_vdev *vdev) 585 { 586 return QDF_STATUS_SUCCESS; 587 } 588 589 #else 590 static inline 591 QDF_STATUS mlo_dev_config_check(struct wlan_mlo_dev_context *ml_dev, 592 struct wlan_objmgr_vdev *vdev) 593 { 594 enum QDF_OPMODE opmode = wlan_vdev_mlme_get_opmode(vdev); 595 596 if (wlan_mlo_check_valid_config(ml_dev, wlan_vdev_get_pdev(vdev), 597 opmode) != QDF_STATUS_SUCCESS) 598 return QDF_STATUS_E_FAILURE; 599 600 return QDF_STATUS_SUCCESS; 601 } 602 603 static inline 604 QDF_STATUS wlan_mlo_pdev_check(struct wlan_objmgr_pdev *ref_pdev, 605 struct wlan_objmgr_vdev *vdev) 606 { 607 return QDF_STATUS_SUCCESS; 608 } 609 #endif 610 611 QDF_STATUS wlan_mlo_check_valid_config(struct wlan_mlo_dev_context *ml_dev, 612 struct wlan_objmgr_pdev *pdev, 613 enum QDF_OPMODE opmode) 614 { 615 uint32_t id = 0; 616 struct wlan_objmgr_vdev *vdev; 617 618 if (!ml_dev) 619 return QDF_STATUS_E_FAILURE; 620 621 if (!pdev) 622 return QDF_STATUS_E_FAILURE; 623 624 mlo_dev_lock_acquire(ml_dev); 625 while (id < WLAN_UMAC_MLO_MAX_VDEVS) { 626 vdev = ml_dev->wlan_vdev_list[id]; 627 if (vdev) { 628 if (wlan_mlo_pdev_check(pdev, vdev)) { 629 mlo_dev_lock_release(ml_dev); 630 return QDF_STATUS_E_FAILURE; 631 } 632 633 if (wlan_vdev_mlme_get_opmode(vdev) != opmode) { 634 mlo_err("Invalid opmode %d type found expected %d, investigate config", 635 wlan_vdev_mlme_get_opmode(vdev), 636 opmode); 637 mlo_dev_lock_release(ml_dev); 638 return QDF_STATUS_E_FAILURE; 639 } 640 } 641 id++; 642 } 643 644 mlo_dev_lock_release(ml_dev); 645 return QDF_STATUS_SUCCESS; 646 } 647 648 /** 649 * mlo_t2lm_ctx_init() - API to initialize the t2lm context with the default 650 * values. 651 * @ml_dev: Pointer to ML Dev context 652 * @vdev: Pointer to vdev structure 653 * 654 * Return: None 655 */ 656 static inline void mlo_t2lm_ctx_init(struct wlan_mlo_dev_context *ml_dev, 657 struct wlan_objmgr_vdev *vdev) 658 { 659 struct wlan_t2lm_info *t2lm; 660 661 t2lm = &ml_dev->t2lm_ctx.established_t2lm.t2lm; 662 663 qdf_mem_zero(&ml_dev->t2lm_ctx, sizeof(struct wlan_t2lm_context)); 664 665 t2lm->direction = WLAN_T2LM_BIDI_DIRECTION; 666 t2lm->default_link_mapping = 1; 667 t2lm->link_mapping_size = 0; 668 669 wlan_mlo_t2lm_timer_init(vdev); 670 } 671 672 /** 673 * mlo_epcs_ctx_init() - API to initialize the epcs context with the 674 * default values. 675 * @ml_dev: Pointer to ML Dev context 676 * 677 * Return: None 678 */ 679 static inline void mlo_epcs_ctx_init(struct wlan_mlo_dev_context *ml_dev) 680 { 681 struct wlan_epcs_context *epcs_ctx; 682 683 epcs_ctx = &ml_dev->epcs_ctx; 684 qdf_mem_zero(epcs_ctx, sizeof(struct wlan_epcs_context)); 685 } 686 687 static QDF_STATUS mlo_dev_ctx_init(struct wlan_objmgr_vdev *vdev) 688 { 689 struct wlan_mlo_dev_context *ml_dev; 690 QDF_STATUS status = QDF_STATUS_SUCCESS; 691 struct qdf_mac_addr *mld_addr; 692 struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx(); 693 uint8_t id = 0; 694 695 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 696 ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(mld_addr); 697 698 if (ml_dev) { 699 if (mlo_dev_config_check(ml_dev, vdev) != QDF_STATUS_SUCCESS) 700 return QDF_STATUS_E_FAILURE; 701 702 mlo_dev_lock_acquire(ml_dev); 703 while (id < WLAN_UMAC_MLO_MAX_VDEVS) { 704 if (ml_dev->wlan_vdev_list[id]) { 705 id++; 706 continue; 707 } 708 709 ml_dev->wlan_vdev_list[id] = vdev; 710 ml_dev->wlan_vdev_count++; 711 vdev->mlo_dev_ctx = ml_dev; 712 713 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) 714 wlan_mlo_vdev_alloc_aid_mgr(ml_dev, vdev); 715 716 break; 717 } 718 mlo_dev_lock_release(ml_dev); 719 return QDF_STATUS_SUCCESS; 720 } 721 722 /* Create a new ML dev context */ 723 ml_dev = qdf_mem_malloc(sizeof(*ml_dev)); 724 if (!ml_dev) { 725 mlo_err("Failed to allocate memory for ML dev"); 726 return QDF_STATUS_E_NOMEM; 727 } 728 729 qdf_copy_macaddr(&ml_dev->mld_addr, mld_addr); 730 ml_dev->wlan_vdev_list[0] = vdev; 731 ml_dev->wlan_vdev_count++; 732 vdev->mlo_dev_ctx = ml_dev; 733 734 mlo_dev_lock_create(ml_dev); 735 tsf_recalculation_lock_create(ml_dev); 736 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) { 737 ml_dev->sta_ctx = qdf_mem_malloc(sizeof(struct wlan_mlo_sta)); 738 if (!ml_dev->sta_ctx) { 739 tsf_recalculation_lock_destroy(ml_dev); 740 mlo_dev_lock_destroy(ml_dev); 741 qdf_mem_free(ml_dev); 742 return QDF_STATUS_E_NOMEM; 743 } 744 copied_conn_req_lock_create(ml_dev->sta_ctx); 745 } else if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) { 746 if (mlo_ap_ctx_init(ml_dev) != QDF_STATUS_SUCCESS) { 747 tsf_recalculation_lock_destroy(ml_dev); 748 mlo_dev_lock_destroy(ml_dev); 749 qdf_mem_free(ml_dev); 750 mlo_err("Failed to allocate memory for ap ctx"); 751 return QDF_STATUS_E_NOMEM; 752 } 753 } 754 755 mlo_dev_mlpeer_list_init(ml_dev); 756 757 ml_link_lock_acquire(g_mlo_ctx); 758 if (qdf_list_size(&g_mlo_ctx->ml_dev_list) < WLAN_UMAC_MLO_MAX_DEV) 759 qdf_list_insert_back(&g_mlo_ctx->ml_dev_list, &ml_dev->node); 760 ml_link_lock_release(g_mlo_ctx); 761 762 mlo_t2lm_ctx_init(ml_dev, vdev); 763 mlo_epcs_ctx_init(ml_dev); 764 765 return status; 766 } 767 768 /** 769 * mlo_t2lm_ctx_deinit() - API to deinitialize the t2lm context with the default 770 * values. 771 * @vdev: Pointer to vdev structure 772 * 773 * Return: None 774 */ 775 static inline void mlo_t2lm_ctx_deinit(struct wlan_objmgr_vdev *vdev) 776 { 777 wlan_mlo_t2lm_timer_deinit(vdev); 778 } 779 780 static QDF_STATUS mlo_dev_ctx_deinit(struct wlan_objmgr_vdev *vdev) 781 { 782 struct wlan_mlo_dev_context *ml_dev; 783 QDF_STATUS status = QDF_STATUS_SUCCESS; 784 struct qdf_mac_addr *mld_addr; 785 struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx(); 786 uint8_t id = 0; 787 struct wlan_cm_connect_req *connect_req; 788 789 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 790 ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(mld_addr); 791 if (!ml_dev) { 792 mlo_err("Failed to get MLD dev context by mld addr "QDF_MAC_ADDR_FMT, 793 QDF_MAC_ADDR_REF(mld_addr->bytes)); 794 if (!vdev->mlo_dev_ctx) { 795 mlo_err("Failed to get MLD dev context from vdev"); 796 return QDF_STATUS_SUCCESS; 797 } 798 ml_dev = vdev->mlo_dev_ctx; 799 } 800 801 mlo_debug("deleting vdev from MLD device ctx "QDF_MAC_ADDR_FMT, 802 QDF_MAC_ADDR_REF(mld_addr->bytes)); 803 mlo_dev_lock_acquire(ml_dev); 804 while (id < WLAN_UMAC_MLO_MAX_VDEVS) { 805 if (ml_dev->wlan_vdev_list[id] == vdev) { 806 if (wlan_vdev_mlme_get_opmode(vdev) == 807 QDF_SAP_MODE) 808 wlan_mlo_vdev_free_aid_mgr(ml_dev, 809 vdev); 810 ml_dev->wlan_vdev_list[id] = NULL; 811 ml_dev->wlan_vdev_count--; 812 vdev->mlo_dev_ctx = NULL; 813 break; 814 } 815 id++; 816 } 817 mlo_dev_lock_release(ml_dev); 818 819 ml_link_lock_acquire(g_mlo_ctx); 820 if (!ml_dev->wlan_vdev_count) { 821 if (ml_dev->ap_ctx) 822 mlo_ap_ctx_deinit(ml_dev); 823 824 mlo_dev_mlpeer_list_deinit(ml_dev); 825 qdf_list_remove_node(&g_mlo_ctx->ml_dev_list, 826 &ml_dev->node); 827 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) { 828 connect_req = ml_dev->sta_ctx->connect_req; 829 if (connect_req) { 830 if (connect_req->scan_ie.ptr) { 831 qdf_mem_free(connect_req->scan_ie.ptr); 832 connect_req->scan_ie.ptr = NULL; 833 } 834 835 if (connect_req->assoc_ie.ptr) { 836 qdf_mem_free(connect_req->assoc_ie.ptr); 837 connect_req->assoc_ie.ptr = NULL; 838 } 839 qdf_mem_free(ml_dev->sta_ctx->connect_req); 840 } 841 842 if (ml_dev->sta_ctx->disconn_req) 843 qdf_mem_free(ml_dev->sta_ctx->disconn_req); 844 845 if (ml_dev->sta_ctx->assoc_rsp.ptr) 846 qdf_mem_free(ml_dev->sta_ctx->assoc_rsp.ptr); 847 848 copied_conn_req_lock_destroy(ml_dev->sta_ctx); 849 850 qdf_mem_free(ml_dev->sta_ctx); 851 } 852 else if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) 853 qdf_mem_free(ml_dev->ap_ctx); 854 855 mlo_t2lm_ctx_deinit(vdev); 856 tsf_recalculation_lock_destroy(ml_dev); 857 mlo_dev_lock_destroy(ml_dev); 858 qdf_mem_free(ml_dev); 859 } 860 ml_link_lock_release(g_mlo_ctx); 861 return status; 862 } 863 864 QDF_STATUS wlan_mlo_mgr_vdev_created_notification(struct wlan_objmgr_vdev *vdev, 865 void *arg_list) 866 { 867 QDF_STATUS status = QDF_STATUS_SUCCESS; 868 struct qdf_mac_addr *mld_addr; 869 870 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 871 if (qdf_is_macaddr_zero(mld_addr)) { 872 /* It's not a ML interface*/ 873 return QDF_STATUS_SUCCESS; 874 } 875 mlo_debug("MLD addr" QDF_MAC_ADDR_FMT, 876 QDF_MAC_ADDR_REF(mld_addr->bytes)); 877 status = mlo_dev_ctx_init(vdev); 878 879 wlan_vdev_set_link_id(vdev, WLAN_LINK_ID_INVALID); 880 881 return status; 882 } 883 884 QDF_STATUS wlan_mlo_mgr_vdev_destroyed_notification(struct wlan_objmgr_vdev *vdev, 885 void *arg_list) 886 { 887 QDF_STATUS status = QDF_STATUS_SUCCESS; 888 struct qdf_mac_addr *mld_addr; 889 890 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 891 if (qdf_is_macaddr_zero(mld_addr)) { 892 /* It's not a ML interface*/ 893 return QDF_STATUS_SUCCESS; 894 } 895 mlo_debug("MLD addr" QDF_MAC_ADDR_FMT, 896 QDF_MAC_ADDR_REF(mld_addr->bytes)); 897 898 status = mlo_dev_ctx_deinit(vdev); 899 900 return status; 901 } 902 903 QDF_STATUS wlan_mlo_mgr_update_mld_addr(struct qdf_mac_addr *old_mac, 904 struct qdf_mac_addr *new_mac) 905 { 906 struct wlan_mlo_dev_context *ml_dev; 907 908 ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(old_mac); 909 if (!ml_dev) { 910 mlo_err("ML dev context not found for MLD:" QDF_MAC_ADDR_FMT, 911 QDF_MAC_ADDR_REF(old_mac->bytes)); 912 return QDF_STATUS_E_INVAL; 913 } 914 mlo_dev_lock_acquire(ml_dev); 915 qdf_copy_macaddr(&ml_dev->mld_addr, new_mac); 916 mlo_dev_lock_release(ml_dev); 917 918 return QDF_STATUS_SUCCESS; 919 } 920