1 /* 2 * Copyright (c) 2019 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 <qdf_platform.h> 33 #include <wlan_vdev_mlme_main.h> 34 35 void target_if_vdev_mgr_rsp_timer_mgmt_cb(void *arg) 36 { 37 struct wlan_objmgr_vdev *vdev = arg; 38 struct wlan_objmgr_psoc *psoc; 39 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 40 struct vdev_response_timer *vdev_rsp; 41 struct crash_inject param; 42 struct wmi_unified *wmi_handle; 43 struct vdev_start_response start_rsp = {0}; 44 struct vdev_stop_response stop_rsp = {0}; 45 struct vdev_delete_response del_rsp = {0}; 46 uint8_t vdev_id; 47 48 vdev_id = wlan_vdev_get_id(vdev); 49 mlme_debug("Response timer expired for VDEV %d", vdev_id); 50 51 psoc = wlan_vdev_get_psoc(vdev); 52 if (!psoc) { 53 mlme_err("PSOC is NULL"); 54 return; 55 } 56 57 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 58 if (!rx_ops || !rx_ops->vdev_mgr_get_response_timer_info) { 59 mlme_err("No Rx Ops"); 60 return; 61 } 62 63 vdev_rsp = rx_ops->vdev_mgr_get_response_timer_info(vdev); 64 if (!qdf_atomic_test_bit(START_RESPONSE_BIT, &vdev_rsp->rsp_status) && 65 !qdf_atomic_test_bit(RESTART_RESPONSE_BIT, &vdev_rsp->rsp_status) && 66 !qdf_atomic_test_bit(STOP_RESPONSE_BIT, &vdev_rsp->rsp_status) && 67 !qdf_atomic_test_bit(DELETE_RESPONSE_BIT, &vdev_rsp->rsp_status)) { 68 mlme_debug("No response bit is set, ignoring actions"); 69 return; 70 } 71 72 if (target_if_vdev_mgr_is_driver_unloading() || qdf_is_recovering() || 73 qdf_is_fw_down()) { 74 /* this ensures stop timer will not be done in target_if */ 75 vdev_rsp->timer_status = QDF_STATUS_E_TIMEOUT; 76 if (qdf_atomic_test_bit(START_RESPONSE_BIT, 77 &vdev_rsp->rsp_status) || 78 qdf_atomic_test_bit(RESTART_RESPONSE_BIT, 79 &vdev_rsp->rsp_status)) { 80 start_rsp.vdev_id = wlan_vdev_get_id(vdev); 81 start_rsp.status = WLAN_MLME_HOST_VDEV_START_TIMEOUT; 82 if (qdf_atomic_test_bit(START_RESPONSE_BIT, 83 &vdev_rsp->rsp_status)) 84 start_rsp.resp_type = 85 WMI_HOST_VDEV_START_RESP_EVENT; 86 else 87 start_rsp.resp_type = 88 WMI_HOST_VDEV_RESTART_RESP_EVENT; 89 90 rx_ops->vdev_mgr_start_response(psoc, &start_rsp); 91 } 92 93 if (qdf_atomic_test_bit(STOP_RESPONSE_BIT, 94 &vdev_rsp->rsp_status)) { 95 stop_rsp.vdev_id = wlan_vdev_get_id(vdev); 96 rx_ops->vdev_mgr_stop_response(psoc, &stop_rsp); 97 } 98 99 if (qdf_atomic_test_bit(DELETE_RESPONSE_BIT, 100 &vdev_rsp->rsp_status)) { 101 del_rsp.vdev_id = wlan_vdev_get_id(vdev); 102 rx_ops->vdev_mgr_delete_response(psoc, &del_rsp); 103 } 104 105 return; 106 } 107 108 if (target_if_vdev_mgr_is_panic_on_bug()) { 109 QDF_DEBUG_PANIC("PSOC_%d VDEV_%d: Panic on bug, rsp status:%d", 110 wlan_psoc_get_id(psoc), 111 vdev_id, vdev_rsp->rsp_status); 112 } else { 113 mlme_err("PSOC_%d VDEV_%d: Trigger Self recovery, rsp status%d", 114 wlan_psoc_get_id(psoc), 115 vdev_id, vdev_rsp->rsp_status); 116 wmi_handle = target_if_vdev_mgr_wmi_handle_get(vdev); 117 118 qdf_mem_set(¶m, sizeof(param), 0); 119 /* RECOVERY_SIM_SELF_RECOVERY*/ 120 param.type = 0x08; 121 wmi_crash_inject(wmi_handle, ¶m); 122 } 123 } 124 125 static int target_if_vdev_mgr_start_response_handler( 126 ol_scn_t scn, 127 uint8_t *data, 128 uint32_t datalen) 129 { 130 QDF_STATUS status; 131 struct wlan_objmgr_psoc *psoc; 132 struct wmi_unified *wmi_handle; 133 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 134 struct vdev_start_response rsp = {0}; 135 wmi_host_vdev_start_resp vdev_start_resp; 136 137 if (!scn || !data) { 138 mlme_err("scn: 0x%pK, data: 0x%pK", scn, data); 139 return -EINVAL; 140 } 141 142 psoc = target_if_get_psoc_from_scn_hdl(scn); 143 if (!psoc) { 144 mlme_err("PSOC is NULL"); 145 return -EINVAL; 146 } 147 148 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 149 if (!rx_ops || !rx_ops->vdev_mgr_start_response) { 150 mlme_err("No Rx Ops"); 151 return -EINVAL; 152 } 153 154 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 155 if (!wmi_handle) { 156 mlme_err("wmi_handle is null"); 157 return -EINVAL; 158 } 159 160 if (wmi_extract_vdev_start_resp(wmi_handle, data, &vdev_start_resp)) { 161 mlme_err("WMI extract failed"); 162 return -EINVAL; 163 } 164 165 rsp.vdev_id = vdev_start_resp.vdev_id; 166 rsp.requestor_id = vdev_start_resp.requestor_id; 167 rsp.status = vdev_start_resp.status; 168 rsp.resp_type = vdev_start_resp.resp_type; 169 rsp.chain_mask = vdev_start_resp.chain_mask; 170 rsp.smps_mode = vdev_start_resp.smps_mode; 171 rsp.mac_id = vdev_start_resp.mac_id; 172 rsp.cfgd_tx_streams = vdev_start_resp.cfgd_tx_streams; 173 rsp.cfgd_rx_streams = vdev_start_resp.cfgd_rx_streams; 174 175 status = rx_ops->vdev_mgr_start_response(psoc, &rsp); 176 177 return qdf_status_to_os_return(status); 178 } 179 180 static int target_if_vdev_mgr_stop_response_handler( 181 ol_scn_t scn, 182 uint8_t *data, 183 uint32_t datalen) 184 { 185 QDF_STATUS status; 186 struct wlan_objmgr_psoc *psoc; 187 struct wmi_unified *wmi_handle; 188 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 189 struct vdev_stop_response rsp = {0}; 190 uint32_t vdev_id; 191 192 if (!scn || !data) { 193 mlme_err("scn: 0x%pK, data: 0x%pK", scn, data); 194 return -EINVAL; 195 } 196 197 psoc = target_if_get_psoc_from_scn_hdl(scn); 198 if (!psoc) { 199 mlme_err("PSOC is NULL"); 200 return -EINVAL; 201 } 202 203 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 204 if (!rx_ops || !rx_ops->vdev_mgr_stop_response) { 205 mlme_err("No Rx Ops"); 206 return -EINVAL; 207 } 208 209 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 210 if (!wmi_handle) { 211 mlme_err("wmi_handle is null"); 212 return -EINVAL; 213 } 214 215 if (wmi_extract_vdev_stopped_param(wmi_handle, data, &vdev_id)) { 216 mlme_err("WMI extract failed"); 217 return -EINVAL; 218 } 219 220 rsp.vdev_id = vdev_id; 221 status = rx_ops->vdev_mgr_stop_response(psoc, &rsp); 222 223 return qdf_status_to_os_return(status); 224 } 225 226 static int target_if_vdev_mgr_delete_response_handler( 227 ol_scn_t scn, 228 uint8_t *data, 229 uint32_t datalen) 230 { 231 QDF_STATUS status; 232 struct wlan_objmgr_psoc *psoc; 233 struct wmi_unified *wmi_handle; 234 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 235 struct vdev_delete_response rsp = {0}; 236 struct wmi_host_vdev_delete_resp vdev_del_resp; 237 238 if (!scn || !data) { 239 mlme_err("scn: 0x%pK, data: 0x%pK", scn, data); 240 return -EINVAL; 241 } 242 243 psoc = target_if_get_psoc_from_scn_hdl(scn); 244 if (!psoc) { 245 mlme_err("PSOC is NULL"); 246 return -EINVAL; 247 } 248 249 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 250 if (!rx_ops || !rx_ops->vdev_mgr_stop_response || 251 !rx_ops->vdev_mgr_get_response_timer_info) { 252 mlme_err("No Rx Ops"); 253 return -EINVAL; 254 } 255 256 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 257 if (!wmi_handle) { 258 mlme_err("wmi_handle is null"); 259 return -EINVAL; 260 } 261 262 if (wmi_extract_vdev_delete_resp(wmi_handle, data, &vdev_del_resp)) { 263 mlme_err("WMI extract failed"); 264 return -EINVAL; 265 } 266 267 rsp.vdev_id = vdev_del_resp.vdev_id; 268 status = rx_ops->vdev_mgr_delete_response(psoc, &rsp); 269 270 return qdf_status_to_os_return(status); 271 } 272 273 static int target_if_vdev_mgr_offload_bcn_tx_status_handler( 274 ol_scn_t scn, 275 uint8_t *data, 276 uint32_t datalen) 277 { 278 QDF_STATUS status; 279 struct wlan_objmgr_psoc *psoc; 280 struct wmi_unified *wmi_handle; 281 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 282 uint32_t vdev_id, tx_status; 283 284 if (!scn || !data) { 285 mlme_err("scn: 0x%pK, data: 0x%pK", scn, data); 286 return -EINVAL; 287 } 288 psoc = target_if_get_psoc_from_scn_hdl(scn); 289 if (!psoc) { 290 mlme_err("PSOC is NULL"); 291 return -EINVAL; 292 } 293 294 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 295 if (!rx_ops || !rx_ops->vdev_mgr_offload_bcn_tx_status_event_handle) { 296 mlme_err("No Rx Ops"); 297 return -EINVAL; 298 } 299 300 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 301 if (!wmi_handle) { 302 mlme_err("wmi_handle is null"); 303 return -EINVAL; 304 } 305 306 if (wmi_extract_offload_bcn_tx_status_evt(wmi_handle, data, 307 &vdev_id, &tx_status)) { 308 mlme_err("WMI extract failed"); 309 return -EINVAL; 310 } 311 312 status = rx_ops->vdev_mgr_offload_bcn_tx_status_event_handle( 313 vdev_id, 314 tx_status); 315 316 return qdf_status_to_os_return(status); 317 } 318 319 static int target_if_vdev_mgr_tbttoffset_update_handler( 320 ol_scn_t scn, 321 uint8_t *data, 322 uint32_t datalen) 323 { 324 QDF_STATUS status; 325 struct wlan_objmgr_psoc *psoc; 326 struct wmi_unified *wmi_handle; 327 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 328 uint32_t num_vdevs = 0; 329 330 if (!scn || !data) { 331 mlme_err("scn: 0x%pK, data: 0x%pK", scn, data); 332 return -EINVAL; 333 } 334 psoc = target_if_get_psoc_from_scn_hdl(scn); 335 if (!psoc) { 336 mlme_err("PSOC is NULL"); 337 return -EINVAL; 338 } 339 340 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 341 if (!rx_ops || !rx_ops->vdev_mgr_tbttoffset_update_handle) { 342 mlme_err("No Rx Ops"); 343 return -EINVAL; 344 } 345 346 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 347 if (!wmi_handle) { 348 mlme_err("wmi_handle is null"); 349 return -EINVAL; 350 } 351 352 if (wmi_extract_tbttoffset_num_vdevs(wmi_handle, data, &num_vdevs)) { 353 mlme_err("WMI extract failed"); 354 return -EINVAL; 355 } 356 357 status = rx_ops->vdev_mgr_tbttoffset_update_handle(num_vdevs, false); 358 359 return qdf_status_to_os_return(status); 360 } 361 362 static int target_if_vdev_mgr_ext_tbttoffset_update_handler( 363 ol_scn_t scn, 364 uint8_t *data, 365 uint32_t datalen) 366 { 367 QDF_STATUS status; 368 struct wlan_objmgr_psoc *psoc; 369 struct wmi_unified *wmi_handle; 370 struct wlan_lmac_if_mlme_rx_ops *rx_ops; 371 uint32_t num_vdevs = 0; 372 373 if (!scn || !data) { 374 mlme_err("scn: 0x%pK, data: 0x%pK", scn, data); 375 return -EINVAL; 376 } 377 psoc = target_if_get_psoc_from_scn_hdl(scn); 378 if (!psoc) { 379 mlme_err("PSOC is NULL"); 380 return -EINVAL; 381 } 382 383 rx_ops = target_if_vdev_mgr_get_rx_ops(psoc); 384 if (!rx_ops || !rx_ops->vdev_mgr_tbttoffset_update_handle) { 385 mlme_err("No Rx Ops"); 386 return -EINVAL; 387 } 388 389 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 390 if (!wmi_handle) { 391 mlme_err("wmi_handle is null"); 392 return -EINVAL; 393 } 394 395 if (wmi_extract_ext_tbttoffset_num_vdevs(wmi_handle, data, 396 &num_vdevs)) { 397 mlme_err("WMI extract failed"); 398 return -EINVAL; 399 } 400 401 status = rx_ops->vdev_mgr_tbttoffset_update_handle(num_vdevs, true); 402 403 return qdf_status_to_os_return(status); 404 } 405 406 QDF_STATUS target_if_vdev_mgr_wmi_event_register( 407 struct wlan_objmgr_psoc *psoc) 408 { 409 int retval = 0; 410 struct wmi_unified *wmi_handle; 411 412 if (!psoc) { 413 mlme_err("PSOC is NULL"); 414 return QDF_STATUS_E_NULL_VALUE; 415 } 416 417 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 418 if (!wmi_handle) { 419 mlme_err("wmi_handle is null"); 420 return QDF_STATUS_E_INVAL; 421 } 422 423 retval = wmi_unified_register_event_handler( 424 wmi_handle, 425 wmi_vdev_stopped_event_id, 426 target_if_vdev_mgr_stop_response_handler, 427 WMI_RX_UMAC_CTX); 428 if (retval) 429 mlme_err("failed to register for stop response"); 430 431 retval = wmi_unified_register_event_handler( 432 wmi_handle, 433 wmi_vdev_delete_resp_event_id, 434 target_if_vdev_mgr_delete_response_handler, 435 WMI_RX_UMAC_CTX); 436 if (retval) 437 mlme_err("failed to register for delete response"); 438 439 retval = wmi_unified_register_event_handler( 440 wmi_handle, 441 wmi_vdev_start_resp_event_id, 442 target_if_vdev_mgr_start_response_handler, 443 WMI_RX_UMAC_CTX); 444 if (retval) 445 mlme_err("failed to register for start response"); 446 447 return qdf_status_from_os_return(retval); 448 } 449 450 QDF_STATUS target_if_vdev_mgr_wmi_event_unregister( 451 struct wlan_objmgr_psoc *psoc) 452 { 453 struct wmi_unified *wmi_handle; 454 455 if (!psoc) { 456 mlme_err("PSOC is NULL"); 457 return QDF_STATUS_E_INVAL; 458 } 459 460 wmi_handle = get_wmi_unified_hdl_from_psoc(psoc); 461 if (!wmi_handle) { 462 mlme_err("wmi_handle is null"); 463 return QDF_STATUS_E_INVAL; 464 } 465 466 wmi_unified_unregister_event_handler(wmi_handle, 467 wmi_vdev_stopped_event_id); 468 469 wmi_unified_unregister_event_handler(wmi_handle, 470 wmi_vdev_delete_resp_event_id); 471 472 wmi_unified_unregister_event_handler(wmi_handle, 473 wmi_vdev_start_resp_event_id); 474 475 return QDF_STATUS_SUCCESS; 476 } 477