1 /* 2 * Copyright (c) 2021-2023 Qualcomm Innovation Center, Inc. All rights reserved. 3 * 4 * Permission to use, copy, modify, and/or distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 /** 18 * DOC: target_if_mlo_mgr.c 19 * 20 * This file provide definition for APIs registered through lmac Tx Ops 21 */ 22 23 #include <wmi_unified_11be_api.h> 24 #include <init_deinit_lmac.h> 25 #include "target_if_mlo_mgr.h" 26 #include <wlan_objmgr_peer_obj.h> 27 #include <wlan_mlo_t2lm.h> 28 29 /** 30 * target_if_mlo_link_set_active_resp_handler() - function to handle mlo link 31 * set active response from firmware. 32 * @scn: scn handle 33 * @data: data buffer for event 34 * @datalen: data length 35 * 36 * Return: 0 on success, else error on failure 37 */ 38 static int 39 target_if_mlo_link_set_active_resp_handler(ol_scn_t scn, uint8_t *data, 40 uint32_t datalen) 41 { 42 QDF_STATUS status; 43 struct wlan_objmgr_psoc *psoc; 44 struct wmi_unified *wmi_handle; 45 struct wlan_lmac_if_mlo_rx_ops *rx_ops; 46 struct mlo_link_set_active_resp resp; 47 48 if (!scn || !data) { 49 target_if_err("scn: 0x%pK, data: 0x%pK", scn, data); 50 return -EINVAL; 51 } 52 53 psoc = target_if_get_psoc_from_scn_hdl(scn); 54 if (!psoc) { 55 target_if_err("null psoc"); 56 return -EINVAL; 57 } 58 59 rx_ops = target_if_mlo_get_rx_ops(psoc); 60 if (!rx_ops || !rx_ops->process_link_set_active_resp) { 61 target_if_err("callback not registered"); 62 return -EINVAL; 63 } 64 65 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 66 if (!wmi_handle) { 67 target_if_err("wmi_handle is null"); 68 return -EINVAL; 69 } 70 qdf_mem_zero(&resp, sizeof(resp)); 71 if (wmi_extract_mlo_link_set_active_resp(wmi_handle, data, &resp) != 72 QDF_STATUS_SUCCESS) { 73 target_if_err("Unable to extract mlo link set active resp"); 74 return -EINVAL; 75 } 76 77 status = rx_ops->process_link_set_active_resp(psoc, &resp); 78 79 return qdf_status_to_os_return(status); 80 } 81 82 /** 83 * target_if_mlo_link_removal_event_handler() - Handler for MLO link removal 84 * event sent by the FW 85 * @scn: scn handle 86 * @data: data buffer for event 87 * @datalen: data length 88 * 89 * Return: 0 on success, else error on failure 90 */ 91 static int 92 target_if_mlo_link_removal_event_handler(ol_scn_t scn, uint8_t *data, 93 uint32_t datalen) 94 { 95 struct wlan_objmgr_psoc *psoc; 96 struct wmi_unified *wmi_handle; 97 struct wlan_lmac_if_mlo_rx_ops *mlo_rx_ops; 98 QDF_STATUS status; 99 struct mlo_link_removal_evt_params evt_params; 100 101 if (!scn || !data) { 102 target_if_err("scn: 0x%pK, data: 0x%pK", scn, data); 103 return -EINVAL; 104 } 105 106 psoc = target_if_get_psoc_from_scn_hdl(scn); 107 if (!psoc) { 108 target_if_err("null psoc"); 109 return -EINVAL; 110 } 111 112 mlo_rx_ops = target_if_mlo_get_rx_ops(psoc); 113 if (!mlo_rx_ops || !mlo_rx_ops->mlo_link_removal_handler) { 114 target_if_err("callback not registered"); 115 return -EINVAL; 116 } 117 118 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 119 if (!wmi_handle) { 120 target_if_err("wmi_handle is null"); 121 return -EINVAL; 122 } 123 124 status = wmi_extract_mlo_link_removal_evt_fixed_param(wmi_handle, data, 125 &evt_params); 126 if (QDF_IS_STATUS_ERROR(status)) { 127 target_if_err("Unable to extract fixed param, ret = %d", 128 status); 129 goto exit; 130 } 131 132 status = wmi_extract_mlo_link_removal_tbtt_update( 133 wmi_handle, data, &evt_params.tbtt_info); 134 if (QDF_IS_STATUS_ERROR(status)) { 135 target_if_err("Unable to extract TBTT update TLV, ret = %d", 136 status); 137 goto exit; 138 } 139 140 status = mlo_rx_ops->mlo_link_removal_handler(psoc, &evt_params); 141 exit: 142 return qdf_status_to_os_return(status); 143 } 144 145 QDF_STATUS 146 target_if_extract_mlo_link_removal_info_mgmt_rx( 147 wmi_unified_t wmi_handle, 148 void *evt_buf, 149 struct mgmt_rx_event_params *rx_event) 150 { 151 QDF_STATUS status; 152 struct mgmt_rx_mlo_link_removal_info *link_removal_info; 153 154 if (!rx_event) { 155 target_if_err("Invalid rx_event"); 156 return QDF_STATUS_E_NULL_VALUE; 157 } 158 159 rx_event->link_removal_info = NULL; 160 if (!rx_event->num_link_removal_info) { 161 /** 162 * This is not an error. Only probe request frames will contain 163 * Link removal TLVs, that too only till the link removal TBTT 164 * countdown completion. 165 */ 166 target_if_debug("Link removal TLVs are not present"); 167 return QDF_STATUS_SUCCESS; 168 } 169 170 link_removal_info = qdf_mem_malloc(rx_event->num_link_removal_info * 171 sizeof(*link_removal_info)); 172 if (!link_removal_info) { 173 target_if_err("Couldn't allocate memory for link_removal_info"); 174 rx_event->num_link_removal_info = 0; 175 return QDF_STATUS_E_NOMEM; 176 } 177 178 status = wmi_extract_mgmt_rx_mlo_link_removal_info( 179 wmi_handle, evt_buf, 180 link_removal_info, 181 rx_event->num_link_removal_info); 182 if (QDF_IS_STATUS_ERROR(status)) { 183 target_if_err("Unable to extract link removal TLVs"); 184 rx_event->num_link_removal_info = 0; 185 qdf_mem_free(link_removal_info); 186 return status; 187 } 188 189 rx_event->link_removal_info = link_removal_info; 190 191 return QDF_STATUS_SUCCESS; 192 } 193 194 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE 195 static QDF_STATUS 196 target_if_send_mlo_link_switch_cnf_cmd(struct wlan_objmgr_psoc *psoc, 197 struct wlan_mlo_link_switch_cnf *params) 198 { 199 struct wmi_unified *wmi_handle = NULL; 200 201 if (!psoc) { 202 target_if_err("null pdev"); 203 return QDF_STATUS_E_NULL_VALUE; 204 } 205 206 if (!params) { 207 target_if_err("params is null"); 208 return QDF_STATUS_E_NULL_VALUE; 209 } 210 211 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 212 if (!wmi_handle) { 213 target_if_err("null wmi handle"); 214 return QDF_STATUS_E_NULL_VALUE; 215 } 216 217 return wmi_send_mlo_link_switch_req_cnf_cmd(wmi_handle, params); 218 } 219 220 static int 221 target_if_mlo_link_switch_request_event_handler(ol_scn_t scn, uint8_t *data, 222 uint32_t datalen) 223 { 224 struct wlan_objmgr_psoc *psoc; 225 struct wmi_unified *wmi_handle; 226 struct wlan_lmac_if_mlo_rx_ops *mlo_rx_ops; 227 QDF_STATUS status; 228 struct wlan_mlo_link_switch_req req = {0}; 229 230 if (!scn || !data) { 231 target_if_err("scn: 0x%pK, data: 0x%pK", scn, data); 232 return -EINVAL; 233 } 234 235 psoc = target_if_get_psoc_from_scn_hdl(scn); 236 if (!psoc) { 237 target_if_err("null psoc"); 238 return -EINVAL; 239 } 240 241 mlo_rx_ops = target_if_mlo_get_rx_ops(psoc); 242 if (!mlo_rx_ops || !mlo_rx_ops->mlo_link_switch_request_handler) { 243 target_if_err("callback not registered"); 244 return -EINVAL; 245 } 246 247 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 248 if (!wmi_handle) { 249 target_if_err("wmi_handle is null"); 250 return -EINVAL; 251 } 252 253 status = wmi_extract_mlo_link_switch_request_evt(wmi_handle, data, 254 &req); 255 256 if (QDF_IS_STATUS_ERROR(status)) { 257 target_if_err("Unable to extract fixed param, ret = %d", 258 status); 259 goto exit; 260 } 261 262 status = mlo_rx_ops->mlo_link_switch_request_handler(psoc, &req); 263 264 exit: 265 return status; 266 } 267 268 static inline void 269 target_if_mlo_register_link_switch_cnf_handler(struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops) 270 { 271 mlo_tx_ops->send_mlo_link_switch_cnf_cmd = 272 target_if_send_mlo_link_switch_cnf_cmd; 273 } 274 275 static QDF_STATUS 276 target_if_mlo_register_link_switch_event_handler(struct wmi_unified *wmi_handle) 277 { 278 QDF_STATUS status; 279 280 status = wmi_unified_register_event_handler( 281 wmi_handle, 282 wmi_mlo_link_switch_request_eventid, 283 target_if_mlo_link_switch_request_event_handler, 284 WMI_RX_SERIALIZER_CTX); 285 286 return status; 287 } 288 289 static inline void 290 target_if_mlo_unregister_link_switch_event_handler(struct wmi_unified *wmi_handle) 291 { 292 wmi_unified_unregister_event(wmi_handle, 293 wmi_mlo_link_switch_request_eventid); 294 } 295 #else 296 static inline QDF_STATUS 297 target_if_mlo_register_link_switch_event_handler(struct wmi_unified *wmi_handle) 298 { 299 return QDF_STATUS_E_NOSUPPORT; 300 } 301 302 static inline void 303 target_if_mlo_unregister_link_switch_event_handler(struct wmi_unified *wmi_handle) 304 { 305 } 306 307 static inline QDF_STATUS 308 target_if_send_mlo_link_switch_cnf_cmd(struct wlan_objmgr_psoc *psoc, 309 struct wlan_mlo_link_switch_cnf *params) 310 { 311 return QDF_STATUS_SUCCESS; 312 } 313 314 static inline void 315 target_if_mlo_register_link_switch_cnf_handler(struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops) 316 { 317 } 318 319 static inline int 320 target_if_mlo_link_switch_request_event_handler(ol_scn_t scn, uint8_t *data, 321 uint32_t datalen) 322 { 323 return 0; 324 } 325 #endif 326 327 /** 328 * target_if_mlo_link_disable_request_event_handler() - Handler for MLO 329 * link disable request event sent by the FW 330 * @scn: scn handle 331 * @data: data buffer for event 332 * @datalen: data length 333 * 334 * Return: 0 on success, else error on failure 335 */ 336 static int 337 target_if_mlo_link_disable_request_event_handler(ol_scn_t scn, uint8_t *data, 338 uint32_t datalen) 339 { 340 struct wlan_objmgr_psoc *psoc; 341 struct wmi_unified *wmi_handle; 342 struct wlan_lmac_if_mlo_rx_ops *mlo_rx_ops; 343 QDF_STATUS status; 344 struct mlo_link_disable_request_evt_params evt_params; 345 346 if (!scn || !data) { 347 target_if_err("scn: 0x%pK, data: 0x%pK", scn, data); 348 return -EINVAL; 349 } 350 351 psoc = target_if_get_psoc_from_scn_hdl(scn); 352 if (!psoc) { 353 target_if_err("null psoc"); 354 return -EINVAL; 355 } 356 357 mlo_rx_ops = target_if_mlo_get_rx_ops(psoc); 358 if (!mlo_rx_ops || !mlo_rx_ops->mlo_link_disable_request_handler) { 359 target_if_err("callback not registered"); 360 return -EINVAL; 361 } 362 363 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 364 if (!wmi_handle) { 365 target_if_err("wmi_handle is null"); 366 return -EINVAL; 367 } 368 369 status = wmi_extract_mlo_link_disable_request_evt(wmi_handle, data, 370 &evt_params); 371 if (QDF_IS_STATUS_ERROR(status)) { 372 target_if_err("Unable to extract fixed param, ret = %d", 373 status); 374 goto exit; 375 } 376 377 status = mlo_rx_ops->mlo_link_disable_request_handler(psoc, 378 &evt_params); 379 exit: 380 return qdf_status_to_os_return(status); 381 } 382 383 /** 384 * target_if_mlo_register_event_handler() - function to register handler for 385 * mlo related wmi event from firmware. 386 * @psoc: psoc pointer 387 * 388 * Return: QDF_STATUS 389 */ 390 static QDF_STATUS 391 target_if_mlo_register_event_handler(struct wlan_objmgr_psoc *psoc) 392 { 393 QDF_STATUS status; 394 struct wmi_unified *wmi_handle; 395 396 if (!psoc) { 397 target_if_err("PSOC is NULL!"); 398 return QDF_STATUS_E_NULL_VALUE; 399 } 400 401 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 402 if (!wmi_handle) { 403 target_if_err("wmi_handle is null"); 404 return QDF_STATUS_E_INVAL; 405 } 406 407 status = wmi_unified_register_event( 408 wmi_handle, 409 wmi_mlo_link_removal_eventid, 410 target_if_mlo_link_removal_event_handler); 411 if (QDF_IS_STATUS_ERROR(status)) 412 target_if_err("Couldn't register handler for Link removal WMI event %d", 413 status); 414 415 status = wmi_unified_register_event_handler( 416 wmi_handle, 417 wmi_mlo_link_set_active_resp_eventid, 418 target_if_mlo_link_set_active_resp_handler, 419 WMI_RX_SERIALIZER_CTX); 420 if (QDF_IS_STATUS_ERROR(status)) { 421 target_if_err("Register mlo link set active resp cb errcode %d", 422 status); 423 if (status == QDF_STATUS_E_NOSUPPORT) 424 status = QDF_STATUS_SUCCESS; 425 } 426 427 target_if_mlo_register_vdev_tid_to_link_map_event(wmi_handle); 428 target_if_mlo_register_mlo_link_state_info_event(wmi_handle); 429 430 status = wmi_unified_register_event_handler(wmi_handle, 431 wmi_mlo_link_disable_request_eventid, 432 target_if_mlo_link_disable_request_event_handler, 433 WMI_RX_SERIALIZER_CTX); 434 if (QDF_IS_STATUS_ERROR(status)) { 435 target_if_err("Couldn't register handler for link disable request WMI event %d", 436 status); 437 if (status == QDF_STATUS_E_NOSUPPORT) 438 status = QDF_STATUS_SUCCESS; 439 } 440 441 status = target_if_mlo_register_link_switch_event_handler(wmi_handle); 442 if (QDF_IS_STATUS_ERROR(status)) { 443 target_if_err("Couldn't register handler for link switch WMI event %d", 444 status); 445 if (status == QDF_STATUS_E_NOSUPPORT) 446 status = QDF_STATUS_SUCCESS; 447 } 448 449 return status; 450 } 451 452 /** 453 * target_if_mlo_unregister_event_handler() - function to unregister handler for 454 * mlo related wmi event from firmware. 455 * @psoc: psoc pointer 456 * 457 * Return: QDF_STATUS 458 */ 459 static QDF_STATUS 460 target_if_mlo_unregister_event_handler(struct wlan_objmgr_psoc *psoc) 461 { 462 struct wmi_unified *wmi_handle; 463 464 if (!psoc) { 465 target_if_err("PSOC is NULL!"); 466 return QDF_STATUS_E_INVAL; 467 } 468 469 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 470 if (!wmi_handle) { 471 target_if_err("wmi_handle is null"); 472 return QDF_STATUS_E_INVAL; 473 } 474 475 wmi_unified_unregister_event_handler(wmi_handle, 476 wmi_mlo_link_set_active_resp_eventid); 477 478 wmi_unified_unregister_event(wmi_handle, 479 wmi_mlo_link_removal_eventid); 480 481 target_if_mlo_unregister_vdev_tid_to_link_map_event(wmi_handle); 482 target_if_mlo_unregister_mlo_link_state_info_event(wmi_handle); 483 484 wmi_unified_unregister_event(wmi_handle, 485 wmi_mlo_link_disable_request_eventid); 486 487 target_if_mlo_unregister_link_switch_event_handler(wmi_handle); 488 489 return QDF_STATUS_SUCCESS; 490 } 491 492 /** 493 * target_if_mlo_link_set_active() - Send WMI command for set mlo link active 494 * @psoc: psoc pointer 495 * @param: parameter for setting mlo link active 496 * 497 * Return: QDF_STATUS 498 */ 499 static QDF_STATUS 500 target_if_mlo_link_set_active(struct wlan_objmgr_psoc *psoc, 501 struct mlo_link_set_active_param *param) 502 { 503 QDF_STATUS ret; 504 struct wmi_unified *wmi_handle; 505 506 if (!psoc) { 507 target_if_err("null psoc"); 508 return QDF_STATUS_E_FAILURE; 509 } 510 511 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 512 if (!wmi_handle) { 513 target_if_err("null handle"); 514 return QDF_STATUS_E_FAILURE; 515 } 516 517 ret = wmi_send_mlo_link_set_active_cmd(wmi_handle, param); 518 if (QDF_IS_STATUS_ERROR(ret)) 519 target_if_err("wmi mlo link set active send failed: %d", ret); 520 521 return ret; 522 } 523 524 static int target_if_mlo_vdev_tid_to_link_map_event_handler( 525 ol_scn_t scn, uint8_t *event_buff, uint32_t len) 526 { 527 struct wlan_objmgr_psoc *psoc; 528 struct mlo_vdev_host_tid_to_link_map_resp event = {0}; 529 struct wmi_unified *wmi_handle; 530 struct wlan_lmac_if_mlo_rx_ops *rx_ops; 531 QDF_STATUS status; 532 533 if (!event_buff) { 534 mlme_err("Received NULL event ptr from FW"); 535 return -EINVAL; 536 } 537 538 psoc = target_if_get_psoc_from_scn_hdl(scn); 539 if (!psoc) { 540 mlme_err("PSOC is NULL"); 541 return -EINVAL; 542 } 543 544 rx_ops = target_if_mlo_get_rx_ops(psoc); 545 if (!rx_ops || !rx_ops->process_mlo_vdev_tid_to_link_map_event) { 546 target_if_err("callback not registered"); 547 return -EINVAL; 548 } 549 550 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 551 if (!wmi_handle) { 552 mlme_err("wmi_handle is null"); 553 return -EINVAL; 554 } 555 556 if (wmi_extract_mlo_vdev_tid_to_link_map_event(wmi_handle, event_buff, 557 &event)) { 558 mlme_err("Failed to extract TID-to-link mapping event"); 559 return -EINVAL; 560 } 561 562 status = rx_ops->process_mlo_vdev_tid_to_link_map_event(psoc, &event); 563 564 return qdf_status_to_os_return(status); 565 } 566 567 void target_if_mlo_register_vdev_tid_to_link_map_event( 568 struct wmi_unified *wmi_handle) 569 { 570 wmi_unified_register_event_handler( 571 wmi_handle, wmi_mlo_ap_vdev_tid_to_link_map_eventid, 572 target_if_mlo_vdev_tid_to_link_map_event_handler, 573 WMI_RX_EXECUTION_CTX); 574 } 575 576 void target_if_mlo_unregister_vdev_tid_to_link_map_event( 577 struct wmi_unified *wmi_handle) 578 { 579 wmi_unified_unregister_event_handler( 580 wmi_handle, wmi_mlo_ap_vdev_tid_to_link_map_eventid); 581 } 582 583 static int target_if_mlo_link_state_info_event_handler( 584 ol_scn_t scn, uint8_t *event_buff, uint32_t len) 585 { 586 struct wlan_objmgr_psoc *psoc; 587 struct wmi_unified *wmi_handle; 588 QDF_STATUS status; 589 struct wlan_lmac_if_mlo_rx_ops *mlo_rx_ops; 590 struct ml_link_state_info_event event = {0}; 591 592 if (!event_buff) { 593 target_if_err("Received NULL event ptr from FW"); 594 return -EINVAL; 595 } 596 597 psoc = target_if_get_psoc_from_scn_hdl(scn); 598 if (!psoc) { 599 target_if_err("PSOC is NULL"); 600 return -EINVAL; 601 } 602 603 mlo_rx_ops = target_if_mlo_get_rx_ops(psoc); 604 if (!mlo_rx_ops || !mlo_rx_ops->process_mlo_link_state_info_event) { 605 target_if_err("callback not registered"); 606 return -EINVAL; 607 } 608 609 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 610 if (!wmi_handle) { 611 target_if_err("wmi_handle is null"); 612 return -EINVAL; 613 } 614 615 if (wmi_extract_mlo_link_state_info_event(wmi_handle, event_buff, 616 &event)) { 617 target_if_err("Failed to extract link status event"); 618 return -EINVAL; 619 } 620 621 status = mlo_rx_ops->process_mlo_link_state_info_event(psoc, &event); 622 return qdf_status_to_os_return(status); 623 } 624 625 void target_if_mlo_register_mlo_link_state_info_event( 626 struct wmi_unified *wmi_handle) 627 { 628 wmi_unified_register_event_handler( 629 wmi_handle, wmi_mlo_link_state_info_eventid, 630 target_if_mlo_link_state_info_event_handler, 631 WMI_RX_EXECUTION_CTX); 632 } 633 634 void target_if_mlo_unregister_mlo_link_state_info_event( 635 struct wmi_unified *wmi_handle) 636 { 637 wmi_unified_unregister_event_handler( 638 wmi_handle, 639 wmi_mlo_link_state_info_eventid); 640 } 641 642 #ifdef WLAN_FEATURE_11BE_MLO_ADV_FEATURE 643 /** 644 * target_if_fill_provisioned_links() - API to fill the provisioned links 645 * @params: Pointer to T2LM params structure 646 * @t2lm: Pointer to T2LM info structure 647 * 648 * Return: none 649 */ 650 static inline void target_if_fill_provisioned_links( 651 struct wmi_host_tid_to_link_map_params *params, 652 struct wlan_t2lm_info *t2lm) 653 { 654 qdf_mem_copy(¶ms->t2lm_info[params->num_dir].t2lm_provisioned_links, 655 &t2lm->ieee_link_map_tid, 656 sizeof(uint16_t) * T2LM_MAX_NUM_TIDS); 657 } 658 #else 659 static inline void target_if_fill_provisioned_links( 660 struct wmi_host_tid_to_link_map_params *params, 661 struct wlan_t2lm_info *t2lm) 662 { 663 qdf_mem_copy(¶ms->t2lm_info[params->num_dir].t2lm_provisioned_links, 664 &t2lm->hw_link_map_tid, 665 sizeof(uint16_t) * T2LM_MAX_NUM_TIDS); 666 } 667 #endif 668 669 static QDF_STATUS 670 target_if_mlo_send_tid_to_link_mapping(struct wlan_objmgr_vdev *vdev, 671 struct wlan_t2lm_info *t2lm) 672 { 673 struct wmi_unified *wmi_handle = NULL; 674 struct wmi_host_tid_to_link_map_params params = {0}; 675 struct wlan_objmgr_pdev *pdev = NULL; 676 int tid = 0; 677 QDF_STATUS status; 678 679 pdev = wlan_vdev_get_pdev(vdev); 680 if (!pdev) { 681 t2lm_err("null pdev"); 682 return QDF_STATUS_E_NULL_VALUE; 683 } 684 685 wmi_handle = lmac_get_pdev_wmi_handle(pdev); 686 if (!wmi_handle) { 687 t2lm_err("null wmi handle"); 688 return QDF_STATUS_E_NULL_VALUE; 689 } 690 691 params.pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 692 qdf_mem_copy(params.peer_macaddr, vdev->vdev_objmgr.bss_peer->macaddr, 693 QDF_MAC_ADDR_SIZE); 694 695 t2lm_debug("Fill T2LM WMI info for peer: " QDF_MAC_ADDR_FMT " pdev_id:%d", 696 QDF_MAC_ADDR_REF(params.peer_macaddr), params.pdev_id); 697 698 params.t2lm_info[params.num_dir].direction = t2lm->direction; 699 params.t2lm_info[params.num_dir].default_link_mapping = 700 t2lm->default_link_mapping; 701 702 if (!params.t2lm_info[params.num_dir].default_link_mapping) 703 target_if_fill_provisioned_links(¶ms, t2lm); 704 705 t2lm_debug("num_dir:%d direction:%d default_link_mapping:%d", 706 params.num_dir, params.t2lm_info[params.num_dir].direction, 707 params.t2lm_info[params.num_dir].default_link_mapping); 708 709 for (tid = 0; tid < T2LM_MAX_NUM_TIDS; tid++) { 710 t2lm_debug("tid:%d hw_link_map:%x ieee_link_map:%x", tid, 711 params.t2lm_info[params.num_dir].t2lm_provisioned_links[tid], 712 t2lm->ieee_link_map_tid[tid]); 713 } 714 715 params.num_dir++; 716 717 status = wmi_send_mlo_peer_tid_to_link_map_cmd(wmi_handle, ¶ms, true); 718 if (QDF_IS_STATUS_ERROR(status)) { 719 t2lm_err("Failed to send T2LM WMI command for pdev_id:%d peer_mac: " QDF_MAC_ADDR_FMT, 720 params.pdev_id, 721 QDF_MAC_ADDR_REF(params.peer_macaddr)); 722 return status; 723 } 724 725 return status; 726 } 727 728 static QDF_STATUS 729 target_if_request_ml_link_state_info(struct wlan_objmgr_psoc *psoc, 730 struct mlo_link_state_cmd_params *cmd) 731 { 732 struct wmi_unified *wmi_handle = NULL; 733 struct wmi_host_link_state_params params = {0}; 734 QDF_STATUS status; 735 736 if (!psoc) { 737 target_if_err("null pdev"); 738 return QDF_STATUS_E_NULL_VALUE; 739 } 740 741 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 742 if (!wmi_handle) { 743 target_if_err("null wmi handle"); 744 return QDF_STATUS_E_NULL_VALUE; 745 } 746 747 if (!cmd) { 748 target_if_err("cmd is null"); 749 return QDF_STATUS_E_NULL_VALUE; 750 } 751 752 params.vdev_id = cmd->vdev_id; 753 qdf_mem_copy(params.mld_mac, cmd->mld_mac, 754 QDF_MAC_ADDR_SIZE); 755 756 status = wmi_send_mlo_link_state_request_cmd(wmi_handle, ¶ms); 757 return status; 758 } 759 760 QDF_STATUS target_if_mlo_send_link_removal_cmd( 761 struct wlan_objmgr_psoc *psoc, 762 const struct mlo_link_removal_cmd_params *param) 763 { 764 struct wmi_unified *wmi_handle; 765 766 if (!psoc) { 767 target_if_err("null psoc"); 768 return QDF_STATUS_E_NULL_VALUE; 769 } 770 771 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 772 if (!wmi_handle) { 773 target_if_err("null handle"); 774 return QDF_STATUS_E_FAILURE; 775 } 776 777 return wmi_send_mlo_link_removal_cmd(wmi_handle, param); 778 } 779 780 QDF_STATUS target_if_mlo_send_vdev_pause(struct wlan_objmgr_psoc *psoc, 781 struct mlo_vdev_pause *info) 782 { 783 struct wmi_unified *wmi_handle; 784 785 if (!psoc) { 786 target_if_err("null psoc"); 787 return QDF_STATUS_E_NULL_VALUE; 788 } 789 790 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 791 if (!wmi_handle) { 792 target_if_err("null handle"); 793 return QDF_STATUS_E_FAILURE; 794 } 795 796 return wmi_send_mlo_vdev_pause(wmi_handle, info); 797 } 798 799 #ifdef QCA_SUPPORT_PRIMARY_LINK_MIGRATE 800 static QDF_STATUS target_if_mlo_send_peer_ptqm_migrate_cmd( 801 struct wlan_objmgr_vdev *vdev, 802 struct peer_ptqm_migrate_params *param) 803 { 804 struct wlan_objmgr_pdev *pdev = NULL; 805 struct wmi_unified *wmi_handle; 806 QDF_STATUS status; 807 808 if (!vdev || !param) { 809 target_if_err("Invalid input"); 810 return QDF_STATUS_E_INVAL; 811 } 812 813 pdev = wlan_vdev_get_pdev(vdev); 814 if (!pdev) { 815 target_if_err("null pdev"); 816 return QDF_STATUS_E_NULL_VALUE; 817 } 818 819 wmi_handle = lmac_get_pdev_wmi_handle(pdev); 820 if (!wmi_handle) { 821 target_if_err("Failed to get WMI handle!"); 822 return QDF_STATUS_E_INVAL; 823 } 824 825 status = wmi_unified_peer_ptqm_migrate_send(wmi_handle, param); 826 if (QDF_IS_STATUS_ERROR(status)) 827 target_if_err("Failed to send peer ptqm migration WMI"); 828 829 return status; 830 } 831 832 static void target_if_mlo_register_peer_ptqm_migrate_send( 833 struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops) 834 { 835 mlo_tx_ops->peer_ptqm_migrate_send = 836 target_if_mlo_send_peer_ptqm_migrate_cmd; 837 } 838 #else 839 static void target_if_mlo_register_peer_ptqm_migrate_send( 840 struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops) 841 { 842 } 843 #endif 844 845 /** 846 * target_if_mlo_register_tx_ops() - lmac handler to register mlo tx ops 847 * callback functions 848 * @tx_ops: wlan_lmac_if_tx_ops object 849 * 850 * Return: QDF_STATUS 851 */ 852 QDF_STATUS 853 target_if_mlo_register_tx_ops(struct wlan_lmac_if_tx_ops *tx_ops) 854 { 855 struct wlan_lmac_if_mlo_tx_ops *mlo_tx_ops; 856 857 if (!tx_ops) { 858 target_if_err("lmac tx ops is NULL!"); 859 return QDF_STATUS_E_INVAL; 860 } 861 862 mlo_tx_ops = &tx_ops->mlo_ops; 863 if (!mlo_tx_ops) { 864 target_if_err("lmac tx ops is NULL!"); 865 return QDF_STATUS_E_FAILURE; 866 } 867 868 mlo_tx_ops->register_events = 869 target_if_mlo_register_event_handler; 870 mlo_tx_ops->unregister_events = 871 target_if_mlo_unregister_event_handler; 872 mlo_tx_ops->link_set_active = target_if_mlo_link_set_active; 873 mlo_tx_ops->send_tid_to_link_mapping = 874 target_if_mlo_send_tid_to_link_mapping; 875 mlo_tx_ops->send_link_removal_cmd = target_if_mlo_send_link_removal_cmd; 876 mlo_tx_ops->request_link_state_info_cmd = 877 target_if_request_ml_link_state_info; 878 mlo_tx_ops->send_vdev_pause = target_if_mlo_send_vdev_pause; 879 880 target_if_mlo_register_link_switch_cnf_handler(mlo_tx_ops); 881 882 target_if_mlo_register_peer_ptqm_migrate_send(mlo_tx_ops); 883 return QDF_STATUS_SUCCESS; 884 } 885 886