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 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, uint8_t is_disassoc) 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, is_disassoc); 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(uint8_t grp_id) 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 if (grp_id >= mlo_ctx->total_grp) { 313 mlo_err("Invalid grp id %d, total no of groups %d", 314 grp_id, mlo_ctx->total_grp); 315 return WLAN_MLO_INVALID_NUM_LINKS; 316 } 317 318 return (mlo_ctx->setup_info[grp_id].tot_socs * 319 WLAN_MAX_MLO_LINKS_PER_SOC); 320 } 321 322 int8_t wlan_mlo_get_num_active_links(uint8_t grp_id) 323 { 324 struct mlo_mgr_context *mlo_ctx; 325 326 mlo_ctx = wlan_objmgr_get_mlo_ctx(); 327 328 if (!mlo_ctx) 329 return WLAN_MLO_INVALID_NUM_LINKS; 330 331 if (grp_id >= mlo_ctx->total_grp) { 332 qdf_err("Invalid grp id %d, total no of groups %d", 333 grp_id, mlo_ctx->total_grp); 334 return WLAN_MLO_INVALID_NUM_LINKS; 335 } 336 337 return mlo_ctx->setup_info[grp_id].tot_links; 338 } 339 340 uint16_t wlan_mlo_get_valid_link_bitmap(uint8_t grp_id) 341 { 342 struct mlo_mgr_context *mlo_ctx; 343 344 mlo_ctx = wlan_objmgr_get_mlo_ctx(); 345 if (!mlo_ctx) 346 return 0; 347 348 if (grp_id >= mlo_ctx->total_grp) { 349 qdf_err("Invalid grp id %d, total no of groups %d", 350 grp_id, mlo_ctx->total_grp); 351 return 0; 352 } 353 354 return mlo_ctx->setup_info[grp_id].valid_link_bitmap; 355 } 356 357 uint8_t wlan_mlo_get_psoc_group_id(struct wlan_objmgr_psoc *psoc) 358 { 359 struct wlan_lmac_if_tx_ops *tx_ops; 360 uint8_t ml_grp_id = WLAN_MLO_GROUP_INVALID; 361 362 if (!psoc) { 363 qdf_err("PSOC is NULL"); 364 return -EINVAL; 365 } 366 367 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 368 if (tx_ops && tx_ops->mops.get_psoc_mlo_group_id) 369 ml_grp_id = tx_ops->mops.get_psoc_mlo_group_id(psoc); 370 371 return ml_grp_id; 372 } 373 374 qdf_export_symbol(wlan_mlo_get_psoc_group_id); 375 376 bool wlan_mlo_get_psoc_capable(struct wlan_objmgr_psoc *psoc) 377 { 378 struct target_psoc_info *tgt_hdl; 379 380 if (!psoc) { 381 qdf_err("PSOC is NULL"); 382 return false; 383 } 384 385 tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc); 386 if (!tgt_hdl) { 387 target_if_err("target_psoc_info is null"); 388 return false; 389 } 390 391 if ((tgt_hdl->tif_ops) && 392 (tgt_hdl->tif_ops->mlo_capable)) 393 return tgt_hdl->tif_ops->mlo_capable(psoc); 394 395 return false; 396 } 397 398 uint16_t wlan_mlo_get_pdev_hw_link_id(struct wlan_objmgr_pdev *pdev) 399 { 400 struct wlan_objmgr_psoc *psoc; 401 struct wlan_lmac_if_tx_ops *tx_ops; 402 uint16_t hw_link_id = INVALID_HW_LINK_ID; 403 404 psoc = wlan_pdev_get_psoc(pdev); 405 if (psoc) { 406 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 407 if (tx_ops && tx_ops->mops.get_hw_link_id) 408 hw_link_id = tx_ops->mops.get_hw_link_id(pdev); 409 } 410 411 return hw_link_id; 412 } 413 414 qdf_export_symbol(wlan_mlo_get_pdev_hw_link_id); 415 416 static void wlan_pdev_hw_link_iterator(struct wlan_objmgr_psoc *psoc, 417 void *obj, void *arg) 418 { 419 struct hw_link_id_iterator *itr = (struct hw_link_id_iterator *)arg; 420 struct wlan_objmgr_pdev *pdev = (struct wlan_objmgr_pdev *)obj; 421 uint16_t hw_link_id; 422 uint8_t ml_grp_id; 423 424 if (itr->pdev) 425 return; 426 427 ml_grp_id = wlan_mlo_get_psoc_group_id(psoc); 428 if (ml_grp_id > WLAN_MAX_MLO_GROUPS) 429 return; 430 431 if (ml_grp_id != itr->mlo_grp_id) 432 return; 433 434 hw_link_id = wlan_mlo_get_pdev_hw_link_id(pdev); 435 if (hw_link_id == itr->hw_link_id) { 436 if (wlan_objmgr_pdev_try_get_ref(pdev, itr->dbgid) == 437 QDF_STATUS_SUCCESS) 438 itr->pdev = pdev; 439 } 440 } 441 442 static void wlan_mlo_find_hw_link_id(struct wlan_objmgr_psoc *psoc, 443 void *arg, 444 uint8_t index) 445 { 446 struct hw_link_id_iterator *itr = (struct hw_link_id_iterator *)arg; 447 448 wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP, 449 wlan_pdev_hw_link_iterator, 450 arg, false, itr->dbgid); 451 } 452 453 struct wlan_objmgr_pdev * 454 wlan_mlo_get_pdev_by_hw_link_id(uint16_t hw_link_id, uint8_t ml_grp_id, 455 wlan_objmgr_ref_dbgid refdbgid) 456 { 457 struct hw_link_id_iterator itr; 458 459 itr.hw_link_id = hw_link_id; 460 itr.pdev = NULL; 461 itr.mlo_grp_id = ml_grp_id; 462 itr.dbgid = refdbgid; 463 464 wlan_objmgr_iterate_psoc_list(wlan_mlo_find_hw_link_id, 465 &itr, refdbgid); 466 467 return itr.pdev; 468 } 469 470 qdf_export_symbol(wlan_mlo_get_pdev_by_hw_link_id); 471 #endif /*WLAN_MLO_MULTI_CHIP*/ 472 473 void mlo_get_ml_vdev_list(struct wlan_objmgr_vdev *vdev, 474 uint16_t *vdev_count, 475 struct wlan_objmgr_vdev **wlan_vdev_list) 476 { 477 struct wlan_mlo_dev_context *dev_ctx; 478 int i; 479 QDF_STATUS status; 480 481 *vdev_count = 0; 482 483 if (!vdev || !vdev->mlo_dev_ctx) { 484 mlo_err("Invalid input"); 485 return; 486 } 487 488 dev_ctx = vdev->mlo_dev_ctx; 489 490 mlo_dev_lock_acquire(dev_ctx); 491 *vdev_count = 0; 492 for (i = 0; i < QDF_ARRAY_SIZE(dev_ctx->wlan_vdev_list); i++) { 493 if (dev_ctx->wlan_vdev_list[i] && 494 wlan_vdev_mlme_is_mlo_vdev(dev_ctx->wlan_vdev_list[i])) { 495 status = wlan_objmgr_vdev_try_get_ref( 496 dev_ctx->wlan_vdev_list[i], 497 WLAN_MLO_MGR_ID); 498 if (QDF_IS_STATUS_ERROR(status)) 499 break; 500 wlan_vdev_list[*vdev_count] = 501 dev_ctx->wlan_vdev_list[i]; 502 (*vdev_count) += 1; 503 } 504 } 505 mlo_dev_lock_release(dev_ctx); 506 } 507 508 /** 509 * mlo_link_set_active() - send MLO link set active command 510 * @psoc: PSOC object 511 * @req: MLO link set active request 512 * 513 * Return: QDF_STATUS 514 */ 515 static QDF_STATUS 516 mlo_link_set_active(struct wlan_objmgr_psoc *psoc, 517 struct mlo_link_set_active_req *req) 518 { 519 struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops; 520 struct mlo_link_set_active_param *param = &req->param; 521 QDF_STATUS status; 522 struct mlo_link_set_active_resp rsp_evt; 523 524 if (!psoc) { 525 mlo_err("psoc is null"); 526 return QDF_STATUS_E_NULL_VALUE; 527 } 528 529 mlo_tx_ops = target_if_mlo_get_tx_ops(psoc); 530 if (!mlo_tx_ops) { 531 mlo_err("tx_ops is null!"); 532 return QDF_STATUS_E_NULL_VALUE; 533 } 534 535 if (!mlo_tx_ops->link_set_active) { 536 mlo_err("link_set_active function is null!"); 537 return QDF_STATUS_E_NULL_VALUE; 538 } 539 540 if (req->ctx.validate_set_mlo_link_cb) { 541 status = req->ctx.validate_set_mlo_link_cb(psoc, param); 542 if (QDF_IS_STATUS_ERROR(status)) { 543 qdf_mem_zero(&rsp_evt, sizeof(rsp_evt)); 544 rsp_evt.status = status; 545 if (req->ctx.set_mlo_link_cb) 546 req->ctx.set_mlo_link_cb(req->ctx.vdev, 547 req->ctx.cb_arg, 548 &rsp_evt); 549 return status; 550 } 551 } 552 553 return mlo_tx_ops->link_set_active(psoc, param); 554 } 555 556 /** 557 * mlo_release_ser_link_set_active_cmd() - releases serialization command for 558 * forcing MLO link active/inactive 559 * @vdev: Object manager vdev 560 * 561 * Return: None 562 */ 563 static void 564 mlo_release_ser_link_set_active_cmd(struct wlan_objmgr_vdev *vdev) 565 { 566 struct wlan_serialization_queued_cmd_info cmd = {0}; 567 568 cmd.cmd_type = WLAN_SER_CMD_SET_MLO_LINK; 569 cmd.requestor = WLAN_UMAC_COMP_MLO_MGR; 570 cmd.cmd_id = 0; 571 cmd.vdev = vdev; 572 573 mlo_debug("release serialization command"); 574 wlan_serialization_remove_cmd(&cmd); 575 } 576 577 /** 578 * mlo_link_set_active_resp_vdev_handler() - vdev handler for mlo link set 579 * active response event. 580 * @psoc: psoc object 581 * @obj: vdev object 582 * @arg: mlo link set active response 583 * 584 * Return: None 585 */ 586 static void 587 mlo_link_set_active_resp_vdev_handler(struct wlan_objmgr_psoc *psoc, 588 void *obj, void *arg) 589 { 590 struct mlo_link_set_active_req *req; 591 struct wlan_objmgr_vdev *vdev = obj; 592 struct mlo_link_set_active_resp *event = arg; 593 594 req = wlan_serialization_get_active_cmd(wlan_vdev_get_psoc(vdev), 595 wlan_vdev_get_id(vdev), 596 WLAN_SER_CMD_SET_MLO_LINK); 597 if (!req) 598 return; 599 600 if (req->ctx.set_mlo_link_cb) 601 req->ctx.set_mlo_link_cb(vdev, req->ctx.cb_arg, event); 602 603 mlo_release_ser_link_set_active_cmd(vdev); 604 } 605 606 QDF_STATUS 607 mlo_process_link_set_active_resp(struct wlan_objmgr_psoc *psoc, 608 struct mlo_link_set_active_resp *event) 609 { 610 wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP, 611 mlo_link_set_active_resp_vdev_handler, 612 event, true, WLAN_MLO_MGR_ID); 613 return QDF_STATUS_SUCCESS; 614 } 615 616 /** 617 * mlo_ser_set_link_cb() - Serialization callback function 618 * @cmd: Serialization command info 619 * @reason: Serialization reason for callback execution 620 * 621 * Return: Status of callback execution 622 */ 623 static QDF_STATUS 624 mlo_ser_set_link_cb(struct wlan_serialization_command *cmd, 625 enum wlan_serialization_cb_reason reason) 626 { 627 QDF_STATUS status = QDF_STATUS_SUCCESS; 628 struct wlan_objmgr_vdev *vdev; 629 struct wlan_objmgr_psoc *psoc; 630 struct mlo_link_set_active_req *req; 631 struct mlo_mgr_context *mlo_ctx; 632 633 if (!cmd || !cmd->vdev) 634 return QDF_STATUS_E_FAILURE; 635 636 mlo_ctx = wlan_objmgr_get_mlo_ctx(); 637 if (!mlo_ctx) 638 return QDF_STATUS_E_FAILURE; 639 640 psoc = wlan_vdev_get_psoc(cmd->vdev); 641 if (!psoc) { 642 mlo_err("psoc is NULL, reason: %d", reason); 643 return QDF_STATUS_E_NULL_VALUE; 644 } 645 646 req = cmd->umac_cmd; 647 if (!req) 648 return QDF_STATUS_E_INVAL; 649 650 vdev = cmd->vdev; 651 switch (reason) { 652 case WLAN_SER_CB_ACTIVATE_CMD: 653 status = mlo_link_set_active(psoc, req); 654 break; 655 case WLAN_SER_CB_CANCEL_CMD: 656 case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT: 657 mlo_err("vdev %d command not execute: %d", 658 wlan_vdev_get_id(vdev), reason); 659 if (req->ctx.set_mlo_link_cb) 660 req->ctx.set_mlo_link_cb(vdev, req->ctx.cb_arg, NULL); 661 break; 662 case WLAN_SER_CB_RELEASE_MEM_CMD: 663 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID); 664 qdf_mem_free(req); 665 break; 666 default: 667 QDF_ASSERT(0); 668 status = QDF_STATUS_E_INVAL; 669 break; 670 } 671 672 return status; 673 } 674 675 #define MLO_SER_CMD_TIMEOUT_MS 5000 676 QDF_STATUS mlo_ser_set_link_req(struct mlo_link_set_active_req *req) 677 { 678 struct wlan_serialization_command cmd = {0, }; 679 enum wlan_serialization_status ser_cmd_status; 680 QDF_STATUS status; 681 struct wlan_objmgr_vdev *vdev; 682 683 if (!req) 684 return QDF_STATUS_E_INVAL; 685 686 vdev = req->ctx.vdev; 687 status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_MLO_MGR_ID); 688 if (QDF_IS_STATUS_ERROR(status)) { 689 mlo_err("vdev %d unable to get reference", 690 wlan_vdev_get_id(vdev)); 691 return status; 692 } 693 694 cmd.cmd_type = WLAN_SER_CMD_SET_MLO_LINK; 695 cmd.cmd_id = 0; 696 cmd.cmd_cb = mlo_ser_set_link_cb; 697 cmd.source = WLAN_UMAC_COMP_MLO_MGR; 698 cmd.is_high_priority = false; 699 cmd.cmd_timeout_duration = MLO_SER_CMD_TIMEOUT_MS; 700 cmd.vdev = vdev; 701 cmd.is_blocking = true; 702 cmd.umac_cmd = (void *)req; 703 704 ser_cmd_status = wlan_serialization_request(&cmd); 705 switch (ser_cmd_status) { 706 case WLAN_SER_CMD_PENDING: 707 /* command moved to pending list.Do nothing */ 708 break; 709 case WLAN_SER_CMD_ACTIVE: 710 /* command moved to active list. Do nothing */ 711 break; 712 default: 713 mlo_err("vdev %d ser cmd status %d", 714 wlan_vdev_get_id(vdev), ser_cmd_status); 715 status = QDF_STATUS_E_FAILURE; 716 } 717 718 if (QDF_IS_STATUS_SUCCESS(status)) 719 return status; 720 721 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID); 722 723 return status; 724 } 725 726 void mlo_mlme_handle_sta_csa_param(struct wlan_objmgr_vdev *vdev, 727 struct csa_offload_params *csa_param) 728 { 729 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 730 731 if (!mlo_ctx || !mlo_ctx->mlme_ops || 732 !mlo_ctx->mlme_ops->mlo_mlme_ext_handle_sta_csa_param) 733 return; 734 735 mlo_ctx->mlme_ops->mlo_mlme_ext_handle_sta_csa_param(vdev, csa_param); 736 } 737 738 QDF_STATUS 739 mlo_get_mlstats_vdev_params(struct wlan_objmgr_psoc *psoc, 740 struct mlo_stats_vdev_params *info, 741 uint8_t vdev_id) 742 { 743 struct wlan_objmgr_vdev *ml_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS] = {0}; 744 struct wlan_objmgr_vdev *vdev; 745 int i; 746 uint16_t ml_vdev_cnt = 0; 747 748 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 749 WLAN_MLO_MGR_ID); 750 if (!vdev) { 751 mlo_err("vdev object is NULL for vdev %d", vdev_id); 752 return QDF_STATUS_E_INVAL; 753 } 754 755 mlo_get_ml_vdev_list(vdev, &ml_vdev_cnt, ml_vdev_list); 756 for (i = 0; i < ml_vdev_cnt; i++) { 757 info->ml_vdev_id[i] = wlan_vdev_get_id(ml_vdev_list[i]); 758 mlo_release_vdev_ref(ml_vdev_list[i]); 759 } 760 info->ml_vdev_count = ml_vdev_cnt; 761 mlo_release_vdev_ref(vdev); 762 763 return QDF_STATUS_SUCCESS; 764 } 765