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