1 /* 2 * Copyright (c) 2019-2020 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 /** 21 * DOC: target_if_vdev_mgr_rx_ops.c 22 * 23 * This file provide definition for APIs registered through events received 24 * from FW 25 */ 26 #include <target_if_vdev_mgr_rx_ops.h> 27 #include <target_if_vdev_mgr_tx_ops.h> 28 #include <wlan_vdev_mgr_tgt_if_rx_defs.h> 29 #include <wlan_vdev_mgr_tgt_if_tx_defs.h> 30 #include <wmi_unified_param.h> 31 #include <wlan_mlme_dbg.h> 32 #include <target_if.h> 33 #include <wlan_vdev_mlme_main.h> 34 #include <wmi_unified_vdev_api.h> 35 #include <target_if_psoc_wake_lock.h> 36 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 37 #include <target_if_cm_roam_offload.h> 38 #endif 39 40 static inline 41 void target_if_vdev_mgr_handle_recovery(struct wlan_objmgr_psoc *psoc, 42 uint8_t vdev_id, 43 enum qdf_hang_reason recovery_reason, 44 uint16_t rsp_pos) 45 { 46 mlme_nofl_err("PSOC_%d VDEV_%d: %s rsp timeout", wlan_psoc_get_id(psoc), 47 vdev_id, string_from_rsp_bit(rsp_pos)); 48 if (target_if_vdev_mgr_is_panic_allowed()) 49 qdf_trigger_self_recovery(psoc, recovery_reason); 50 else 51 mlme_nofl_debug("PSOC_%d VDEV_%d: Panic not allowed", 52 wlan_psoc_get_id(psoc), vdev_id); 53 } 54 55 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 56 static inline QDF_STATUS 57 target_if_send_rso_stop_failure_rsp(struct wlan_objmgr_psoc *psoc, 58 uint8_t vdev_id) 59 { 60 return target_if_cm_send_rso_stop_failure_rsp(psoc, vdev_id); 61 } 62 #else 63 static inline QDF_STATUS 64 target_if_send_rso_stop_failure_rsp(struct wlan_objmgr_psoc *psoc, 65 uint8_t vdev_id) 66 { 67 return QDF_STATUS_E_NOSUPPORT; 68 } 69 #endif 70 71 void target_if_vdev_mgr_rsp_timer_cb(void *arg) 72 { 73 struct wlan_objmgr_psoc *psoc; 74 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 75 struct vdev_start_response start_rsp = {0}; 76 struct vdev_stop_response stop_rsp = {0}; 77 struct vdev_delete_response del_rsp = {0}; 78 struct peer_delete_all_response peer_del_all_rsp = {0}; 79 struct vdev_response_timer *vdev_rsp = arg; 80 enum qdf_hang_reason recovery_reason; 81 uint8_t vdev_id; 82 uint16_t rsp_pos = RESPONSE_BIT_MAX; 83 84 if (!vdev_rsp) { 85 mlme_err("Vdev response timer is NULL"); 86 return; 87 } 88 89 psoc = vdev_rsp->psoc; 90 if (!psoc) { 91 mlme_err("PSOC is NULL"); 92 return; 93 } 94 95 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 96 if (!rx_ops || !rx_ops->psoc_get_vdev_response_timer_info) { 97 mlme_err("No Rx Ops"); 98 return; 99 } 100 101 if (!qdf_atomic_test_bit(START_RESPONSE_BIT, &vdev_rsp->rsp_status) && 102 !qdf_atomic_test_bit(RESTART_RESPONSE_BIT, &vdev_rsp->rsp_status) && 103 !qdf_atomic_test_bit(STOP_RESPONSE_BIT, &vdev_rsp->rsp_status) && 104 !qdf_atomic_test_bit(DELETE_RESPONSE_BIT, &vdev_rsp->rsp_status) && 105 !qdf_atomic_test_bit(PEER_DELETE_ALL_RESPONSE_BIT, 106 &vdev_rsp->rsp_status) && 107 !qdf_atomic_test_bit(RSO_STOP_RESPONSE_BIT, 108 &vdev_rsp->rsp_status)) { 109 mlme_debug("No response bit is set, ignoring actions :%d", 110 vdev_rsp->vdev_id); 111 return; 112 } 113 114 vdev_id = vdev_rsp->vdev_id; 115 if (vdev_id >= WLAN_UMAC_PSOC_MAX_VDEVS) { 116 mlme_err("Invalid VDEV_%d PSOC_%d", vdev_id, 117 wlan_psoc_get_id(psoc)); 118 return; 119 } 120 121 vdev_rsp->timer_status = QDF_STATUS_E_TIMEOUT; 122 if (qdf_atomic_test_bit(START_RESPONSE_BIT, 123 &vdev_rsp->rsp_status) || 124 qdf_atomic_test_bit(RESTART_RESPONSE_BIT, 125 &vdev_rsp->rsp_status)) { 126 start_rsp.vdev_id = vdev_id; 127 start_rsp.status = WLAN_MLME_HOST_VDEV_START_TIMEOUT; 128 if (qdf_atomic_test_bit(START_RESPONSE_BIT, 129 &vdev_rsp->rsp_status)) { 130 start_rsp.resp_type = 131 WMI_HOST_VDEV_START_RESP_EVENT; 132 rsp_pos = START_RESPONSE_BIT; 133 recovery_reason = QDF_VDEV_START_RESPONSE_TIMED_OUT; 134 } else { 135 start_rsp.resp_type = 136 WMI_HOST_VDEV_RESTART_RESP_EVENT; 137 rsp_pos = RESTART_RESPONSE_BIT; 138 recovery_reason = QDF_VDEV_RESTART_RESPONSE_TIMED_OUT; 139 } 140 141 target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, rsp_pos); 142 target_if_vdev_mgr_handle_recovery(psoc, vdev_id, 143 recovery_reason, rsp_pos); 144 rx_ops->vdev_mgr_start_response(psoc, &start_rsp); 145 } else if (qdf_atomic_test_bit(STOP_RESPONSE_BIT, 146 &vdev_rsp->rsp_status)) { 147 rsp_pos = STOP_RESPONSE_BIT; 148 stop_rsp.vdev_id = vdev_id; 149 recovery_reason = QDF_VDEV_STOP_RESPONSE_TIMED_OUT; 150 151 target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, rsp_pos); 152 target_if_vdev_mgr_handle_recovery(psoc, vdev_id, 153 recovery_reason, rsp_pos); 154 rx_ops->vdev_mgr_stop_response(psoc, &stop_rsp); 155 } else if (qdf_atomic_test_bit(DELETE_RESPONSE_BIT, 156 &vdev_rsp->rsp_status)) { 157 del_rsp.vdev_id = vdev_id; 158 rsp_pos = DELETE_RESPONSE_BIT; 159 recovery_reason = QDF_VDEV_DELETE_RESPONSE_TIMED_OUT; 160 target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, rsp_pos); 161 target_if_vdev_mgr_handle_recovery(psoc, vdev_id, 162 recovery_reason, rsp_pos); 163 rx_ops->vdev_mgr_delete_response(psoc, &del_rsp); 164 } else if (qdf_atomic_test_bit(PEER_DELETE_ALL_RESPONSE_BIT, 165 &vdev_rsp->rsp_status)) { 166 peer_del_all_rsp.vdev_id = vdev_id; 167 peer_del_all_rsp.peer_type_bitmap = vdev_rsp->peer_type_bitmap; 168 rsp_pos = PEER_DELETE_ALL_RESPONSE_BIT; 169 recovery_reason = QDF_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT; 170 target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, rsp_pos); 171 target_if_vdev_mgr_handle_recovery(psoc, vdev_id, 172 recovery_reason, rsp_pos); 173 rx_ops->vdev_mgr_peer_delete_all_response(psoc, 174 &peer_del_all_rsp); 175 } else if (qdf_atomic_test_bit(RSO_STOP_RESPONSE_BIT, 176 &vdev_rsp->rsp_status)) { 177 rsp_pos = RSO_STOP_RESPONSE_BIT; 178 target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, rsp_pos); 179 /** 180 * FW did not respond to rso stop cmd, as roaming is 181 * disabled either due to race condition 182 * that happened during previous disconnect OR 183 * supplicant disabled roaming. 184 * To solve this issue, skip recovery and host will 185 * continue disconnect and cleanup rso state. 186 */ 187 mlme_debug("No rsp from FW received , continue with disconnect"); 188 target_if_send_rso_stop_failure_rsp(psoc, vdev_id); 189 } else { 190 mlme_err("PSOC_%d VDEV_%d: Unknown error", 191 wlan_psoc_get_id(psoc), vdev_id); 192 return; 193 } 194 } 195 196 #ifdef SERIALIZE_VDEV_RESP 197 static QDF_STATUS target_if_vdev_mgr_rsp_flush_cb(struct scheduler_msg *msg) 198 { 199 struct vdev_response_timer *vdev_rsp; 200 struct wlan_objmgr_psoc *psoc; 201 202 if (!msg->bodyptr) { 203 mlme_err("Message bodyptr is NULL"); 204 return QDF_STATUS_E_INVAL; 205 } 206 207 vdev_rsp = msg->bodyptr; 208 if (!vdev_rsp) { 209 mlme_err("vdev response timer is NULL"); 210 return QDF_STATUS_E_INVAL; 211 } 212 213 psoc = vdev_rsp->psoc; 214 if (!psoc) { 215 mlme_err("PSOC is NULL"); 216 return QDF_STATUS_E_INVAL; 217 } 218 219 if (vdev_rsp->rsp_status) 220 wlan_objmgr_psoc_release_ref(psoc, WLAN_PSOC_TARGET_IF_ID); 221 222 return QDF_STATUS_SUCCESS; 223 } 224 225 static void 226 target_if_vdev_mgr_rsp_cb_mc_ctx(void *arg) 227 { 228 struct scheduler_msg msg = {0}; 229 struct vdev_response_timer *vdev_rsp = arg; 230 struct wlan_objmgr_psoc *psoc; 231 232 psoc = vdev_rsp->psoc; 233 if (!psoc) { 234 mlme_err("PSOC is NULL"); 235 return; 236 } 237 238 msg.type = SYS_MSG_ID_MC_TIMER; 239 msg.reserved = SYS_MSG_COOKIE; 240 241 /* msg.callback will explicitly cast back to qdf_mc_timer_callback_t 242 * in scheduler_timer_q_mq_handler. 243 * but in future we do not want to introduce more this kind of 244 * typecast by properly using QDF MC timer for MCC from get go in 245 * common code. 246 */ 247 msg.callback = 248 (scheduler_msg_process_fn_t)target_if_vdev_mgr_rsp_timer_cb; 249 msg.bodyptr = arg; 250 msg.bodyval = 0; 251 msg.flush_callback = target_if_vdev_mgr_rsp_flush_cb; 252 253 if (scheduler_post_message(QDF_MODULE_ID_TARGET_IF, 254 QDF_MODULE_ID_TARGET_IF, 255 QDF_MODULE_ID_SYS, &msg) == 256 QDF_STATUS_SUCCESS) 257 return; 258 259 mlme_err("Could not enqueue timer to timer queue"); 260 if (psoc) 261 wlan_objmgr_psoc_release_ref(psoc, WLAN_PSOC_TARGET_IF_ID); 262 } 263 264 void target_if_vdev_mgr_rsp_timer_mgmt_cb(void *arg) 265 { 266 target_if_vdev_mgr_rsp_cb_mc_ctx(arg); 267 } 268 269 #define VDEV_RSP_RX_CTX WMI_RX_SERIALIZER_CTX 270 #else 271 void target_if_vdev_mgr_rsp_timer_mgmt_cb(void *arg) 272 { 273 target_if_vdev_mgr_rsp_timer_cb(arg); 274 } 275 276 #define VDEV_RSP_RX_CTX WMI_RX_UMAC_CTX 277 #endif 278 279 static int target_if_vdev_mgr_start_response_handler(ol_scn_t scn, 280 uint8_t *data, 281 uint32_t datalen) 282 { 283 QDF_STATUS status = QDF_STATUS_E_INVAL; 284 struct wlan_objmgr_psoc *psoc; 285 struct wmi_unified *wmi_handle; 286 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 287 struct vdev_start_response vdev_start_resp = {0}; 288 uint8_t vdev_id; 289 struct vdev_response_timer *vdev_rsp; 290 291 if (!scn || !data) { 292 mlme_err("Invalid input"); 293 return -EINVAL; 294 } 295 296 psoc = target_if_get_psoc_from_scn_hdl(scn); 297 if (!psoc) { 298 mlme_err("PSOC is NULL"); 299 return -EINVAL; 300 } 301 302 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 303 if (!rx_ops || !rx_ops->vdev_mgr_start_response) { 304 mlme_err("No Rx Ops"); 305 return -EINVAL; 306 } 307 308 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 309 if (!wmi_handle) { 310 mlme_err("wmi_handle is null"); 311 return -EINVAL; 312 } 313 314 if (wmi_extract_vdev_start_resp(wmi_handle, data, &vdev_start_resp)) { 315 mlme_err("WMI extract failed"); 316 return -EINVAL; 317 } 318 319 vdev_id = vdev_start_resp.vdev_id; 320 vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, vdev_id); 321 if (!vdev_rsp) { 322 mlme_err("vdev response timer is null VDEV_%d PSOC_%d", 323 vdev_id, wlan_psoc_get_id(psoc)); 324 return -EINVAL; 325 } 326 327 if (vdev_start_resp.resp_type == WMI_HOST_VDEV_RESTART_RESP_EVENT) 328 status = target_if_vdev_mgr_rsp_timer_stop( 329 psoc, vdev_rsp, 330 RESTART_RESPONSE_BIT); 331 else 332 status = target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, 333 START_RESPONSE_BIT); 334 335 if (QDF_IS_STATUS_ERROR(status)) { 336 mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed", 337 psoc->soc_objmgr.psoc_id, vdev_id); 338 goto err; 339 } 340 341 status = rx_ops->vdev_mgr_start_response(psoc, &vdev_start_resp); 342 343 err: 344 return qdf_status_to_os_return(status); 345 } 346 347 static int target_if_vdev_mgr_stop_response_handler(ol_scn_t scn, 348 uint8_t *data, 349 uint32_t datalen) 350 { 351 QDF_STATUS status = QDF_STATUS_E_INVAL; 352 struct wlan_objmgr_psoc *psoc; 353 struct wmi_unified *wmi_handle; 354 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 355 struct vdev_stop_response rsp = {0}; 356 uint32_t vdev_id; 357 struct vdev_response_timer *vdev_rsp; 358 359 if (!scn || !data) { 360 mlme_err("Invalid input"); 361 return -EINVAL; 362 } 363 364 psoc = target_if_get_psoc_from_scn_hdl(scn); 365 if (!psoc) { 366 mlme_err("PSOC is NULL"); 367 return -EINVAL; 368 } 369 370 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 371 if (!rx_ops || !rx_ops->vdev_mgr_stop_response) { 372 mlme_err("No Rx Ops"); 373 return -EINVAL; 374 } 375 376 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 377 if (!wmi_handle) { 378 mlme_err("wmi_handle is null"); 379 return -EINVAL; 380 } 381 382 if (wmi_extract_vdev_stopped_param(wmi_handle, data, &vdev_id)) { 383 mlme_err("WMI extract failed"); 384 return -EINVAL; 385 } 386 387 vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, vdev_id); 388 if (!vdev_rsp) { 389 mlme_err("vdev response timer is null VDEV_%d PSOC_%d", 390 vdev_id, wlan_psoc_get_id(psoc)); 391 return -EINVAL; 392 } 393 394 status = target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, 395 STOP_RESPONSE_BIT); 396 397 if (QDF_IS_STATUS_ERROR(status)) { 398 mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed", 399 psoc->soc_objmgr.psoc_id, vdev_id); 400 goto err; 401 } 402 403 rsp.vdev_id = vdev_id; 404 status = rx_ops->vdev_mgr_stop_response(psoc, &rsp); 405 406 err: 407 return qdf_status_to_os_return(status); 408 } 409 410 static int target_if_vdev_mgr_delete_response_handler(ol_scn_t scn, 411 uint8_t *data, 412 uint32_t datalen) 413 { 414 QDF_STATUS status = QDF_STATUS_E_INVAL; 415 struct wlan_objmgr_psoc *psoc; 416 struct wmi_unified *wmi_handle; 417 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 418 struct vdev_delete_response vdev_del_resp = {0}; 419 struct vdev_response_timer *vdev_rsp; 420 421 if (!scn || !data) { 422 mlme_err("Invalid input"); 423 return -EINVAL; 424 } 425 426 psoc = target_if_get_psoc_from_scn_hdl(scn); 427 if (!psoc) { 428 mlme_err("PSOC is NULL"); 429 return -EINVAL; 430 } 431 432 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 433 if (!rx_ops || !rx_ops->vdev_mgr_delete_response) { 434 mlme_err("No Rx Ops"); 435 return -EINVAL; 436 } 437 438 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 439 if (!wmi_handle) { 440 mlme_err("wmi_handle is null"); 441 return -EINVAL; 442 } 443 444 if (wmi_extract_vdev_delete_resp(wmi_handle, data, &vdev_del_resp)) { 445 mlme_err("WMI extract failed"); 446 return -EINVAL; 447 } 448 449 vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, 450 vdev_del_resp.vdev_id); 451 if (!vdev_rsp) { 452 mlme_err("vdev response timer is null VDEV_%d PSOC_%d", 453 vdev_del_resp.vdev_id, wlan_psoc_get_id(psoc)); 454 return -EINVAL; 455 } 456 457 status = target_if_vdev_mgr_rsp_timer_stop( 458 psoc, vdev_rsp, 459 DELETE_RESPONSE_BIT); 460 461 if (QDF_IS_STATUS_ERROR(status)) { 462 mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed", 463 wlan_psoc_get_id(psoc), vdev_del_resp.vdev_id); 464 goto err; 465 } 466 467 status = rx_ops->vdev_mgr_delete_response(psoc, &vdev_del_resp); 468 target_if_wake_lock_timeout_release(psoc, DELETE_WAKELOCK); 469 err: 470 return qdf_status_to_os_return(status); 471 } 472 473 static int target_if_vdev_mgr_peer_delete_all_response_handler( 474 ol_scn_t scn, 475 uint8_t *data, 476 uint32_t datalen) 477 { 478 QDF_STATUS status = QDF_STATUS_E_INVAL; 479 struct wlan_objmgr_psoc *psoc; 480 struct wmi_unified *wmi_handle; 481 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 482 struct peer_delete_all_response vdev_peer_del_all_resp = {0}; 483 struct vdev_response_timer *vdev_rsp; 484 485 if (!scn || !data) { 486 mlme_err("Invalid input"); 487 return -EINVAL; 488 } 489 490 psoc = target_if_get_psoc_from_scn_hdl(scn); 491 if (!psoc) { 492 mlme_err("PSOC is NULL"); 493 return -EINVAL; 494 } 495 496 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 497 if (!rx_ops || !rx_ops->vdev_mgr_peer_delete_all_response) { 498 mlme_err("No Rx Ops"); 499 return -EINVAL; 500 } 501 502 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 503 if (!wmi_handle) { 504 mlme_err("wmi_handle is null"); 505 return -EINVAL; 506 } 507 508 if (wmi_extract_vdev_peer_delete_all_response_event( 509 wmi_handle, data, 510 &vdev_peer_del_all_resp)) { 511 mlme_err("WMI extract failed"); 512 return -EINVAL; 513 } 514 515 vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, 516 vdev_peer_del_all_resp.vdev_id); 517 if (!vdev_rsp) { 518 mlme_err("vdev response timer is null VDEV_%d PSOC_%d", 519 vdev_peer_del_all_resp.vdev_id, 520 wlan_psoc_get_id(psoc)); 521 return -EINVAL; 522 } 523 524 status = target_if_vdev_mgr_rsp_timer_stop( 525 psoc, 526 vdev_rsp, 527 PEER_DELETE_ALL_RESPONSE_BIT); 528 529 if (QDF_IS_STATUS_ERROR(status)) { 530 mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed", 531 psoc->soc_objmgr.psoc_id, 532 vdev_peer_del_all_resp.vdev_id); 533 goto err; 534 } 535 536 vdev_peer_del_all_resp.peer_type_bitmap = vdev_rsp->peer_type_bitmap; 537 538 status = rx_ops->vdev_mgr_peer_delete_all_response( 539 psoc, 540 &vdev_peer_del_all_resp); 541 542 err: 543 return qdf_status_to_os_return(status); 544 } 545 546 int target_if_vdev_mgr_offload_bcn_tx_status_handler( 547 ol_scn_t scn, 548 uint8_t *data, 549 uint32_t datalen) 550 { 551 QDF_STATUS status; 552 struct wlan_objmgr_psoc *psoc; 553 struct wmi_unified *wmi_handle; 554 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 555 uint32_t vdev_id, tx_status; 556 557 if (!scn || !data) { 558 mlme_err("Invalid input"); 559 return -EINVAL; 560 } 561 psoc = target_if_get_psoc_from_scn_hdl(scn); 562 if (!psoc) { 563 mlme_err("PSOC is NULL"); 564 return -EINVAL; 565 } 566 567 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 568 if (!rx_ops || !rx_ops->vdev_mgr_offload_bcn_tx_status_event_handle) { 569 mlme_err("No Rx Ops"); 570 return -EINVAL; 571 } 572 573 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 574 if (!wmi_handle) { 575 mlme_err("wmi_handle is null"); 576 return -EINVAL; 577 } 578 579 if (wmi_extract_offload_bcn_tx_status_evt(wmi_handle, data, 580 &vdev_id, &tx_status)) { 581 mlme_err("WMI extract failed"); 582 return -EINVAL; 583 } 584 585 status = rx_ops->vdev_mgr_offload_bcn_tx_status_event_handle( 586 vdev_id, 587 tx_status); 588 589 return qdf_status_to_os_return(status); 590 } 591 592 int target_if_vdev_mgr_tbttoffset_update_handler( 593 ol_scn_t scn, uint8_t *data, 594 uint32_t datalen) 595 { 596 QDF_STATUS status; 597 struct wlan_objmgr_psoc *psoc; 598 struct wmi_unified *wmi_handle; 599 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 600 uint32_t num_vdevs = 0; 601 602 if (!scn || !data) { 603 mlme_err("Invalid input"); 604 return -EINVAL; 605 } 606 psoc = target_if_get_psoc_from_scn_hdl(scn); 607 if (!psoc) { 608 mlme_err("PSOC is NULL"); 609 return -EINVAL; 610 } 611 612 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 613 if (!rx_ops || !rx_ops->vdev_mgr_tbttoffset_update_handle) { 614 mlme_err("No Rx Ops"); 615 return -EINVAL; 616 } 617 618 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 619 if (!wmi_handle) { 620 mlme_err("wmi_handle is null"); 621 return -EINVAL; 622 } 623 624 if (wmi_extract_tbttoffset_num_vdevs(wmi_handle, data, &num_vdevs)) { 625 mlme_err("WMI extract failed"); 626 return -EINVAL; 627 } 628 629 status = rx_ops->vdev_mgr_tbttoffset_update_handle(num_vdevs, 630 false); 631 632 return qdf_status_to_os_return(status); 633 } 634 635 int target_if_vdev_mgr_ext_tbttoffset_update_handler( 636 ol_scn_t scn, 637 uint8_t *data, 638 uint32_t datalen) 639 { 640 QDF_STATUS status; 641 struct wlan_objmgr_psoc *psoc; 642 struct wmi_unified *wmi_handle; 643 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 644 uint32_t num_vdevs = 0; 645 646 if (!scn || !data) { 647 mlme_err("Invalid input"); 648 return -EINVAL; 649 } 650 psoc = target_if_get_psoc_from_scn_hdl(scn); 651 if (!psoc) { 652 mlme_err("PSOC is NULL"); 653 return -EINVAL; 654 } 655 656 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 657 if (!rx_ops || !rx_ops->vdev_mgr_tbttoffset_update_handle) { 658 mlme_err("No Rx Ops"); 659 return -EINVAL; 660 } 661 662 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 663 if (!wmi_handle) { 664 mlme_err("wmi_handle is null"); 665 return -EINVAL; 666 } 667 668 if (wmi_extract_ext_tbttoffset_num_vdevs(wmi_handle, data, 669 &num_vdevs)) { 670 mlme_err("WMI extract failed"); 671 return -EINVAL; 672 } 673 674 status = rx_ops->vdev_mgr_tbttoffset_update_handle(num_vdevs, 675 true); 676 677 return qdf_status_to_os_return(status); 678 } 679 680 static int target_if_vdev_mgr_multi_vdev_restart_resp_handler( 681 ol_scn_t scn, 682 uint8_t *data, 683 uint32_t datalen) 684 { 685 QDF_STATUS status = QDF_STATUS_E_INVAL; 686 struct wlan_objmgr_psoc *psoc; 687 struct wmi_unified *wmi_handle; 688 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 689 struct multi_vdev_restart_resp restart_resp; 690 struct vdev_response_timer *vdev_rsp; 691 uint8_t max_vdevs, vdev_idx; 692 693 if (!scn || !data) { 694 mlme_err("Invalid input"); 695 return -EINVAL; 696 } 697 698 psoc = target_if_get_psoc_from_scn_hdl(scn); 699 if (!psoc) { 700 mlme_err("PSOC is NULL"); 701 return -EINVAL; 702 } 703 704 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 705 if (!rx_ops || !rx_ops->vdev_mgr_multi_vdev_restart_resp || 706 !rx_ops->psoc_get_vdev_response_timer_info) { 707 mlme_err("No Rx Ops"); 708 return -EINVAL; 709 } 710 711 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 712 if (!wmi_handle) { 713 mlme_err("wmi_handle is null"); 714 return -EINVAL; 715 } 716 717 qdf_mem_zero(&restart_resp, sizeof(restart_resp)); 718 if (wmi_extract_multi_vdev_restart_resp_event(wmi_handle, data, 719 &restart_resp)) { 720 mlme_err("WMI extract failed"); 721 return -EINVAL; 722 } 723 724 max_vdevs = wlan_psoc_get_max_vdev_count(psoc); 725 for (vdev_idx = 0; vdev_idx < max_vdevs; vdev_idx++) { 726 if (!qdf_test_bit(vdev_idx, restart_resp.vdev_id_bmap)) 727 continue; 728 729 mlme_debug("PSOC_%d VDEV_%d: Restart resp received", 730 wlan_psoc_get_id(psoc), vdev_idx); 731 vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, 732 vdev_idx); 733 if (!vdev_rsp) { 734 mlme_err("PSOC_%d VDEV_%d: VDEV RSP is NULL", 735 wlan_psoc_get_id(psoc), vdev_idx); 736 continue; 737 } 738 739 status = target_if_vdev_mgr_rsp_timer_stop( 740 psoc, vdev_rsp, RESTART_RESPONSE_BIT); 741 if (QDF_IS_STATUS_ERROR(status)) 742 mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed", 743 wlan_psoc_get_id(psoc), vdev_idx); 744 } 745 746 status = rx_ops->vdev_mgr_multi_vdev_restart_resp(psoc, &restart_resp); 747 748 return qdf_status_to_os_return(status); 749 } 750 751 /** 752 * target_if_vdev_csa_complete - CSA complete event handler 753 * @psoc: psoc 754 * @vdev_id: vdev id 755 * 756 * Return: 0 on success 757 */ 758 static int target_if_vdev_csa_complete(struct wlan_objmgr_psoc *psoc, 759 uint8_t vdev_id) 760 { 761 QDF_STATUS status = QDF_STATUS_E_FAILURE; 762 struct vdev_mlme_obj *vdev_mlme; 763 struct wlan_objmgr_vdev *vdev; 764 int ret = 0; 765 766 if (!psoc) { 767 mlme_err("Invalid input"); 768 return -EINVAL; 769 } 770 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 771 WLAN_VDEV_TARGET_IF_ID); 772 if (!vdev) { 773 mlme_err("VDEV is NULL"); 774 return -EINVAL; 775 } 776 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 777 if (!vdev_mlme) { 778 mlme_err("VDEV_%d: PSOC_%d VDEV_MLME is NULL", vdev_id, 779 wlan_psoc_get_id(psoc)); 780 ret = -EINVAL; 781 goto end; 782 } 783 784 if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_csa_complete) { 785 status = vdev_mlme->ops->mlme_vdev_csa_complete(vdev_mlme); 786 if (QDF_IS_STATUS_ERROR(status)) { 787 mlme_err("vdev csa complete failed"); 788 ret = -EINVAL; 789 } 790 } 791 end: 792 wlan_objmgr_vdev_release_ref(vdev, WLAN_VDEV_TARGET_IF_ID); 793 return ret; 794 } 795 796 /** 797 * target_if_pdev_csa_status_event_handler - CSA event handler 798 * @scn: Pointer to scn structure 799 * @data: pointer to event data 800 * @datalen: event data length 801 * 802 * Return: 0 on success 803 */ 804 static int target_if_pdev_csa_status_event_handler( 805 ol_scn_t scn, 806 uint8_t *data, 807 uint32_t datalen) 808 { 809 struct pdev_csa_switch_count_status csa_status; 810 struct wlan_objmgr_psoc *psoc; 811 struct wmi_unified *wmi_handle; 812 struct target_psoc_info *tgt_hdl; 813 int i; 814 QDF_STATUS status; 815 struct wlan_lmac_if_mlme_rx_ops *rx_ops = NULL; 816 817 if (!scn || !data) { 818 mlme_err("Invalid input"); 819 return -EINVAL; 820 } 821 822 psoc = target_if_get_psoc_from_scn_hdl(scn); 823 if (!psoc) { 824 mlme_err("PSOC is NULL"); 825 return -EINVAL; 826 } 827 828 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 829 if (!rx_ops || !rx_ops->vdev_mgr_set_max_channel_switch_time) { 830 mlme_err("No Rx Ops"); 831 return -EINVAL; 832 } 833 834 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 835 if (!wmi_handle) { 836 mlme_err("wmi_handle is null"); 837 return -EINVAL; 838 } 839 840 tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc); 841 if (!tgt_hdl) { 842 mlme_err("target_psoc_info is null"); 843 return -EINVAL; 844 } 845 846 qdf_mem_zero(&csa_status, sizeof(csa_status)); 847 status = wmi_extract_pdev_csa_switch_count_status( 848 wmi_handle, data, &csa_status); 849 if (QDF_IS_STATUS_ERROR(status)) { 850 mlme_err("Extracting CSA switch count status event failed"); 851 return -EINVAL; 852 } 853 854 if (csa_status.current_switch_count == 1) 855 rx_ops->vdev_mgr_set_max_channel_switch_time 856 (psoc, csa_status.vdev_ids, csa_status.num_vdevs); 857 858 if (wlan_psoc_nif_fw_ext_cap_get(psoc, WLAN_SOC_CEXT_CSA_TX_OFFLOAD)) { 859 for (i = 0; i < csa_status.num_vdevs; i++) { 860 if (!csa_status.current_switch_count) 861 target_if_vdev_csa_complete(psoc, 862 csa_status.vdev_ids[i]); 863 } 864 } 865 866 return target_if_csa_switch_count_status(psoc, tgt_hdl, csa_status); 867 } 868 869 #ifdef WLAN_FEATURE_DYNAMIC_MAC_ADDR_UPDATE 870 /** 871 * target_if_update_macaddr_conf_evt_handler() - Set MAC address confirmation 872 * event handler 873 * @scn: Pointer to scn structure 874 * @event_buff: event data 875 * @len: length 876 * 877 * Response handler for set MAC address request command. 878 * 879 * Return: 0 for success or error code 880 */ 881 static int target_if_update_macaddr_conf_evt_handler(ol_scn_t scn, 882 uint8_t *event_buff, 883 uint32_t len) 884 { 885 struct wlan_objmgr_psoc *psoc; 886 struct wmi_unified *wmi_handle; 887 uint8_t vdev_id, resp_status; 888 QDF_STATUS status; 889 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 890 891 if (!event_buff) { 892 mlme_err("Received NULL event ptr from FW"); 893 return -EINVAL; 894 } 895 896 psoc = target_if_get_psoc_from_scn_hdl(scn); 897 if (!psoc) { 898 mlme_err("PSOC is NULL"); 899 return -EINVAL; 900 } 901 902 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 903 if (!wmi_handle) { 904 mlme_err("wmi_handle is null"); 905 return -EINVAL; 906 } 907 908 status = wmi_extract_update_mac_address_event(wmi_handle, event_buff, 909 &vdev_id, &resp_status); 910 if (QDF_IS_STATUS_ERROR(status)) { 911 mlme_err("Failed to extract update MAC address event"); 912 return -EINVAL; 913 } 914 915 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 916 if (!rx_ops || !rx_ops->vdev_mgr_set_mac_addr_response) { 917 mlme_err("No Rx Ops"); 918 return -EINVAL; 919 } 920 921 rx_ops->vdev_mgr_set_mac_addr_response(vdev_id, resp_status); 922 923 return 0; 924 } 925 926 static inline void 927 target_if_register_set_mac_addr_evt_cbk(struct wmi_unified *wmi_handle) 928 { 929 wmi_unified_register_event_handler( 930 wmi_handle, wmi_vdev_update_mac_addr_conf_eventid, 931 target_if_update_macaddr_conf_evt_handler, VDEV_RSP_RX_CTX); 932 } 933 934 static inline void 935 target_if_unregister_set_mac_addr_evt_cbk(struct wmi_unified *wmi_handle) 936 { 937 wmi_unified_unregister_event_handler( 938 wmi_handle, wmi_vdev_update_mac_addr_conf_eventid); 939 } 940 #else 941 static inline void 942 target_if_register_set_mac_addr_evt_cbk(struct wmi_unified *wmi_handle) 943 { 944 } 945 946 static inline void 947 target_if_unregister_set_mac_addr_evt_cbk(struct wmi_unified *wmi_handle) 948 { 949 } 950 #endif 951 952 #ifdef WLAN_FEATURE_11BE_MLO 953 /** 954 * target_if_quiet_offload_event_handler() - Quiet IE offload mlo 955 * station event handler 956 * @scn: Pointer to scn structure 957 * @event_buff: event data 958 * @len: length 959 * 960 * Return: 0 for success or error code 961 */ 962 static int target_if_quiet_offload_event_handler(ol_scn_t scn, 963 uint8_t *event_buff, 964 uint32_t len) 965 { 966 struct wlan_objmgr_psoc *psoc; 967 struct wmi_unified *wmi_handle; 968 QDF_STATUS status; 969 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 970 struct vdev_sta_quiet_event sta_quiet_event = {0}; 971 972 if (!event_buff) { 973 mlme_err("Received NULL event ptr from FW"); 974 return -EINVAL; 975 } 976 977 psoc = target_if_get_psoc_from_scn_hdl(scn); 978 if (!psoc) { 979 mlme_err("PSOC is NULL"); 980 return -EINVAL; 981 } 982 983 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 984 if (!wmi_handle) { 985 mlme_err("wmi_handle is null"); 986 return -EINVAL; 987 } 988 989 status = wmi_extract_quiet_offload_event(wmi_handle, event_buff, 990 &sta_quiet_event); 991 if (QDF_IS_STATUS_ERROR(status)) { 992 mlme_err("Failed to extract quiet IE offload event"); 993 return -EINVAL; 994 } 995 996 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 997 if (!rx_ops || !rx_ops->vdev_mgr_quiet_offload) { 998 mlme_err("No Rx Ops"); 999 return -EINVAL; 1000 } 1001 1002 rx_ops->vdev_mgr_quiet_offload(psoc, &sta_quiet_event); 1003 1004 return 0; 1005 } 1006 1007 static inline void 1008 target_if_register_quiet_offload_event(struct wmi_unified *wmi_handle) 1009 { 1010 wmi_unified_register_event_handler( 1011 wmi_handle, wmi_vdev_quiet_offload_eventid, 1012 target_if_quiet_offload_event_handler, VDEV_RSP_RX_CTX); 1013 } 1014 1015 static inline void 1016 target_if_unregister_quiet_offload_event(struct wmi_unified *wmi_handle) 1017 { 1018 wmi_unified_unregister_event_handler( 1019 wmi_handle, wmi_vdev_quiet_offload_eventid); 1020 } 1021 #else 1022 static inline void 1023 target_if_register_quiet_offload_event(struct wmi_unified *wmi_handle) 1024 { 1025 } 1026 1027 static inline void 1028 target_if_unregister_quiet_offload_event(struct wmi_unified *wmi_handle) 1029 { 1030 } 1031 #endif 1032 1033 QDF_STATUS target_if_vdev_mgr_wmi_event_register( 1034 struct wlan_objmgr_psoc *psoc) 1035 { 1036 QDF_STATUS retval = QDF_STATUS_SUCCESS; 1037 struct wmi_unified *wmi_handle; 1038 1039 if (!psoc) { 1040 mlme_err("PSOC is NULL"); 1041 return QDF_STATUS_E_NULL_VALUE; 1042 } 1043 1044 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 1045 if (!wmi_handle) { 1046 mlme_err("wmi_handle is null"); 1047 return QDF_STATUS_E_INVAL; 1048 } 1049 1050 retval = wmi_unified_register_event_handler( 1051 wmi_handle, 1052 wmi_vdev_stopped_event_id, 1053 target_if_vdev_mgr_stop_response_handler, 1054 VDEV_RSP_RX_CTX); 1055 if (QDF_IS_STATUS_ERROR(retval)) 1056 mlme_err("failed to register for stop response"); 1057 1058 retval = wmi_unified_register_event_handler( 1059 wmi_handle, 1060 wmi_vdev_delete_resp_event_id, 1061 target_if_vdev_mgr_delete_response_handler, 1062 VDEV_RSP_RX_CTX); 1063 if (QDF_IS_STATUS_ERROR(retval)) 1064 mlme_err("failed to register for delete response"); 1065 1066 retval = wmi_unified_register_event_handler( 1067 wmi_handle, 1068 wmi_vdev_start_resp_event_id, 1069 target_if_vdev_mgr_start_response_handler, 1070 VDEV_RSP_RX_CTX); 1071 if (QDF_IS_STATUS_ERROR(retval)) 1072 mlme_err("failed to register for start response"); 1073 1074 retval = wmi_unified_register_event_handler( 1075 wmi_handle, 1076 wmi_peer_delete_all_response_event_id, 1077 target_if_vdev_mgr_peer_delete_all_response_handler, 1078 VDEV_RSP_RX_CTX); 1079 if (QDF_IS_STATUS_ERROR(retval)) 1080 mlme_err("failed to register for peer delete all response"); 1081 1082 retval = wmi_unified_register_event_handler( 1083 wmi_handle, 1084 wmi_pdev_multi_vdev_restart_response_event_id, 1085 target_if_vdev_mgr_multi_vdev_restart_resp_handler, 1086 VDEV_RSP_RX_CTX); 1087 if (QDF_IS_STATUS_ERROR(retval)) 1088 mlme_err("failed to register for multivdev restart response"); 1089 1090 if (wmi_service_enabled(wmi_handle, wmi_service_beacon_offload)) { 1091 retval = wmi_unified_register_event_handler( 1092 wmi_handle, 1093 wmi_pdev_csa_switch_count_status_event_id, 1094 target_if_pdev_csa_status_event_handler, 1095 VDEV_RSP_RX_CTX); 1096 if (QDF_IS_STATUS_ERROR(retval)) 1097 mlme_err("failed to register for csa event handler"); 1098 } 1099 1100 target_if_register_set_mac_addr_evt_cbk(wmi_handle); 1101 1102 target_if_register_quiet_offload_event(wmi_handle); 1103 1104 return retval; 1105 } 1106 1107 QDF_STATUS target_if_vdev_mgr_wmi_event_unregister( 1108 struct wlan_objmgr_psoc *psoc) 1109 { 1110 struct wmi_unified *wmi_handle; 1111 1112 if (!psoc) { 1113 mlme_err("PSOC is NULL"); 1114 return QDF_STATUS_E_INVAL; 1115 } 1116 1117 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 1118 if (!wmi_handle) { 1119 mlme_err("wmi_handle is null"); 1120 return QDF_STATUS_E_INVAL; 1121 } 1122 1123 target_if_unregister_quiet_offload_event(wmi_handle); 1124 1125 target_if_unregister_set_mac_addr_evt_cbk(wmi_handle); 1126 1127 wmi_unified_unregister_event_handler( 1128 wmi_handle, 1129 wmi_pdev_multi_vdev_restart_response_event_id); 1130 1131 wmi_unified_unregister_event_handler( 1132 wmi_handle, 1133 wmi_peer_delete_all_response_event_id); 1134 1135 wmi_unified_unregister_event_handler(wmi_handle, 1136 wmi_vdev_start_resp_event_id); 1137 1138 wmi_unified_unregister_event_handler(wmi_handle, 1139 wmi_vdev_delete_resp_event_id); 1140 1141 wmi_unified_unregister_event_handler(wmi_handle, 1142 wmi_vdev_stopped_event_id); 1143 1144 return QDF_STATUS_SUCCESS; 1145 } 1146