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 recovery_reason = QDF_RSO_STOP_RSP_TIMEOUT; 179 target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, rsp_pos); 180 target_if_vdev_mgr_handle_recovery(psoc, vdev_id, 181 recovery_reason, rsp_pos); 182 target_if_send_rso_stop_failure_rsp(psoc, vdev_id); 183 } else { 184 mlme_err("PSOC_%d VDEV_%d: Unknown error", 185 wlan_psoc_get_id(psoc), vdev_id); 186 return; 187 } 188 } 189 190 #ifdef SERIALIZE_VDEV_RESP 191 static QDF_STATUS target_if_vdev_mgr_rsp_flush_cb(struct scheduler_msg *msg) 192 { 193 struct vdev_response_timer *vdev_rsp; 194 struct wlan_objmgr_psoc *psoc; 195 196 if (!msg->bodyptr) { 197 mlme_err("Message bodyptr is NULL"); 198 return QDF_STATUS_E_INVAL; 199 } 200 201 vdev_rsp = msg->bodyptr; 202 if (!vdev_rsp) { 203 mlme_err("vdev response timer is NULL"); 204 return QDF_STATUS_E_INVAL; 205 } 206 207 psoc = vdev_rsp->psoc; 208 if (!psoc) { 209 mlme_err("PSOC is NULL"); 210 return QDF_STATUS_E_INVAL; 211 } 212 213 if (vdev_rsp->rsp_status) 214 wlan_objmgr_psoc_release_ref(psoc, WLAN_PSOC_TARGET_IF_ID); 215 216 return QDF_STATUS_SUCCESS; 217 } 218 219 static void 220 target_if_vdev_mgr_rsp_cb_mc_ctx(void *arg) 221 { 222 struct scheduler_msg msg = {0}; 223 struct vdev_response_timer *vdev_rsp = arg; 224 struct wlan_objmgr_psoc *psoc; 225 226 psoc = vdev_rsp->psoc; 227 if (!psoc) { 228 mlme_err("PSOC is NULL"); 229 return; 230 } 231 232 msg.type = SYS_MSG_ID_MC_TIMER; 233 msg.reserved = SYS_MSG_COOKIE; 234 235 /* msg.callback will explicitly cast back to qdf_mc_timer_callback_t 236 * in scheduler_timer_q_mq_handler. 237 * but in future we do not want to introduce more this kind of 238 * typecast by properly using QDF MC timer for MCC from get go in 239 * common code. 240 */ 241 msg.callback = 242 (scheduler_msg_process_fn_t)target_if_vdev_mgr_rsp_timer_cb; 243 msg.bodyptr = arg; 244 msg.bodyval = 0; 245 msg.flush_callback = target_if_vdev_mgr_rsp_flush_cb; 246 247 if (scheduler_post_message(QDF_MODULE_ID_TARGET_IF, 248 QDF_MODULE_ID_TARGET_IF, 249 QDF_MODULE_ID_SYS, &msg) == 250 QDF_STATUS_SUCCESS) 251 return; 252 253 mlme_err("Could not enqueue timer to timer queue"); 254 if (psoc) 255 wlan_objmgr_psoc_release_ref(psoc, WLAN_PSOC_TARGET_IF_ID); 256 } 257 258 void target_if_vdev_mgr_rsp_timer_mgmt_cb(void *arg) 259 { 260 target_if_vdev_mgr_rsp_cb_mc_ctx(arg); 261 } 262 263 #define VDEV_RSP_RX_CTX WMI_RX_SERIALIZER_CTX 264 #else 265 void target_if_vdev_mgr_rsp_timer_mgmt_cb(void *arg) 266 { 267 target_if_vdev_mgr_rsp_timer_cb(arg); 268 } 269 270 #define VDEV_RSP_RX_CTX WMI_RX_UMAC_CTX 271 #endif 272 273 static int target_if_vdev_mgr_start_response_handler(ol_scn_t scn, 274 uint8_t *data, 275 uint32_t datalen) 276 { 277 QDF_STATUS status = QDF_STATUS_E_INVAL; 278 struct wlan_objmgr_psoc *psoc; 279 struct wmi_unified *wmi_handle; 280 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 281 struct vdev_start_response vdev_start_resp = {0}; 282 uint8_t vdev_id; 283 struct vdev_response_timer *vdev_rsp; 284 285 if (!scn || !data) { 286 mlme_err("Invalid input"); 287 return -EINVAL; 288 } 289 290 psoc = target_if_get_psoc_from_scn_hdl(scn); 291 if (!psoc) { 292 mlme_err("PSOC is NULL"); 293 return -EINVAL; 294 } 295 296 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 297 if (!rx_ops || !rx_ops->vdev_mgr_start_response) { 298 mlme_err("No Rx Ops"); 299 return -EINVAL; 300 } 301 302 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 303 if (!wmi_handle) { 304 mlme_err("wmi_handle is null"); 305 return -EINVAL; 306 } 307 308 if (wmi_extract_vdev_start_resp(wmi_handle, data, &vdev_start_resp)) { 309 mlme_err("WMI extract failed"); 310 return -EINVAL; 311 } 312 313 vdev_id = vdev_start_resp.vdev_id; 314 vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, vdev_id); 315 if (!vdev_rsp) { 316 mlme_err("vdev response timer is null VDEV_%d PSOC_%d", 317 vdev_id, wlan_psoc_get_id(psoc)); 318 return -EINVAL; 319 } 320 321 if (vdev_start_resp.resp_type == WMI_HOST_VDEV_RESTART_RESP_EVENT) 322 status = target_if_vdev_mgr_rsp_timer_stop( 323 psoc, vdev_rsp, 324 RESTART_RESPONSE_BIT); 325 else 326 status = target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, 327 START_RESPONSE_BIT); 328 329 if (QDF_IS_STATUS_ERROR(status)) { 330 mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed", 331 psoc->soc_objmgr.psoc_id, vdev_id); 332 goto err; 333 } 334 335 status = rx_ops->vdev_mgr_start_response(psoc, &vdev_start_resp); 336 337 err: 338 return qdf_status_to_os_return(status); 339 } 340 341 static int target_if_vdev_mgr_stop_response_handler(ol_scn_t scn, 342 uint8_t *data, 343 uint32_t datalen) 344 { 345 QDF_STATUS status = QDF_STATUS_E_INVAL; 346 struct wlan_objmgr_psoc *psoc; 347 struct wmi_unified *wmi_handle; 348 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 349 struct vdev_stop_response rsp = {0}; 350 uint32_t vdev_id; 351 struct vdev_response_timer *vdev_rsp; 352 353 if (!scn || !data) { 354 mlme_err("Invalid input"); 355 return -EINVAL; 356 } 357 358 psoc = target_if_get_psoc_from_scn_hdl(scn); 359 if (!psoc) { 360 mlme_err("PSOC is NULL"); 361 return -EINVAL; 362 } 363 364 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 365 if (!rx_ops || !rx_ops->vdev_mgr_stop_response) { 366 mlme_err("No Rx Ops"); 367 return -EINVAL; 368 } 369 370 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 371 if (!wmi_handle) { 372 mlme_err("wmi_handle is null"); 373 return -EINVAL; 374 } 375 376 if (wmi_extract_vdev_stopped_param(wmi_handle, data, &vdev_id)) { 377 mlme_err("WMI extract failed"); 378 return -EINVAL; 379 } 380 381 vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, vdev_id); 382 if (!vdev_rsp) { 383 mlme_err("vdev response timer is null VDEV_%d PSOC_%d", 384 vdev_id, wlan_psoc_get_id(psoc)); 385 return -EINVAL; 386 } 387 388 status = target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, 389 STOP_RESPONSE_BIT); 390 391 if (QDF_IS_STATUS_ERROR(status)) { 392 mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed", 393 psoc->soc_objmgr.psoc_id, vdev_id); 394 goto err; 395 } 396 397 rsp.vdev_id = vdev_id; 398 status = rx_ops->vdev_mgr_stop_response(psoc, &rsp); 399 400 err: 401 return qdf_status_to_os_return(status); 402 } 403 404 static int target_if_vdev_mgr_delete_response_handler(ol_scn_t scn, 405 uint8_t *data, 406 uint32_t datalen) 407 { 408 QDF_STATUS status = QDF_STATUS_E_INVAL; 409 struct wlan_objmgr_psoc *psoc; 410 struct wmi_unified *wmi_handle; 411 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 412 struct vdev_delete_response vdev_del_resp = {0}; 413 struct vdev_response_timer *vdev_rsp; 414 415 if (!scn || !data) { 416 mlme_err("Invalid input"); 417 return -EINVAL; 418 } 419 420 psoc = target_if_get_psoc_from_scn_hdl(scn); 421 if (!psoc) { 422 mlme_err("PSOC is NULL"); 423 return -EINVAL; 424 } 425 426 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 427 if (!rx_ops || !rx_ops->vdev_mgr_delete_response) { 428 mlme_err("No Rx Ops"); 429 return -EINVAL; 430 } 431 432 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 433 if (!wmi_handle) { 434 mlme_err("wmi_handle is null"); 435 return -EINVAL; 436 } 437 438 if (wmi_extract_vdev_delete_resp(wmi_handle, data, &vdev_del_resp)) { 439 mlme_err("WMI extract failed"); 440 return -EINVAL; 441 } 442 443 vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, 444 vdev_del_resp.vdev_id); 445 if (!vdev_rsp) { 446 mlme_err("vdev response timer is null VDEV_%d PSOC_%d", 447 vdev_del_resp.vdev_id, wlan_psoc_get_id(psoc)); 448 return -EINVAL; 449 } 450 451 status = target_if_vdev_mgr_rsp_timer_stop( 452 psoc, vdev_rsp, 453 DELETE_RESPONSE_BIT); 454 455 if (QDF_IS_STATUS_ERROR(status)) { 456 mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed", 457 wlan_psoc_get_id(psoc), vdev_del_resp.vdev_id); 458 goto err; 459 } 460 461 status = rx_ops->vdev_mgr_delete_response(psoc, &vdev_del_resp); 462 target_if_wake_lock_timeout_release(psoc, DELETE_WAKELOCK); 463 err: 464 return qdf_status_to_os_return(status); 465 } 466 467 static int target_if_vdev_mgr_peer_delete_all_response_handler( 468 ol_scn_t scn, 469 uint8_t *data, 470 uint32_t datalen) 471 { 472 QDF_STATUS status = QDF_STATUS_E_INVAL; 473 struct wlan_objmgr_psoc *psoc; 474 struct wmi_unified *wmi_handle; 475 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 476 struct peer_delete_all_response vdev_peer_del_all_resp = {0}; 477 struct vdev_response_timer *vdev_rsp; 478 479 if (!scn || !data) { 480 mlme_err("Invalid input"); 481 return -EINVAL; 482 } 483 484 psoc = target_if_get_psoc_from_scn_hdl(scn); 485 if (!psoc) { 486 mlme_err("PSOC is NULL"); 487 return -EINVAL; 488 } 489 490 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 491 if (!rx_ops || !rx_ops->vdev_mgr_peer_delete_all_response) { 492 mlme_err("No Rx Ops"); 493 return -EINVAL; 494 } 495 496 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 497 if (!wmi_handle) { 498 mlme_err("wmi_handle is null"); 499 return -EINVAL; 500 } 501 502 if (wmi_extract_vdev_peer_delete_all_response_event( 503 wmi_handle, data, 504 &vdev_peer_del_all_resp)) { 505 mlme_err("WMI extract failed"); 506 return -EINVAL; 507 } 508 509 vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, 510 vdev_peer_del_all_resp.vdev_id); 511 if (!vdev_rsp) { 512 mlme_err("vdev response timer is null VDEV_%d PSOC_%d", 513 vdev_peer_del_all_resp.vdev_id, 514 wlan_psoc_get_id(psoc)); 515 return -EINVAL; 516 } 517 518 status = target_if_vdev_mgr_rsp_timer_stop( 519 psoc, 520 vdev_rsp, 521 PEER_DELETE_ALL_RESPONSE_BIT); 522 523 if (QDF_IS_STATUS_ERROR(status)) { 524 mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed", 525 psoc->soc_objmgr.psoc_id, 526 vdev_peer_del_all_resp.vdev_id); 527 goto err; 528 } 529 530 vdev_peer_del_all_resp.peer_type_bitmap = vdev_rsp->peer_type_bitmap; 531 532 status = rx_ops->vdev_mgr_peer_delete_all_response( 533 psoc, 534 &vdev_peer_del_all_resp); 535 536 err: 537 return qdf_status_to_os_return(status); 538 } 539 540 int target_if_vdev_mgr_offload_bcn_tx_status_handler( 541 ol_scn_t scn, 542 uint8_t *data, 543 uint32_t datalen) 544 { 545 QDF_STATUS status; 546 struct wlan_objmgr_psoc *psoc; 547 struct wmi_unified *wmi_handle; 548 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 549 uint32_t vdev_id, tx_status; 550 551 if (!scn || !data) { 552 mlme_err("Invalid input"); 553 return -EINVAL; 554 } 555 psoc = target_if_get_psoc_from_scn_hdl(scn); 556 if (!psoc) { 557 mlme_err("PSOC is NULL"); 558 return -EINVAL; 559 } 560 561 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 562 if (!rx_ops || !rx_ops->vdev_mgr_offload_bcn_tx_status_event_handle) { 563 mlme_err("No Rx Ops"); 564 return -EINVAL; 565 } 566 567 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 568 if (!wmi_handle) { 569 mlme_err("wmi_handle is null"); 570 return -EINVAL; 571 } 572 573 if (wmi_extract_offload_bcn_tx_status_evt(wmi_handle, data, 574 &vdev_id, &tx_status)) { 575 mlme_err("WMI extract failed"); 576 return -EINVAL; 577 } 578 579 status = rx_ops->vdev_mgr_offload_bcn_tx_status_event_handle( 580 vdev_id, 581 tx_status); 582 583 return qdf_status_to_os_return(status); 584 } 585 586 int target_if_vdev_mgr_tbttoffset_update_handler( 587 ol_scn_t scn, uint8_t *data, 588 uint32_t datalen) 589 { 590 QDF_STATUS status; 591 struct wlan_objmgr_psoc *psoc; 592 struct wmi_unified *wmi_handle; 593 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 594 uint32_t num_vdevs = 0; 595 596 if (!scn || !data) { 597 mlme_err("Invalid input"); 598 return -EINVAL; 599 } 600 psoc = target_if_get_psoc_from_scn_hdl(scn); 601 if (!psoc) { 602 mlme_err("PSOC is NULL"); 603 return -EINVAL; 604 } 605 606 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 607 if (!rx_ops || !rx_ops->vdev_mgr_tbttoffset_update_handle) { 608 mlme_err("No Rx Ops"); 609 return -EINVAL; 610 } 611 612 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 613 if (!wmi_handle) { 614 mlme_err("wmi_handle is null"); 615 return -EINVAL; 616 } 617 618 if (wmi_extract_tbttoffset_num_vdevs(wmi_handle, data, &num_vdevs)) { 619 mlme_err("WMI extract failed"); 620 return -EINVAL; 621 } 622 623 status = rx_ops->vdev_mgr_tbttoffset_update_handle(num_vdevs, 624 false); 625 626 return qdf_status_to_os_return(status); 627 } 628 629 int target_if_vdev_mgr_ext_tbttoffset_update_handler( 630 ol_scn_t scn, 631 uint8_t *data, 632 uint32_t datalen) 633 { 634 QDF_STATUS status; 635 struct wlan_objmgr_psoc *psoc; 636 struct wmi_unified *wmi_handle; 637 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 638 uint32_t num_vdevs = 0; 639 640 if (!scn || !data) { 641 mlme_err("Invalid input"); 642 return -EINVAL; 643 } 644 psoc = target_if_get_psoc_from_scn_hdl(scn); 645 if (!psoc) { 646 mlme_err("PSOC is NULL"); 647 return -EINVAL; 648 } 649 650 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 651 if (!rx_ops || !rx_ops->vdev_mgr_tbttoffset_update_handle) { 652 mlme_err("No Rx Ops"); 653 return -EINVAL; 654 } 655 656 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 657 if (!wmi_handle) { 658 mlme_err("wmi_handle is null"); 659 return -EINVAL; 660 } 661 662 if (wmi_extract_ext_tbttoffset_num_vdevs(wmi_handle, data, 663 &num_vdevs)) { 664 mlme_err("WMI extract failed"); 665 return -EINVAL; 666 } 667 668 status = rx_ops->vdev_mgr_tbttoffset_update_handle(num_vdevs, 669 true); 670 671 return qdf_status_to_os_return(status); 672 } 673 674 static int target_if_vdev_mgr_multi_vdev_restart_resp_handler( 675 ol_scn_t scn, 676 uint8_t *data, 677 uint32_t datalen) 678 { 679 QDF_STATUS status = QDF_STATUS_E_INVAL; 680 struct wlan_objmgr_psoc *psoc; 681 struct wmi_unified *wmi_handle; 682 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 683 struct multi_vdev_restart_resp restart_resp; 684 struct vdev_response_timer *vdev_rsp; 685 uint8_t max_vdevs, vdev_idx; 686 687 if (!scn || !data) { 688 mlme_err("Invalid input"); 689 return -EINVAL; 690 } 691 692 psoc = target_if_get_psoc_from_scn_hdl(scn); 693 if (!psoc) { 694 mlme_err("PSOC is NULL"); 695 return -EINVAL; 696 } 697 698 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 699 if (!rx_ops || !rx_ops->vdev_mgr_multi_vdev_restart_resp || 700 !rx_ops->psoc_get_vdev_response_timer_info) { 701 mlme_err("No Rx Ops"); 702 return -EINVAL; 703 } 704 705 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 706 if (!wmi_handle) { 707 mlme_err("wmi_handle is null"); 708 return -EINVAL; 709 } 710 711 qdf_mem_zero(&restart_resp, sizeof(restart_resp)); 712 if (wmi_extract_multi_vdev_restart_resp_event(wmi_handle, data, 713 &restart_resp)) { 714 mlme_err("WMI extract failed"); 715 return -EINVAL; 716 } 717 718 max_vdevs = wlan_psoc_get_max_vdev_count(psoc); 719 for (vdev_idx = 0; vdev_idx < max_vdevs; vdev_idx++) { 720 if (!qdf_test_bit(vdev_idx, restart_resp.vdev_id_bmap)) 721 continue; 722 723 mlme_debug("PSOC_%d VDEV_%d: Restart resp received", 724 wlan_psoc_get_id(psoc), vdev_idx); 725 vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, 726 vdev_idx); 727 if (!vdev_rsp) { 728 mlme_err("PSOC_%d VDEV_%d: VDEV RSP is NULL", 729 wlan_psoc_get_id(psoc), vdev_idx); 730 continue; 731 } 732 733 status = target_if_vdev_mgr_rsp_timer_stop( 734 psoc, vdev_rsp, RESTART_RESPONSE_BIT); 735 if (QDF_IS_STATUS_ERROR(status)) 736 mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed", 737 wlan_psoc_get_id(psoc), vdev_idx); 738 } 739 740 status = rx_ops->vdev_mgr_multi_vdev_restart_resp(psoc, &restart_resp); 741 742 return qdf_status_to_os_return(status); 743 } 744 745 /** 746 * target_if_vdev_csa_complete - CSA complete event handler 747 * @psoc: psoc 748 * @vdev_id: vdev id 749 * 750 * Return: 0 on success 751 */ 752 static int target_if_vdev_csa_complete(struct wlan_objmgr_psoc *psoc, 753 uint8_t vdev_id) 754 { 755 QDF_STATUS status = QDF_STATUS_E_FAILURE; 756 struct vdev_mlme_obj *vdev_mlme; 757 struct wlan_objmgr_vdev *vdev; 758 int ret = 0; 759 760 if (!psoc) { 761 mlme_err("Invalid input"); 762 return -EINVAL; 763 } 764 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, vdev_id, 765 WLAN_VDEV_TARGET_IF_ID); 766 if (!vdev) { 767 mlme_err("VDEV is NULL"); 768 return -EINVAL; 769 } 770 vdev_mlme = wlan_vdev_mlme_get_cmpt_obj(vdev); 771 if (!vdev_mlme) { 772 mlme_err("VDEV_%d: PSOC_%d VDEV_MLME is NULL", vdev_id, 773 wlan_psoc_get_id(psoc)); 774 ret = -EINVAL; 775 goto end; 776 } 777 778 if ((vdev_mlme->ops) && vdev_mlme->ops->mlme_vdev_csa_complete) { 779 status = vdev_mlme->ops->mlme_vdev_csa_complete(vdev_mlme); 780 if (QDF_IS_STATUS_ERROR(status)) { 781 mlme_err("vdev csa complete failed"); 782 ret = -EINVAL; 783 } 784 } 785 end: 786 wlan_objmgr_vdev_release_ref(vdev, WLAN_VDEV_TARGET_IF_ID); 787 return ret; 788 } 789 790 /** 791 * target_if_pdev_csa_status_event_handler - CSA event handler 792 * @scn: Pointer to scn structure 793 * @data: pointer to event data 794 * @datalen: event data length 795 * 796 * Return: 0 on success 797 */ 798 static int target_if_pdev_csa_status_event_handler( 799 ol_scn_t scn, 800 uint8_t *data, 801 uint32_t datalen) 802 { 803 struct pdev_csa_switch_count_status csa_status; 804 struct wlan_objmgr_psoc *psoc; 805 struct wmi_unified *wmi_handle; 806 struct target_psoc_info *tgt_hdl; 807 int i; 808 QDF_STATUS status; 809 struct wlan_lmac_if_mlme_rx_ops *rx_ops = NULL; 810 811 if (!scn || !data) { 812 mlme_err("Invalid input"); 813 return -EINVAL; 814 } 815 816 psoc = target_if_get_psoc_from_scn_hdl(scn); 817 if (!psoc) { 818 mlme_err("PSOC is NULL"); 819 return -EINVAL; 820 } 821 822 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 823 if (!rx_ops || !rx_ops->vdev_mgr_set_max_channel_switch_time) { 824 mlme_err("No Rx Ops"); 825 return -EINVAL; 826 } 827 828 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 829 if (!wmi_handle) { 830 mlme_err("wmi_handle is null"); 831 return -EINVAL; 832 } 833 834 tgt_hdl = wlan_psoc_get_tgt_if_handle(psoc); 835 if (!tgt_hdl) { 836 mlme_err("target_psoc_info is null"); 837 return -EINVAL; 838 } 839 840 qdf_mem_zero(&csa_status, sizeof(csa_status)); 841 status = wmi_extract_pdev_csa_switch_count_status( 842 wmi_handle, data, &csa_status); 843 if (QDF_IS_STATUS_ERROR(status)) { 844 mlme_err("Extracting CSA switch count status event failed"); 845 return -EINVAL; 846 } 847 848 if (csa_status.current_switch_count == 1) 849 rx_ops->vdev_mgr_set_max_channel_switch_time 850 (psoc, csa_status.vdev_ids, csa_status.num_vdevs); 851 852 if (wlan_psoc_nif_fw_ext_cap_get(psoc, WLAN_SOC_CEXT_CSA_TX_OFFLOAD)) { 853 for (i = 0; i < csa_status.num_vdevs; i++) { 854 if (!csa_status.current_switch_count) 855 target_if_vdev_csa_complete(psoc, 856 csa_status.vdev_ids[i]); 857 } 858 } 859 860 return target_if_csa_switch_count_status(psoc, tgt_hdl, csa_status); 861 } 862 863 #ifdef WLAN_FEATURE_DYNAMIC_MAC_ADDR_UPDATE 864 /** 865 * target_if_update_macaddr_conf_evt_handler() - Set MAC address confirmation 866 * event handler 867 * @scn: Pointer to scn structure 868 * @event_buff: event data 869 * @len: length 870 * 871 * Response handler for set MAC address request command. 872 * 873 * Return: 0 for success or error code 874 */ 875 static int target_if_update_macaddr_conf_evt_handler(ol_scn_t scn, 876 uint8_t *event_buff, 877 uint32_t len) 878 { 879 struct wlan_objmgr_psoc *psoc; 880 struct wmi_unified *wmi_handle; 881 uint8_t vdev_id, resp_status; 882 QDF_STATUS status; 883 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 884 885 if (!event_buff) { 886 mlme_err("Received NULL event ptr from FW"); 887 return -EINVAL; 888 } 889 890 psoc = target_if_get_psoc_from_scn_hdl(scn); 891 if (!psoc) { 892 mlme_err("PSOC is NULL"); 893 return -EINVAL; 894 } 895 896 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 897 if (!wmi_handle) { 898 mlme_err("wmi_handle is null"); 899 return -EINVAL; 900 } 901 902 status = wmi_extract_update_mac_address_event(wmi_handle, event_buff, 903 &vdev_id, &resp_status); 904 if (QDF_IS_STATUS_ERROR(status)) { 905 mlme_err("Failed to extract update MAC address event"); 906 return -EINVAL; 907 } 908 909 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 910 if (!rx_ops || !rx_ops->vdev_mgr_set_mac_addr_response) { 911 mlme_err("No Rx Ops"); 912 return -EINVAL; 913 } 914 915 rx_ops->vdev_mgr_set_mac_addr_response(vdev_id, resp_status); 916 917 return 0; 918 } 919 920 static inline void 921 target_if_register_set_mac_addr_evt_cbk(struct wmi_unified *wmi_handle) 922 { 923 wmi_unified_register_event_handler( 924 wmi_handle, wmi_vdev_update_mac_addr_conf_eventid, 925 target_if_update_macaddr_conf_evt_handler, VDEV_RSP_RX_CTX); 926 } 927 928 static inline void 929 target_if_unregister_set_mac_addr_evt_cbk(struct wmi_unified *wmi_handle) 930 { 931 wmi_unified_unregister_event_handler( 932 wmi_handle, wmi_vdev_update_mac_addr_conf_eventid); 933 } 934 #else 935 static inline void 936 target_if_register_set_mac_addr_evt_cbk(struct wmi_unified *wmi_handle) 937 { 938 } 939 940 static inline void 941 target_if_unregister_set_mac_addr_evt_cbk(struct wmi_unified *wmi_handle) 942 { 943 } 944 #endif 945 946 #ifdef WLAN_FEATURE_11BE_MLO 947 /** 948 * target_if_quiet_offload_event_handler() - Quiet IE offload mlo 949 * station event handler 950 * @scn: Pointer to scn structure 951 * @event_buff: event data 952 * @len: length 953 * 954 * Return: 0 for success or error code 955 */ 956 static int target_if_quiet_offload_event_handler(ol_scn_t scn, 957 uint8_t *event_buff, 958 uint32_t len) 959 { 960 struct wlan_objmgr_psoc *psoc; 961 struct wmi_unified *wmi_handle; 962 QDF_STATUS status; 963 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 964 struct vdev_sta_quiet_event sta_quiet_event = {0}; 965 966 if (!event_buff) { 967 mlme_err("Received NULL event ptr from FW"); 968 return -EINVAL; 969 } 970 971 psoc = target_if_get_psoc_from_scn_hdl(scn); 972 if (!psoc) { 973 mlme_err("PSOC is NULL"); 974 return -EINVAL; 975 } 976 977 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 978 if (!wmi_handle) { 979 mlme_err("wmi_handle is null"); 980 return -EINVAL; 981 } 982 983 status = wmi_extract_quiet_offload_event(wmi_handle, event_buff, 984 &sta_quiet_event); 985 if (QDF_IS_STATUS_ERROR(status)) { 986 mlme_err("Failed to extract quiet IE offload event"); 987 return -EINVAL; 988 } 989 990 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 991 if (!rx_ops || !rx_ops->vdev_mgr_quiet_offload) { 992 mlme_err("No Rx Ops"); 993 return -EINVAL; 994 } 995 996 rx_ops->vdev_mgr_quiet_offload(psoc, &sta_quiet_event); 997 998 return 0; 999 } 1000 1001 static inline void 1002 target_if_register_quiet_offload_event(struct wmi_unified *wmi_handle) 1003 { 1004 wmi_unified_register_event_handler( 1005 wmi_handle, wmi_vdev_quiet_offload_eventid, 1006 target_if_quiet_offload_event_handler, VDEV_RSP_RX_CTX); 1007 } 1008 1009 static inline void 1010 target_if_unregister_quiet_offload_event(struct wmi_unified *wmi_handle) 1011 { 1012 wmi_unified_unregister_event_handler( 1013 wmi_handle, wmi_vdev_quiet_offload_eventid); 1014 } 1015 #else 1016 static inline void 1017 target_if_register_quiet_offload_event(struct wmi_unified *wmi_handle) 1018 { 1019 } 1020 1021 static inline void 1022 target_if_unregister_quiet_offload_event(struct wmi_unified *wmi_handle) 1023 { 1024 } 1025 #endif 1026 1027 QDF_STATUS target_if_vdev_mgr_wmi_event_register( 1028 struct wlan_objmgr_psoc *psoc) 1029 { 1030 QDF_STATUS retval = QDF_STATUS_SUCCESS; 1031 struct wmi_unified *wmi_handle; 1032 1033 if (!psoc) { 1034 mlme_err("PSOC is NULL"); 1035 return QDF_STATUS_E_NULL_VALUE; 1036 } 1037 1038 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 1039 if (!wmi_handle) { 1040 mlme_err("wmi_handle is null"); 1041 return QDF_STATUS_E_INVAL; 1042 } 1043 1044 retval = wmi_unified_register_event_handler( 1045 wmi_handle, 1046 wmi_vdev_stopped_event_id, 1047 target_if_vdev_mgr_stop_response_handler, 1048 VDEV_RSP_RX_CTX); 1049 if (QDF_IS_STATUS_ERROR(retval)) 1050 mlme_err("failed to register for stop response"); 1051 1052 retval = wmi_unified_register_event_handler( 1053 wmi_handle, 1054 wmi_vdev_delete_resp_event_id, 1055 target_if_vdev_mgr_delete_response_handler, 1056 VDEV_RSP_RX_CTX); 1057 if (QDF_IS_STATUS_ERROR(retval)) 1058 mlme_err("failed to register for delete response"); 1059 1060 retval = wmi_unified_register_event_handler( 1061 wmi_handle, 1062 wmi_vdev_start_resp_event_id, 1063 target_if_vdev_mgr_start_response_handler, 1064 VDEV_RSP_RX_CTX); 1065 if (QDF_IS_STATUS_ERROR(retval)) 1066 mlme_err("failed to register for start response"); 1067 1068 retval = wmi_unified_register_event_handler( 1069 wmi_handle, 1070 wmi_peer_delete_all_response_event_id, 1071 target_if_vdev_mgr_peer_delete_all_response_handler, 1072 VDEV_RSP_RX_CTX); 1073 if (QDF_IS_STATUS_ERROR(retval)) 1074 mlme_err("failed to register for peer delete all response"); 1075 1076 retval = wmi_unified_register_event_handler( 1077 wmi_handle, 1078 wmi_pdev_multi_vdev_restart_response_event_id, 1079 target_if_vdev_mgr_multi_vdev_restart_resp_handler, 1080 VDEV_RSP_RX_CTX); 1081 if (QDF_IS_STATUS_ERROR(retval)) 1082 mlme_err("failed to register for multivdev restart response"); 1083 1084 if (wmi_service_enabled(wmi_handle, wmi_service_beacon_offload)) { 1085 retval = wmi_unified_register_event_handler( 1086 wmi_handle, 1087 wmi_pdev_csa_switch_count_status_event_id, 1088 target_if_pdev_csa_status_event_handler, 1089 VDEV_RSP_RX_CTX); 1090 if (QDF_IS_STATUS_ERROR(retval)) 1091 mlme_err("failed to register for csa event handler"); 1092 } 1093 1094 target_if_register_set_mac_addr_evt_cbk(wmi_handle); 1095 1096 target_if_register_quiet_offload_event(wmi_handle); 1097 1098 return retval; 1099 } 1100 1101 QDF_STATUS target_if_vdev_mgr_wmi_event_unregister( 1102 struct wlan_objmgr_psoc *psoc) 1103 { 1104 struct wmi_unified *wmi_handle; 1105 1106 if (!psoc) { 1107 mlme_err("PSOC is NULL"); 1108 return QDF_STATUS_E_INVAL; 1109 } 1110 1111 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 1112 if (!wmi_handle) { 1113 mlme_err("wmi_handle is null"); 1114 return QDF_STATUS_E_INVAL; 1115 } 1116 1117 target_if_unregister_quiet_offload_event(wmi_handle); 1118 1119 target_if_unregister_set_mac_addr_evt_cbk(wmi_handle); 1120 1121 wmi_unified_unregister_event_handler( 1122 wmi_handle, 1123 wmi_pdev_multi_vdev_restart_response_event_id); 1124 1125 wmi_unified_unregister_event_handler( 1126 wmi_handle, 1127 wmi_peer_delete_all_response_event_id); 1128 1129 wmi_unified_unregister_event_handler(wmi_handle, 1130 wmi_vdev_start_resp_event_id); 1131 1132 wmi_unified_unregister_event_handler(wmi_handle, 1133 wmi_vdev_delete_resp_event_id); 1134 1135 wmi_unified_unregister_event_handler(wmi_handle, 1136 wmi_vdev_stopped_event_id); 1137 1138 return QDF_STATUS_SUCCESS; 1139 } 1140