1 /* 2 * Copyright (c) 2018-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: init_event_handler.c 21 * 22 * WMI common event handler implementation source file 23 */ 24 25 #include <qdf_status.h> 26 #include <wlan_objmgr_psoc_obj.h> 27 #include <wlan_objmgr_pdev_obj.h> 28 #include <target_if.h> 29 #include <target_if_reg.h> 30 #include <init_event_handler.h> 31 #include <service_ready_util.h> 32 #include <service_ready_param.h> 33 #include <init_cmd_api.h> 34 #include <cdp_txrx_cmn.h> 35 36 static int init_deinit_service_ready_event_handler(ol_scn_t scn_handle, 37 uint8_t *event, 38 uint32_t data_len) 39 { 40 int err_code; 41 struct wlan_objmgr_psoc *psoc; 42 struct target_psoc_info *tgt_hdl; 43 wmi_legacy_service_ready_callback legacy_callback; 44 struct common_wmi_handle *wmi_handle; 45 QDF_STATUS ret_val; 46 47 if (!scn_handle) { 48 target_if_err("scn handle NULL in service ready handler"); 49 return -EINVAL; 50 } 51 52 psoc = target_if_get_psoc_from_scn_hdl(scn_handle); 53 if (!psoc) { 54 target_if_err("psoc is null in service ready handler"); 55 return -EINVAL; 56 } 57 58 tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle( 59 psoc); 60 if (!tgt_hdl) { 61 target_if_err("target_psoc_info is null in service ready ev"); 62 return -EINVAL; 63 } 64 65 ret_val = target_if_sw_version_check(psoc, tgt_hdl, event); 66 67 wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl); 68 69 err_code = init_deinit_populate_service_bitmap(wmi_handle, event, 70 tgt_hdl->info.service_bitmap); 71 if (err_code) 72 goto exit; 73 74 err_code = init_deinit_populate_fw_version_cmd(wmi_handle, event); 75 if (err_code) 76 goto exit; 77 78 err_code = init_deinit_populate_target_cap(wmi_handle, event, 79 &(tgt_hdl->info.target_caps)); 80 if (err_code) 81 goto exit; 82 83 err_code = init_deinit_populate_phy_reg_cap(psoc, wmi_handle, event, 84 &(tgt_hdl->info), true); 85 if (err_code) 86 goto exit; 87 88 if (init_deinit_validate_160_80p80_fw_caps(psoc, tgt_hdl) != 89 QDF_STATUS_SUCCESS) { 90 wlan_psoc_nif_op_flag_set(psoc, WLAN_SOC_OP_VHT_INVALID_CAP); 91 } 92 93 target_if_ext_res_cfg_enable(psoc, tgt_hdl, event); 94 95 if (wmi_service_enabled(wmi_handle, wmi_service_tt)) 96 wlan_psoc_nif_fw_ext_cap_set(psoc, WLAN_SOC_CEXT_TT_SUPPORT); 97 98 if (wmi_service_enabled(wmi_handle, wmi_service_widebw_scan)) 99 wlan_psoc_nif_fw_ext_cap_set(psoc, WLAN_SOC_CEXT_WIDEBAND_SCAN); 100 101 if (wmi_service_enabled(wmi_handle, wmi_service_check_cal_version)) 102 wlan_psoc_nif_fw_ext_cap_set(psoc, WLAN_SOC_CEXT_SW_CAL); 103 104 if (wmi_service_enabled(wmi_handle, wmi_service_twt_requestor)) 105 wlan_psoc_nif_fw_ext_cap_set(psoc, WLAN_SOC_CEXT_TWT_REQUESTER); 106 107 if (wmi_service_enabled(wmi_handle, wmi_service_twt_responder)) 108 wlan_psoc_nif_fw_ext_cap_set(psoc, WLAN_SOC_CEXT_TWT_RESPONDER); 109 110 if (wmi_service_enabled(wmi_handle, wmi_service_bss_color_offload)) 111 target_if_debug(" BSS COLOR OFFLOAD supported"); 112 113 if (wmi_service_enabled(wmi_handle, wmi_service_ul_ru26_allowed)) 114 wlan_psoc_nif_fw_ext_cap_set(psoc, WLAN_SOC_CEXT_OBSS_NBW_RU); 115 116 target_if_debug(" TT support %d, Wide BW Scan %d, SW cal %d", 117 wlan_psoc_nif_fw_ext_cap_get(psoc, WLAN_SOC_CEXT_TT_SUPPORT), 118 wlan_psoc_nif_fw_ext_cap_get(psoc, WLAN_SOC_CEXT_WIDEBAND_SCAN), 119 wlan_psoc_nif_fw_ext_cap_get(psoc, WLAN_SOC_CEXT_SW_CAL)); 120 121 target_if_mesh_support_enable(psoc, tgt_hdl, event); 122 123 target_if_eapol_minrate_enable(psoc, tgt_hdl, event); 124 125 target_if_smart_antenna_enable(psoc, tgt_hdl, event); 126 127 target_if_cfr_support_enable(psoc, tgt_hdl, event); 128 129 target_if_peer_cfg_enable(psoc, tgt_hdl, event); 130 131 target_if_atf_cfg_enable(psoc, tgt_hdl, event); 132 133 if (!wmi_service_enabled(wmi_handle, wmi_service_ext_msg)) 134 target_if_qwrap_cfg_enable(psoc, tgt_hdl, event); 135 136 target_if_lteu_cfg_enable(psoc, tgt_hdl, event); 137 138 /* override derived value, if it exceeds max peer count */ 139 if ((wlan_psoc_get_max_peer_count(psoc) > 140 tgt_hdl->info.wlan_res_cfg.num_active_peers) && 141 (wlan_psoc_get_max_peer_count(psoc) < 142 (tgt_hdl->info.wlan_res_cfg.num_peers - 143 tgt_hdl->info.wlan_res_cfg.num_vdevs))) { 144 tgt_hdl->info.wlan_res_cfg.num_peers = 145 wlan_psoc_get_max_peer_count(psoc) + 146 tgt_hdl->info.wlan_res_cfg.num_vdevs; 147 } 148 legacy_callback = target_if_get_psoc_legacy_service_ready_cb(); 149 if (!legacy_callback) { 150 err_code = -EINVAL; 151 goto exit; 152 } 153 154 err_code = legacy_callback(wmi_service_ready_event_id, 155 scn_handle, event, data_len); 156 init_deinit_chainmask_config(psoc, tgt_hdl); 157 158 if (wmi_service_enabled(wmi_handle, wmi_service_mgmt_tx_wmi)) { 159 wlan_psoc_nif_fw_ext_cap_set(psoc, WLAN_SOC_CEXT_WMI_MGMT_REF); 160 target_if_debug("WMI mgmt service enabled"); 161 } else { 162 wlan_psoc_nif_fw_ext_cap_clear(psoc, 163 WLAN_SOC_CEXT_WMI_MGMT_REF); 164 target_if_debug("WMI mgmt service disabled"); 165 } 166 167 err_code = init_deinit_handle_host_mem_req(psoc, tgt_hdl, event); 168 if (err_code != QDF_STATUS_SUCCESS) 169 goto exit; 170 171 target_if_reg_set_offloaded_info(psoc); 172 if (!wmi_service_enabled(wmi_handle, wmi_service_ext_msg)) { 173 target_if_debug("No EXT message, send init command"); 174 tgt_hdl->info.wmi_service_ready = TRUE; 175 target_psoc_set_num_radios(tgt_hdl, 1); 176 /* send init command */ 177 init_deinit_prepare_send_init_cmd(psoc, tgt_hdl); 178 } else { 179 target_if_debug("Wait for EXT message"); 180 } 181 182 exit: 183 return err_code; 184 } 185 186 static int init_deinit_service_ext_ready_event_handler(ol_scn_t scn_handle, 187 uint8_t *event, 188 uint32_t data_len) 189 { 190 int err_code; 191 struct wlan_objmgr_psoc *psoc; 192 struct target_psoc_info *tgt_hdl; 193 struct common_wmi_handle *wmi_handle; 194 struct tgt_info *info; 195 wmi_legacy_service_ready_callback legacy_callback; 196 197 if (!scn_handle) { 198 target_if_err("scn handle NULL in service ready handler"); 199 return -EINVAL; 200 } 201 202 psoc = target_if_get_psoc_from_scn_hdl(scn_handle); 203 if (!psoc) { 204 target_if_err("psoc is null in service ready handler"); 205 return -EINVAL; 206 } 207 208 tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle( 209 psoc); 210 if (!tgt_hdl) { 211 target_if_err("target_psoc_info is null in service ready ev"); 212 return -EINVAL; 213 } 214 215 wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl); 216 info = (&tgt_hdl->info); 217 218 err_code = init_deinit_populate_service_ready_ext_param(wmi_handle, 219 event, &(info->service_ext_param)); 220 if (err_code) 221 goto exit; 222 223 target_psoc_set_num_radios(tgt_hdl, 0); 224 err_code = init_deinit_populate_hw_mode_capability(wmi_handle, 225 event, tgt_hdl); 226 if (err_code) 227 goto exit; 228 229 if (init_deinit_is_preferred_hw_mode_supported(psoc, tgt_hdl) 230 == FALSE) { 231 target_if_err("Preferred mode %d not supported", 232 info->preferred_hw_mode); 233 return -EINVAL; 234 } 235 236 if (info->preferred_hw_mode != WMI_HOST_HW_MODE_MAX) { 237 struct wlan_psoc_host_hw_mode_caps *hw_cap = &info->hw_mode_cap; 238 /* prune info mac_phy cap to preferred/selected mode caps */ 239 info->total_mac_phy_cnt = 0; 240 err_code = init_deinit_populate_mac_phy_capability(wmi_handle, 241 event, 242 hw_cap, 243 info); 244 if (err_code) 245 goto exit; 246 247 info->num_radios = info->total_mac_phy_cnt; 248 target_if_debug("num radios is %d\n", info->num_radios); 249 } 250 251 target_if_print_service_ready_ext_param(psoc, tgt_hdl); 252 253 err_code = init_deinit_populate_phy_reg_cap(psoc, wmi_handle, 254 event, info, false); 255 if (err_code) 256 goto exit; 257 258 target_if_add_11ax_modes(psoc, tgt_hdl); 259 260 if (init_deinit_chainmask_table_alloc( 261 &(info->service_ext_param)) == 262 QDF_STATUS_SUCCESS) { 263 err_code = init_deinit_populate_chainmask_tables(wmi_handle, 264 event, 265 &(info->service_ext_param.chainmask_table[0])); 266 if (err_code) 267 goto exit; 268 } 269 270 err_code = init_deinit_populate_dbr_ring_cap(psoc, wmi_handle, 271 event, info); 272 if (err_code) 273 goto exit; 274 275 err_code = init_deinit_populate_spectral_bin_scale_params(psoc, 276 wmi_handle, 277 event, info); 278 if (err_code) 279 goto exit; 280 281 legacy_callback = target_if_get_psoc_legacy_service_ready_cb(); 282 if (legacy_callback) 283 legacy_callback(wmi_service_ready_ext_event_id, 284 scn_handle, event, data_len); 285 286 target_if_qwrap_cfg_enable(psoc, tgt_hdl, event); 287 288 info->wlan_res_cfg.num_vdevs = (target_psoc_get_num_radios(tgt_hdl) * 289 info->wlan_res_cfg.num_vdevs); 290 info->wlan_res_cfg.beacon_tx_offload_max_vdev = 291 (target_psoc_get_num_radios(tgt_hdl) * 292 info->wlan_res_cfg.beacon_tx_offload_max_vdev); 293 info->wlan_res_cfg.max_bssid_indicator = 294 info->service_ext_param.max_bssid_indicator; 295 296 info->wmi_service_ready = TRUE; 297 298 init_deinit_prepare_send_init_cmd(psoc, tgt_hdl); 299 300 exit: 301 return err_code; 302 } 303 304 static int init_deinit_service_available_handler(ol_scn_t scn_handle, 305 uint8_t *event, 306 uint32_t data_len) 307 { 308 struct wlan_objmgr_psoc *psoc; 309 struct target_psoc_info *tgt_hdl; 310 struct common_wmi_handle *wmi_handle; 311 312 if (!scn_handle) { 313 target_if_err("scn handle NULL"); 314 return -EINVAL; 315 } 316 317 psoc = target_if_get_psoc_from_scn_hdl(scn_handle); 318 if (!psoc) { 319 target_if_err("psoc is null"); 320 return -EINVAL; 321 } 322 323 tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle( 324 psoc); 325 if (!tgt_hdl) { 326 target_if_err("target_psoc_info is null"); 327 return -EINVAL; 328 } 329 330 wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl); 331 332 if (wmi_save_ext_service_bitmap(wmi_handle, event, NULL) != 333 QDF_STATUS_SUCCESS) { 334 target_if_err("Failed to save ext service bitmap"); 335 return -EINVAL; 336 } 337 338 return 0; 339 } 340 341 /* MAC address fourth byte index */ 342 #define MAC_BYTE_4 4 343 344 static int init_deinit_ready_event_handler(ol_scn_t scn_handle, 345 uint8_t *event, 346 uint32_t data_len) 347 { 348 struct wlan_objmgr_psoc *psoc; 349 struct wlan_objmgr_pdev *pdev; 350 struct target_psoc_info *tgt_hdl; 351 struct common_wmi_handle *wmi_handle; 352 struct wmi_host_fw_abi_ver fw_ver; 353 uint8_t myaddr[QDF_MAC_ADDR_SIZE]; 354 struct tgt_info *info; 355 struct wmi_host_ready_ev_param ready_ev; 356 wmi_legacy_service_ready_callback legacy_callback; 357 uint8_t num_radios, i; 358 uint32_t max_peers; 359 uint32_t max_ast_index; 360 target_resource_config *tgt_cfg; 361 362 if (!scn_handle) { 363 target_if_err("scn handle NULL"); 364 return -EINVAL; 365 } 366 367 psoc = target_if_get_psoc_from_scn_hdl(scn_handle); 368 if (!psoc) { 369 target_if_err("psoc is null"); 370 return -EINVAL; 371 } 372 373 tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle( 374 psoc); 375 if (!tgt_hdl) { 376 target_if_err("target_psoc_info is null"); 377 return -EINVAL; 378 } 379 380 wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl); 381 info = (&tgt_hdl->info); 382 383 if (wmi_extract_fw_abi_version(wmi_handle, event, &fw_ver) == 384 QDF_STATUS_SUCCESS) { 385 info->version.wlan_ver = fw_ver.sw_version; 386 info->version.wlan_ver = fw_ver.abi_version; 387 } 388 389 if (wmi_check_and_update_fw_version(wmi_handle, event) < 0) { 390 target_if_err("Version mismatch with FW"); 391 return -EINVAL; 392 } 393 394 if (wmi_extract_ready_event_params(wmi_handle, event, &ready_ev) != 395 QDF_STATUS_SUCCESS) { 396 target_if_err("Failed to extract ready event"); 397 return -EINVAL; 398 } 399 400 if ((ready_ev.num_total_peer != 0) && 401 (info->wlan_res_cfg.num_peers != ready_ev.num_total_peer)) { 402 /* FW allocated number of peers is different than host 403 * requested. Update host max with FW reported value. 404 */ 405 target_if_err("Host Requested %d peers. FW Supports %d peers", 406 info->wlan_res_cfg.num_peers, 407 ready_ev.num_total_peer); 408 info->wlan_res_cfg.num_peers = ready_ev.num_total_peer; 409 } 410 411 /* for non legacy num_total_peer will be non zero 412 * allocate peer memory in this case 413 */ 414 if (ready_ev.num_total_peer != 0) { 415 tgt_cfg = &info->wlan_res_cfg; 416 max_peers = tgt_cfg->num_peers + ready_ev.num_extra_peer + 1; 417 max_ast_index = ready_ev.max_ast_index + 1; 418 419 cdp_peer_map_attach(wlan_psoc_get_dp_handle(psoc), max_peers, 420 max_ast_index, tgt_cfg->peer_map_unmap_v2); 421 } 422 423 /* Indicate to the waiting thread that the ready 424 * event was received 425 */ 426 info->wlan_init_status = wmi_ready_extract_init_status( 427 wmi_handle, event); 428 429 legacy_callback = target_if_get_psoc_legacy_service_ready_cb(); 430 if (legacy_callback) 431 legacy_callback(wmi_ready_event_id, 432 scn_handle, event, data_len); 433 434 num_radios = target_psoc_get_num_radios(tgt_hdl); 435 /* 436 * For non-legacy HW, MAC addr list is extracted. 437 */ 438 if (num_radios > 1) { 439 uint8_t num_mac_addr; 440 wmi_host_mac_addr *addr_list; 441 int i; 442 443 addr_list = wmi_ready_extract_mac_addr_list(wmi_handle, event, 444 &num_mac_addr); 445 if ((num_mac_addr >= num_radios) && (addr_list)) { 446 for (i = 0; i < num_radios; i++) { 447 WMI_HOST_MAC_ADDR_TO_CHAR_ARRAY(&addr_list[i], 448 myaddr); 449 pdev = wlan_objmgr_get_pdev_by_id(psoc, i, 450 WLAN_INIT_DEINIT_ID); 451 if (!pdev) { 452 target_if_err(" PDEV %d is NULL", i); 453 return -EINVAL; 454 } 455 wlan_pdev_set_hw_macaddr(pdev, myaddr); 456 wlan_objmgr_pdev_release_ref(pdev, 457 WLAN_INIT_DEINIT_ID); 458 459 /* assign 1st radio addr to psoc */ 460 if (i == 0) 461 wlan_psoc_set_hw_macaddr(psoc, myaddr); 462 } 463 goto out; 464 } else { 465 target_if_err("Using default MAC addr for all radios.."); 466 } 467 } 468 469 /* 470 * We extract single MAC address in two scenarios: 471 * 1. In non-legacy case, if addr list is NULL or num_mac_addr < num_radios 472 * 2. In all legacy cases 473 */ 474 for (i = 0; i < num_radios; i++) { 475 wmi_ready_extract_mac_addr(wmi_handle, event, myaddr); 476 myaddr[MAC_BYTE_4] += i; 477 pdev = wlan_objmgr_get_pdev_by_id(psoc, i, WLAN_INIT_DEINIT_ID); 478 if (!pdev) { 479 target_if_err(" PDEV %d is NULL", i); 480 return -EINVAL; 481 } 482 wlan_pdev_set_hw_macaddr(pdev, myaddr); 483 wlan_objmgr_pdev_release_ref(pdev, WLAN_INIT_DEINIT_ID); 484 /* assign 1st radio addr to psoc */ 485 if (i == 0) 486 wlan_psoc_set_hw_macaddr(psoc, myaddr); 487 } 488 489 out: 490 target_if_btcoex_cfg_enable(psoc, tgt_hdl, event); 491 tgt_hdl->info.wmi_ready = TRUE; 492 init_deinit_wakeup_host_wait(psoc, tgt_hdl); 493 494 return 0; 495 } 496 497 498 QDF_STATUS init_deinit_register_tgt_psoc_ev_handlers( 499 struct wlan_objmgr_psoc *psoc) 500 { 501 struct target_psoc_info *tgt_hdl; 502 wmi_unified_t wmi_handle; 503 QDF_STATUS retval = QDF_STATUS_SUCCESS; 504 505 if (!psoc) { 506 target_if_err("psoc is null in register wmi handler"); 507 return QDF_STATUS_E_FAILURE; 508 } 509 510 tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle( 511 psoc); 512 if (!tgt_hdl) { 513 target_if_err("target_psoc_info null in register wmi hadler"); 514 return QDF_STATUS_E_FAILURE; 515 } 516 517 wmi_handle = (wmi_unified_t)target_psoc_get_wmi_hdl(tgt_hdl); 518 519 retval = wmi_unified_register_event_handler(wmi_handle, 520 wmi_service_ready_event_id, 521 init_deinit_service_ready_event_handler, 522 WMI_RX_WORK_CTX); 523 retval = wmi_unified_register_event_handler(wmi_handle, 524 wmi_service_ready_ext_event_id, 525 init_deinit_service_ext_ready_event_handler, 526 WMI_RX_WORK_CTX); 527 retval = wmi_unified_register_event_handler(wmi_handle, 528 wmi_service_available_event_id, 529 init_deinit_service_available_handler, 530 WMI_RX_UMAC_CTX); 531 retval = wmi_unified_register_event_handler(wmi_handle, 532 wmi_ready_event_id, 533 init_deinit_ready_event_handler, 534 WMI_RX_WORK_CTX); 535 536 return retval; 537 } 538 539