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 static inline struct wlan_mlo_dev_context *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 static inline 199 struct wlan_mlo_dev_context *mlo_get_next_mld_ctx(qdf_list_t *ml_list, 200 struct wlan_mlo_dev_context *mld_cur) 201 { 202 struct wlan_mlo_dev_context *mld_next; 203 qdf_list_node_t *node = &mld_cur->node; 204 qdf_list_node_t *next_node = NULL; 205 206 /* This API is invoked with lock acquired, do not add log prints */ 207 if (!node) 208 return NULL; 209 210 if (qdf_list_peek_next(ml_list, node, &next_node) != 211 QDF_STATUS_SUCCESS) 212 return NULL; 213 214 mld_next = qdf_container_of(next_node, struct wlan_mlo_dev_context, 215 node); 216 return mld_next; 217 } 218 219 uint8_t wlan_mlo_get_sta_mld_ctx_count(void) 220 { 221 struct wlan_mlo_dev_context *mld_cur; 222 struct wlan_mlo_dev_context *mld_next; 223 qdf_list_t *ml_list; 224 struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx(); 225 uint8_t count = 0; 226 227 if (!mlo_mgr_ctx) 228 return count; 229 230 ml_link_lock_acquire(mlo_mgr_ctx); 231 ml_list = &mlo_mgr_ctx->ml_dev_list; 232 /* Get first mld context */ 233 mld_cur = mlo_list_peek_head(ml_list); 234 235 while (mld_cur) { 236 /* get next mld node */ 237 if (mld_cur->sta_ctx) 238 count++; 239 mld_next = mlo_get_next_mld_ctx(ml_list, mld_cur); 240 mld_cur = mld_next; 241 } 242 ml_link_lock_release(mlo_mgr_ctx); 243 244 return count; 245 } 246 247 struct wlan_mlo_dev_context 248 *wlan_mlo_get_mld_ctx_by_mldaddr(struct qdf_mac_addr *mldaddr) 249 { 250 struct wlan_mlo_dev_context *mld_cur; 251 struct wlan_mlo_dev_context *mld_next; 252 qdf_list_t *ml_list; 253 struct mlo_mgr_context *mlo_mgr_ctx = wlan_objmgr_get_mlo_ctx(); 254 255 if (!mlo_mgr_ctx) 256 return NULL; 257 258 ml_link_lock_acquire(mlo_mgr_ctx); 259 ml_list = &mlo_mgr_ctx->ml_dev_list; 260 /* Get first mld context */ 261 mld_cur = mlo_list_peek_head(ml_list); 262 /** 263 * Iterate through ml list, till ml mldaddr matches with 264 * entry of list 265 */ 266 while (mld_cur) { 267 if (QDF_IS_STATUS_SUCCESS(WLAN_ADDR_EQ(&mld_cur->mld_addr, 268 mldaddr))) { 269 ml_link_lock_release(mlo_mgr_ctx); 270 return mld_cur; 271 } 272 /* get next mld node */ 273 mld_next = mlo_get_next_mld_ctx(ml_list, mld_cur); 274 mld_cur = mld_next; 275 } 276 ml_link_lock_release(mlo_mgr_ctx); 277 278 return NULL; 279 } 280 281 bool wlan_mlo_is_mld_ctx_exist(struct qdf_mac_addr *mldaddr) 282 { 283 struct wlan_mlo_dev_context *mld_ctx = NULL; 284 285 mld_ctx = wlan_mlo_get_mld_ctx_by_mldaddr(mldaddr); 286 if (mld_ctx) 287 return true; 288 289 return false; 290 } 291 292 #ifdef WLAN_FEATURE_11BE_MLO 293 bool mlo_mgr_ml_peer_exist_on_diff_ml_ctx(uint8_t *peer_addr, 294 uint8_t *peer_vdev_id) 295 { 296 qdf_list_t *ml_list; 297 uint32_t idx, count; 298 struct wlan_mlo_dev_context *mld_cur, *mld_next; 299 struct wlan_mlo_peer_list *mlo_peer_list; 300 struct wlan_objmgr_vdev *vdev; 301 bool ret_status = false, same_ml_ctx = false; 302 struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx(); 303 304 if (!g_mlo_ctx || !peer_addr || 305 qdf_is_macaddr_zero((struct qdf_mac_addr *)peer_addr)) 306 return ret_status; 307 308 ml_link_lock_acquire(g_mlo_ctx); 309 ml_list = &g_mlo_ctx->ml_dev_list; 310 if (!qdf_list_size(ml_list)) 311 goto g_ml_ref; 312 313 mld_cur = mlo_list_peek_head(ml_list); 314 while (mld_cur) { 315 mlo_dev_lock_acquire(mld_cur); 316 if (qdf_is_macaddr_equal(&mld_cur->mld_addr, 317 (struct qdf_mac_addr *)peer_addr)) { 318 /* For self peer, the address passed will match the 319 * MLD address of its own ML dev context, so allow 320 * peer creation in this scenario as both are in 321 * same ML dev context. 322 */ 323 if (peer_vdev_id) { 324 count = QDF_ARRAY_SIZE(mld_cur->wlan_vdev_list); 325 for (idx = 0; idx < count; idx++) { 326 vdev = mld_cur->wlan_vdev_list[idx]; 327 if (!vdev) 328 continue; 329 if (*peer_vdev_id == 330 wlan_vdev_get_id(vdev)) { 331 same_ml_ctx = true; 332 break; 333 } 334 } 335 } 336 mlo_dev_lock_release(mld_cur); 337 mlo_err("MLD ID %d exists with mac " QDF_MAC_ADDR_FMT, 338 mld_cur->mld_id, QDF_MAC_ADDR_REF(peer_addr)); 339 ret_status = true; 340 goto check_same_ml_ctx; 341 } 342 343 /* Check the peer list for a MAC address match */ 344 mlo_peer_list = &mld_cur->mlo_peer_list; 345 ml_peerlist_lock_acquire(mlo_peer_list); 346 if (mlo_get_mlpeer(mld_cur, (struct qdf_mac_addr *)peer_addr)) { 347 /* If peer_vdev_id is NULL, then API will treat any 348 * match as happening on another dev context 349 */ 350 if (peer_vdev_id) { 351 count = QDF_ARRAY_SIZE(mld_cur->wlan_vdev_list); 352 for (idx = 0; idx < count; idx++) { 353 vdev = mld_cur->wlan_vdev_list[idx]; 354 if (!vdev) 355 continue; 356 if (*peer_vdev_id == 357 wlan_vdev_get_id(vdev)) { 358 same_ml_ctx = true; 359 break; 360 } 361 } 362 } 363 ml_peerlist_lock_release(mlo_peer_list); 364 mlo_dev_lock_release(mld_cur); 365 mlo_err("MLD ID %d ML Peer exists with mac " QDF_MAC_ADDR_FMT, 366 mld_cur->mld_id, QDF_MAC_ADDR_REF(peer_addr)); 367 ret_status = true; 368 goto check_same_ml_ctx; 369 } 370 ml_peerlist_lock_release(mlo_peer_list); 371 372 mld_next = mlo_get_next_mld_ctx(ml_list, mld_cur); 373 mlo_dev_lock_release(mld_cur); 374 mld_cur = mld_next; 375 } 376 377 check_same_ml_ctx: 378 if (same_ml_ctx) 379 ret_status = false; 380 381 g_ml_ref: 382 ml_link_lock_release(g_mlo_ctx); 383 return ret_status; 384 } 385 386 #define WLAN_HDD_MGMT_FRAME_DA_OFFSET 4 387 #define WLAN_HDD_MGMT_FRAME_SA_OFFSET (WLAN_HDD_MGMT_FRAME_DA_OFFSET + 6) 388 #define WLAN_HDD_MGMT_FRAME_BSSID_OFFSET (WLAN_HDD_MGMT_FRAME_SA_OFFSET + 6) 389 #define WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET \ 390 (WLAN_HDD_MGMT_FRAME_BSSID_OFFSET + 6 + 2) 391 #define WLAN_HDD_MGMT_FRAME_ACTION_TYPE_OFFSET \ 392 (WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET + 1) 393 #define WLAN_HDD_ACTION_FRAME_CATEGORY_PUBLIC 0x04 394 395 /* 396 * Typical 802.11 Action Frame Format 397 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- 398 * | FC | DUR | DA | SA | BSSID |Seq.|Cat.|Act| Elements | FCS | 399 * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+- 400 * 2 2 6 6 6 2 1 1 Variable Len 4 401 */ 402 void wlan_mlo_update_action_frame_from_user(struct wlan_objmgr_vdev *vdev, 403 uint8_t *frame, 404 uint32_t frame_len) 405 { 406 struct wlan_objmgr_peer *peer; 407 uint8_t *da, *sa, *bssid; 408 409 if (!wlan_vdev_mlme_is_mlo_vdev(vdev) || 410 (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE)) 411 return; 412 413 if (frame_len <= WLAN_HDD_MGMT_FRAME_ACTION_TYPE_OFFSET) { 414 mlo_debug("Not a valid Action frame len: %d", frame_len); 415 return; 416 } 417 418 /* Translate address only for action frames 419 * which are not of public category. 420 * Reference: 802.11-2012, Subclause: 8.5 421 */ 422 423 if (frame[WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET] == 424 WLAN_HDD_ACTION_FRAME_CATEGORY_PUBLIC) 425 return; 426 427 da = frame + WLAN_HDD_MGMT_FRAME_DA_OFFSET; 428 sa = frame + WLAN_HDD_MGMT_FRAME_SA_OFFSET; 429 bssid = frame + WLAN_HDD_MGMT_FRAME_BSSID_OFFSET; 430 431 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_MLO_MGR_ID); 432 if (!peer) { 433 mlo_debug("Peer not found"); 434 return; 435 } 436 437 mlo_debug("Change MLD addr to link addr for non-Public action frame"); 438 /* DA = VDEV's BSS peer's link address. 439 * SA = VDEV's link address. 440 * BSSID = VDEV's BSS peer's link address. 441 */ 442 443 qdf_ether_addr_copy(da, wlan_peer_get_macaddr(peer)); 444 qdf_ether_addr_copy(sa, wlan_vdev_mlme_get_macaddr(vdev)); 445 qdf_ether_addr_copy(bssid, wlan_peer_get_macaddr(peer)); 446 447 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID); 448 } 449 450 void wlan_mlo_update_action_frame_to_user(struct wlan_objmgr_vdev *vdev, 451 uint8_t *frame, 452 uint32_t frame_len) 453 { 454 struct wlan_objmgr_peer *peer; 455 uint8_t *da, *sa, *bssid; 456 457 if (!wlan_vdev_mlme_is_mlo_vdev(vdev) || 458 (wlan_vdev_mlme_get_opmode(vdev) != QDF_STA_MODE)) 459 return; 460 461 if (frame_len <= WLAN_HDD_MGMT_FRAME_ACTION_TYPE_OFFSET) { 462 mlo_debug("Not a valid Action frame len: %d", frame_len); 463 return; 464 } 465 466 /* Translate address only for action frames 467 * which are not of public category. 468 * Reference: 802.11-2012, Subclause: 8.5 469 */ 470 471 if (frame[WLAN_HDD_MGMT_FRAME_ACTION_CATEGORY_OFFSET] == 472 WLAN_HDD_ACTION_FRAME_CATEGORY_PUBLIC) 473 return; 474 475 da = frame + WLAN_HDD_MGMT_FRAME_DA_OFFSET; 476 sa = frame + WLAN_HDD_MGMT_FRAME_SA_OFFSET; 477 bssid = frame + WLAN_HDD_MGMT_FRAME_BSSID_OFFSET; 478 479 peer = wlan_objmgr_vdev_try_get_bsspeer(vdev, WLAN_MLO_MGR_ID); 480 if (!peer) { 481 mlo_debug("Peer not found"); 482 return; 483 } 484 485 mlo_debug("Change link addr to MLD addr for non-Public action frame"); 486 /* DA = VDEV's MLD address. 487 * SA = VDEV's BSS peer's MLD address. 488 * BSSID = VDEV's BSS peer's MLD address. 489 */ 490 491 qdf_ether_addr_copy(da, wlan_vdev_mlme_get_mldaddr(vdev)); 492 qdf_ether_addr_copy(sa, wlan_peer_mlme_get_mldaddr(peer)); 493 qdf_ether_addr_copy(bssid, wlan_peer_mlme_get_mldaddr(peer)); 494 495 wlan_objmgr_peer_release_ref(peer, WLAN_MLO_MGR_ID); 496 } 497 #endif 498 499 static QDF_STATUS mlo_ap_ctx_deinit(struct wlan_mlo_dev_context *ml_dev) 500 { 501 wlan_mlo_vdev_aid_mgr_deinit(ml_dev); 502 mlo_ap_lock_destroy(ml_dev->ap_ctx); 503 qdf_mem_free(ml_dev->ap_ctx); 504 ml_dev->ap_ctx = NULL; 505 506 return QDF_STATUS_SUCCESS; 507 } 508 509 static QDF_STATUS mlo_ap_ctx_init(struct wlan_mlo_dev_context *ml_dev) 510 { 511 struct wlan_mlo_ap *ap_ctx; 512 513 ap_ctx = qdf_mem_malloc(sizeof(*ap_ctx)); 514 if (!ap_ctx) { 515 mlo_err("MLO AP ctx alloc failure"); 516 return QDF_STATUS_E_NOMEM; 517 } 518 519 ml_dev->ap_ctx = ap_ctx; 520 mlo_ap_lock_create(ml_dev->ap_ctx); 521 if (wlan_mlo_vdev_aid_mgr_init(ml_dev) != QDF_STATUS_SUCCESS) { 522 mlo_ap_ctx_deinit(ml_dev); 523 return QDF_STATUS_E_NOMEM; 524 } 525 526 return QDF_STATUS_SUCCESS; 527 } 528 529 #ifdef CONFIG_AP_PLATFORM 530 static inline 531 QDF_STATUS wlan_mlo_check_grp_id(uint8_t ref_id, 532 struct wlan_objmgr_vdev *vdev) 533 { 534 struct wlan_objmgr_psoc *psoc; 535 uint8_t grp_id = 0; 536 537 psoc = wlan_vdev_get_psoc(vdev); 538 if (!mlo_psoc_get_grp_id(psoc, &grp_id)) { 539 mlo_err("Unable to get mlo group id"); 540 return QDF_STATUS_E_FAILURE; 541 } 542 543 if (grp_id != ref_id) { 544 mlo_err("Error : MLD VAP Configuration with different WSI/MLD Groups"); 545 return QDF_STATUS_E_FAILURE; 546 } 547 548 return QDF_STATUS_SUCCESS; 549 } 550 551 static inline 552 QDF_STATUS wlan_mlo_pdev_check(struct wlan_objmgr_pdev *ref_pdev, 553 struct wlan_objmgr_vdev *vdev) 554 { 555 struct wlan_objmgr_pdev *pdev; 556 struct wlan_objmgr_psoc *psoc; 557 uint8_t grp_id = 0; 558 559 pdev = wlan_vdev_get_pdev(vdev); 560 561 psoc = wlan_pdev_get_psoc(ref_pdev); 562 if (!mlo_psoc_get_grp_id(psoc, &grp_id)) { 563 mlo_err("Unable to get the MLO Group ID for the vdev"); 564 return QDF_STATUS_E_FAILURE; 565 } 566 567 if (mlo_check_all_pdev_state(psoc, grp_id, MLO_LINK_SETUP_DONE)) { 568 mlo_err("Pdev link is not in ready state, initial link setup failed"); 569 return QDF_STATUS_E_FAILURE; 570 } 571 572 if (ref_pdev == pdev) { 573 mlo_err("MLD vdev for this pdev already found, investigate config"); 574 return QDF_STATUS_E_FAILURE; 575 } 576 577 if (wlan_mlo_check_grp_id(grp_id, vdev)) 578 return QDF_STATUS_E_FAILURE; 579 580 return QDF_STATUS_SUCCESS; 581 } 582 583 static inline 584 QDF_STATUS mlo_dev_config_check(struct wlan_mlo_dev_context *ml_dev, 585 struct wlan_objmgr_vdev *vdev) 586 { 587 return QDF_STATUS_SUCCESS; 588 } 589 590 #else 591 static inline 592 QDF_STATUS mlo_dev_config_check(struct wlan_mlo_dev_context *ml_dev, 593 struct wlan_objmgr_vdev *vdev) 594 { 595 enum QDF_OPMODE opmode = wlan_vdev_mlme_get_opmode(vdev); 596 597 if (wlan_mlo_check_valid_config(ml_dev, wlan_vdev_get_pdev(vdev), 598 opmode) != QDF_STATUS_SUCCESS) 599 return QDF_STATUS_E_FAILURE; 600 601 return QDF_STATUS_SUCCESS; 602 } 603 604 static inline 605 QDF_STATUS wlan_mlo_pdev_check(struct wlan_objmgr_pdev *ref_pdev, 606 struct wlan_objmgr_vdev *vdev) 607 { 608 return QDF_STATUS_SUCCESS; 609 } 610 #endif 611 612 QDF_STATUS wlan_mlo_check_valid_config(struct wlan_mlo_dev_context *ml_dev, 613 struct wlan_objmgr_pdev *pdev, 614 enum QDF_OPMODE opmode) 615 { 616 uint32_t id = 0; 617 struct wlan_objmgr_vdev *vdev; 618 619 if (!ml_dev) 620 return QDF_STATUS_E_FAILURE; 621 622 if (!pdev) 623 return QDF_STATUS_E_FAILURE; 624 625 mlo_dev_lock_acquire(ml_dev); 626 while (id < WLAN_UMAC_MLO_MAX_VDEVS) { 627 vdev = ml_dev->wlan_vdev_list[id]; 628 if (vdev) { 629 if (wlan_mlo_pdev_check(pdev, vdev)) { 630 mlo_dev_lock_release(ml_dev); 631 return QDF_STATUS_E_FAILURE; 632 } 633 634 if (wlan_vdev_mlme_get_opmode(vdev) != opmode) { 635 mlo_err("Invalid opmode %d type found expected %d, investigate config", 636 wlan_vdev_mlme_get_opmode(vdev), 637 opmode); 638 mlo_dev_lock_release(ml_dev); 639 return QDF_STATUS_E_FAILURE; 640 } 641 } 642 id++; 643 } 644 645 mlo_dev_lock_release(ml_dev); 646 return QDF_STATUS_SUCCESS; 647 } 648 649 /** 650 * mlo_t2lm_ctx_init() - API to initialize the t2lm context with the default 651 * values. 652 * @ml_dev: Pointer to ML Dev context 653 * @vdev: Pointer to vdev structure 654 * 655 * Return: None 656 */ 657 static inline void mlo_t2lm_ctx_init(struct wlan_mlo_dev_context *ml_dev, 658 struct wlan_objmgr_vdev *vdev) 659 { 660 struct wlan_t2lm_info *t2lm; 661 662 t2lm = &ml_dev->t2lm_ctx.established_t2lm.t2lm; 663 664 qdf_mem_zero(&ml_dev->t2lm_ctx, sizeof(struct wlan_t2lm_context)); 665 666 t2lm->direction = WLAN_T2LM_BIDI_DIRECTION; 667 t2lm->default_link_mapping = 1; 668 669 wlan_mlo_t2lm_timer_init(vdev); 670 } 671 672 static QDF_STATUS mlo_dev_ctx_init(struct wlan_objmgr_vdev *vdev) 673 { 674 struct wlan_mlo_dev_context *ml_dev; 675 QDF_STATUS status = QDF_STATUS_SUCCESS; 676 struct qdf_mac_addr *mld_addr; 677 struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx(); 678 uint8_t id = 0; 679 680 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 681 ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(mld_addr); 682 683 if (ml_dev) { 684 if (mlo_dev_config_check(ml_dev, vdev) != QDF_STATUS_SUCCESS) 685 return QDF_STATUS_E_FAILURE; 686 687 mlo_dev_lock_acquire(ml_dev); 688 while (id < WLAN_UMAC_MLO_MAX_VDEVS) { 689 if (ml_dev->wlan_vdev_list[id]) { 690 id++; 691 continue; 692 } 693 694 ml_dev->wlan_vdev_list[id] = vdev; 695 ml_dev->wlan_vdev_count++; 696 vdev->mlo_dev_ctx = ml_dev; 697 698 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) 699 wlan_mlo_vdev_alloc_aid_mgr(ml_dev, vdev); 700 701 break; 702 } 703 mlo_dev_lock_release(ml_dev); 704 return QDF_STATUS_SUCCESS; 705 } 706 707 /* Create a new ML dev context */ 708 ml_dev = qdf_mem_malloc(sizeof(*ml_dev)); 709 if (!ml_dev) { 710 mlo_err("Failed to allocate memory for ML dev"); 711 return QDF_STATUS_E_NOMEM; 712 } 713 714 qdf_copy_macaddr(&ml_dev->mld_addr, mld_addr); 715 ml_dev->wlan_vdev_list[0] = vdev; 716 ml_dev->wlan_vdev_count++; 717 vdev->mlo_dev_ctx = ml_dev; 718 719 mlo_dev_lock_create(ml_dev); 720 tsf_recalculation_lock_create(ml_dev); 721 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) { 722 ml_dev->sta_ctx = qdf_mem_malloc(sizeof(struct wlan_mlo_sta)); 723 if (!ml_dev->sta_ctx) { 724 tsf_recalculation_lock_destroy(ml_dev); 725 mlo_dev_lock_destroy(ml_dev); 726 qdf_mem_free(ml_dev); 727 return QDF_STATUS_E_NOMEM; 728 } 729 copied_conn_req_lock_create(ml_dev->sta_ctx); 730 } else if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) { 731 if (mlo_ap_ctx_init(ml_dev) != QDF_STATUS_SUCCESS) { 732 tsf_recalculation_lock_destroy(ml_dev); 733 mlo_dev_lock_destroy(ml_dev); 734 qdf_mem_free(ml_dev); 735 mlo_err("Failed to allocate memory for ap ctx"); 736 return QDF_STATUS_E_NOMEM; 737 } 738 } 739 740 mlo_dev_mlpeer_list_init(ml_dev); 741 742 ml_link_lock_acquire(g_mlo_ctx); 743 if (qdf_list_size(&g_mlo_ctx->ml_dev_list) < WLAN_UMAC_MLO_MAX_DEV) 744 qdf_list_insert_back(&g_mlo_ctx->ml_dev_list, &ml_dev->node); 745 ml_link_lock_release(g_mlo_ctx); 746 747 mlo_t2lm_ctx_init(ml_dev, vdev); 748 749 return status; 750 } 751 752 /** 753 * mlo_t2lm_ctx_deinit() - API to deinitialize the t2lm context with the default 754 * values. 755 * @vdev: Pointer to vdev structure 756 * 757 * Return: None 758 */ 759 static inline void mlo_t2lm_ctx_deinit(struct wlan_objmgr_vdev *vdev) 760 { 761 wlan_mlo_t2lm_timer_deinit(vdev); 762 } 763 764 static QDF_STATUS mlo_dev_ctx_deinit(struct wlan_objmgr_vdev *vdev) 765 { 766 struct wlan_mlo_dev_context *ml_dev; 767 QDF_STATUS status = QDF_STATUS_SUCCESS; 768 struct qdf_mac_addr *mld_addr; 769 struct mlo_mgr_context *g_mlo_ctx = wlan_objmgr_get_mlo_ctx(); 770 uint8_t id = 0; 771 struct wlan_cm_connect_req *connect_req; 772 773 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 774 ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(mld_addr); 775 if (!ml_dev) { 776 mlo_err("Failed to get MLD dev context by mld addr "QDF_MAC_ADDR_FMT, 777 QDF_MAC_ADDR_REF(mld_addr->bytes)); 778 if (!vdev->mlo_dev_ctx) { 779 mlo_err("Failed to get MLD dev context from vdev"); 780 return QDF_STATUS_SUCCESS; 781 } 782 ml_dev = vdev->mlo_dev_ctx; 783 } 784 785 mlo_debug("deleting vdev from MLD device ctx "QDF_MAC_ADDR_FMT, 786 QDF_MAC_ADDR_REF(mld_addr->bytes)); 787 mlo_dev_lock_acquire(ml_dev); 788 while (id < WLAN_UMAC_MLO_MAX_VDEVS) { 789 if (ml_dev->wlan_vdev_list[id] == vdev) { 790 if (wlan_vdev_mlme_get_opmode(vdev) == 791 QDF_SAP_MODE) 792 wlan_mlo_vdev_free_aid_mgr(ml_dev, 793 vdev); 794 ml_dev->wlan_vdev_list[id] = NULL; 795 ml_dev->wlan_vdev_count--; 796 vdev->mlo_dev_ctx = NULL; 797 break; 798 } 799 id++; 800 } 801 mlo_dev_lock_release(ml_dev); 802 803 ml_link_lock_acquire(g_mlo_ctx); 804 if (!ml_dev->wlan_vdev_count) { 805 if (ml_dev->ap_ctx) 806 mlo_ap_ctx_deinit(ml_dev); 807 808 mlo_dev_mlpeer_list_deinit(ml_dev); 809 qdf_list_remove_node(&g_mlo_ctx->ml_dev_list, 810 &ml_dev->node); 811 if (wlan_vdev_mlme_get_opmode(vdev) == QDF_STA_MODE) { 812 connect_req = ml_dev->sta_ctx->connect_req; 813 if (connect_req) { 814 if (connect_req->scan_ie.ptr) { 815 qdf_mem_free(connect_req->scan_ie.ptr); 816 connect_req->scan_ie.ptr = NULL; 817 } 818 819 if (connect_req->assoc_ie.ptr) { 820 qdf_mem_free(connect_req->assoc_ie.ptr); 821 connect_req->assoc_ie.ptr = NULL; 822 } 823 qdf_mem_free(ml_dev->sta_ctx->connect_req); 824 } 825 826 if (ml_dev->sta_ctx->disconn_req) 827 qdf_mem_free(ml_dev->sta_ctx->disconn_req); 828 829 if (ml_dev->sta_ctx->assoc_rsp.ptr) 830 qdf_mem_free(ml_dev->sta_ctx->assoc_rsp.ptr); 831 832 copied_conn_req_lock_destroy(ml_dev->sta_ctx); 833 834 qdf_mem_free(ml_dev->sta_ctx); 835 } 836 else if (wlan_vdev_mlme_get_opmode(vdev) == QDF_SAP_MODE) 837 qdf_mem_free(ml_dev->ap_ctx); 838 839 mlo_t2lm_ctx_deinit(vdev); 840 tsf_recalculation_lock_destroy(ml_dev); 841 mlo_dev_lock_destroy(ml_dev); 842 qdf_mem_free(ml_dev); 843 } 844 ml_link_lock_release(g_mlo_ctx); 845 return status; 846 } 847 848 QDF_STATUS wlan_mlo_mgr_vdev_created_notification(struct wlan_objmgr_vdev *vdev, 849 void *arg_list) 850 { 851 QDF_STATUS status = QDF_STATUS_SUCCESS; 852 struct qdf_mac_addr *mld_addr; 853 854 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 855 if (qdf_is_macaddr_zero(mld_addr)) { 856 /* It's not a ML interface*/ 857 return QDF_STATUS_SUCCESS; 858 } 859 mlo_debug("MLD addr" QDF_MAC_ADDR_FMT, 860 QDF_MAC_ADDR_REF(mld_addr->bytes)); 861 status = mlo_dev_ctx_init(vdev); 862 863 return status; 864 } 865 866 QDF_STATUS wlan_mlo_mgr_vdev_destroyed_notification(struct wlan_objmgr_vdev *vdev, 867 void *arg_list) 868 { 869 QDF_STATUS status = QDF_STATUS_SUCCESS; 870 struct qdf_mac_addr *mld_addr; 871 872 mld_addr = (struct qdf_mac_addr *)wlan_vdev_mlme_get_mldaddr(vdev); 873 if (qdf_is_macaddr_zero(mld_addr)) { 874 /* It's not a ML interface*/ 875 return QDF_STATUS_SUCCESS; 876 } 877 mlo_debug("MLD addr" QDF_MAC_ADDR_FMT, 878 QDF_MAC_ADDR_REF(mld_addr->bytes)); 879 880 status = mlo_dev_ctx_deinit(vdev); 881 882 return status; 883 } 884 885 QDF_STATUS wlan_mlo_mgr_update_mld_addr(struct qdf_mac_addr *old_mac, 886 struct qdf_mac_addr *new_mac) 887 { 888 struct wlan_mlo_dev_context *ml_dev; 889 890 ml_dev = wlan_mlo_get_mld_ctx_by_mldaddr(old_mac); 891 if (!ml_dev) { 892 mlo_err("ML dev context not found for MLD:" QDF_MAC_ADDR_FMT, 893 QDF_MAC_ADDR_REF(old_mac->bytes)); 894 return QDF_STATUS_E_INVAL; 895 } 896 mlo_dev_lock_acquire(ml_dev); 897 qdf_copy_macaddr(&ml_dev->mld_addr, new_mac); 898 mlo_dev_lock_release(ml_dev); 899 900 return QDF_STATUS_SUCCESS; 901 } 902