1 /* 2 * Copyright (c) 2021, The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022-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: target_if_mgmt_txrx_rx_reo.c 20 * This file contains definitions of management rx re-ordering related APIs. 21 */ 22 23 #include <wlan_objmgr_psoc_obj.h> 24 #include <wlan_objmgr_pdev_obj.h> 25 #include <qdf_status.h> 26 #include <target_if.h> 27 #include <wlan_mgmt_txrx_rx_reo_public_structs.h> 28 #include <target_if_mgmt_txrx_rx_reo.h> 29 #include <wlan_lmac_if_api.h> 30 #include <init_deinit_lmac.h> 31 #include <wlan_mlo_mgr_setup.h> 32 #include <qdf_platform.h> 33 34 /** 35 * target_if_mgmt_rx_reo_fw_consumed_event_handler() - WMI event handler to 36 * process MGMT Rx FW consumed event handler 37 * @scn: Pointer to scn object 38 * @data: Pointer to event buffer 39 * @datalen: Length of event buffer 40 * 41 * Return: 0 for success, else failure 42 */ 43 static int 44 target_if_mgmt_rx_reo_fw_consumed_event_handler( 45 ol_scn_t scn, uint8_t *data, uint32_t datalen) 46 { 47 struct wlan_objmgr_psoc *psoc; 48 struct wlan_objmgr_pdev *pdev; 49 struct wmi_unified *wmi_handle; 50 QDF_STATUS status; 51 struct mgmt_rx_reo_params params; 52 struct wlan_lmac_if_mgmt_rx_reo_rx_ops *mgmt_rx_reo_rx_ops; 53 54 psoc = target_if_get_psoc_from_scn_hdl(scn); 55 if (!psoc) { 56 mgmt_rx_reo_err("null psoc"); 57 return -EINVAL; 58 } 59 60 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 61 if (!wmi_handle) { 62 mgmt_rx_reo_err("wmi_handle is NULL"); 63 return -EINVAL; 64 } 65 66 status = wmi_extract_mgmt_rx_fw_consumed(wmi_handle, data, ¶ms); 67 if (QDF_IS_STATUS_ERROR(status)) { 68 mgmt_rx_reo_err("Failed to extract mgmt rx params"); 69 return -EINVAL; 70 } 71 72 mgmt_rx_reo_rx_ops = target_if_mgmt_rx_reo_get_rx_ops(psoc); 73 if (!mgmt_rx_reo_rx_ops) { 74 mgmt_rx_reo_err("rx_ops of MGMT Rx REO module is NULL"); 75 return -EINVAL; 76 } 77 78 if (!mgmt_rx_reo_rx_ops->fw_consumed_event_handler) { 79 mgmt_rx_reo_err("FW consumed event handler is NULL"); 80 return -EINVAL; 81 } 82 83 /* Take the pdev reference */ 84 pdev = wlan_objmgr_get_pdev_by_id(psoc, params.pdev_id, 85 WLAN_MGMT_SB_ID); 86 if (!pdev) { 87 mgmt_rx_reo_err("Couldn't get pdev for pdev_id: %d" 88 "on psoc: %pK", params.pdev_id, psoc); 89 return -EINVAL; 90 } 91 92 status = mgmt_rx_reo_rx_ops->fw_consumed_event_handler(pdev, ¶ms); 93 if (QDF_IS_STATUS_ERROR(status)) { 94 mgmt_rx_reo_warn_rl("FW consumed event handling failed"); 95 wlan_objmgr_pdev_release_ref(pdev, WLAN_MGMT_SB_ID); 96 return -EINVAL; 97 } 98 99 wlan_objmgr_pdev_release_ref(pdev, WLAN_MGMT_SB_ID); 100 return 0; 101 } 102 103 void target_if_mgmt_rx_reo_release_frames(void *arg) 104 { 105 ol_scn_t scn = arg; 106 struct wlan_objmgr_psoc *psoc; 107 struct wlan_lmac_if_mgmt_rx_reo_rx_ops *mgmt_rx_reo_rx_ops; 108 QDF_STATUS status; 109 110 psoc = target_if_get_psoc_from_scn_hdl(scn); 111 if (!psoc) { 112 mgmt_rx_reo_err("null psoc"); 113 return; 114 } 115 116 mgmt_rx_reo_rx_ops = target_if_mgmt_rx_reo_get_rx_ops(psoc); 117 if (!mgmt_rx_reo_rx_ops) { 118 mgmt_rx_reo_err("rx_ops of MGMT Rx REO module is NULL"); 119 return; 120 } 121 122 status = mgmt_rx_reo_rx_ops->release_frames(psoc); 123 if (QDF_IS_STATUS_ERROR(status)) { 124 mgmt_rx_reo_err("Failed to release entries, ret = %d", status); 125 return; 126 } 127 } 128 129 QDF_STATUS 130 target_if_mgmt_rx_reo_register_event_handlers(struct wlan_objmgr_psoc *psoc) 131 { 132 struct wmi_unified *wmi_handle; 133 QDF_STATUS status; 134 135 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 136 if (!wmi_handle) { 137 mgmt_rx_reo_err("Invalid WMI handle"); 138 return QDF_STATUS_E_INVAL; 139 } 140 141 status = wmi_unified_register_event_handler( 142 wmi_handle, 143 wmi_mgmt_rx_fw_consumed_eventid, 144 target_if_mgmt_rx_reo_fw_consumed_event_handler, 145 WMI_RX_UMAC_CTX); 146 147 if (QDF_IS_STATUS_ERROR(status)) { 148 mgmt_rx_reo_err("Register Rx FW consumed event cb errcode %d", 149 status); 150 if (status == QDF_STATUS_E_NOSUPPORT) 151 status = QDF_STATUS_SUCCESS; 152 } 153 154 return status; 155 } 156 157 QDF_STATUS 158 target_if_mgmt_rx_reo_unregister_event_handlers(struct wlan_objmgr_psoc *psoc) 159 { 160 struct wmi_unified *wmi_handle; 161 QDF_STATUS status; 162 163 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 164 if (!wmi_handle) { 165 mgmt_rx_reo_err("Invalid WMI handle"); 166 return QDF_STATUS_E_INVAL; 167 } 168 169 status = wmi_unified_unregister_event_handler( 170 wmi_handle, 171 wmi_mgmt_rx_fw_consumed_eventid); 172 173 if (QDF_IS_STATUS_ERROR(status)) { 174 mgmt_rx_reo_err("Unregister Rx FW consumed event cb errcode %d", 175 status); 176 if (status == QDF_STATUS_E_NOSUPPORT) 177 status = QDF_STATUS_SUCCESS; 178 } 179 180 return status; 181 } 182 183 /** 184 * target_if_mgmt_rx_reo_get_num_active_hw_links() - Get number of active MLO HW 185 * links 186 * @psoc: Pointer to psoc object 187 * @num_active_hw_links: pointer to number of active MLO HW links 188 * 189 * Get number of active MLO HW links from the MLO global shared memory arena. 190 * 191 * Return: QDF_STATUS 192 */ 193 static QDF_STATUS 194 target_if_mgmt_rx_reo_get_num_active_hw_links(struct wlan_objmgr_psoc *psoc, 195 int8_t *num_active_hw_links) 196 { 197 struct wlan_lmac_if_mgmt_rx_reo_low_level_ops *low_level_ops; 198 uint8_t grp_id; 199 200 if (!psoc) { 201 mgmt_rx_reo_err("psoc is null"); 202 return QDF_STATUS_E_NULL_VALUE; 203 } 204 205 if (!num_active_hw_links) { 206 mgmt_rx_reo_err("Pointer to num_active_hw_links is null"); 207 return QDF_STATUS_E_NULL_VALUE; 208 } 209 210 if (!mlo_psoc_get_grp_id(psoc, &grp_id)) { 211 mgmt_rx_reo_err("Failed to get valid MLO Group id"); 212 return QDF_STATUS_E_INVAL; 213 } 214 215 low_level_ops = target_if_get_mgmt_rx_reo_low_level_ops(psoc); 216 217 if (!low_level_ops) { 218 mgmt_rx_reo_err("Low level ops of MGMT Rx REO is null"); 219 return QDF_STATUS_E_NULL_VALUE; 220 } 221 222 if (!low_level_ops->implemented) { 223 mgmt_rx_reo_err("Low level ops not implemented"); 224 return QDF_STATUS_E_INVAL; 225 } 226 227 *num_active_hw_links = low_level_ops->get_num_links(grp_id); 228 229 return QDF_STATUS_SUCCESS; 230 } 231 232 /** 233 * target_if_mgmt_rx_reo_get_valid_hw_link_bitmap() - Get valid MLO HW link 234 * bitmap 235 * @psoc: Pointer to psoc object 236 * @valid_hw_link_bitmap: Pointer to valid MLO HW link bitmap 237 * 238 * Get valid MLO HW link bitmap from the MLO global shared memory arena. 239 * 240 * Return: QDF_STATUS 241 */ 242 QDF_STATUS 243 target_if_mgmt_rx_reo_get_valid_hw_link_bitmap(struct wlan_objmgr_psoc *psoc, 244 uint16_t *valid_hw_link_bitmap) 245 { 246 struct wlan_lmac_if_mgmt_rx_reo_low_level_ops *low_level_ops; 247 uint8_t grp_id; 248 249 if (!psoc) { 250 mgmt_rx_reo_err("psoc is null"); 251 return QDF_STATUS_E_NULL_VALUE; 252 } 253 254 if (!valid_hw_link_bitmap) { 255 mgmt_rx_reo_err("Pointer to valid_hw_link_bitmap is null"); 256 return QDF_STATUS_E_NULL_VALUE; 257 } 258 259 if (!mlo_psoc_get_grp_id(psoc, &grp_id)) { 260 mgmt_rx_reo_err("Failed to get valid MLO Group id"); 261 return QDF_STATUS_E_INVAL; 262 } 263 264 low_level_ops = target_if_get_mgmt_rx_reo_low_level_ops(psoc); 265 266 if (!low_level_ops) { 267 mgmt_rx_reo_err("Low level ops of MGMT Rx REO is null"); 268 return QDF_STATUS_E_NULL_VALUE; 269 } 270 271 if (!low_level_ops->implemented) { 272 mgmt_rx_reo_err("Low level ops not implemented"); 273 return QDF_STATUS_E_INVAL; 274 } 275 276 *valid_hw_link_bitmap = low_level_ops->get_valid_link_bitmap(grp_id); 277 278 return QDF_STATUS_SUCCESS; 279 } 280 281 /** 282 * target_if_mgmt_rx_reo_read_snapshot_raw() - Read raw value of management 283 * rx-reorder snapshot 284 * @pdev: pointer to pdev object 285 * @snapshot_address: snapshot address 286 * @mgmt_rx_reo_snapshot_low: Pointer to lower 32 bits of snapshot value 287 * @mgmt_rx_reo_snapshot_high: Pointer to higher 32 bits of snapshot value 288 * @snapshot_version: snapshot version 289 * @raw_snapshot: Raw snapshot data 290 * 291 * Read raw value of management rx-reorder snapshots. 292 * 293 * Return: QDF_STATUS 294 */ 295 static QDF_STATUS 296 target_if_mgmt_rx_reo_read_snapshot_raw 297 (struct wlan_objmgr_pdev *pdev, 298 struct mgmt_rx_reo_shared_snapshot *snapshot_address, 299 uint32_t *mgmt_rx_reo_snapshot_low, 300 uint32_t *mgmt_rx_reo_snapshot_high, 301 uint8_t snapshot_version, 302 struct mgmt_rx_reo_shared_snapshot *raw_snapshot) 303 { 304 uint32_t prev_snapshot_low; 305 uint32_t prev_snapshot_high; 306 uint32_t cur_snapshot_low; 307 uint32_t cur_snapshot_high; 308 uint8_t retry_count = 0; 309 310 if (snapshot_version == 1) { 311 *mgmt_rx_reo_snapshot_low = 312 qdf_le32_to_cpu(snapshot_address->mgmt_rx_reo_snapshot_low); 313 *mgmt_rx_reo_snapshot_high = 314 qdf_le32_to_cpu(snapshot_address->mgmt_rx_reo_snapshot_high); 315 raw_snapshot->mgmt_rx_reo_snapshot_low = 316 *mgmt_rx_reo_snapshot_low; 317 raw_snapshot->mgmt_rx_reo_snapshot_high = 318 *mgmt_rx_reo_snapshot_high; 319 return QDF_STATUS_SUCCESS; 320 } 321 322 prev_snapshot_low = 323 qdf_le32_to_cpu(snapshot_address->mgmt_rx_reo_snapshot_low); 324 prev_snapshot_high = 325 qdf_le32_to_cpu(snapshot_address->mgmt_rx_reo_snapshot_high); 326 raw_snapshot->mgmt_rx_reo_snapshot_low = prev_snapshot_low; 327 raw_snapshot->mgmt_rx_reo_snapshot_high = prev_snapshot_high; 328 329 for (; retry_count < (MGMT_RX_REO_SNAPSHOT_B2B_READ_SWAR_RETRY_LIMIT - 1); 330 retry_count++) { 331 cur_snapshot_low = 332 qdf_le32_to_cpu(snapshot_address->mgmt_rx_reo_snapshot_low); 333 cur_snapshot_high = 334 qdf_le32_to_cpu(snapshot_address->mgmt_rx_reo_snapshot_high); 335 336 raw_snapshot[retry_count + 1].mgmt_rx_reo_snapshot_low = 337 cur_snapshot_low; 338 raw_snapshot[retry_count + 1].mgmt_rx_reo_snapshot_high = 339 cur_snapshot_high; 340 341 if (prev_snapshot_low == cur_snapshot_low && 342 prev_snapshot_high == cur_snapshot_high) 343 break; 344 345 prev_snapshot_low = cur_snapshot_low; 346 prev_snapshot_high = cur_snapshot_high; 347 } 348 349 if (retry_count == 350 (MGMT_RX_REO_SNAPSHOT_B2B_READ_SWAR_RETRY_LIMIT - 1)) { 351 enum qdf_hang_reason reason; 352 353 reason = QDF_MGMT_RX_REO_INCONSISTENT_SNAPSHOT; 354 mgmt_rx_reo_err("Triggering self recovery, inconsistent SS"); 355 qdf_trigger_self_recovery(wlan_pdev_get_psoc(pdev), reason); 356 } 357 358 *mgmt_rx_reo_snapshot_low = cur_snapshot_low; 359 *mgmt_rx_reo_snapshot_high = cur_snapshot_high; 360 361 return QDF_STATUS_SUCCESS; 362 } 363 364 /** 365 * target_if_mgmt_rx_reo_read_snapshot() - Read management rx-reorder snapshot 366 * @pdev: pdev pointer 367 * @snapshot_info: Snapshot info 368 * @id: Snapshot ID 369 * @snapshot_value: Pointer to snapshot value 370 * @raw_snapshot: Raw snapshot data 371 * 372 * Read management rx-reorder snapshots from target. 373 * 374 * Return: QDF_STATUS 375 */ 376 static QDF_STATUS 377 target_if_mgmt_rx_reo_read_snapshot( 378 struct wlan_objmgr_pdev *pdev, 379 struct mgmt_rx_reo_snapshot_info *snapshot_info, 380 enum mgmt_rx_reo_shared_snapshot_id id, 381 struct mgmt_rx_reo_snapshot_params *snapshot_value, 382 struct mgmt_rx_reo_shared_snapshot (*raw_snapshot) 383 [MGMT_RX_REO_SNAPSHOT_B2B_READ_SWAR_RETRY_LIMIT]) 384 { 385 bool snapshot_valid; 386 uint16_t mgmt_pkt_ctr; 387 uint32_t global_timestamp; 388 uint32_t mgmt_rx_reo_snapshot_low; 389 uint32_t mgmt_rx_reo_snapshot_high; 390 uint8_t retry_count; 391 QDF_STATUS status; 392 struct wlan_lmac_if_mgmt_rx_reo_low_level_ops *low_level_ops; 393 struct mgmt_rx_reo_shared_snapshot *snapshot_address; 394 uint8_t snapshot_version; 395 396 if (!snapshot_info) { 397 mgmt_rx_reo_err("Mgmt Rx REO snapshot info null"); 398 return QDF_STATUS_E_INVAL; 399 } 400 401 snapshot_address = snapshot_info->address; 402 if (!snapshot_address) { 403 mgmt_rx_reo_err("Mgmt Rx REO snapshot address null"); 404 return QDF_STATUS_E_INVAL; 405 } 406 407 snapshot_version = snapshot_info->version; 408 409 if (!snapshot_value) { 410 mgmt_rx_reo_err("Mgmt Rx REO snapshot null"); 411 return QDF_STATUS_E_INVAL; 412 } 413 414 qdf_mem_zero(snapshot_value, sizeof(*snapshot_value)); 415 416 low_level_ops = target_if_get_mgmt_rx_reo_low_level_ops( 417 wlan_pdev_get_psoc(pdev)); 418 419 if (!low_level_ops) { 420 mgmt_rx_reo_err("Low level ops of MGMT Rx REO is null"); 421 return QDF_STATUS_E_FAILURE; 422 } 423 424 /* Make sure that function pointers are populated */ 425 if (!low_level_ops->implemented) { 426 mgmt_rx_reo_err("Low level ops not implemented"); 427 return QDF_STATUS_E_INVAL; 428 } 429 430 switch (id) { 431 case MGMT_RX_REO_SHARED_SNAPSHOT_MAC_HW: 432 case MGMT_RX_REO_SHARED_SNAPSHOT_FW_CONSUMED: 433 case MGMT_RX_REO_SHARED_SNAPSHOT_FW_FORWARDED: 434 retry_count = 0; 435 for (; retry_count < MGMT_RX_REO_SNAPSHOT_READ_RETRY_LIMIT; 436 retry_count++) { 437 status = target_if_mgmt_rx_reo_read_snapshot_raw 438 (pdev, snapshot_address, 439 &mgmt_rx_reo_snapshot_low, 440 &mgmt_rx_reo_snapshot_high, 441 snapshot_version, 442 raw_snapshot[retry_count]); 443 444 if (QDF_IS_STATUS_ERROR(status)) { 445 mgmt_rx_reo_err("Failed to read snapshot %d", 446 id); 447 return QDF_STATUS_E_FAILURE; 448 } 449 450 snapshot_valid = low_level_ops->snapshot_is_valid( 451 mgmt_rx_reo_snapshot_low, 452 snapshot_version); 453 454 if (!snapshot_valid) { 455 mgmt_rx_reo_info("Invalid REO snapshot value"); 456 snapshot_value->valid = false; 457 snapshot_value->mgmt_pkt_ctr = 458 low_level_ops->snapshot_get_mgmt_pkt_ctr 459 (mgmt_rx_reo_snapshot_low, 460 snapshot_version); 461 snapshot_value->global_timestamp = 462 low_level_ops->snapshot_get_global_timestamp 463 (mgmt_rx_reo_snapshot_low, 464 mgmt_rx_reo_snapshot_high, 465 snapshot_version); 466 snapshot_value->retry_count = retry_count + 1; 467 return QDF_STATUS_SUCCESS; 468 } 469 470 if (low_level_ops->snapshot_is_consistent 471 (mgmt_rx_reo_snapshot_low, 472 mgmt_rx_reo_snapshot_high, 473 snapshot_version)) { 474 global_timestamp = 475 low_level_ops->snapshot_get_global_timestamp 476 (mgmt_rx_reo_snapshot_low, 477 mgmt_rx_reo_snapshot_high, 478 snapshot_version); 479 mgmt_pkt_ctr = 480 low_level_ops->snapshot_get_mgmt_pkt_ctr 481 (mgmt_rx_reo_snapshot_low, 482 snapshot_version); 483 break; 484 } 485 mgmt_rx_reo_info("Inconsistent snapshot %d, version=%u, low=0x%x, high=0x%x, retry=%u", 486 id, snapshot_version, 487 mgmt_rx_reo_snapshot_low, 488 mgmt_rx_reo_snapshot_high, 489 retry_count); 490 } 491 492 if (retry_count == MGMT_RX_REO_SNAPSHOT_READ_RETRY_LIMIT) { 493 enum qdf_hang_reason reason; 494 495 mgmt_rx_reo_err("Read retry limit, id = %d, ver = %u", 496 id, snapshot_version); 497 snapshot_value->valid = false; 498 snapshot_value->mgmt_pkt_ctr = 0xFFFF; 499 snapshot_value->global_timestamp = 0xFFFFFFFF; 500 snapshot_value->retry_count = retry_count; 501 reason = QDF_MGMT_RX_REO_INCONSISTENT_SNAPSHOT; 502 mgmt_rx_reo_err("Triggering self recovery, retry fail"); 503 qdf_trigger_self_recovery(wlan_pdev_get_psoc(pdev), 504 reason); 505 return QDF_STATUS_E_FAILURE; 506 } 507 508 snapshot_value->valid = true; 509 snapshot_value->mgmt_pkt_ctr = mgmt_pkt_ctr; 510 snapshot_value->global_timestamp = global_timestamp; 511 snapshot_value->retry_count = retry_count + 1; 512 status = QDF_STATUS_SUCCESS; 513 break; 514 515 default: 516 mgmt_rx_reo_err("Invalid snapshot id %d", id); 517 status = QDF_STATUS_E_INVAL; 518 break; 519 } 520 521 return status; 522 } 523 524 /** 525 * target_if_mgmt_rx_reo_get_snapshot_info() - Get information related to 526 * management rx-reorder snapshot 527 * @pdev: Pointer to pdev object 528 * @id: Snapshot ID 529 * @snapshot_info: Pointer to snapshot info 530 * 531 * Return: QDF_STATUS 532 */ 533 static QDF_STATUS 534 target_if_mgmt_rx_reo_get_snapshot_info 535 (struct wlan_objmgr_pdev *pdev, 536 enum mgmt_rx_reo_shared_snapshot_id id, 537 struct mgmt_rx_reo_snapshot_info *snapshot_info) 538 { 539 struct wlan_lmac_if_mgmt_rx_reo_low_level_ops *low_level_ops; 540 int8_t link_id; 541 int8_t snapshot_version; 542 uint8_t grp_id; 543 struct wlan_objmgr_psoc *psoc; 544 545 if (!pdev) { 546 mgmt_rx_reo_err("pdev is null"); 547 return QDF_STATUS_E_NULL_VALUE; 548 } 549 550 psoc = wlan_pdev_get_psoc(pdev); 551 if (!psoc) { 552 mgmt_rx_reo_err("psoc is null"); 553 return QDF_STATUS_E_NULL_VALUE; 554 } 555 556 if (id >= MGMT_RX_REO_SHARED_SNAPSHOT_MAX) { 557 mgmt_rx_reo_err("Mgmt RX REO snapshot id invalid %d", id); 558 return QDF_STATUS_E_INVAL; 559 } 560 561 if (!snapshot_info) { 562 mgmt_rx_reo_err("Ref to mgmt RX REO snapshot info is null"); 563 return QDF_STATUS_E_NULL_VALUE; 564 } 565 566 if (!mlo_psoc_get_grp_id(psoc, &grp_id)) { 567 mgmt_rx_reo_err("Failed to get valid MLO Group id"); 568 return QDF_STATUS_E_INVAL; 569 } 570 571 low_level_ops = target_if_get_mgmt_rx_reo_low_level_ops(psoc); 572 573 if (!low_level_ops) { 574 mgmt_rx_reo_err("Low level ops of MGMT Rx REO is null"); 575 return QDF_STATUS_E_FAILURE; 576 } 577 578 if (!low_level_ops->implemented) { 579 mgmt_rx_reo_err("Low level ops not implemented"); 580 return QDF_STATUS_E_INVAL; 581 } 582 583 link_id = wlan_get_mlo_link_id_from_pdev(pdev); 584 if (link_id < 0) { 585 mgmt_rx_reo_err("Invalid link id %d", link_id); 586 return QDF_STATUS_E_INVAL; 587 } 588 589 snapshot_info->address = 590 low_level_ops->get_snapshot_address(grp_id, 591 link_id, id); 592 593 snapshot_version = low_level_ops->get_snapshot_version(grp_id, id); 594 if (snapshot_version < 0) { 595 mgmt_rx_reo_err("Invalid snapshot version %d MLO Group id %d", 596 snapshot_version, grp_id); 597 return QDF_STATUS_E_INVAL; 598 } 599 600 snapshot_info->version = snapshot_version; 601 602 return QDF_STATUS_SUCCESS; 603 } 604 605 /** 606 * target_if_mgmt_rx_reo_filter_config() - Configure MGMT Rx REO filter 607 * @pdev: Pointer to pdev objmgr 608 * @filter: Pointer to MGMT Rx REO filter 609 * 610 * Return: QDF_STATUS_SUCCESS for success or error code 611 */ 612 static QDF_STATUS 613 target_if_mgmt_rx_reo_filter_config( 614 struct wlan_objmgr_pdev *pdev, 615 struct mgmt_rx_reo_filter *filter) 616 { 617 QDF_STATUS status; 618 struct wmi_unified *wmi_handle; 619 uint8_t pdev_id; 620 621 wmi_handle = lmac_get_pdev_wmi_handle(pdev); 622 if (!wmi_handle) { 623 mgmt_rx_reo_err("Invalid WMI handle"); 624 return QDF_STATUS_E_INVAL; 625 } 626 pdev_id = wlan_objmgr_pdev_get_pdev_id(pdev); 627 628 status = wmi_unified_mgmt_rx_reo_filter_config_cmd(wmi_handle, pdev_id, 629 filter); 630 if (QDF_IS_STATUS_ERROR(status)) 631 mgmt_rx_reo_err("Unable to send MGMT Rx REO Filter config cmd"); 632 633 return status; 634 } 635 636 QDF_STATUS 637 target_if_mgmt_rx_reo_extract_reo_params( 638 wmi_unified_t wmi_handle, void *evt_buf, 639 struct mgmt_rx_event_params *params) 640 { 641 struct wlan_objmgr_psoc *psoc; 642 643 if (!wmi_handle) { 644 mgmt_rx_reo_err("wmi_handle is null"); 645 return QDF_STATUS_E_NULL_VALUE; 646 } 647 648 psoc = target_if_get_psoc_from_scn_hdl(wmi_handle->scn_handle); 649 if (!psoc) { 650 mgmt_rx_reo_err("null psoc"); 651 return QDF_STATUS_E_NULL_VALUE; 652 } 653 654 /* If REO feature is not enabled in FW, no need to extract REO params */ 655 if (!wlan_psoc_nif_feat_cap_get(psoc, WLAN_SOC_F_MGMT_RX_REO_CAPABLE)) 656 return QDF_STATUS_SUCCESS; 657 658 if (!params) { 659 mgmt_rx_reo_err("MGMT Rx event parameters is NULL"); 660 return QDF_STATUS_E_NULL_VALUE; 661 } 662 663 return wmi_extract_mgmt_rx_reo_params(wmi_handle, evt_buf, 664 params->reo_params); 665 } 666 667 /** 668 * target_if_mgmt_rx_reo_schedule_delivery() - Schedule the delivery of 669 * management frames of the given psoc 670 * @psoc: Pointer to psoc object 671 * 672 * Return: QDF_STATUS 673 */ 674 static QDF_STATUS 675 target_if_mgmt_rx_reo_schedule_delivery(struct wlan_objmgr_psoc *psoc) 676 { 677 struct wmi_unified *wmi_handle; 678 QDF_STATUS status; 679 HTC_ENDPOINT_ID wmi_endpoint_id; 680 HTC_HANDLE htc_handle; 681 682 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 683 if (!wmi_handle) { 684 mgmt_rx_reo_err("wmi_handle is NULL"); 685 return QDF_STATUS_E_NULL_VALUE; 686 } 687 688 htc_handle = lmac_get_htc_hdl(psoc); 689 if (!htc_handle) { 690 mgmt_rx_reo_err("HTC_handle is NULL"); 691 return QDF_STATUS_E_NULL_VALUE; 692 } 693 694 wmi_endpoint_id = wmi_get_endpoint(wmi_handle); 695 696 status = htc_enable_custom_cb(htc_handle, wmi_endpoint_id); 697 if (QDF_IS_STATUS_ERROR(status)) { 698 mgmt_rx_reo_err("Failed to schedule delivery"); 699 return status; 700 } 701 702 return QDF_STATUS_SUCCESS; 703 } 704 705 /** 706 * target_if_mgmt_rx_reo_cancel_scheduled_delivery() - Cancel the scheduled 707 * delivery of management frames of the given psoc 708 * @psoc: Pointer to psoc object 709 * 710 * Return: QDF_STATUS 711 */ 712 static QDF_STATUS 713 target_if_mgmt_rx_reo_cancel_scheduled_delivery(struct wlan_objmgr_psoc *psoc) 714 { 715 struct wmi_unified *wmi_handle; 716 QDF_STATUS status; 717 HTC_ENDPOINT_ID wmi_endpoint_id; 718 HTC_HANDLE htc_handle; 719 720 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 721 if (!wmi_handle) { 722 mgmt_rx_reo_err("wmi_handle is NULL"); 723 return QDF_STATUS_E_NULL_VALUE; 724 } 725 726 htc_handle = lmac_get_htc_hdl(psoc); 727 if (!htc_handle) { 728 mgmt_rx_reo_err("HTC_handle is NULL"); 729 return QDF_STATUS_E_NULL_VALUE; 730 } 731 732 wmi_endpoint_id = wmi_get_endpoint(wmi_handle); 733 734 status = htc_disable_custom_cb(htc_handle, wmi_endpoint_id); 735 if (QDF_IS_STATUS_ERROR(status)) { 736 mgmt_rx_reo_err("Failed to cancel scheduled delivery"); 737 return status; 738 } 739 740 return QDF_STATUS_SUCCESS; 741 } 742 743 QDF_STATUS 744 target_if_mgmt_rx_reo_tx_ops_register( 745 struct wlan_lmac_if_mgmt_txrx_tx_ops *mgmt_txrx_tx_ops) 746 { 747 struct wlan_lmac_if_mgmt_rx_reo_tx_ops *mgmt_rx_reo_tx_ops; 748 749 if (!mgmt_txrx_tx_ops) { 750 mgmt_rx_reo_err("mgmt_txrx txops NULL"); 751 return QDF_STATUS_E_FAILURE; 752 } 753 mgmt_rx_reo_tx_ops = &mgmt_txrx_tx_ops->mgmt_rx_reo_tx_ops; 754 mgmt_rx_reo_tx_ops->get_num_active_hw_links = 755 target_if_mgmt_rx_reo_get_num_active_hw_links; 756 mgmt_rx_reo_tx_ops->get_valid_hw_link_bitmap = 757 target_if_mgmt_rx_reo_get_valid_hw_link_bitmap; 758 mgmt_rx_reo_tx_ops->read_mgmt_rx_reo_snapshot = 759 target_if_mgmt_rx_reo_read_snapshot; 760 mgmt_rx_reo_tx_ops->get_mgmt_rx_reo_snapshot_info = 761 target_if_mgmt_rx_reo_get_snapshot_info; 762 mgmt_rx_reo_tx_ops->mgmt_rx_reo_filter_config = 763 target_if_mgmt_rx_reo_filter_config; 764 mgmt_rx_reo_tx_ops->schedule_delivery = 765 target_if_mgmt_rx_reo_schedule_delivery; 766 mgmt_rx_reo_tx_ops->cancel_scheduled_delivery = 767 target_if_mgmt_rx_reo_cancel_scheduled_delivery; 768 769 return QDF_STATUS_SUCCESS; 770 } 771 772 QDF_STATUS 773 target_if_mgmt_rx_reo_host_drop_handler(struct wlan_objmgr_pdev *pdev, 774 struct mgmt_rx_event_params *params) 775 { 776 struct wlan_lmac_if_mgmt_rx_reo_rx_ops *mgmt_rx_reo_rx_ops; 777 778 if (!pdev) { 779 mgmt_rx_reo_err("pdev is null"); 780 return QDF_STATUS_E_NULL_VALUE; 781 } 782 783 if (!params) { 784 mgmt_rx_reo_err("mgmt rx event params are null"); 785 return QDF_STATUS_E_NULL_VALUE; 786 } 787 788 mgmt_rx_reo_rx_ops = target_if_mgmt_rx_reo_get_rx_ops( 789 wlan_pdev_get_psoc(pdev)); 790 if (!mgmt_rx_reo_rx_ops) { 791 mgmt_rx_reo_err("rx_ops of MGMT Rx REO module is NULL"); 792 return QDF_STATUS_E_NULL_VALUE; 793 } 794 795 return mgmt_rx_reo_rx_ops->host_drop_handler(pdev, params->reo_params); 796 } 797