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 35 static inline 36 void target_if_vdev_mgr_handle_recovery(struct wlan_objmgr_psoc *psoc, 37 uint8_t vdev_id, 38 enum qdf_hang_reason recovery_reason, 39 uint16_t rsp_pos) 40 { 41 mlme_nofl_err("PSOC_%d VDEV_%d: %s rsp timeout", wlan_psoc_get_id(psoc), 42 vdev_id, string_from_rsp_bit(rsp_pos)); 43 if (target_if_vdev_mgr_is_panic_allowed()) 44 qdf_trigger_self_recovery(psoc, recovery_reason); 45 else 46 mlme_nofl_debug("PSOC_%d VDEV_%d: Panic not allowed", 47 wlan_psoc_get_id(psoc), vdev_id); 48 } 49 50 void target_if_vdev_mgr_rsp_timer_cb(struct vdev_response_timer *vdev_rsp) 51 { 52 struct wlan_objmgr_psoc *psoc; 53 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 54 struct vdev_start_response start_rsp = {0}; 55 struct vdev_stop_response stop_rsp = {0}; 56 struct vdev_delete_response del_rsp = {0}; 57 struct peer_delete_all_response peer_del_all_rsp = {0}; 58 enum qdf_hang_reason recovery_reason; 59 uint8_t vdev_id; 60 uint16_t rsp_pos = RESPONSE_BIT_MAX; 61 62 if (!vdev_rsp) { 63 mlme_err("Vdev response timer is NULL"); 64 return; 65 } 66 67 psoc = vdev_rsp->psoc; 68 if (!psoc) { 69 mlme_err("PSOC is NULL"); 70 return; 71 } 72 73 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 74 if (!rx_ops || !rx_ops->psoc_get_vdev_response_timer_info) { 75 mlme_err("No Rx Ops"); 76 return; 77 } 78 79 if (!qdf_atomic_test_bit(START_RESPONSE_BIT, &vdev_rsp->rsp_status) && 80 !qdf_atomic_test_bit(RESTART_RESPONSE_BIT, &vdev_rsp->rsp_status) && 81 !qdf_atomic_test_bit(STOP_RESPONSE_BIT, &vdev_rsp->rsp_status) && 82 !qdf_atomic_test_bit(DELETE_RESPONSE_BIT, &vdev_rsp->rsp_status) && 83 !qdf_atomic_test_bit( 84 PEER_DELETE_ALL_RESPONSE_BIT, 85 &vdev_rsp->rsp_status)) { 86 mlme_debug("No response bit is set, ignoring actions :%d", 87 vdev_rsp->vdev_id); 88 return; 89 } 90 91 vdev_id = vdev_rsp->vdev_id; 92 if (vdev_id >= WLAN_UMAC_PSOC_MAX_VDEVS) { 93 mlme_err("Invalid VDEV_%d PSOC_%d", vdev_id, 94 wlan_psoc_get_id(psoc)); 95 return; 96 } 97 98 vdev_rsp->timer_status = QDF_STATUS_E_TIMEOUT; 99 if (qdf_atomic_test_bit(START_RESPONSE_BIT, 100 &vdev_rsp->rsp_status) || 101 qdf_atomic_test_bit(RESTART_RESPONSE_BIT, 102 &vdev_rsp->rsp_status)) { 103 start_rsp.vdev_id = vdev_id; 104 start_rsp.status = WLAN_MLME_HOST_VDEV_START_TIMEOUT; 105 if (qdf_atomic_test_bit(START_RESPONSE_BIT, 106 &vdev_rsp->rsp_status)) { 107 start_rsp.resp_type = 108 WMI_HOST_VDEV_START_RESP_EVENT; 109 rsp_pos = START_RESPONSE_BIT; 110 recovery_reason = QDF_VDEV_START_RESPONSE_TIMED_OUT; 111 } else { 112 start_rsp.resp_type = 113 WMI_HOST_VDEV_RESTART_RESP_EVENT; 114 rsp_pos = RESTART_RESPONSE_BIT; 115 recovery_reason = QDF_VDEV_RESTART_RESPONSE_TIMED_OUT; 116 } 117 118 target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, rsp_pos); 119 target_if_vdev_mgr_handle_recovery(psoc, vdev_id, 120 recovery_reason, rsp_pos); 121 rx_ops->vdev_mgr_start_response(psoc, &start_rsp); 122 } else if (qdf_atomic_test_bit(STOP_RESPONSE_BIT, 123 &vdev_rsp->rsp_status)) { 124 rsp_pos = STOP_RESPONSE_BIT; 125 stop_rsp.vdev_id = vdev_id; 126 recovery_reason = QDF_VDEV_STOP_RESPONSE_TIMED_OUT; 127 128 target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, rsp_pos); 129 target_if_vdev_mgr_handle_recovery(psoc, vdev_id, 130 recovery_reason, rsp_pos); 131 rx_ops->vdev_mgr_stop_response(psoc, &stop_rsp); 132 } else if (qdf_atomic_test_bit(DELETE_RESPONSE_BIT, 133 &vdev_rsp->rsp_status)) { 134 del_rsp.vdev_id = vdev_id; 135 rsp_pos = DELETE_RESPONSE_BIT; 136 recovery_reason = QDF_VDEV_DELETE_RESPONSE_TIMED_OUT; 137 target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, rsp_pos); 138 target_if_vdev_mgr_handle_recovery(psoc, vdev_id, 139 recovery_reason, rsp_pos); 140 rx_ops->vdev_mgr_delete_response(psoc, &del_rsp); 141 } else if (qdf_atomic_test_bit(PEER_DELETE_ALL_RESPONSE_BIT, 142 &vdev_rsp->rsp_status)) { 143 peer_del_all_rsp.vdev_id = vdev_id; 144 rsp_pos = PEER_DELETE_ALL_RESPONSE_BIT; 145 recovery_reason = QDF_VDEV_PEER_DELETE_ALL_RESPONSE_TIMED_OUT; 146 target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, rsp_pos); 147 target_if_vdev_mgr_handle_recovery(psoc, vdev_id, 148 recovery_reason, rsp_pos); 149 rx_ops->vdev_mgr_peer_delete_all_response(psoc, 150 &peer_del_all_rsp); 151 } else { 152 mlme_err("PSOC_%d VDEV_%d: Unknown error", 153 wlan_psoc_get_id(psoc), vdev_id); 154 return; 155 } 156 } 157 158 #ifdef SERIALIZE_VDEV_RESP 159 static QDF_STATUS target_if_vdev_mgr_rsp_flush_cb(struct scheduler_msg *msg) 160 { 161 struct vdev_response_timer *vdev_rsp; 162 struct wlan_objmgr_psoc *psoc; 163 164 if (!msg->bodyptr) { 165 mlme_err("Message bodyptr is NULL"); 166 return QDF_STATUS_E_INVAL; 167 } 168 169 vdev_rsp = msg->bodyptr; 170 if (!vdev_rsp) { 171 mlme_err("vdev response timer is NULL"); 172 return QDF_STATUS_E_INVAL; 173 } 174 175 psoc = vdev_rsp->psoc; 176 if (!psoc) { 177 mlme_err("PSOC is NULL"); 178 return QDF_STATUS_E_INVAL; 179 } 180 181 if (vdev_rsp->rsp_status) 182 wlan_objmgr_psoc_release_ref(psoc, WLAN_PSOC_TARGET_IF_ID); 183 184 return QDF_STATUS_SUCCESS; 185 } 186 187 static void 188 target_if_vdev_mgr_rsp_cb_mc_ctx(void *arg) 189 { 190 struct scheduler_msg msg = {0}; 191 struct vdev_response_timer *vdev_rsp = arg; 192 struct wlan_objmgr_psoc *psoc; 193 194 psoc = vdev_rsp->psoc; 195 if (!psoc) { 196 mlme_err("PSOC is NULL"); 197 return; 198 } 199 200 msg.type = SYS_MSG_ID_MC_TIMER; 201 msg.reserved = SYS_MSG_COOKIE; 202 msg.callback = target_if_vdev_mgr_rsp_timer_cb; 203 msg.bodyptr = vdev_rsp; 204 msg.bodyval = 0; 205 msg.flush_callback = target_if_vdev_mgr_rsp_flush_cb; 206 207 if (scheduler_post_message(QDF_MODULE_ID_TARGET_IF, 208 QDF_MODULE_ID_TARGET_IF, 209 QDF_MODULE_ID_SYS, &msg) == 210 QDF_STATUS_SUCCESS) 211 return; 212 213 mlme_err("Could not enqueue timer to timer queue"); 214 if (psoc) 215 wlan_objmgr_psoc_release_ref(psoc, WLAN_PSOC_TARGET_IF_ID); 216 } 217 218 void target_if_vdev_mgr_rsp_timer_mgmt_cb(void *arg) 219 { 220 target_if_vdev_mgr_rsp_cb_mc_ctx(arg); 221 } 222 223 #define VDEV_RSP_RX_CTX WMI_RX_SERIALIZER_CTX 224 #else 225 void target_if_vdev_mgr_rsp_timer_mgmt_cb(void *arg) 226 { 227 target_if_vdev_mgr_rsp_timer_cb(arg); 228 } 229 230 #define VDEV_RSP_RX_CTX WMI_RX_UMAC_CTX 231 #endif 232 233 static int target_if_vdev_mgr_start_response_handler(ol_scn_t scn, 234 uint8_t *data, 235 uint32_t datalen) 236 { 237 QDF_STATUS status = QDF_STATUS_E_INVAL; 238 struct wlan_objmgr_psoc *psoc; 239 struct wmi_unified *wmi_handle; 240 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 241 struct vdev_start_response vdev_start_resp = {0}; 242 uint8_t vdev_id; 243 struct vdev_response_timer *vdev_rsp; 244 245 if (!scn || !data) { 246 mlme_err("Invalid input"); 247 return -EINVAL; 248 } 249 250 psoc = target_if_get_psoc_from_scn_hdl(scn); 251 if (!psoc) { 252 mlme_err("PSOC is NULL"); 253 return -EINVAL; 254 } 255 256 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 257 if (!rx_ops || !rx_ops->vdev_mgr_start_response) { 258 mlme_err("No Rx Ops"); 259 return -EINVAL; 260 } 261 262 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 263 if (!wmi_handle) { 264 mlme_err("wmi_handle is null"); 265 return -EINVAL; 266 } 267 268 if (wmi_extract_vdev_start_resp(wmi_handle, data, &vdev_start_resp)) { 269 mlme_err("WMI extract failed"); 270 return -EINVAL; 271 } 272 273 vdev_id = vdev_start_resp.vdev_id; 274 vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, vdev_id); 275 if (!vdev_rsp) { 276 mlme_err("vdev response timer is null VDEV_%d PSOC_%d", 277 vdev_id, wlan_psoc_get_id(psoc)); 278 return -EINVAL; 279 } 280 281 if (vdev_start_resp.resp_type == WMI_HOST_VDEV_RESTART_RESP_EVENT) 282 status = target_if_vdev_mgr_rsp_timer_stop( 283 psoc, vdev_rsp, 284 RESTART_RESPONSE_BIT); 285 else 286 status = target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, 287 START_RESPONSE_BIT); 288 289 if (QDF_IS_STATUS_ERROR(status)) { 290 mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed", 291 psoc->soc_objmgr.psoc_id, vdev_id); 292 goto err; 293 } 294 295 status = rx_ops->vdev_mgr_start_response(psoc, &vdev_start_resp); 296 297 err: 298 return qdf_status_to_os_return(status); 299 } 300 301 static int target_if_vdev_mgr_stop_response_handler(ol_scn_t scn, 302 uint8_t *data, 303 uint32_t datalen) 304 { 305 QDF_STATUS status = QDF_STATUS_E_INVAL; 306 struct wlan_objmgr_psoc *psoc; 307 struct wmi_unified *wmi_handle; 308 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 309 struct vdev_stop_response rsp = {0}; 310 uint32_t vdev_id; 311 struct vdev_response_timer *vdev_rsp; 312 313 if (!scn || !data) { 314 mlme_err("Invalid input"); 315 return -EINVAL; 316 } 317 318 psoc = target_if_get_psoc_from_scn_hdl(scn); 319 if (!psoc) { 320 mlme_err("PSOC is NULL"); 321 return -EINVAL; 322 } 323 324 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 325 if (!rx_ops || !rx_ops->vdev_mgr_stop_response) { 326 mlme_err("No Rx Ops"); 327 return -EINVAL; 328 } 329 330 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 331 if (!wmi_handle) { 332 mlme_err("wmi_handle is null"); 333 return -EINVAL; 334 } 335 336 if (wmi_extract_vdev_stopped_param(wmi_handle, data, &vdev_id)) { 337 mlme_err("WMI extract failed"); 338 return -EINVAL; 339 } 340 341 vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, vdev_id); 342 if (!vdev_rsp) { 343 mlme_err("vdev response timer is null VDEV_%d PSOC_%d", 344 vdev_id, wlan_psoc_get_id(psoc)); 345 return -EINVAL; 346 } 347 348 status = target_if_vdev_mgr_rsp_timer_stop(psoc, vdev_rsp, 349 STOP_RESPONSE_BIT); 350 351 if (QDF_IS_STATUS_ERROR(status)) { 352 mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed", 353 psoc->soc_objmgr.psoc_id, vdev_id); 354 goto err; 355 } 356 357 rsp.vdev_id = vdev_id; 358 status = rx_ops->vdev_mgr_stop_response(psoc, &rsp); 359 360 err: 361 return qdf_status_to_os_return(status); 362 } 363 364 static int target_if_vdev_mgr_delete_response_handler(ol_scn_t scn, 365 uint8_t *data, 366 uint32_t datalen) 367 { 368 QDF_STATUS status = QDF_STATUS_E_INVAL; 369 struct wlan_objmgr_psoc *psoc; 370 struct wmi_unified *wmi_handle; 371 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 372 struct vdev_delete_response vdev_del_resp = {0}; 373 struct vdev_response_timer *vdev_rsp; 374 375 if (!scn || !data) { 376 mlme_err("Invalid input"); 377 return -EINVAL; 378 } 379 380 psoc = target_if_get_psoc_from_scn_hdl(scn); 381 if (!psoc) { 382 mlme_err("PSOC is NULL"); 383 return -EINVAL; 384 } 385 386 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 387 if (!rx_ops || !rx_ops->vdev_mgr_delete_response) { 388 mlme_err("No Rx Ops"); 389 return -EINVAL; 390 } 391 392 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 393 if (!wmi_handle) { 394 mlme_err("wmi_handle is null"); 395 return -EINVAL; 396 } 397 398 if (wmi_extract_vdev_delete_resp(wmi_handle, data, &vdev_del_resp)) { 399 mlme_err("WMI extract failed"); 400 return -EINVAL; 401 } 402 403 vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, 404 vdev_del_resp.vdev_id); 405 if (!vdev_rsp) { 406 mlme_err("vdev response timer is null VDEV_%d PSOC_%d", 407 vdev_del_resp.vdev_id, wlan_psoc_get_id(psoc)); 408 return -EINVAL; 409 } 410 411 status = target_if_vdev_mgr_rsp_timer_stop( 412 psoc, vdev_rsp, 413 DELETE_RESPONSE_BIT); 414 415 if (QDF_IS_STATUS_ERROR(status)) { 416 mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed", 417 wlan_psoc_get_id(psoc), vdev_del_resp.vdev_id); 418 goto err; 419 } 420 421 status = rx_ops->vdev_mgr_delete_response(psoc, &vdev_del_resp); 422 423 err: 424 return qdf_status_to_os_return(status); 425 } 426 427 static int target_if_vdev_mgr_peer_delete_all_response_handler( 428 ol_scn_t scn, 429 uint8_t *data, 430 uint32_t datalen) 431 { 432 QDF_STATUS status = QDF_STATUS_E_INVAL; 433 struct wlan_objmgr_psoc *psoc; 434 struct wmi_unified *wmi_handle; 435 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 436 struct peer_delete_all_response vdev_peer_del_all_resp = {0}; 437 struct vdev_response_timer *vdev_rsp; 438 439 if (!scn || !data) { 440 mlme_err("Invalid input"); 441 return -EINVAL; 442 } 443 444 psoc = target_if_get_psoc_from_scn_hdl(scn); 445 if (!psoc) { 446 mlme_err("PSOC is NULL"); 447 return -EINVAL; 448 } 449 450 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 451 if (!rx_ops || !rx_ops->vdev_mgr_peer_delete_all_response) { 452 mlme_err("No Rx Ops"); 453 return -EINVAL; 454 } 455 456 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 457 if (!wmi_handle) { 458 mlme_err("wmi_handle is null"); 459 return -EINVAL; 460 } 461 462 if (wmi_extract_vdev_peer_delete_all_response_event( 463 wmi_handle, data, 464 &vdev_peer_del_all_resp)) { 465 mlme_err("WMI extract failed"); 466 return -EINVAL; 467 } 468 469 vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, 470 vdev_peer_del_all_resp.vdev_id); 471 if (!vdev_rsp) { 472 mlme_err("vdev response timer is null VDEV_%d PSOC_%d", 473 vdev_peer_del_all_resp.vdev_id, 474 wlan_psoc_get_id(psoc)); 475 return -EINVAL; 476 } 477 478 status = target_if_vdev_mgr_rsp_timer_stop( 479 psoc, 480 vdev_rsp, 481 PEER_DELETE_ALL_RESPONSE_BIT); 482 483 if (QDF_IS_STATUS_ERROR(status)) { 484 mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed", 485 psoc->soc_objmgr.psoc_id, 486 vdev_peer_del_all_resp.vdev_id); 487 goto err; 488 } 489 490 status = rx_ops->vdev_mgr_peer_delete_all_response( 491 psoc, 492 &vdev_peer_del_all_resp); 493 494 err: 495 return qdf_status_to_os_return(status); 496 } 497 498 int target_if_vdev_mgr_offload_bcn_tx_status_handler( 499 ol_scn_t scn, 500 uint8_t *data, 501 uint32_t datalen) 502 { 503 QDF_STATUS status; 504 struct wlan_objmgr_psoc *psoc; 505 struct wmi_unified *wmi_handle; 506 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 507 uint32_t vdev_id, tx_status; 508 509 if (!scn || !data) { 510 mlme_err("Invalid input"); 511 return -EINVAL; 512 } 513 psoc = target_if_get_psoc_from_scn_hdl(scn); 514 if (!psoc) { 515 mlme_err("PSOC is NULL"); 516 return -EINVAL; 517 } 518 519 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 520 if (!rx_ops || !rx_ops->vdev_mgr_offload_bcn_tx_status_event_handle) { 521 mlme_err("No Rx Ops"); 522 return -EINVAL; 523 } 524 525 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 526 if (!wmi_handle) { 527 mlme_err("wmi_handle is null"); 528 return -EINVAL; 529 } 530 531 if (wmi_extract_offload_bcn_tx_status_evt(wmi_handle, data, 532 &vdev_id, &tx_status)) { 533 mlme_err("WMI extract failed"); 534 return -EINVAL; 535 } 536 537 status = rx_ops->vdev_mgr_offload_bcn_tx_status_event_handle( 538 vdev_id, 539 tx_status); 540 541 return qdf_status_to_os_return(status); 542 } 543 544 int target_if_vdev_mgr_tbttoffset_update_handler( 545 ol_scn_t scn, uint8_t *data, 546 uint32_t datalen) 547 { 548 QDF_STATUS status; 549 struct wlan_objmgr_psoc *psoc; 550 struct wmi_unified *wmi_handle; 551 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 552 uint32_t num_vdevs = 0; 553 554 if (!scn || !data) { 555 mlme_err("Invalid input"); 556 return -EINVAL; 557 } 558 psoc = target_if_get_psoc_from_scn_hdl(scn); 559 if (!psoc) { 560 mlme_err("PSOC is NULL"); 561 return -EINVAL; 562 } 563 564 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 565 if (!rx_ops || !rx_ops->vdev_mgr_tbttoffset_update_handle) { 566 mlme_err("No Rx Ops"); 567 return -EINVAL; 568 } 569 570 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 571 if (!wmi_handle) { 572 mlme_err("wmi_handle is null"); 573 return -EINVAL; 574 } 575 576 if (wmi_extract_tbttoffset_num_vdevs(wmi_handle, data, &num_vdevs)) { 577 mlme_err("WMI extract failed"); 578 return -EINVAL; 579 } 580 581 status = rx_ops->vdev_mgr_tbttoffset_update_handle(num_vdevs, 582 false); 583 584 return qdf_status_to_os_return(status); 585 } 586 587 int target_if_vdev_mgr_ext_tbttoffset_update_handler( 588 ol_scn_t scn, 589 uint8_t *data, 590 uint32_t datalen) 591 { 592 QDF_STATUS status; 593 struct wlan_objmgr_psoc *psoc; 594 struct wmi_unified *wmi_handle; 595 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 596 uint32_t num_vdevs = 0; 597 598 if (!scn || !data) { 599 mlme_err("Invalid input"); 600 return -EINVAL; 601 } 602 psoc = target_if_get_psoc_from_scn_hdl(scn); 603 if (!psoc) { 604 mlme_err("PSOC is NULL"); 605 return -EINVAL; 606 } 607 608 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 609 if (!rx_ops || !rx_ops->vdev_mgr_tbttoffset_update_handle) { 610 mlme_err("No Rx Ops"); 611 return -EINVAL; 612 } 613 614 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 615 if (!wmi_handle) { 616 mlme_err("wmi_handle is null"); 617 return -EINVAL; 618 } 619 620 if (wmi_extract_ext_tbttoffset_num_vdevs(wmi_handle, data, 621 &num_vdevs)) { 622 mlme_err("WMI extract failed"); 623 return -EINVAL; 624 } 625 626 status = rx_ops->vdev_mgr_tbttoffset_update_handle(num_vdevs, 627 true); 628 629 return qdf_status_to_os_return(status); 630 } 631 632 static int target_if_vdev_mgr_multi_vdev_restart_resp_handler( 633 ol_scn_t scn, 634 uint8_t *data, 635 uint32_t datalen) 636 { 637 QDF_STATUS status = QDF_STATUS_E_INVAL; 638 struct wlan_objmgr_psoc *psoc; 639 struct wmi_unified *wmi_handle; 640 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 641 struct multi_vdev_restart_resp restart_resp; 642 struct vdev_response_timer *vdev_rsp; 643 uint8_t max_vdevs, vdev_idx; 644 645 if (!scn || !data) { 646 mlme_err("Invalid input"); 647 return -EINVAL; 648 } 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_multi_vdev_restart_resp || 658 !rx_ops->psoc_get_vdev_response_timer_info) { 659 mlme_err("No Rx Ops"); 660 return -EINVAL; 661 } 662 663 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 664 if (!wmi_handle) { 665 mlme_err("wmi_handle is null"); 666 return -EINVAL; 667 } 668 669 qdf_mem_zero(&restart_resp, sizeof(restart_resp)); 670 if (wmi_extract_multi_vdev_restart_resp_event(wmi_handle, data, 671 &restart_resp)) { 672 mlme_err("WMI extract failed"); 673 return -EINVAL; 674 } 675 676 max_vdevs = wlan_psoc_get_max_vdev_count(psoc); 677 for (vdev_idx = 0; vdev_idx < max_vdevs; vdev_idx++) { 678 if (!qdf_test_bit(vdev_idx, restart_resp.vdev_id_bmap)) 679 continue; 680 681 mlme_debug("PSOC_%d VDEV_%d: Restart resp received", 682 wlan_psoc_get_id(psoc), vdev_idx); 683 vdev_rsp = rx_ops->psoc_get_vdev_response_timer_info(psoc, 684 vdev_idx); 685 if (!vdev_rsp) { 686 mlme_err("PSOC_%d VDEV_%d: VDEV RSP is NULL", 687 wlan_psoc_get_id(psoc), vdev_idx); 688 continue; 689 } 690 691 status = target_if_vdev_mgr_rsp_timer_stop( 692 psoc, vdev_rsp, RESTART_RESPONSE_BIT); 693 if (QDF_IS_STATUS_ERROR(status)) 694 mlme_err("PSOC_%d VDEV_%d: VDE MGR RSP Timer stop failed", 695 wlan_psoc_get_id(psoc), vdev_idx); 696 } 697 698 status = rx_ops->vdev_mgr_multi_vdev_restart_resp(psoc, &restart_resp); 699 700 return qdf_status_to_os_return(status); 701 } 702 703 QDF_STATUS target_if_vdev_mgr_wmi_event_register( 704 struct wlan_objmgr_psoc *psoc) 705 { 706 int retval = 0; 707 struct wmi_unified *wmi_handle; 708 709 if (!psoc) { 710 mlme_err("PSOC is NULL"); 711 return QDF_STATUS_E_NULL_VALUE; 712 } 713 714 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 715 if (!wmi_handle) { 716 mlme_err("wmi_handle is null"); 717 return QDF_STATUS_E_INVAL; 718 } 719 720 retval = wmi_unified_register_event_handler( 721 wmi_handle, 722 wmi_vdev_stopped_event_id, 723 target_if_vdev_mgr_stop_response_handler, 724 VDEV_RSP_RX_CTX); 725 if (retval) 726 mlme_err("failed to register for stop response"); 727 728 retval = wmi_unified_register_event_handler( 729 wmi_handle, 730 wmi_vdev_delete_resp_event_id, 731 target_if_vdev_mgr_delete_response_handler, 732 VDEV_RSP_RX_CTX); 733 if (retval) 734 mlme_err("failed to register for delete response"); 735 736 retval = wmi_unified_register_event_handler( 737 wmi_handle, 738 wmi_vdev_start_resp_event_id, 739 target_if_vdev_mgr_start_response_handler, 740 VDEV_RSP_RX_CTX); 741 if (retval) 742 mlme_err("failed to register for start response"); 743 744 retval = wmi_unified_register_event_handler( 745 wmi_handle, 746 wmi_peer_delete_all_response_event_id, 747 target_if_vdev_mgr_peer_delete_all_response_handler, 748 VDEV_RSP_RX_CTX); 749 if (retval) 750 mlme_err("failed to register for peer delete all response"); 751 752 retval = wmi_unified_register_event_handler( 753 wmi_handle, 754 wmi_pdev_multi_vdev_restart_response_event_id, 755 target_if_vdev_mgr_multi_vdev_restart_resp_handler, 756 VDEV_RSP_RX_CTX); 757 if (retval) 758 mlme_err("failed to register for multivdev restart response"); 759 760 return qdf_status_from_os_return(retval); 761 } 762 763 QDF_STATUS target_if_vdev_mgr_wmi_event_unregister( 764 struct wlan_objmgr_psoc *psoc) 765 { 766 struct wmi_unified *wmi_handle; 767 768 if (!psoc) { 769 mlme_err("PSOC is NULL"); 770 return QDF_STATUS_E_INVAL; 771 } 772 773 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 774 if (!wmi_handle) { 775 mlme_err("wmi_handle is null"); 776 return QDF_STATUS_E_INVAL; 777 } 778 779 wmi_unified_unregister_event_handler( 780 wmi_handle, 781 wmi_pdev_multi_vdev_restart_response_event_id); 782 783 wmi_unified_unregister_event_handler( 784 wmi_handle, 785 wmi_peer_delete_all_response_event_id); 786 787 wmi_unified_unregister_event_handler(wmi_handle, 788 wmi_vdev_start_resp_event_id); 789 790 wmi_unified_unregister_event_handler(wmi_handle, 791 wmi_vdev_delete_resp_event_id); 792 793 wmi_unified_unregister_event_handler(wmi_handle, 794 wmi_vdev_stopped_event_id); 795 796 return QDF_STATUS_SUCCESS; 797 } 798