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