1 /* 2 * Copyright (c) 2021, The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2024 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 #include "wlan_mlo_mgr_sta.h" 24 #ifdef WLAN_MLO_MULTI_CHIP 25 #include "wlan_lmac_if_def.h" 26 #endif 27 #include "wlan_serialization_api.h" 28 #include <target_if_mlo_mgr.h> 29 #include <cdp_txrx_cmn.h> 30 #include <wlan_cfg.h> 31 #include "wlan_utility.h" 32 mlo_get_link_information(struct qdf_mac_addr * mld_addr,struct mlo_link_info * info)33 void mlo_get_link_information(struct qdf_mac_addr *mld_addr, 34 struct mlo_link_info *info) 35 { 36 /* Pass the partner link information*/ 37 } 38 is_mlo_all_links_up(struct wlan_mlo_dev_context * mldev)39 void is_mlo_all_links_up(struct wlan_mlo_dev_context *mldev) 40 { 41 /* Loop through all the vdev's part of the ML device*/ 42 /* STA: Loop through all the associated vdev status. */ 43 } 44 mlo_get_vdev_by_link_id(struct wlan_objmgr_vdev * vdev,uint8_t link_id,wlan_objmgr_ref_dbgid id)45 struct wlan_objmgr_vdev *mlo_get_vdev_by_link_id(struct wlan_objmgr_vdev *vdev, 46 uint8_t link_id, 47 wlan_objmgr_ref_dbgid id) 48 { 49 struct wlan_mlo_dev_context *dev_ctx; 50 int i; 51 struct wlan_objmgr_vdev *partner_vdev = NULL; 52 53 if (!vdev || !vdev->mlo_dev_ctx) { 54 mlo_err("Invalid input"); 55 return partner_vdev; 56 } 57 58 dev_ctx = vdev->mlo_dev_ctx; 59 60 mlo_dev_lock_acquire(dev_ctx); 61 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 62 if (dev_ctx->wlan_vdev_list[i] && 63 wlan_vdev_mlme_is_mlo_vdev(dev_ctx->wlan_vdev_list[i]) && 64 dev_ctx->wlan_vdev_list[i]->vdev_mlme.mlo_link_id == 65 link_id) { 66 if (wlan_objmgr_vdev_try_get_ref( 67 dev_ctx->wlan_vdev_list[i], 68 id) == QDF_STATUS_SUCCESS) 69 partner_vdev = dev_ctx->wlan_vdev_list[i]; 70 71 break; 72 } 73 } 74 mlo_dev_lock_release(dev_ctx); 75 76 return partner_vdev; 77 } 78 mlo_release_vdev_ref(struct wlan_objmgr_vdev * vdev)79 void mlo_release_vdev_ref(struct wlan_objmgr_vdev *vdev) 80 { 81 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID); 82 } 83 mlo_reg_mlme_ext_cb(struct mlo_mgr_context * ctx,struct mlo_mlme_ext_ops * ops)84 QDF_STATUS mlo_reg_mlme_ext_cb(struct mlo_mgr_context *ctx, 85 struct mlo_mlme_ext_ops *ops) 86 { 87 if (!ctx) 88 return QDF_STATUS_E_FAILURE; 89 90 ctx->mlme_ops = ops; 91 return QDF_STATUS_SUCCESS; 92 } 93 mlo_unreg_mlme_ext_cb(struct mlo_mgr_context * ctx)94 QDF_STATUS mlo_unreg_mlme_ext_cb(struct mlo_mgr_context *ctx) 95 { 96 if (!ctx) 97 return QDF_STATUS_E_FAILURE; 98 99 ctx->mlme_ops = NULL; 100 return QDF_STATUS_SUCCESS; 101 } 102 103 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE wlan_mlo_mgr_register_osif_ext_ops(struct mlo_mgr_context * mlo_ctx,struct mlo_osif_ext_ops * ops)104 QDF_STATUS wlan_mlo_mgr_register_osif_ext_ops(struct mlo_mgr_context *mlo_ctx, 105 struct mlo_osif_ext_ops *ops) 106 { 107 if (!ops || !mlo_ctx) 108 return QDF_STATUS_E_FAILURE; 109 110 mlo_ctx->osif_ops = ops; 111 return QDF_STATUS_SUCCESS; 112 } 113 wlan_mlo_mgr_unregister_osif_ext_ops(struct mlo_mgr_context * mlo_ctx)114 QDF_STATUS wlan_mlo_mgr_unregister_osif_ext_ops(struct mlo_mgr_context *mlo_ctx) 115 { 116 if (!mlo_ctx) 117 return QDF_STATUS_E_FAILURE; 118 119 mlo_ctx->osif_ops = NULL; 120 return QDF_STATUS_SUCCESS; 121 } 122 #endif 123 mlo_mlme_clone_sta_security(struct wlan_objmgr_vdev * vdev,struct wlan_cm_connect_req * req)124 QDF_STATUS mlo_mlme_clone_sta_security(struct wlan_objmgr_vdev *vdev, 125 struct wlan_cm_connect_req *req) 126 { 127 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 128 struct vdev_mlme_obj *vdev_mlme; 129 QDF_STATUS status = QDF_STATUS_SUCCESS; 130 131 if (!req || !mlo_ctx || !mlo_ctx->mlme_ops || 132 !mlo_ctx->mlme_ops->mlo_mlme_ext_validate_conn_req) 133 return QDF_STATUS_E_FAILURE; 134 135 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 136 if (!vdev_mlme) 137 return QDF_STATUS_E_FAILURE; 138 139 if (mlo_ctx->mlme_ops->mlo_mlme_ext_clone_security_param) { 140 status = 141 mlo_ctx->mlme_ops->mlo_mlme_ext_clone_security_param( 142 vdev_mlme, req); 143 } 144 145 return status; 146 } 147 mlo_mlme_sta_op_class(struct wlan_objmgr_vdev * vdev,uint8_t * ml_ie)148 QDF_STATUS mlo_mlme_sta_op_class(struct wlan_objmgr_vdev *vdev, 149 uint8_t *ml_ie) 150 { 151 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 152 struct vdev_mlme_obj *vdev_mlme; 153 QDF_STATUS status = QDF_STATUS_SUCCESS; 154 155 if (!mlo_ctx || !mlo_ctx->mlme_ops || 156 !mlo_ctx->mlme_ops->mlo_mlme_ext_validate_conn_req) 157 return QDF_STATUS_E_FAILURE; 158 159 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 160 if (!vdev_mlme) 161 return QDF_STATUS_E_FAILURE; 162 163 if (mlo_ctx->mlme_ops->mlo_mlme_ext_sta_op_class) 164 status = 165 mlo_ctx->mlme_ops->mlo_mlme_ext_sta_op_class( 166 vdev_mlme, ml_ie); 167 168 return status; 169 } 170 mlo_mlme_validate_conn_req(struct wlan_objmgr_vdev * vdev,void * ext_data)171 QDF_STATUS mlo_mlme_validate_conn_req(struct wlan_objmgr_vdev *vdev, 172 void *ext_data) 173 { 174 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 175 struct vdev_mlme_obj *vdev_mlme; 176 QDF_STATUS status; 177 178 if (!mlo_ctx || !mlo_ctx->mlme_ops || 179 !mlo_ctx->mlme_ops->mlo_mlme_ext_validate_conn_req) 180 return QDF_STATUS_E_FAILURE; 181 182 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 183 if (!vdev_mlme) 184 return QDF_STATUS_E_FAILURE; 185 186 status = 187 mlo_ctx->mlme_ops->mlo_mlme_ext_validate_conn_req(vdev_mlme, 188 ext_data); 189 return status; 190 } 191 mlo_mlme_create_link_vdev(struct wlan_objmgr_vdev * vdev,void * ext_data)192 QDF_STATUS mlo_mlme_create_link_vdev(struct wlan_objmgr_vdev *vdev, 193 void *ext_data) 194 { 195 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 196 struct vdev_mlme_obj *vdev_mlme; 197 QDF_STATUS status; 198 199 if (!mlo_ctx || !mlo_ctx->mlme_ops || 200 !mlo_ctx->mlme_ops->mlo_mlme_ext_create_link_vdev) 201 return QDF_STATUS_E_FAILURE; 202 203 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 204 if (!vdev_mlme) 205 return QDF_STATUS_E_FAILURE; 206 207 status = 208 mlo_ctx->mlme_ops->mlo_mlme_ext_create_link_vdev(vdev_mlme, 209 ext_data); 210 return status; 211 } 212 mlo_mlme_peer_create(struct wlan_objmgr_vdev * vdev,struct wlan_mlo_peer_context * ml_peer,struct qdf_mac_addr * addr,qdf_nbuf_t frm_buf)213 void mlo_mlme_peer_create(struct wlan_objmgr_vdev *vdev, 214 struct wlan_mlo_peer_context *ml_peer, 215 struct qdf_mac_addr *addr, 216 qdf_nbuf_t frm_buf) 217 { 218 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 219 220 if (!mlo_ctx || !mlo_ctx->mlme_ops || 221 !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_create) 222 return; 223 224 mlo_ctx->mlme_ops->mlo_mlme_ext_peer_create(vdev, ml_peer, 225 addr, frm_buf); 226 } 227 mlo_mlme_bridge_peer_create(struct wlan_objmgr_vdev * vdev,struct wlan_mlo_peer_context * ml_peer,struct qdf_mac_addr * addr,qdf_nbuf_t frm_buf)228 void mlo_mlme_bridge_peer_create(struct wlan_objmgr_vdev *vdev, 229 struct wlan_mlo_peer_context *ml_peer, 230 struct qdf_mac_addr *addr, 231 qdf_nbuf_t frm_buf) 232 { 233 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 234 235 if (!mlo_ctx || !mlo_ctx->mlme_ops || 236 !mlo_ctx->mlme_ops->mlo_mlme_ext_bridge_peer_create) 237 return; 238 239 mlo_ctx->mlme_ops->mlo_mlme_ext_bridge_peer_create(vdev, ml_peer, 240 addr, frm_buf); 241 } 242 mlo_mlme_peer_assoc(struct wlan_objmgr_peer * peer)243 void mlo_mlme_peer_assoc(struct wlan_objmgr_peer *peer) 244 { 245 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 246 247 if (!mlo_ctx || !mlo_ctx->mlme_ops || 248 !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_assoc) 249 return; 250 251 mlo_ctx->mlme_ops->mlo_mlme_ext_peer_assoc(peer); 252 } 253 mlo_mlme_peer_assoc_fail(struct wlan_objmgr_peer * peer)254 void mlo_mlme_peer_assoc_fail(struct wlan_objmgr_peer *peer) 255 { 256 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 257 258 if (!mlo_ctx || !mlo_ctx->mlme_ops || 259 !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_assoc_fail) 260 return; 261 262 mlo_ctx->mlme_ops->mlo_mlme_ext_peer_assoc_fail(peer); 263 } 264 mlo_mlme_peer_delete(struct wlan_objmgr_peer * peer)265 void mlo_mlme_peer_delete(struct wlan_objmgr_peer *peer) 266 { 267 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 268 269 if (!mlo_ctx || !mlo_ctx->mlme_ops || 270 !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_delete) 271 return; 272 273 mlo_ctx->mlme_ops->mlo_mlme_ext_peer_delete(peer); 274 } 275 mlo_mlme_peer_assoc_resp(struct wlan_objmgr_peer * peer)276 void mlo_mlme_peer_assoc_resp(struct wlan_objmgr_peer *peer) 277 { 278 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 279 280 if (!mlo_ctx || !mlo_ctx->mlme_ops || 281 !mlo_ctx->mlme_ops->mlo_mlme_ext_assoc_resp) 282 return; 283 284 mlo_ctx->mlme_ops->mlo_mlme_ext_assoc_resp(peer); 285 } 286 mlo_mlme_get_link_assoc_req(struct wlan_objmgr_peer * peer,uint8_t link_ix)287 qdf_nbuf_t mlo_mlme_get_link_assoc_req(struct wlan_objmgr_peer *peer, 288 uint8_t link_ix) 289 { 290 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 291 292 if (!mlo_ctx || !mlo_ctx->mlme_ops || 293 !mlo_ctx->mlme_ops->mlo_mlme_get_link_assoc_req) 294 return NULL; 295 296 return mlo_ctx->mlme_ops->mlo_mlme_get_link_assoc_req(peer, link_ix); 297 } 298 mlo_mlme_peer_deauth(struct wlan_objmgr_peer * peer,uint8_t is_disassoc)299 void mlo_mlme_peer_deauth(struct wlan_objmgr_peer *peer, uint8_t is_disassoc) 300 { 301 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 302 303 if (!mlo_ctx || !mlo_ctx->mlme_ops || 304 !mlo_ctx->mlme_ops->mlo_mlme_ext_deauth) 305 return; 306 307 mlo_ctx->mlme_ops->mlo_mlme_ext_deauth(peer, is_disassoc); 308 } 309 310 #ifdef UMAC_MLO_AUTH_DEFER mlo_mlme_peer_process_auth(struct mlpeer_auth_params * auth_param)311 void mlo_mlme_peer_process_auth(struct mlpeer_auth_params *auth_param) 312 { 313 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 314 315 if (!mlo_ctx || !mlo_ctx->mlme_ops || 316 !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_process_auth) 317 return; 318 319 mlo_ctx->mlme_ops->mlo_mlme_ext_peer_process_auth(auth_param); 320 } 321 #endif 322 mlo_mlme_peer_reassoc(struct wlan_objmgr_vdev * vdev,struct wlan_mlo_peer_context * ml_peer,struct qdf_mac_addr * addr,qdf_nbuf_t frm_buf)323 void mlo_mlme_peer_reassoc(struct wlan_objmgr_vdev *vdev, 324 struct wlan_mlo_peer_context *ml_peer, 325 struct qdf_mac_addr *addr, 326 qdf_nbuf_t frm_buf) 327 { 328 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 329 330 if (!mlo_ctx || !mlo_ctx->mlme_ops || 331 !mlo_ctx->mlme_ops->mlo_mlme_ext_peer_reassoc) 332 return; 333 334 mlo_ctx->mlme_ops->mlo_mlme_ext_peer_reassoc(vdev, ml_peer, addr, 335 frm_buf); 336 } 337 mlo_get_link_vdev_ix(struct wlan_mlo_dev_context * ml_dev,struct wlan_objmgr_vdev * vdev)338 uint8_t mlo_get_link_vdev_ix(struct wlan_mlo_dev_context *ml_dev, 339 struct wlan_objmgr_vdev *vdev) 340 { 341 uint8_t i; 342 343 mlo_dev_lock_acquire(ml_dev); 344 for (i = 0; i < WLAN_UMAC_MLO_MAX_VDEVS; i++) { 345 if (vdev == ml_dev->wlan_vdev_list[i]) { 346 mlo_dev_lock_release(ml_dev); 347 return i; 348 } 349 } 350 mlo_dev_lock_release(ml_dev); 351 352 return (uint8_t)-1; 353 } 354 355 #ifdef WLAN_MLO_MULTI_CHIP wlan_mlo_get_max_num_links(uint8_t grp_id)356 int8_t wlan_mlo_get_max_num_links(uint8_t grp_id) 357 { 358 struct mlo_mgr_context *mlo_ctx; 359 360 mlo_ctx = wlan_objmgr_get_mlo_ctx(); 361 if (!mlo_ctx) 362 return WLAN_MLO_INVALID_NUM_LINKS; 363 364 if (grp_id >= mlo_ctx->total_grp) { 365 mlo_err("Invalid grp id %d, total no of groups %d", 366 grp_id, mlo_ctx->total_grp); 367 return WLAN_MLO_INVALID_NUM_LINKS; 368 } 369 370 return (mlo_ctx->setup_info[grp_id].tot_socs * 371 WLAN_MAX_MLO_LINKS_PER_SOC); 372 } 373 wlan_mlo_get_num_active_links(uint8_t grp_id)374 int8_t wlan_mlo_get_num_active_links(uint8_t grp_id) 375 { 376 struct mlo_mgr_context *mlo_ctx; 377 378 mlo_ctx = wlan_objmgr_get_mlo_ctx(); 379 380 if (!mlo_ctx) 381 return WLAN_MLO_INVALID_NUM_LINKS; 382 383 if (grp_id >= mlo_ctx->total_grp) { 384 qdf_err("Invalid grp id %d, total no of groups %d", 385 grp_id, mlo_ctx->total_grp); 386 return WLAN_MLO_INVALID_NUM_LINKS; 387 } 388 389 return mlo_ctx->setup_info[grp_id].tot_links; 390 } 391 wlan_mlo_get_valid_link_bitmap(uint8_t grp_id)392 uint16_t wlan_mlo_get_valid_link_bitmap(uint8_t grp_id) 393 { 394 struct mlo_mgr_context *mlo_ctx; 395 396 mlo_ctx = wlan_objmgr_get_mlo_ctx(); 397 if (!mlo_ctx) 398 return 0; 399 400 if (grp_id >= mlo_ctx->total_grp) { 401 qdf_err("Invalid grp id %d, total no of groups %d", 402 grp_id, mlo_ctx->total_grp); 403 return 0; 404 } 405 406 return mlo_ctx->setup_info[grp_id].valid_link_bitmap; 407 } 408 wlan_mlo_get_psoc_mlo_chip_id(struct wlan_objmgr_psoc * psoc)409 uint8_t wlan_mlo_get_psoc_mlo_chip_id(struct wlan_objmgr_psoc *psoc) 410 { 411 struct wlan_lmac_if_tx_ops *tx_ops; 412 uint8_t mlo_chip_id = WLAN_MLO_CHIP_ID_INVALID; 413 414 if (!psoc) { 415 qdf_err("PSOC is NULL"); 416 return mlo_chip_id; 417 } 418 419 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 420 if (tx_ops && tx_ops->mops.get_psoc_mlo_chip_id) 421 mlo_chip_id = tx_ops->mops.get_psoc_mlo_chip_id(psoc); 422 423 return mlo_chip_id; 424 } 425 426 qdf_export_symbol(wlan_mlo_get_psoc_mlo_chip_id); 427 wlan_mlo_get_psoc_group_id(struct wlan_objmgr_psoc * psoc)428 uint8_t wlan_mlo_get_psoc_group_id(struct wlan_objmgr_psoc *psoc) 429 { 430 struct wlan_lmac_if_tx_ops *tx_ops; 431 uint8_t ml_grp_id = WLAN_MLO_GROUP_INVALID; 432 433 if (!psoc) { 434 qdf_err("PSOC is NULL"); 435 return -EINVAL; 436 } 437 438 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 439 if (tx_ops && tx_ops->mops.get_psoc_mlo_group_id) 440 ml_grp_id = tx_ops->mops.get_psoc_mlo_group_id(psoc); 441 442 return ml_grp_id; 443 } 444 445 qdf_export_symbol(wlan_mlo_get_psoc_group_id); 446 wlan_mlo_get_psoc_capable(struct wlan_objmgr_psoc * psoc)447 bool wlan_mlo_get_psoc_capable(struct wlan_objmgr_psoc *psoc) 448 { 449 struct target_psoc_info *tgt_hdl; 450 451 if (!psoc) { 452 qdf_err("PSOC is NULL"); 453 return false; 454 } 455 456 tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc); 457 if (!tgt_hdl) { 458 target_if_err("target_psoc_info is null"); 459 return false; 460 } 461 462 if ((tgt_hdl->tif_ops) && 463 (tgt_hdl->tif_ops->mlo_capable)) 464 return tgt_hdl->tif_ops->mlo_capable(psoc); 465 466 return false; 467 } 468 wlan_mlo_get_pdev_hw_link_id(struct wlan_objmgr_pdev * pdev)469 uint16_t wlan_mlo_get_pdev_hw_link_id(struct wlan_objmgr_pdev *pdev) 470 { 471 struct wlan_objmgr_psoc *psoc; 472 struct wlan_lmac_if_tx_ops *tx_ops; 473 uint16_t hw_link_id = INVALID_HW_LINK_ID; 474 475 psoc = wlan_pdev_get_psoc(pdev); 476 if (psoc) { 477 tx_ops = wlan_psoc_get_lmac_if_txops(psoc); 478 if (tx_ops && tx_ops->mops.get_hw_link_id) 479 hw_link_id = tx_ops->mops.get_hw_link_id(pdev); 480 } 481 482 return hw_link_id; 483 } 484 485 qdf_export_symbol(wlan_mlo_get_pdev_hw_link_id); 486 wlan_pdev_hw_link_iterator(struct wlan_objmgr_psoc * psoc,void * obj,void * arg)487 static void wlan_pdev_hw_link_iterator(struct wlan_objmgr_psoc *psoc, 488 void *obj, void *arg) 489 { 490 struct hw_link_id_iterator *itr = (struct hw_link_id_iterator *)arg; 491 struct wlan_objmgr_pdev *pdev = (struct wlan_objmgr_pdev *)obj; 492 uint16_t hw_link_id; 493 uint8_t ml_grp_id; 494 495 if (itr->pdev) 496 return; 497 498 ml_grp_id = wlan_mlo_get_psoc_group_id(psoc); 499 if (ml_grp_id > WLAN_MAX_MLO_GROUPS) 500 return; 501 502 if (ml_grp_id != itr->mlo_grp_id) 503 return; 504 505 hw_link_id = wlan_mlo_get_pdev_hw_link_id(pdev); 506 if (hw_link_id == itr->hw_link_id) { 507 if (wlan_objmgr_pdev_try_get_ref(pdev, itr->dbgid) == 508 QDF_STATUS_SUCCESS) 509 itr->pdev = pdev; 510 } 511 } 512 wlan_mlo_find_hw_link_id(struct wlan_objmgr_psoc * psoc,void * arg,uint8_t index)513 static void wlan_mlo_find_hw_link_id(struct wlan_objmgr_psoc *psoc, 514 void *arg, 515 uint8_t index) 516 { 517 struct hw_link_id_iterator *itr = (struct hw_link_id_iterator *)arg; 518 519 wlan_objmgr_iterate_obj_list(psoc, WLAN_PDEV_OP, 520 wlan_pdev_hw_link_iterator, 521 arg, false, itr->dbgid); 522 } 523 524 struct wlan_objmgr_pdev * wlan_mlo_get_pdev_by_hw_link_id(uint16_t hw_link_id,uint8_t ml_grp_id,wlan_objmgr_ref_dbgid refdbgid)525 wlan_mlo_get_pdev_by_hw_link_id(uint16_t hw_link_id, uint8_t ml_grp_id, 526 wlan_objmgr_ref_dbgid refdbgid) 527 { 528 struct hw_link_id_iterator itr; 529 530 itr.hw_link_id = hw_link_id; 531 itr.pdev = NULL; 532 itr.mlo_grp_id = ml_grp_id; 533 itr.dbgid = refdbgid; 534 535 wlan_objmgr_iterate_psoc_list(wlan_mlo_find_hw_link_id, 536 &itr, refdbgid); 537 538 return itr.pdev; 539 } 540 541 qdf_export_symbol(wlan_mlo_get_pdev_by_hw_link_id); 542 #endif /*WLAN_MLO_MULTI_CHIP*/ 543 mlo_get_ml_vdev_list(struct wlan_objmgr_vdev * vdev,uint16_t * vdev_count,struct wlan_objmgr_vdev ** wlan_vdev_list)544 void mlo_get_ml_vdev_list(struct wlan_objmgr_vdev *vdev, 545 uint16_t *vdev_count, 546 struct wlan_objmgr_vdev **wlan_vdev_list) 547 { 548 struct wlan_mlo_dev_context *dev_ctx; 549 int i; 550 QDF_STATUS status; 551 552 *vdev_count = 0; 553 554 if (!vdev || !vdev->mlo_dev_ctx) { 555 mlo_err("Invalid input"); 556 return; 557 } 558 559 dev_ctx = vdev->mlo_dev_ctx; 560 561 mlo_dev_lock_acquire(dev_ctx); 562 *vdev_count = 0; 563 for (i = 0; i < QDF_ARRAY_SIZE(dev_ctx->wlan_vdev_list); i++) { 564 if (dev_ctx->wlan_vdev_list[i] && 565 wlan_vdev_mlme_is_mlo_vdev(dev_ctx->wlan_vdev_list[i])) { 566 status = wlan_objmgr_vdev_try_get_ref( 567 dev_ctx->wlan_vdev_list[i], 568 WLAN_MLO_MGR_ID); 569 if (QDF_IS_STATUS_ERROR(status)) 570 break; 571 wlan_vdev_list[*vdev_count] = 572 dev_ctx->wlan_vdev_list[i]; 573 (*vdev_count) += 1; 574 } 575 } 576 mlo_dev_lock_release(dev_ctx); 577 } 578 579 /** 580 * mlo_link_set_active() - send MLO link set active command 581 * @psoc: PSOC object 582 * @req: MLO link set active request 583 * 584 * Return: QDF_STATUS 585 */ 586 static QDF_STATUS mlo_link_set_active(struct wlan_objmgr_psoc * psoc,struct mlo_link_set_active_req * req)587 mlo_link_set_active(struct wlan_objmgr_psoc *psoc, 588 struct mlo_link_set_active_req *req) 589 { 590 struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops; 591 struct mlo_link_set_active_param *param = &req->param; 592 QDF_STATUS status; 593 struct mlo_link_set_active_resp rsp_evt; 594 595 if (!psoc) { 596 mlo_err("psoc is null"); 597 return QDF_STATUS_E_NULL_VALUE; 598 } 599 600 mlo_tx_ops = target_if_mlo_get_tx_ops(psoc); 601 if (!mlo_tx_ops) { 602 mlo_err("tx_ops is null!"); 603 return QDF_STATUS_E_NULL_VALUE; 604 } 605 606 if (!mlo_tx_ops->link_set_active) { 607 mlo_err("link_set_active function is null!"); 608 return QDF_STATUS_E_NULL_VALUE; 609 } 610 611 if (req->ctx.validate_set_mlo_link_cb) { 612 status = req->ctx.validate_set_mlo_link_cb(psoc, param); 613 if (QDF_IS_STATUS_ERROR(status)) { 614 qdf_mem_zero(&rsp_evt, sizeof(rsp_evt)); 615 rsp_evt.status = status; 616 if (req->ctx.set_mlo_link_cb) 617 req->ctx.set_mlo_link_cb(req->ctx.vdev, 618 req->ctx.cb_arg, 619 &rsp_evt); 620 return status; 621 } 622 } 623 624 return mlo_tx_ops->link_set_active(psoc, param); 625 } 626 627 /** 628 * mlo_release_ser_link_set_active_cmd() - releases serialization command for 629 * forcing MLO link active/inactive 630 * @vdev: Object manager vdev 631 * 632 * Return: None 633 */ 634 static void mlo_release_ser_link_set_active_cmd(struct wlan_objmgr_vdev * vdev)635 mlo_release_ser_link_set_active_cmd(struct wlan_objmgr_vdev *vdev) 636 { 637 struct wlan_serialization_queued_cmd_info cmd = {0}; 638 639 cmd.cmd_type = WLAN_SER_CMD_SET_MLO_LINK; 640 cmd.requestor = WLAN_UMAC_COMP_MLO_MGR; 641 cmd.cmd_id = 0; 642 cmd.vdev = vdev; 643 644 mlo_debug("release serialization command"); 645 wlan_serialization_remove_cmd(&cmd); 646 } 647 648 /** 649 * mlo_link_set_active_resp_vdev_handler() - vdev handler for mlo link set 650 * active response event. 651 * @psoc: psoc object 652 * @obj: vdev object 653 * @arg: mlo link set active response 654 * 655 * Return: None 656 */ 657 static void mlo_link_set_active_resp_vdev_handler(struct wlan_objmgr_psoc * psoc,void * obj,void * arg)658 mlo_link_set_active_resp_vdev_handler(struct wlan_objmgr_psoc *psoc, 659 void *obj, void *arg) 660 { 661 struct mlo_link_set_active_req *req; 662 struct wlan_objmgr_vdev *vdev = obj; 663 struct mlo_link_set_active_resp *event = arg; 664 665 if (event->evt_handled) 666 return; 667 req = wlan_serialization_get_active_cmd(wlan_vdev_get_psoc(vdev), 668 wlan_vdev_get_id(vdev), 669 WLAN_SER_CMD_SET_MLO_LINK); 670 if (!req) 671 return; 672 673 if (req->ctx.set_mlo_link_cb) 674 req->ctx.set_mlo_link_cb(vdev, req->ctx.cb_arg, event); 675 676 mlo_release_ser_link_set_active_cmd(vdev); 677 event->evt_handled = true; 678 } 679 680 QDF_STATUS mlo_process_link_set_active_resp(struct wlan_objmgr_psoc * psoc,struct mlo_link_set_active_resp * event)681 mlo_process_link_set_active_resp(struct wlan_objmgr_psoc *psoc, 682 struct mlo_link_set_active_resp *event) 683 { 684 wlan_objmgr_iterate_obj_list(psoc, WLAN_VDEV_OP, 685 mlo_link_set_active_resp_vdev_handler, 686 event, true, WLAN_MLO_MGR_ID); 687 if (!event->evt_handled) 688 mlo_debug("link set resp evt not handled"); 689 690 return QDF_STATUS_SUCCESS; 691 } 692 693 /** 694 * mlo_ser_set_link_cb() - Serialization callback function 695 * @cmd: Serialization command info 696 * @reason: Serialization reason for callback execution 697 * 698 * Return: Status of callback execution 699 */ 700 static QDF_STATUS mlo_ser_set_link_cb(struct wlan_serialization_command * cmd,enum wlan_serialization_cb_reason reason)701 mlo_ser_set_link_cb(struct wlan_serialization_command *cmd, 702 enum wlan_serialization_cb_reason reason) 703 { 704 QDF_STATUS status = QDF_STATUS_SUCCESS; 705 struct wlan_objmgr_vdev *vdev; 706 struct wlan_objmgr_psoc *psoc; 707 struct mlo_link_set_active_req *req; 708 struct mlo_mgr_context *mlo_ctx; 709 710 if (!cmd || !cmd->vdev) 711 return QDF_STATUS_E_FAILURE; 712 713 mlo_ctx = wlan_objmgr_get_mlo_ctx(); 714 if (!mlo_ctx) 715 return QDF_STATUS_E_FAILURE; 716 717 psoc = wlan_vdev_get_psoc(cmd->vdev); 718 if (!psoc) { 719 mlo_err("psoc is NULL, reason: %d", reason); 720 return QDF_STATUS_E_NULL_VALUE; 721 } 722 723 req = cmd->umac_cmd; 724 if (!req) 725 return QDF_STATUS_E_INVAL; 726 727 vdev = cmd->vdev; 728 switch (reason) { 729 case WLAN_SER_CB_ACTIVATE_CMD: 730 status = mlo_link_set_active(psoc, req); 731 break; 732 case WLAN_SER_CB_CANCEL_CMD: 733 case WLAN_SER_CB_ACTIVE_CMD_TIMEOUT: 734 mlo_err("vdev %d command not execute: %d", 735 wlan_vdev_get_id(vdev), reason); 736 if (req->ctx.set_mlo_link_cb) 737 req->ctx.set_mlo_link_cb(vdev, req->ctx.cb_arg, NULL); 738 break; 739 case WLAN_SER_CB_RELEASE_MEM_CMD: 740 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID); 741 qdf_mem_free(req); 742 break; 743 default: 744 QDF_ASSERT(0); 745 status = QDF_STATUS_E_INVAL; 746 break; 747 } 748 749 return status; 750 } 751 752 #define MLO_SER_CMD_TIMEOUT_MS 5000 mlo_ser_set_link_req(struct mlo_link_set_active_req * req)753 QDF_STATUS mlo_ser_set_link_req(struct mlo_link_set_active_req *req) 754 { 755 struct wlan_serialization_command cmd = {0, }; 756 enum wlan_serialization_status ser_cmd_status; 757 QDF_STATUS status; 758 struct wlan_objmgr_vdev *vdev; 759 760 if (!req) 761 return QDF_STATUS_E_INVAL; 762 763 vdev = req->ctx.vdev; 764 status = wlan_objmgr_vdev_try_get_ref(vdev, WLAN_MLO_MGR_ID); 765 if (QDF_IS_STATUS_ERROR(status)) { 766 mlo_err("vdev %d unable to get reference", 767 wlan_vdev_get_id(vdev)); 768 return status; 769 } 770 771 cmd.cmd_type = WLAN_SER_CMD_SET_MLO_LINK; 772 cmd.cmd_id = 0; 773 cmd.cmd_cb = mlo_ser_set_link_cb; 774 cmd.source = WLAN_UMAC_COMP_MLO_MGR; 775 cmd.is_high_priority = false; 776 cmd.cmd_timeout_duration = MLO_SER_CMD_TIMEOUT_MS; 777 cmd.vdev = vdev; 778 cmd.is_blocking = true; 779 cmd.umac_cmd = (void *)req; 780 781 ser_cmd_status = wlan_serialization_request(&cmd); 782 switch (ser_cmd_status) { 783 case WLAN_SER_CMD_PENDING: 784 /* command moved to pending list.Do nothing */ 785 break; 786 case WLAN_SER_CMD_ACTIVE: 787 /* command moved to active list. Do nothing */ 788 break; 789 default: 790 mlo_err("vdev %d ser cmd status %d", 791 wlan_vdev_get_id(vdev), ser_cmd_status); 792 status = QDF_STATUS_E_FAILURE; 793 } 794 795 if (QDF_IS_STATUS_SUCCESS(status)) 796 return status; 797 798 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLO_MGR_ID); 799 800 return status; 801 } 802 mlo_mlme_handle_sta_csa_param(struct wlan_objmgr_vdev * vdev,struct csa_offload_params * csa_param)803 void mlo_mlme_handle_sta_csa_param(struct wlan_objmgr_vdev *vdev, 804 struct csa_offload_params *csa_param) 805 { 806 struct mlo_mgr_context *mlo_ctx = wlan_objmgr_get_mlo_ctx(); 807 808 if (!mlo_ctx || !mlo_ctx->mlme_ops || 809 !mlo_ctx->mlme_ops->mlo_mlme_ext_handle_sta_csa_param) 810 return; 811 812 mlo_ctx->mlme_ops->mlo_mlme_ext_handle_sta_csa_param(vdev, csa_param); 813 } 814 815 QDF_STATUS mlo_get_mlstats_vdev_params(struct wlan_objmgr_psoc * psoc,struct mlo_stats_vdev_params * info,uint8_t vdev_id)816 mlo_get_mlstats_vdev_params(struct wlan_objmgr_psoc *psoc, 817 struct mlo_stats_vdev_params *info, 818 uint8_t vdev_id) 819 { 820 struct wlan_objmgr_vdev *ml_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS] = {0}; 821 struct wlan_objmgr_vdev *vdev; 822 int i; 823 uint16_t ml_vdev_cnt = 0; 824 825 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 826 WLAN_MLO_MGR_ID); 827 if (!vdev) { 828 mlo_err("vdev object is NULL for vdev %d", vdev_id); 829 return QDF_STATUS_E_INVAL; 830 } 831 832 mlo_get_ml_vdev_list(vdev, &ml_vdev_cnt, ml_vdev_list); 833 for (i = 0; i < ml_vdev_cnt; i++) { 834 info->ml_vdev_id[i] = wlan_vdev_get_id(ml_vdev_list[i]); 835 mlo_release_vdev_ref(ml_vdev_list[i]); 836 } 837 info->ml_vdev_count = ml_vdev_cnt; 838 mlo_release_vdev_ref(vdev); 839 840 return QDF_STATUS_SUCCESS; 841 } 842 ml_extract_link_state(struct wlan_objmgr_psoc * psoc,struct ml_link_state_info_event * event)843 static void ml_extract_link_state(struct wlan_objmgr_psoc *psoc, 844 struct ml_link_state_info_event *event) 845 { 846 QDF_STATUS status; 847 get_ml_link_state_cb resp_cb = NULL; 848 void *context = NULL; 849 uint8_t vdev_id; 850 851 vdev_id = event->vdev_id; 852 853 status = mlo_get_link_state_context(psoc, 854 &resp_cb, &context, vdev_id); 855 856 if (QDF_IS_STATUS_ERROR(status)) 857 return; 858 859 if (resp_cb) 860 resp_cb(event, context); 861 } 862 863 QDF_STATUS wlan_handle_ml_link_state_info_event(struct wlan_objmgr_psoc * psoc,struct ml_link_state_info_event * event)864 wlan_handle_ml_link_state_info_event(struct wlan_objmgr_psoc *psoc, 865 struct ml_link_state_info_event *event) 866 { 867 if (!event) 868 return QDF_STATUS_E_NULL_VALUE; 869 870 ml_extract_link_state(psoc, event); 871 872 return QDF_STATUS_SUCCESS; 873 } 874 ml_get_link_state_req_cb(struct scheduler_msg * msg)875 static QDF_STATUS ml_get_link_state_req_cb(struct scheduler_msg *msg) 876 { 877 struct wlan_objmgr_vdev *vdev = msg->bodyptr; 878 struct wlan_mlo_dev_context *mlo_dev_ctx = NULL; 879 struct mlo_link_state_cmd_params cmd = {0}; 880 struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops; 881 struct wlan_objmgr_psoc *psoc; 882 int status = 0; 883 884 if (!vdev) { 885 mlo_err("null input vdev"); 886 return QDF_STATUS_E_INVAL; 887 } 888 889 psoc = wlan_vdev_get_psoc(vdev); 890 891 if (!psoc) { 892 mlo_err("null psoc"); 893 return QDF_STATUS_E_NULL_VALUE; 894 } 895 896 mlo_tx_ops = &psoc->soc_cb.tx_ops->mlo_ops; 897 898 if (!mlo_tx_ops) { 899 mlo_err("tx_ops is null!"); 900 return QDF_STATUS_E_NULL_VALUE; 901 } 902 903 if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) { 904 mlo_err("vdev is not MLO vdev"); 905 return status; 906 } 907 908 mlo_dev_ctx = vdev->mlo_dev_ctx; 909 cmd.vdev_id = vdev->vdev_objmgr.vdev_id; 910 qdf_mem_copy(&cmd.mld_mac[0], &mlo_dev_ctx->mld_addr, 911 QDF_MAC_ADDR_SIZE); 912 913 if (!mlo_tx_ops->request_link_state_info_cmd) { 914 mlo_err("handler is not registered"); 915 return QDF_STATUS_E_NULL_VALUE; 916 } 917 918 status = mlo_tx_ops->request_link_state_info_cmd(psoc, &cmd); 919 920 if (QDF_IS_STATUS_ERROR(status)) 921 mlo_err("failed to send ml link info command to FW"); 922 923 return QDF_STATUS_SUCCESS; 924 } 925 926 QDF_STATUS mlo_get_link_state_register_resp_cb(struct wlan_objmgr_vdev * vdev,struct ml_link_state_cmd_info * req)927 mlo_get_link_state_register_resp_cb(struct wlan_objmgr_vdev *vdev, 928 struct ml_link_state_cmd_info *req) 929 { 930 struct wlan_mlo_dev_context *mlo_ctx; 931 struct wlan_mlo_sta *sta_ctx = NULL; 932 933 if (!vdev || !wlan_vdev_mlme_is_mlo_vdev(vdev)) 934 return QDF_STATUS_E_NULL_VALUE; 935 mlo_ctx = vdev->mlo_dev_ctx; 936 937 if (!mlo_ctx) { 938 mlo_err("null mlo_dev_ctx"); 939 return QDF_STATUS_E_NULL_VALUE; 940 } 941 942 sta_ctx = mlo_ctx->sta_ctx; 943 944 if (!sta_ctx) 945 return QDF_STATUS_E_INVAL; 946 947 mlo_dev_lock_acquire(mlo_ctx); 948 949 sta_ctx->ml_link_state.ml_link_state_resp_cb = 950 req->ml_link_state_resp_cb; 951 sta_ctx->ml_link_state.ml_link_state_req_context = 952 req->request_cookie; 953 mlo_dev_lock_release(mlo_ctx); 954 955 return QDF_STATUS_SUCCESS; 956 } 957 ml_get_link_state_req_flush_cb(struct scheduler_msg * msg)958 static QDF_STATUS ml_get_link_state_req_flush_cb(struct scheduler_msg *msg) 959 { 960 mlo_debug("ml_get_link_state_req flush callback"); 961 return QDF_STATUS_SUCCESS; 962 } 963 ml_post_get_link_state_msg(struct wlan_objmgr_vdev * vdev)964 QDF_STATUS ml_post_get_link_state_msg(struct wlan_objmgr_vdev *vdev) 965 { 966 struct scheduler_msg msg = {0}; 967 QDF_STATUS qdf_status = 0; 968 969 msg.bodyptr = vdev; 970 msg.callback = ml_get_link_state_req_cb; 971 msg.flush_callback = ml_get_link_state_req_flush_cb; 972 973 qdf_status = scheduler_post_message( 974 QDF_MODULE_ID_OS_IF, 975 QDF_MODULE_ID_MLME, 976 QDF_MODULE_ID_OS_IF, 977 &msg); 978 return qdf_status; 979 } 980 981 bool wlan_mlo_is_csa_allow(struct wlan_objmgr_vdev * vdev,uint16_t csa_freq)982 wlan_mlo_is_csa_allow(struct wlan_objmgr_vdev *vdev, uint16_t csa_freq) 983 { 984 struct wlan_channel *chan; 985 struct wlan_objmgr_vdev *ml_vdev_list[WLAN_UMAC_MLO_MAX_VDEVS] = {0}; 986 uint16_t ml_vdev_cnt = 0; 987 struct wlan_objmgr_vdev *t_vdev; 988 int i; 989 bool is_allow = true; 990 991 if (!vdev) { 992 mlo_err("vdev is NULL"); 993 return false; 994 } 995 996 if (!wlan_vdev_mlme_is_mlo_vdev(vdev)) 997 return true; 998 999 mlo_get_ml_vdev_list(vdev, &ml_vdev_cnt, ml_vdev_list); 1000 for (i = 0; i < ml_vdev_cnt; i++) { 1001 t_vdev = ml_vdev_list[i]; 1002 if (t_vdev == vdev) 1003 goto next; 1004 chan = wlan_vdev_get_active_channel(t_vdev); 1005 if (!chan) 1006 goto next; 1007 1008 if (csa_freq == chan->ch_freq) { 1009 mlo_err("vdev %d will SCC with vdev %d on freq %d", 1010 wlan_vdev_get_id(vdev), 1011 wlan_vdev_get_id(t_vdev), csa_freq); 1012 is_allow = false; 1013 } 1014 next: 1015 mlo_release_vdev_ref(t_vdev); 1016 } 1017 1018 return is_allow; 1019 } 1020 1021