1 /* 2 * Copyright (c) 2021, The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2022 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 ap related functionality 20 */ 21 #include "wlan_mlo_mgr_cmn.h" 22 #include "wlan_mlo_mgr_main.h" 23 #ifdef WLAN_MLO_MULTI_CHIP 24 #include "wlan_lmac_if_def.h" 25 #endif 26 #include "wlan_serialization_api.h" 27 #include <target_if_mlo_mgr.h> 28 #include <cdp_txrx_cmn.h> 29 #include <wlan_cfg.h> 30 31 void mlo_get_link_information(struct qdf_mac_addr *mld_addr, 32 struct mlo_link_info *info) 33 { 34 /* Pass the partner link information*/ 35 } 36 37 void is_mlo_all_links_up(struct wlan_mlo_dev_context *mldev) 38 { 39 /* Loop through all the vdev's part of the ML device*/ 40 /* STA: Loop through all the associated vdev status. */ 41 } 42 43 struct wlan_objmgr_vdev *mlo_get_vdev_by_link_id( 44 struct wlan_objmgr_vdev *vdev, 45 uint8_t link_id) 46 { 47 struct wlan_mlo_dev_context *dev_ctx; 48 int i; 49 struct wlan_objmgr_vdev *partner_vdev = NULL; 50 51 if (!vdev || !vdev->mlo_dev_ctx) { 52 mlo_err("Invalid input"); 53 return partner_vdev; 54 } 55 56 dev_ctx = vdev->mlo_dev_ctx; 57 58 mlo_dev_lock_acquire(dev_ctx); 59 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 60 if (dev_ctx->wlan_vdev_list[i] && 61 wlan_vdev_mlme_is_mlo_vdev(dev_ctx->wlan_vdev_list[i]) && 62 dev_ctx->wlan_vdev_list[i]->vdev_mlme.mlo_link_id == 63 link_id) { 64 if (wlan_objmgr_vdev_try_get_ref( 65 dev_ctx->wlan_vdev_list[i], 66 WLAN_MLO_MGR_ID) == 67 QDF_STATUS_SUCCESS) 68 partner_vdev = dev_ctx->wlan_vdev_list[i]; 69 70 break; 71 } 72 } 73 mlo_dev_lock_release(dev_ctx); 74 75 return partner_vdev; 76 } 77 78 void mlo_release_vdev_ref(struct wlan_objmgr_vdev *vdev) 79 { 80 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID); 81 } 82 83 QDF_STATUS mlo_reg_mlme_ext_cb(struct mlo_mgr_context *ctx, 84 struct mlo_mlme_ext_ops *ops) 85 { 86 if (!ctx) 87 return QDF_STATUS_E_FAILURE; 88 89 ctx->mlme_ops = ops; 90 return QDF_STATUS_SUCCESS; 91 } 92 93 QDF_STATUS mlo_unreg_mlme_ext_cb(struct mlo_mgr_context *ctx) 94 { 95 if (!ctx) 96 return QDF_STATUS_E_FAILURE; 97 98 ctx->mlme_ops = NULL; 99 return QDF_STATUS_SUCCESS; 100 } 101 102 QDF_STATUS mlo_mlme_clone_sta_security(struct wlan_objmgr_vdev *vdev, 103 struct wlan_cm_connect_req *req) 104 { 105 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 106 struct vdev_mlme_obj *vdev_mlme; 107 QDF_STATUS status = QDF_STATUS_SUCCESS; 108 109 if (!req || !mlo_ctx || !mlo_ctx->mlme_ops || 110 !mlo_ctx->mlme_ops->mlo_mlme_ext_validate_conn_req) 111 return QDF_STATUS_E_FAILURE; 112 113 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 114 if (!vdev_mlme) 115 return QDF_STATUS_E_FAILURE; 116 117 if (mlo_ctx->mlme_ops->mlo_mlme_ext_clone_security_param) { 118 status = 119 mlo_ctx->mlme_ops->mlo_mlme_ext_clone_security_param( 120 vdev_mlme, req); 121 } 122 123 return status; 124 } 125 126 QDF_STATUS mlo_mlme_sta_op_class(struct wlan_objmgr_vdev *vdev, 127 uint8_t *ml_ie) 128 { 129 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 130 struct vdev_mlme_obj *vdev_mlme; 131 QDF_STATUS status = QDF_STATUS_SUCCESS; 132 133 if (!mlo_ctx || !mlo_ctx->mlme_ops || 134 !mlo_ctx->mlme_ops->mlo_mlme_ext_validate_conn_req) 135 return QDF_STATUS_E_FAILURE; 136 137 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 138 if (!vdev_mlme) 139 return QDF_STATUS_E_FAILURE; 140 141 if (mlo_ctx->mlme_ops->mlo_mlme_ext_sta_op_class) 142 status = 143 mlo_ctx->mlme_ops->mlo_mlme_ext_sta_op_class( 144 vdev_mlme, ml_ie); 145 146 return status; 147 } 148 149 QDF_STATUS mlo_mlme_validate_conn_req(struct wlan_objmgr_vdev *vdev, 150 void *ext_data) 151 { 152 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 153 struct vdev_mlme_obj *vdev_mlme; 154 QDF_STATUS status; 155 156 if (!mlo_ctx || !mlo_ctx->mlme_ops || 157 !mlo_ctx->mlme_ops->mlo_mlme_ext_validate_conn_req) 158 return QDF_STATUS_E_FAILURE; 159 160 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 161 if (!vdev_mlme) 162 return QDF_STATUS_E_FAILURE; 163 164 status = 165 mlo_ctx->mlme_ops->mlo_mlme_ext_validate_conn_req(vdev_mlme, 166 ext_data); 167 return status; 168 } 169 170 QDF_STATUS mlo_mlme_create_link_vdev(struct wlan_objmgr_vdev *vdev, 171 void *ext_data) 172 { 173 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 174 struct vdev_mlme_obj *vdev_mlme; 175 QDF_STATUS status; 176 177 if (!mlo_ctx || !mlo_ctx->mlme_ops || 178 !mlo_ctx->mlme_ops->mlo_mlme_ext_create_link_vdev) 179 return QDF_STATUS_E_FAILURE; 180 181 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 182 if (!vdev_mlme) 183 return QDF_STATUS_E_FAILURE; 184 185 status = 186 mlo_ctx->mlme_ops->mlo_mlme_ext_create_link_vdev(vdev_mlme, 187 ext_data); 188 return status; 189 } 190 191 void mlo_mlme_peer_create(struct wlan_objmgr_vdev *vdev, 192 struct wlan_mlo_peer_context *ml_peer, 193 struct qdf_mac_addr *addr, 194 qdf_nbuf_t frm_buf) 195 { 196 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 197 198 if (!mlo_ctx || !mlo_ctx->mlme_ops || 199 !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_create) 200 return; 201 202 mlo_ctx->mlme_ops->mlo_mlme_ext_peer_create(vdev, ml_peer, 203 addr, frm_buf); 204 } 205 206 void mlo_mlme_peer_assoc(struct wlan_objmgr_peer *peer) 207 { 208 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 209 210 if (!mlo_ctx || !mlo_ctx->mlme_ops || 211 !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_assoc) 212 return; 213 214 mlo_ctx->mlme_ops->mlo_mlme_ext_peer_assoc(peer); 215 } 216 217 void mlo_mlme_peer_assoc_fail(struct wlan_objmgr_peer *peer) 218 { 219 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 220 221 if (!mlo_ctx || !mlo_ctx->mlme_ops || 222 !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_assoc_fail) 223 return; 224 225 mlo_ctx->mlme_ops->mlo_mlme_ext_peer_assoc_fail(peer); 226 } 227 228 void mlo_mlme_peer_delete(struct wlan_objmgr_peer *peer) 229 { 230 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 231 232 if (!mlo_ctx || !mlo_ctx->mlme_ops || 233 !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_delete) 234 return; 235 236 mlo_ctx->mlme_ops->mlo_mlme_ext_peer_delete(peer); 237 } 238 239 void mlo_mlme_peer_assoc_resp(struct wlan_objmgr_peer *peer) 240 { 241 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 242 243 if (!mlo_ctx || !mlo_ctx->mlme_ops || 244 !mlo_ctx->mlme_ops->mlo_mlme_ext_assoc_resp) 245 return; 246 247 mlo_ctx->mlme_ops->mlo_mlme_ext_assoc_resp(peer); 248 } 249 250 qdf_nbuf_t mlo_mlme_get_link_assoc_req(struct wlan_objmgr_peer *peer, 251 uint8_t link_ix) 252 { 253 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 254 255 if (!mlo_ctx || !mlo_ctx->mlme_ops || 256 !mlo_ctx->mlme_ops->mlo_mlme_get_link_assoc_req) 257 return NULL; 258 259 return mlo_ctx->mlme_ops->mlo_mlme_get_link_assoc_req(peer, link_ix); 260 } 261 262 void mlo_mlme_peer_deauth(struct wlan_objmgr_peer *peer) 263 { 264 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 265 266 if (!mlo_ctx || !mlo_ctx->mlme_ops || 267 !mlo_ctx->mlme_ops->mlo_mlme_ext_deauth) 268 return; 269 270 mlo_ctx->mlme_ops->mlo_mlme_ext_deauth(peer); 271 } 272 273 #ifdef UMAC_MLO_AUTH_DEFER 274 void mlo_mlme_peer_process_auth(struct mlpeer_auth_params *auth_param) 275 { 276 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 277 278 if (!mlo_ctx || !mlo_ctx->mlme_ops || 279 !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_process_auth) 280 return; 281 282 mlo_ctx->mlme_ops->mlo_mlme_ext_peer_process_auth(auth_param); 283 } 284 #endif 285 286 uint8_t mlo_get_link_vdev_ix(struct wlan_mlo_dev_context *ml_dev, 287 struct wlan_objmgr_vdev *vdev) 288 { 289 uint8_t i; 290 291 mlo_dev_lock_acquire(ml_dev); 292 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 293 if (vdev == ml_dev->wlan_vdev_list[i]) { 294 mlo_dev_lock_release(ml_dev); 295 return i; 296 } 297 } 298 mlo_dev_lock_release(ml_dev); 299 300 return (uint8_t)-1; 301 } 302 303 #ifdef WLAN_MLO_MULTI_CHIP 304 int8_t wlan_mlo_get_max_num_links(void) 305 { 306 struct mlo_mgr_context *mlo_ctx; 307 308 mlo_ctx = wlan_objmgr_get_mlo_ctx(); 309 if (!mlo_ctx) 310 return WLAN_MLO_INVALID_NUM_LINKS; 311 312 return mlo_ctx->setup_info.tot_socs * WLAN_MAX_MLO_LINKS_PER_SOC; 313 } 314 315 int8_t wlan_mlo_get_num_active_links(void) 316 { 317 struct mlo_mgr_context *mlo_ctx; 318 319 mlo_ctx = wlan_objmgr_get_mlo_ctx(); 320 if (!mlo_ctx) 321 return WLAN_MLO_INVALID_NUM_LINKS; 322 323 return mlo_ctx->setup_info.tot_links; 324 } 325 326 uint16_t wlan_mlo_get_valid_link_bitmap(void) 327 { 328 struct mlo_mgr_context *mlo_ctx; 329 330 mlo_ctx = wlan_objmgr_get_mlo_ctx(); 331 if (!mlo_ctx) 332 return 0; 333 334 return mlo_ctx->setup_info.valid_link_bitmap; 335 } 336 337 uint16_t wlan_mlo_get_pdev_hw_link_id(struct wlan_objmgr_pdev *pdev) 338 { 339 struct wlan_objmgr_psoc *psoc; 340 struct wlan_lmac_if_tx_ops *tx_ops; 341 uint16_t hw_link_id = INVALID_HW_LINK_ID; 342 343 psoc = wlan_pdev_get_psoc(pdev); 344 if (psoc) { 345 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 346 if (tx_ops && tx_ops->mops.get_hw_link_id) 347 hw_link_id = tx_ops->mops.get_hw_link_id(pdev); 348 } 349 350 return hw_link_id; 351 } 352 353 qdf_export_symbol(wlan_mlo_get_pdev_hw_link_id); 354 355 static void wlan_pdev_hw_link_iterator(struct wlan_objmgr_psoc *psoc, 356 void *obj, void *arg) 357 { 358 struct hw_link_id_iterator *itr = (struct hw_link_id_iterator *)arg; 359 struct wlan_objmgr_pdev *pdev = (struct wlan_objmgr_pdev *)obj; 360 uint16_t hw_link_id; 361 362 if (itr->pdev) 363 return; 364 365 hw_link_id = wlan_mlo_get_pdev_hw_link_id(pdev); 366 if (hw_link_id == itr->hw_link_id) { 367 if (wlan_objmgr_pdev_try_get_ref(pdev, itr->dbgid) == 368 QDF_STATUS_SUCCESS) 369 itr->pdev = pdev; 370 } 371 } 372 373 static void wlan_mlo_find_hw_link_id(struct wlan_objmgr_psoc *psoc, 374 void *arg, 375 uint8_t index) 376 { 377 struct hw_link_id_iterator *itr = (struct hw_link_id_iterator *)arg; 378 379 wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP, 380 wlan_pdev_hw_link_iterator, 381 arg, false, itr->dbgid); 382 } 383 384 struct wlan_objmgr_pdev * 385 wlan_mlo_get_pdev_by_hw_link_id(uint16_t hw_link_id, 386 wlan_objmgr_ref_dbgid refdbgid) 387 { 388 struct hw_link_id_iterator itr; 389 390 itr.hw_link_id = hw_link_id; 391 itr.pdev = NULL; 392 itr.dbgid = refdbgid; 393 394 wlan_objmgr_iterate_psoc_list(wlan_mlo_find_hw_link_id, 395 &itr, refdbgid); 396 397 return itr.pdev; 398 } 399 400 qdf_export_symbol(wlan_mlo_get_pdev_by_hw_link_id); 401 #endif /*WLAN_MLO_MULTI_CHIP*/ 402 403 void mlo_get_ml_vdev_list(struct wlan_objmgr_vdev *vdev, 404 uint16_t *vdev_count, 405 struct wlan_objmgr_vdev **wlan_vdev_list) 406 { 407 struct wlan_mlo_dev_context *dev_ctx; 408 int i; 409 QDF_STATUS status; 410 411 *vdev_count = 0; 412 413 if (!vdev || !vdev->mlo_dev_ctx) { 414 mlo_err("Invalid input"); 415 return; 416 } 417 418 dev_ctx = vdev->mlo_dev_ctx; 419 420 mlo_dev_lock_acquire(dev_ctx); 421 *vdev_count = 0; 422 for (i = 0; i < QDF_ARRAY_SIZE(dev_ctx->wlan_vdev_list); i++) { 423 if (dev_ctx->wlan_vdev_list[i] && 424 wlan_vdev_mlme_is_mlo_vdev(dev_ctx->wlan_vdev_list[i])) { 425 status = wlan_objmgr_vdev_try_get_ref( 426 dev_ctx->wlan_vdev_list[i], 427 WLAN_MLO_MGR_ID); 428 if (QDF_IS_STATUS_ERROR(status)) 429 break; 430 wlan_vdev_list[*vdev_count] = 431 dev_ctx->wlan_vdev_list[i]; 432 (*vdev_count) += 1; 433 } 434 } 435 mlo_dev_lock_release(dev_ctx); 436 } 437 438 /** 439 * mlo_link_set_active() - send MLO link set active command 440 * @psoc: PSOC object 441 * @param: MLO link set active params 442 * 443 * Return: QDF_STATUS 444 */ 445 static QDF_STATUS 446 mlo_link_set_active(struct wlan_objmgr_psoc *psoc, 447 struct mlo_link_set_active_param *param) 448 { 449 struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops; 450 451 if (!psoc) { 452 mlo_err("psoc is null"); 453 return QDF_STATUS_E_NULL_VALUE; 454 } 455 456 mlo_tx_ops = target_if_mlo_get_tx_ops(psoc); 457 if (!mlo_tx_ops) { 458 mlo_err("tx_ops is null!"); 459 return QDF_STATUS_E_NULL_VALUE; 460 } 461 462 if (!mlo_tx_ops->link_set_active) { 463 mlo_err("link_set_active function is null!"); 464 return QDF_STATUS_E_NULL_VALUE; 465 } 466 467 return mlo_tx_ops->link_set_active(psoc, param); 468 } 469 470 /** 471 * mlo_release_ser_link_set_active_cmd() - releases serialization command for 472 * forcing MLO link active/inactive 473 * @vdev: Object manager vdev 474 * 475 * Return: None 476 */ 477 static void 478 mlo_release_ser_link_set_active_cmd(struct wlan_objmgr_vdev *vdev) 479 { 480 struct wlan_serialization_queued_cmd_info cmd = {0}; 481 482 cmd.cmd_type = WLAN_SER_CMD_SET_MLO_LINK; 483 cmd.requestor = WLAN_UMAC_COMP_MLO_MGR; 484 cmd.cmd_id = 0; 485 cmd.vdev = vdev; 486 487 mlo_debug("release serialization command"); 488 wlan_serialization_remove_cmd(&cmd); 489 } 490 491 /** 492 * mlo_link_set_active_resp_vdev_handler() - vdev handler for mlo link set 493 * active response event. 494 * @psoc: psoc object 495 * @obj: vdev object 496 * @arg: mlo link set active response 497 * 498 * Return: None 499 */ 500 static void 501 mlo_link_set_active_resp_vdev_handler(struct wlan_objmgr_psoc *psoc, 502 void *obj, void *arg) 503 { 504 struct mlo_link_set_active_req *req; 505 struct wlan_objmgr_vdev *vdev = obj; 506 struct mlo_link_set_active_resp *event = arg; 507 508 req = wlan_serialization_get_active_cmd(wlan_vdev_get_psoc(vdev), 509 wlan_vdev_get_id(vdev), 510 WLAN_SER_CMD_SET_MLO_LINK); 511 if (!req) 512 return; 513 514 if (req->ctx.set_mlo_link_cb) 515 req->ctx.set_mlo_link_cb(vdev, req->ctx.cb_arg, event); 516 517 mlo_release_ser_link_set_active_cmd(vdev); 518 } 519 520 QDF_STATUS 521 mlo_process_link_set_active_resp(struct wlan_objmgr_psoc *psoc, 522 struct mlo_link_set_active_resp *event) 523 { 524 wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP, 525 mlo_link_set_active_resp_vdev_handler, 526 event, true, WLAN_MLO_MGR_ID); 527 return QDF_STATUS_SUCCESS; 528 } 529 530 /** 531 * mlo_ser_set_link_cb() - Serialization callback function 532 * @cmd: Serialization command info 533 * @reason: Serialization reason for callback execution 534 * 535 * Return: Status of callback execution 536 */ 537 static QDF_STATUS 538 mlo_ser_set_link_cb(struct wlan_serialization_command *cmd, 539 enum wlan_serialization_cb_reason reason) 540 { 541 QDF_STATUS status = QDF_STATUS_SUCCESS; 542 struct wlan_objmgr_vdev *vdev; 543 struct wlan_objmgr_psoc *psoc; 544 struct mlo_link_set_active_req *req; 545 struct mlo_mgr_context *mlo_ctx; 546 547 if (!cmd || !cmd->vdev) 548 return QDF_STATUS_E_FAILURE; 549 550 mlo_ctx = wlan_objmgr_get_mlo_ctx(); 551 if (!mlo_ctx) 552 return QDF_STATUS_E_FAILURE; 553 554 psoc = wlan_vdev_get_psoc(cmd->vdev); 555 if (!psoc) { 556 mlo_err("psoc is NULL, reason: %d", reason); 557 return QDF_STATUS_E_NULL_VALUE; 558 } 559 560 req = cmd->umac_cmd; 561 if (!req) 562 return QDF_STATUS_E_INVAL; 563 564 vdev = cmd->vdev; 565 switch (reason) { 566 case WLAN_SER_CB_ACTIVATE_CMD: 567 status = mlo_link_set_active(psoc, &req->param); 568 break; 569 case WLAN_SER_CB_CANCEL_CMD: 570 case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT: 571 mlo_err("vdev %d command not execute: %d", 572 wlan_vdev_get_id(vdev), reason); 573 if (req->ctx.set_mlo_link_cb) 574 req->ctx.set_mlo_link_cb(vdev, req->ctx.cb_arg, NULL); 575 break; 576 case WLAN_SER_CB_RELEASE_MEM_CMD: 577 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID); 578 qdf_mem_free(req); 579 break; 580 default: 581 QDF_ASSERT(0); 582 status = QDF_STATUS_E_INVAL; 583 break; 584 } 585 586 return status; 587 } 588 589 #define MLO_SER_CMD_TIMEOUT_MS 5000 590 QDF_STATUS mlo_ser_set_link_req(struct mlo_link_set_active_req *req) 591 { 592 struct wlan_serialization_command cmd = {0, }; 593 enum wlan_serialization_status ser_cmd_status; 594 QDF_STATUS status; 595 struct wlan_objmgr_vdev *vdev; 596 597 if (!req) 598 return QDF_STATUS_E_INVAL; 599 600 vdev = req->ctx.vdev; 601 status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_MLO_MGR_ID); 602 if (QDF_IS_STATUS_ERROR(status)) { 603 mlo_err("vdev %d unable to get reference", 604 wlan_vdev_get_id(vdev)); 605 return status; 606 } 607 608 cmd.cmd_type = WLAN_SER_CMD_SET_MLO_LINK; 609 cmd.cmd_id = 0; 610 cmd.cmd_cb = mlo_ser_set_link_cb; 611 cmd.source = WLAN_UMAC_COMP_MLO_MGR; 612 cmd.is_high_priority = false; 613 cmd.cmd_timeout_duration = MLO_SER_CMD_TIMEOUT_MS; 614 cmd.vdev = vdev; 615 cmd.is_blocking = true; 616 cmd.umac_cmd = (void *)req; 617 618 ser_cmd_status = wlan_serialization_request(&cmd); 619 switch (ser_cmd_status) { 620 case WLAN_SER_CMD_PENDING: 621 /* command moved to pending list.Do nothing */ 622 break; 623 case WLAN_SER_CMD_ACTIVE: 624 /* command moved to active list. Do nothing */ 625 break; 626 default: 627 mlo_err("vdev %d ser cmd status %d", 628 wlan_vdev_get_id(vdev), ser_cmd_status); 629 status = QDF_STATUS_E_FAILURE; 630 } 631 632 if (QDF_IS_STATUS_SUCCESS(status)) 633 return status; 634 635 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID); 636 637 return status; 638 } 639 640 void mlo_mlme_handle_sta_csa_param(struct wlan_objmgr_vdev *vdev, 641 struct csa_offload_params *csa_param) 642 { 643 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 644 645 if (!mlo_ctx || !mlo_ctx->mlme_ops || 646 !mlo_ctx->mlme_ops->mlo_mlme_ext_handle_sta_csa_param) 647 return; 648 649 mlo_ctx->mlme_ops->mlo_mlme_ext_handle_sta_csa_param(vdev, csa_param); 650 } 651 652 QDF_STATUS 653 mlo_get_mlstats_vdev_params(struct wlan_objmgr_psoc *psoc, 654 struct mlo_stats_vdev_params *info, 655 uint8_t vdev_id) 656 { 657 struct wlan_objmgr_vdev *ml_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS] = {0}; 658 struct wlan_objmgr_vdev *vdev; 659 int i; 660 uint16_t ml_vdev_cnt = 0; 661 662 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 663 WLAN_MLO_MGR_ID); 664 if (!vdev) { 665 mlo_err("vdev object is NULL for vdev %d", vdev_id); 666 return QDF_STATUS_E_INVAL; 667 } 668 669 mlo_get_ml_vdev_list(vdev, &ml_vdev_cnt, ml_vdev_list); 670 for (i = 0; i < ml_vdev_cnt; i++) { 671 info->ml_vdev_id[i] = wlan_vdev_get_id(ml_vdev_list[i]); 672 mlo_release_vdev_ref(ml_vdev_list[i]); 673 } 674 info->ml_vdev_count = ml_vdev_cnt; 675 mlo_release_vdev_ref(vdev); 676 677 return QDF_STATUS_SUCCESS; 678 } 679