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