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