1 /* 2 * Copyright (c) 2017-2021 The Linux Foundation. All rights reserved. 3 * Copyright (c) 2022-2023, Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 /** 20 * DOC: service_ready_util.c 21 * 22 * Public APIs implementation source file for accessing (ext)service ready 23 * data from psoc object 24 */ 25 #include "service_ready_util.h" 26 #include <wlan_reg_ucfg_api.h> 27 #include <target_type.h> 28 #include <qdf_module.h> 29 30 QDF_STATUS init_deinit_chainmask_table_alloc( 31 struct wlan_psoc_host_service_ext_param *ser_ext_par) 32 { 33 int i; 34 uint32_t alloc_size; 35 QDF_STATUS status = QDF_STATUS_SUCCESS; 36 37 if (ser_ext_par->num_chainmask_tables == 0) 38 return QDF_STATUS_E_NOSUPPORT; 39 40 for (i = 0; i < ser_ext_par->num_chainmask_tables; i++) { 41 if (ser_ext_par->chainmask_table[i].num_valid_chainmasks > 42 (UINT_MAX / sizeof( 43 struct wlan_psoc_host_chainmask_capabilities))) { 44 target_if_err("invalid valid chanmask num %d", 45 ser_ext_par->chainmask_table[i]. 46 num_valid_chainmasks); 47 status = QDF_STATUS_E_FAILURE; 48 break; 49 } 50 alloc_size = 51 (sizeof(struct wlan_psoc_host_chainmask_capabilities) * 52 ser_ext_par->chainmask_table[i].num_valid_chainmasks); 53 54 ser_ext_par->chainmask_table[i].cap_list = 55 qdf_mem_malloc(alloc_size); 56 if (!ser_ext_par->chainmask_table[i].cap_list) { 57 init_deinit_chainmask_table_free(ser_ext_par); 58 status = QDF_STATUS_E_NOMEM; 59 break; 60 } 61 } 62 63 return status; 64 } 65 66 qdf_export_symbol(init_deinit_chainmask_table_alloc); 67 68 QDF_STATUS init_deinit_chainmask_table_free( 69 struct wlan_psoc_host_service_ext_param *ser_ext_par) 70 { 71 struct wlan_psoc_host_chainmask_table *table; 72 int i; 73 74 for (i = 0; i < ser_ext_par->num_chainmask_tables; i++) { 75 table = &(ser_ext_par->chainmask_table[i]); 76 if (table->cap_list) { 77 qdf_mem_free(table->cap_list); 78 table->cap_list = NULL; 79 } 80 } 81 82 return QDF_STATUS_SUCCESS; 83 } 84 85 qdf_export_symbol(init_deinit_chainmask_table_free); 86 87 int init_deinit_populate_service_bitmap( 88 wmi_unified_t wmi_handle, uint8_t *event, 89 uint32_t *service_bitmap) 90 { 91 QDF_STATUS status; 92 93 status = wmi_save_service_bitmap(wmi_handle, event, service_bitmap); 94 if (QDF_IS_STATUS_ERROR(status)) { 95 target_if_err("failed to parse service bitmap"); 96 return qdf_status_to_os_return(status); 97 } 98 99 return 0; 100 } 101 102 int init_deinit_populate_fw_version_cmd(wmi_unified_t wmi_handle, 103 uint8_t *event) 104 { 105 QDF_STATUS status; 106 107 status = wmi_unified_save_fw_version_cmd(wmi_handle, event); 108 if (QDF_IS_STATUS_ERROR(status)) 109 target_if_err("failed to save fw version"); 110 111 return 0; 112 } 113 114 int init_deinit_populate_target_cap( 115 wmi_unified_t wmi_handle, uint8_t *event, 116 struct wlan_psoc_target_capability_info *cap) 117 { 118 QDF_STATUS status; 119 120 status = wmi_get_target_cap_from_service_ready(wmi_handle, event, cap); 121 if (QDF_IS_STATUS_ERROR(status)) { 122 target_if_err("failed to parse target cap"); 123 return qdf_status_to_os_return(status); 124 } 125 126 return 0; 127 } 128 129 int init_deinit_populate_service_ready_ext_param( 130 wmi_unified_t handle, uint8_t *evt, 131 struct wlan_psoc_host_service_ext_param *param) 132 { 133 QDF_STATUS status; 134 135 status = wmi_extract_service_ready_ext(handle, evt, param); 136 if (QDF_IS_STATUS_ERROR(status)) { 137 target_if_err("failed to parse wmi service ready ext param"); 138 return qdf_status_to_os_return(status); 139 } 140 141 return 0; 142 } 143 144 int init_deinit_populate_service_ready_ext2_param( 145 wmi_unified_t handle, uint8_t *evt, 146 struct tgt_info *info) 147 { 148 QDF_STATUS status; 149 150 status = wmi_extract_service_ready_ext2(handle, evt, 151 &info->service_ext2_param); 152 if (QDF_IS_STATUS_ERROR(status)) { 153 target_if_err("failed to parse wmi service ready ext param"); 154 return qdf_status_to_os_return(status); 155 } 156 157 return 0; 158 } 159 160 int init_deinit_populate_chainmask_tables( 161 wmi_unified_t handle, uint8_t *evt, 162 struct wlan_psoc_host_chainmask_table *param) 163 { 164 QDF_STATUS status; 165 166 status = wmi_extract_chainmask_tables(handle, evt, param); 167 if (QDF_IS_STATUS_ERROR(status)) { 168 target_if_err("failed to parse wmi service ready ext param"); 169 return qdf_status_to_os_return(status); 170 } 171 172 return 0; 173 } 174 175 int init_deinit_populate_mac_phy_capability( 176 wmi_unified_t handle, uint8_t *evt, 177 struct wlan_psoc_host_hw_mode_caps *hw_cap, struct tgt_info *info) 178 { 179 QDF_STATUS status; 180 uint32_t hw_mode_id; 181 uint32_t phy_bit_map; 182 uint8_t mac_phy_id; 183 184 hw_mode_id = hw_cap->hw_mode_id; 185 phy_bit_map = hw_cap->phy_id_map; 186 target_if_debug("hw_mode_id %d phy_bit_map 0x%x", 187 hw_mode_id, phy_bit_map); 188 189 mac_phy_id = 0; 190 while (phy_bit_map) { 191 if (info->total_mac_phy_cnt >= PSOC_MAX_MAC_PHY_CAP) { 192 target_if_err("total mac phy exceeds max limit %d", 193 info->total_mac_phy_cnt); 194 return -EINVAL; 195 } 196 197 status = wmi_extract_mac_phy_cap_service_ready_ext(handle, 198 evt, hw_mode_id, mac_phy_id, 199 &(info->mac_phy_cap[info->total_mac_phy_cnt])); 200 if (QDF_IS_STATUS_ERROR(status)) { 201 target_if_err("failed to parse mac phy capability"); 202 return qdf_status_to_os_return(status); 203 } 204 info->mac_phy_cap[info->total_mac_phy_cnt].hw_mode_config_type 205 = hw_cap->hw_mode_config_type; 206 info->total_mac_phy_cnt++; 207 phy_bit_map &= (phy_bit_map - 1); 208 mac_phy_id++; 209 } 210 target_if_debug("total_mac_phy_cnt %d", info->total_mac_phy_cnt); 211 212 return 0; 213 } 214 215 static int get_hw_mode(wmi_unified_t handle, uint8_t *evt, uint8_t hw_idx, 216 struct wlan_psoc_host_hw_mode_caps *cap) 217 { 218 QDF_STATUS status; 219 220 status = wmi_extract_hw_mode_cap_service_ready_ext(handle, evt, 221 hw_idx, cap); 222 if (QDF_IS_STATUS_ERROR(status)) { 223 target_if_err("failed to parse hw mode capability"); 224 return qdf_status_to_os_return(status); 225 } 226 227 return 0; 228 } 229 230 static int get_sar_version(wmi_unified_t handle, uint8_t *evt, 231 struct wlan_psoc_host_service_ext_param *ext_param) 232 { 233 QDF_STATUS status; 234 235 status = wmi_extract_sar_cap_service_ready_ext(handle, evt, ext_param); 236 if (QDF_IS_STATUS_ERROR(status)) { 237 target_if_err("failed to parse sar capability"); 238 return qdf_status_to_os_return(status); 239 } 240 241 return 0; 242 } 243 244 static bool new_hw_mode_preferred(uint32_t current_hw_mode, 245 uint32_t new_hw_mode) 246 { 247 uint8_t hw_mode_id_precedence[WMI_HOST_HW_MODE_MAX + 1] = { 6, 2, 5, 248 4, 1, 3, 249 7, 0, 8, 250 9, 10, 11}; 251 252 if (current_hw_mode > WMI_HOST_HW_MODE_MAX || 253 new_hw_mode > WMI_HOST_HW_MODE_MAX) 254 return false; 255 256 /* Above precedence is defined by low to high, lower the value 257 * higher the precedence 258 */ 259 if (hw_mode_id_precedence[current_hw_mode] > 260 hw_mode_id_precedence[new_hw_mode]) 261 return true; 262 263 return false; 264 } 265 266 /** 267 * select_preferred_hw_mode() - Select preferred hw mode based on current mode. 268 * @tgt_hdl: target_psoc_info object 269 * @hw_mode_caps: HW mode caps of new mode id that needs to checked for 270 * selection. 271 * @current_mode: Current mode. 272 * 273 * API to select preferred hw mode based on the current config. 274 * Based on host config for preferred mode, final mode selected as follows- 275 * 1) If preferred_mode == WMI_HOST_HW_MODE_DETECT, Then select mode from FW 276 * supported modes such that it is a super set of all modes FW advertises. 277 * For e.g., If FW supports DBS(2 radio) and DBS_SBS(3 radio)- Choose DBS_SBS 278 * 2) If preferred_mode == WMI_HOST_HW_MODE_MAX, Then do not select any mode 279 * from FW advertised modes. Host needs to maintain all modes supported in FW 280 * and can switch dynamically. 281 * 3) Else, A valid preferred_mode is set, Hence check if this is part of FW 282 * supported modes. If it is found, then use it to bring up the device. 283 * 284 * Return: selected_mode based on the above criteria. 285 */ 286 static uint32_t 287 select_preferred_hw_mode(struct target_psoc_info *tgt_hdl, 288 struct wlan_psoc_host_hw_mode_caps *hw_mode_caps, 289 uint32_t current_mode) 290 { 291 uint32_t preferred_mode, selected_mode = current_mode; 292 struct tgt_info *info; 293 294 info = &tgt_hdl->info; 295 preferred_mode = target_psoc_get_preferred_hw_mode(tgt_hdl); 296 if (preferred_mode == WMI_HOST_HW_MODE_DETECT) { 297 uint32_t new_mode = hw_mode_caps->hw_mode_id; 298 299 /* Choose hw_mode_id based on precedence */ 300 if (new_hw_mode_preferred(selected_mode, new_mode)) { 301 selected_mode = new_mode; 302 qdf_mem_copy(&info->hw_mode_cap, hw_mode_caps, 303 sizeof(info->hw_mode_cap)); 304 } 305 } else if ((preferred_mode != WMI_HOST_HW_MODE_MAX) && 306 (preferred_mode == hw_mode_caps->hw_mode_id)) { 307 selected_mode = preferred_mode; 308 qdf_mem_copy(&info->hw_mode_cap, hw_mode_caps, 309 sizeof(info->hw_mode_cap)); 310 } 311 312 return selected_mode; 313 } 314 315 #ifdef FEATURE_NO_DBS_INTRABAND_MCC_SUPPORT 316 static void init_deinit_change_def_hw_mode(struct target_psoc_info *tgt_hdl, 317 struct wmi_unified *wmi_handle) 318 { 319 struct tgt_info *info = &tgt_hdl->info; 320 321 if ((info->hw_modes.num_modes == 1) && 322 (info->hw_modes.hw_mode_ids[0] == WMI_HOST_HW_MODE_DBS) && 323 !wmi_service_enabled(wmi_handle, 324 wmi_service_dual_band_simultaneous_support)) 325 target_psoc_set_preferred_hw_mode(tgt_hdl, 326 WMI_HOST_HW_MODE_DETECT); 327 } 328 #else 329 static void init_deinit_change_def_hw_mode(struct target_psoc_info *tgt_hdl, 330 struct wmi_unified *wmi_handle) 331 { 332 } 333 #endif 334 335 int init_deinit_populate_hw_mode_capability( 336 wmi_unified_t wmi_handle, uint8_t *event, 337 struct target_psoc_info *tgt_hdl) 338 { 339 QDF_STATUS status = QDF_STATUS_SUCCESS; 340 uint8_t hw_idx; 341 uint32_t num_hw_modes; 342 struct wlan_psoc_host_hw_mode_caps hw_mode_caps[PSOC_MAX_HW_MODE]; 343 uint32_t preferred_mode, selected_mode = WMI_HOST_HW_MODE_MAX; 344 struct tgt_info *info; 345 346 info = &tgt_hdl->info; 347 num_hw_modes = info->service_ext_param.num_hw_modes; 348 if (num_hw_modes > PSOC_MAX_HW_MODE) { 349 target_if_err("invalid num_hw_modes %d", num_hw_modes); 350 return -EINVAL; 351 } 352 target_if_debug("num_hw_modes %d", num_hw_modes); 353 354 qdf_mem_zero(&hw_mode_caps, sizeof(hw_mode_caps)); 355 info->hw_modes.num_modes = 0; 356 info->hw_mode_cap.hw_mode_id = WMI_HOST_HW_MODE_MAX; 357 358 for (hw_idx = 0; hw_idx < num_hw_modes; hw_idx++) { 359 status = get_hw_mode(wmi_handle, event, hw_idx, 360 &hw_mode_caps[hw_idx]); 361 if (status) 362 goto return_exit; 363 364 if (hw_idx < WMI_HOST_HW_MODE_MAX) { 365 info->hw_modes.hw_mode_ids[hw_idx] = 366 hw_mode_caps[hw_idx].hw_mode_id; 367 info->hw_modes.phy_bit_map[hw_idx] = 368 hw_mode_caps[hw_idx].phy_id_map; 369 info->hw_modes.num_modes++; 370 } 371 372 status = init_deinit_populate_mac_phy_capability(wmi_handle, 373 event, &hw_mode_caps[hw_idx], info); 374 if (status) 375 goto return_exit; 376 377 if (num_hw_modes == 1) 378 init_deinit_change_def_hw_mode(tgt_hdl, wmi_handle); 379 380 selected_mode = select_preferred_hw_mode(tgt_hdl, 381 &hw_mode_caps[hw_idx], 382 selected_mode); 383 } 384 385 preferred_mode = target_psoc_get_preferred_hw_mode(tgt_hdl); 386 if (preferred_mode == WMI_HOST_HW_MODE_DETECT) { 387 target_if_info("Preferred mode is not set, use mode id %d\n", 388 selected_mode); 389 target_psoc_set_preferred_hw_mode(tgt_hdl, selected_mode); 390 391 /* Change default DBS hw mode as per selected one */ 392 info->target_caps.default_dbs_hw_mode_index = selected_mode; 393 } 394 395 status = get_sar_version(wmi_handle, event, &info->service_ext_param); 396 target_if_debug("sar version %d", info->service_ext_param.sar_version); 397 398 return_exit: 399 return qdf_status_to_os_return(status); 400 } 401 402 int init_deinit_populate_dbr_ring_cap(struct wlan_objmgr_psoc *psoc, 403 wmi_unified_t handle, uint8_t *event, 404 struct tgt_info *info) 405 406 { 407 uint8_t cap_idx; 408 uint32_t num_dbr_ring_caps; 409 QDF_STATUS status = QDF_STATUS_SUCCESS; 410 411 num_dbr_ring_caps = info->service_ext_param.num_dbr_ring_caps; 412 target_if_debug("Num DMA Capabilities = %d", num_dbr_ring_caps); 413 414 if (!num_dbr_ring_caps) 415 return 0; 416 417 info->dbr_ring_cap = qdf_mem_malloc( 418 sizeof(struct wlan_psoc_host_dbr_ring_caps) * 419 num_dbr_ring_caps); 420 421 if (!info->dbr_ring_cap) 422 return -EINVAL; 423 424 for (cap_idx = 0; cap_idx < num_dbr_ring_caps; cap_idx++) { 425 status = wmi_extract_dbr_ring_cap_service_ready_ext(handle, 426 event, cap_idx, 427 &(info->dbr_ring_cap[cap_idx])); 428 if (QDF_IS_STATUS_ERROR(status)) { 429 target_if_err("Extraction of DMA cap failed"); 430 goto free_and_return; 431 } 432 } 433 434 return 0; 435 436 free_and_return: 437 qdf_mem_free(info->dbr_ring_cap); 438 info->dbr_ring_cap = NULL; 439 440 return qdf_status_to_os_return(status); 441 } 442 443 int init_deinit_populate_dbr_ring_cap_ext2(struct wlan_objmgr_psoc *psoc, 444 wmi_unified_t handle, uint8_t *event, 445 struct tgt_info *info) 446 447 { 448 uint8_t cap_idx; 449 uint32_t num_dbr_ring_caps; 450 QDF_STATUS status = QDF_STATUS_SUCCESS; 451 struct wlan_psoc_host_dbr_ring_caps *param; 452 453 /* 454 * If FW had already sent this info as part of EXT event, 455 * we need to discard the same and use the info from EXT2. 456 */ 457 if (info->service_ext_param.num_dbr_ring_caps) { 458 target_if_debug("dbr_ring_caps already populated"); 459 info->service_ext_param.num_dbr_ring_caps = 0; 460 qdf_mem_free(info->dbr_ring_cap); 461 info->dbr_ring_cap = NULL; 462 } 463 464 num_dbr_ring_caps = info->service_ext2_param.num_dbr_ring_caps; 465 target_if_debug("Num DMA Capabilities = %d", num_dbr_ring_caps); 466 467 if (!num_dbr_ring_caps) 468 return 0; 469 470 info->dbr_ring_cap = qdf_mem_malloc( 471 sizeof(struct wlan_psoc_host_dbr_ring_caps) * 472 num_dbr_ring_caps); 473 474 if (!info->dbr_ring_cap) 475 return -EINVAL; 476 477 for (cap_idx = 0; cap_idx < num_dbr_ring_caps; cap_idx++) { 478 param = &info->dbr_ring_cap[cap_idx]; 479 status = wmi_extract_dbr_ring_cap_service_ready_ext2(handle, 480 event, 481 cap_idx, 482 param); 483 if (QDF_IS_STATUS_ERROR(status)) { 484 target_if_err("Extraction of DMA cap failed"); 485 goto free_and_return; 486 } 487 } 488 489 return 0; 490 491 free_and_return: 492 qdf_mem_free(info->dbr_ring_cap); 493 info->dbr_ring_cap = NULL; 494 495 return qdf_status_to_os_return(status); 496 } 497 int init_deinit_populate_spectral_bin_scale_params( 498 struct wlan_objmgr_psoc *psoc, wmi_unified_t handle, 499 uint8_t *event, struct tgt_info *info) 500 501 { 502 uint8_t param_idx; 503 uint32_t num_bin_scaling_params; 504 QDF_STATUS status = QDF_STATUS_SUCCESS; 505 506 num_bin_scaling_params = info->service_ext_param.num_bin_scaling_params; 507 508 if (!num_bin_scaling_params) 509 return 0; 510 511 info->scaling_params = qdf_mem_malloc( 512 sizeof(struct wlan_psoc_host_spectral_scaling_params) * 513 num_bin_scaling_params); 514 515 if (!info->scaling_params) { 516 target_if_err("Mem alloc for bin scaling params failed"); 517 return -EINVAL; 518 } 519 520 for (param_idx = 0; param_idx < num_bin_scaling_params; param_idx++) { 521 status = wmi_extract_spectral_scaling_params_service_ready_ext( 522 handle, 523 event, param_idx, 524 &info->scaling_params[param_idx]); 525 if (QDF_IS_STATUS_ERROR(status)) { 526 target_if_err("Extraction of scaling params failed"); 527 goto free_and_return; 528 } 529 } 530 531 return 0; 532 533 free_and_return: 534 qdf_mem_free(info->scaling_params); 535 info->scaling_params = NULL; 536 537 return qdf_status_to_os_return(status); 538 } 539 540 #ifdef WLAN_SUPPORT_TWT 541 int init_deinit_populate_twt_cap_ext2(struct wlan_objmgr_psoc *psoc, 542 wmi_unified_t handle, uint8_t *event, 543 struct tgt_info *info) 544 { 545 struct wmi_twt_cap_bitmap_params param; 546 struct target_psoc_info *psoc_info; 547 QDF_STATUS status = QDF_STATUS_SUCCESS; 548 549 status = wmi_extract_twt_cap_service_ready_ext2(handle, event, 550 ¶m); 551 if (QDF_IS_STATUS_ERROR(status)) { 552 target_if_err("Extraction of twt capability failed"); 553 goto exit; 554 } 555 556 psoc_info = wlan_psoc_get_tgt_if_handle(psoc); 557 558 target_psoc_set_twt_ack_cap(psoc_info, param.twt_ack_support_cap); 559 560 exit: 561 return qdf_status_to_os_return(status); 562 } 563 #endif 564 565 #ifdef WLAN_RCC_ENHANCED_AOA_SUPPORT 566 int init_deinit_populate_rcc_aoa_cap_ext2(struct wlan_objmgr_psoc *psoc, 567 wmi_unified_t handle, 568 uint8_t *event, 569 struct tgt_info *info) 570 { 571 QDF_STATUS status = QDF_STATUS_E_FAILURE; 572 573 info->aoa_caps = qdf_mem_malloc( 574 sizeof(struct wlan_psoc_host_rcc_enh_aoa_caps_ext2)); 575 576 if (!info->aoa_caps) { 577 target_if_err("Mem alloc for aoa cap failed"); 578 return -EINVAL; 579 } 580 581 status = wmi_extract_aoa_caps_service_ready_ext2( 582 handle, event, 583 info->aoa_caps); 584 585 if (QDF_IS_STATUS_ERROR(status)) { 586 target_if_err("Extraction of aoa caps failed"); 587 goto free_and_return; 588 } 589 590 return 0; 591 592 free_and_return: 593 qdf_mem_free(info->aoa_caps); 594 info->aoa_caps = NULL; 595 596 return qdf_status_to_os_return(status); 597 } 598 599 QDF_STATUS init_deinit_rcc_aoa_cap_ext2_free( 600 struct target_psoc_info *tgt_psoc_info) 601 { 602 qdf_mem_free(tgt_psoc_info->info.aoa_caps); 603 tgt_psoc_info->info.aoa_caps = NULL; 604 605 return QDF_STATUS_SUCCESS; 606 } 607 #else 608 int init_deinit_populate_rcc_aoa_cap_ext2(struct wlan_objmgr_psoc *psoc, 609 wmi_unified_t handle, 610 uint8_t *event, 611 struct tgt_info *info) 612 { 613 return 0; 614 } 615 616 QDF_STATUS init_deinit_rcc_aoa_cap_ext2_free( 617 struct target_psoc_info *tgt_psoc_info) 618 { 619 return QDF_STATUS_SUCCESS; 620 } 621 #endif /* WLAN_RCC_ENHANCED_AOA_SUPPORT */ 622 623 qdf_export_symbol(init_deinit_rcc_aoa_cap_ext2_free); 624 625 int init_deinit_populate_dbs_or_sbs_cap_ext2(struct wlan_objmgr_psoc *psoc, 626 wmi_unified_t handle, 627 uint8_t *event, 628 struct tgt_info *info) 629 { 630 uint32_t sbs_lower_band_end_freq; 631 struct target_psoc_info *psoc_info; 632 QDF_STATUS status = QDF_STATUS_SUCCESS; 633 634 status = wmi_extract_dbs_or_sbs_cap_service_ready_ext2(handle, event, 635 &sbs_lower_band_end_freq); 636 if (QDF_IS_STATUS_ERROR(status)) { 637 target_if_err("Extraction of twt capability failed"); 638 goto exit; 639 } 640 psoc_info = wlan_psoc_get_tgt_if_handle(psoc); 641 target_psoc_set_sbs_lower_band_end(psoc_info, sbs_lower_band_end_freq); 642 643 exit: 644 return qdf_status_to_os_return(status); 645 } 646 647 int init_deinit_populate_sap_coex_capability(struct wlan_objmgr_psoc *psoc, 648 wmi_unified_t handle, 649 uint8_t *event) 650 { 651 struct wmi_host_coex_fix_chan_cap sap_coex_fixed_chan_cap; 652 struct target_psoc_info *psoc_info; 653 QDF_STATUS status; 654 655 qdf_mem_zero(&sap_coex_fixed_chan_cap, 656 sizeof(struct wmi_host_coex_fix_chan_cap)); 657 658 status = wmi_extract_sap_coex_cap_service_ready_ext2(handle, event, 659 &sap_coex_fixed_chan_cap); 660 if (QDF_IS_STATUS_ERROR(status)) { 661 target_if_err("Extraction of sap_coex_chan_pref cap failed"); 662 goto exit; 663 } 664 psoc_info = wlan_psoc_get_tgt_if_handle(psoc); 665 target_psoc_set_sap_coex_fixed_chan_cap(psoc_info, 666 !!sap_coex_fixed_chan_cap.fix_chan_priority); 667 exit: 668 return qdf_status_to_os_return(status); 669 } 670 671 int init_deinit_populate_aux_dev_cap_ext2(struct wlan_objmgr_psoc *psoc, 672 wmi_unified_t handle, uint8_t *event, 673 struct tgt_info *info) 674 675 { 676 uint8_t cap_idx; 677 uint32_t num_aux_dev_caps; 678 QDF_STATUS status = QDF_STATUS_SUCCESS; 679 struct wlan_psoc_host_aux_dev_caps *param; 680 681 num_aux_dev_caps = info->service_ext2_param.num_aux_dev_caps; 682 target_if_info("num_aux_dev_caps = %d", num_aux_dev_caps); 683 684 if (!num_aux_dev_caps) 685 return 0; 686 687 info->aux_dev_caps = 688 qdf_mem_malloc(sizeof(struct wlan_psoc_host_aux_dev_caps) * 689 num_aux_dev_caps); 690 691 if (!info->aux_dev_caps) 692 return -EINVAL; 693 694 for (cap_idx = 0; cap_idx < num_aux_dev_caps; cap_idx++) { 695 param = &info->aux_dev_caps[cap_idx]; 696 status = wmi_extract_aux_dev_cap_service_ready_ext2(handle, 697 event, 698 cap_idx, 699 param); 700 if (QDF_IS_STATUS_ERROR(status)) { 701 target_if_err("Extraction of aux dev cap failed"); 702 goto free_and_return; 703 } 704 } 705 706 return 0; 707 708 free_and_return: 709 qdf_mem_free(info->aux_dev_caps); 710 info->aux_dev_caps = NULL; 711 /* Set to 0 in case some code later rely on that */ 712 info->service_ext2_param.num_aux_dev_caps = 0; 713 714 return qdf_status_to_os_return(status); 715 } 716 717 QDF_STATUS init_deinit_dbr_ring_cap_free( 718 struct target_psoc_info *tgt_psoc_info) 719 { 720 QDF_STATUS status = QDF_STATUS_SUCCESS; 721 722 if (tgt_psoc_info->info.dbr_ring_cap) { 723 qdf_mem_free(tgt_psoc_info->info.dbr_ring_cap); 724 tgt_psoc_info->info.dbr_ring_cap = NULL; 725 } 726 727 return status; 728 } 729 qdf_export_symbol(init_deinit_dbr_ring_cap_free); 730 731 QDF_STATUS init_deinit_spectral_scaling_params_free( 732 struct target_psoc_info *tgt_psoc_info) 733 { 734 QDF_STATUS status = QDF_STATUS_E_FAILURE; 735 736 if (tgt_psoc_info->info.scaling_params) { 737 qdf_mem_free(tgt_psoc_info->info.scaling_params); 738 tgt_psoc_info->info.scaling_params = NULL; 739 status = QDF_STATUS_SUCCESS; 740 } 741 742 return status; 743 } 744 745 qdf_export_symbol(init_deinit_spectral_scaling_params_free); 746 747 QDF_STATUS init_deinit_aux_dev_cap_free( 748 struct target_psoc_info *tgt_psoc_info) 749 { 750 QDF_STATUS status = QDF_STATUS_SUCCESS; 751 752 if (tgt_psoc_info->info.aux_dev_caps) { 753 qdf_mem_free(tgt_psoc_info->info.aux_dev_caps); 754 tgt_psoc_info->info.aux_dev_caps = NULL; 755 } 756 757 return status; 758 } 759 760 #ifdef DBS_SBS_BAND_LIMITATION_WAR 761 #define phy0 0 762 #define phy2 2 763 #define NUM_RF_MODES 2 /* (DBS + DBS_SBS) */ 764 /** 765 * init_deinit_update_phy_reg_cap() - Update the low/high frequency for phy0. 766 * @psoc: PSOC common object 767 * @info: FW or lower layer related info 768 * @reg_cap: Reg caps per PHY 769 * 770 * For the DBS_SBS capable board, update the low or high frequency 771 * for phy0 by leveraging the frequency populated for phy2 772 * depending on whether it is mapped to upper or lower 5G band by 773 * FW/HAL-PHY. 774 */ 775 static void init_deinit_update_phy_reg_cap(struct wlan_objmgr_psoc *psoc, 776 struct tgt_info *info, 777 struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap) 778 { 779 struct target_psoc_info *tgt_hdl; 780 enum wmi_host_hw_mode_config_type mode; 781 uint32_t num_hw_modes; 782 uint8_t idx; 783 784 tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle( 785 psoc); 786 if (!tgt_hdl) { 787 target_if_err("target_psoc_info is null in service ready ev"); 788 return; 789 } 790 791 mode = target_psoc_get_preferred_hw_mode(tgt_hdl); 792 793 num_hw_modes = info->hw_modes.num_modes; 794 795 if ((mode != WMI_HOST_HW_MODE_DBS) || (num_hw_modes < NUM_RF_MODES)) 796 return; 797 798 for (idx = 0; idx < num_hw_modes; idx++) 799 if (info->hw_modes.hw_mode_ids[idx] == 800 WMI_HOST_HW_MODE_DBS_SBS) { 801 if (reg_cap[phy0].low_5ghz_chan > 802 reg_cap[phy2].low_5ghz_chan) 803 reg_cap[phy0].low_5ghz_chan = 804 reg_cap[phy2].low_5ghz_chan; 805 else if (reg_cap[phy0].high_5ghz_chan < 806 reg_cap[phy2].high_5ghz_chan) 807 reg_cap[phy0].high_5ghz_chan = 808 reg_cap[phy2].high_5ghz_chan; 809 break; 810 } 811 } 812 #else 813 static void init_deinit_update_phy_reg_cap(struct wlan_objmgr_psoc *psoc, 814 struct tgt_info *info, 815 struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap) 816 { 817 } 818 #endif 819 820 /** 821 * init_deinit_fill_host_reg_cap() - Fill the host regulatory cap 822 * with target hal reg capabilities. 823 * @cap: Pointer to wlan_psoc_hal_reg_capability where FW capabilities 824 * are extracted. 825 * @reg_cap: Pointer to wlan_psoc_host_hal_reg_capabilities_ext, host reg 826 * capabilities to be filled. 827 * 828 * Return - None 829 */ 830 static void 831 init_deinit_fill_host_reg_cap(struct wlan_psoc_hal_reg_capability *cap, 832 struct wlan_psoc_host_hal_reg_capabilities_ext 833 *reg_cap) 834 { 835 reg_cap->phy_id = 0; 836 reg_cap->eeprom_reg_domain = cap->eeprom_rd; 837 reg_cap->eeprom_reg_domain_ext = cap->eeprom_rd_ext; 838 reg_cap->regcap1 = cap->regcap1; 839 reg_cap->regcap2 = cap->regcap2; 840 reg_cap->wireless_modes = (uint64_t)cap->wireless_modes; 841 reg_cap->low_2ghz_chan = cap->low_2ghz_chan; 842 reg_cap->high_2ghz_chan = cap->high_2ghz_chan; 843 reg_cap->low_5ghz_chan = cap->low_5ghz_chan; 844 reg_cap->high_5ghz_chan = cap->high_5ghz_chan; 845 } 846 847 static void 848 init_deinit_populate_tgt_ext_param(struct tgt_info *info, 849 struct wlan_psoc_host_hal_reg_capabilities_ext *cap) 850 { 851 struct wlan_psoc_host_service_ext_param *ext_param; 852 853 ext_param = &info->service_ext_param; 854 ext_param->wireless_modes = cap->wireless_modes; 855 ext_param->low_2ghz_chan = cap->low_2ghz_chan; 856 ext_param->high_2ghz_chan = cap->high_2ghz_chan; 857 ext_param->low_5ghz_chan = cap->low_5ghz_chan; 858 ext_param->high_5ghz_chan = cap->high_5ghz_chan; 859 } 860 861 static void 862 init_deinit_populate_tgt_ext2_param(struct tgt_info *info, 863 struct wlan_psoc_host_hal_reg_capabilities_ext2 *cap) 864 { 865 struct wlan_psoc_host_service_ext2_param *ext2_param; 866 867 ext2_param = &info->service_ext2_param; 868 ext2_param->wireless_modes_ext = cap->wireless_modes_ext; 869 ext2_param->low_2ghz_chan_ext = cap->low_2ghz_chan_ext; 870 ext2_param->high_2ghz_chan_ext = cap->high_2ghz_chan_ext; 871 ext2_param->low_5ghz_chan_ext = cap->low_5ghz_chan_ext; 872 ext2_param->high_5ghz_chan_ext = cap->high_5ghz_chan_ext; 873 } 874 875 int init_deinit_populate_phy_reg_cap(struct wlan_objmgr_psoc *psoc, 876 wmi_unified_t handle, uint8_t *event, 877 struct tgt_info *info, 878 bool service_ready) 879 { 880 uint8_t reg_idx; 881 uint32_t num_phy_reg_cap; 882 QDF_STATUS status = QDF_STATUS_SUCCESS; 883 struct wlan_psoc_hal_reg_capability cap; 884 struct wlan_psoc_host_hal_reg_capabilities_ext 885 reg_cap[PSOC_MAX_PHY_REG_CAP] = {{0} }; 886 887 if (service_ready) { 888 status = wmi_extract_hal_reg_cap(handle, event, &cap); 889 if (QDF_IS_STATUS_ERROR(status)) { 890 target_if_err("failed to parse hal reg cap"); 891 return qdf_status_to_os_return(status); 892 } 893 info->service_ext_param.num_phy = 1; 894 num_phy_reg_cap = 1; 895 init_deinit_fill_host_reg_cap(&cap, ®_cap[0]); 896 init_deinit_populate_tgt_ext_param(info, ®_cap[0]); 897 target_if_debug("FW wireless modes 0x%llx", 898 reg_cap[0].wireless_modes); 899 } else { 900 num_phy_reg_cap = info->service_ext_param.num_phy; 901 if (num_phy_reg_cap > PSOC_MAX_PHY_REG_CAP) { 902 target_if_err("Invalid num_phy_reg_cap %d", 903 num_phy_reg_cap); 904 return -EINVAL; 905 } 906 target_if_debug("num_phy_reg_cap %d", num_phy_reg_cap); 907 908 for (reg_idx = 0; reg_idx < num_phy_reg_cap; reg_idx++) { 909 status = wmi_extract_reg_cap_service_ready_ext(handle, 910 event, reg_idx, &(reg_cap[reg_idx])); 911 if (QDF_IS_STATUS_ERROR(status)) { 912 target_if_err("failed to parse reg cap"); 913 return qdf_status_to_os_return(status); 914 } 915 } 916 } 917 918 init_deinit_update_phy_reg_cap(psoc, info, reg_cap); 919 status = ucfg_reg_set_hal_reg_cap(psoc, reg_cap, num_phy_reg_cap); 920 921 return qdf_status_to_os_return(status); 922 } 923 924 int init_deinit_populate_mac_phy_cap_ext2(wmi_unified_t wmi_handle, 925 uint8_t *event, 926 struct tgt_info *info) 927 { 928 uint32_t num_hw_modes; 929 uint8_t hw_idx; 930 uint32_t hw_mode_id; 931 uint32_t phy_bit_map; 932 uint8_t phy_id; 933 uint8_t mac_phy_count = 0; 934 QDF_STATUS status = QDF_STATUS_SUCCESS; 935 struct wlan_psoc_host_mac_phy_caps *mac_phy_cap; 936 struct wlan_psoc_host_mac_phy_caps_ext2 *mac_phy_caps_ext2; 937 938 if (!event) 939 return -EINVAL; 940 941 num_hw_modes = info->hw_modes.num_modes; 942 943 for (hw_idx = 0; hw_idx < num_hw_modes; hw_idx++) { 944 hw_mode_id = info->hw_modes.hw_mode_ids[hw_idx]; 945 phy_bit_map = info->hw_modes.phy_bit_map[hw_idx]; 946 947 phy_id = info->mac_phy_cap[mac_phy_count].phy_id; 948 while (phy_bit_map) { 949 if (mac_phy_count >= info->total_mac_phy_cnt) { 950 target_if_err("total MAC PHY count exceeds max limit %d, mac_phy_count = %d", 951 info->total_mac_phy_cnt, 952 mac_phy_count); 953 return -EINVAL; 954 } 955 956 mac_phy_cap = &info->mac_phy_cap[mac_phy_count]; 957 mac_phy_caps_ext2 = 958 &info->mac_phy_caps_ext2[mac_phy_count]; 959 status = wmi_extract_mac_phy_cap_service_ready_ext2( 960 wmi_handle, event, hw_mode_id, phy_id, 961 mac_phy_cap->phy_idx, 962 mac_phy_caps_ext2); 963 964 if (QDF_IS_STATUS_ERROR(status)) { 965 target_if_err("failed to parse mac phy capability ext2"); 966 return qdf_status_to_os_return(status); 967 } 968 969 mac_phy_cap->reg_cap_ext.wireless_modes |= 970 mac_phy_caps_ext2[phy_id].wireless_modes_ext; 971 972 mac_phy_count++; 973 phy_bit_map &= (phy_bit_map - 1); 974 phy_id++; 975 } 976 } 977 978 return 0; 979 } 980 981 int init_deinit_populate_hal_reg_cap_ext2(wmi_unified_t wmi_handle, 982 uint8_t *event, 983 struct tgt_info *info) 984 { 985 struct wlan_psoc_host_hal_reg_capabilities_ext2 986 reg_cap[PSOC_MAX_PHY_REG_CAP] = {{0} }; 987 struct wlan_objmgr_psoc *psoc; 988 uint32_t num_phy_reg_cap; 989 uint8_t reg_idx; 990 QDF_STATUS status = QDF_STATUS_SUCCESS; 991 992 if (!event) { 993 target_if_err("event buffer is null"); 994 return -EINVAL; 995 } 996 997 psoc = target_if_get_psoc_from_scn_hdl(wmi_handle->scn_handle); 998 if (!psoc) { 999 target_if_err("psoc is null"); 1000 return -EINVAL; 1001 } 1002 1003 num_phy_reg_cap = info->service_ext_param.num_phy; 1004 if (num_phy_reg_cap > PSOC_MAX_PHY_REG_CAP) { 1005 target_if_err("Invalid num_phy_reg_cap %d", num_phy_reg_cap); 1006 return -EINVAL; 1007 } 1008 1009 for (reg_idx = 0; reg_idx < num_phy_reg_cap; reg_idx++) { 1010 status = wmi_extract_hal_reg_cap_ext2( 1011 wmi_handle, event, reg_idx, ®_cap[reg_idx]); 1012 if (QDF_IS_STATUS_ERROR(status)) { 1013 target_if_err("failed to parse hal reg cap ext2"); 1014 return qdf_status_to_os_return(status); 1015 } 1016 1017 init_deinit_populate_tgt_ext2_param(info, ®_cap[reg_idx]); 1018 status = ucfg_reg_update_hal_cap_wireless_modes(psoc, 1019 reg_cap[reg_idx].wireless_modes_ext, 1020 reg_idx); 1021 if (QDF_IS_STATUS_ERROR(status)) { 1022 target_if_err("Failed to update hal reg cap"); 1023 return qdf_status_to_os_return(status); 1024 } 1025 } 1026 1027 return 0; 1028 } 1029 1030 int init_deinit_populate_scan_radio_cap_ext2(wmi_unified_t wmi_handle, 1031 uint8_t *event, 1032 struct tgt_info *info) 1033 { 1034 struct wlan_psoc_host_scan_radio_caps *param; 1035 uint32_t num_scan_radio_caps; 1036 uint8_t cap_idx; 1037 QDF_STATUS status; 1038 1039 if (!event) { 1040 target_if_err("Invalid event buffer"); 1041 return -EINVAL; 1042 } 1043 1044 num_scan_radio_caps = info->service_ext2_param.num_scan_radio_caps; 1045 target_if_debug("num scan radio capabilities = %d", 1046 num_scan_radio_caps); 1047 1048 if (!num_scan_radio_caps) 1049 return 0; 1050 1051 info->scan_radio_caps = qdf_mem_malloc( 1052 sizeof(struct wlan_psoc_host_scan_radio_caps) * 1053 num_scan_radio_caps); 1054 1055 if (!info->scan_radio_caps) { 1056 target_if_err("Failed to allocate memory for scan radio caps"); 1057 return -EINVAL; 1058 } 1059 1060 for (cap_idx = 0; cap_idx < num_scan_radio_caps; cap_idx++) { 1061 param = &info->scan_radio_caps[cap_idx]; 1062 status = wmi_extract_scan_radio_cap_service_ready_ext2( 1063 wmi_handle, event, cap_idx, param); 1064 if (QDF_IS_STATUS_ERROR(status)) { 1065 target_if_err("Extraction of scan radio cap failed"); 1066 goto free_and_return; 1067 } 1068 } 1069 1070 return 0; 1071 1072 free_and_return: 1073 qdf_mem_free(info->scan_radio_caps); 1074 info->scan_radio_caps = NULL; 1075 1076 return qdf_status_to_os_return(status); 1077 } 1078 1079 QDF_STATUS init_deinit_scan_radio_cap_free( 1080 struct target_psoc_info *tgt_psoc_info) 1081 { 1082 qdf_mem_free(tgt_psoc_info->info.scan_radio_caps); 1083 tgt_psoc_info->info.scan_radio_caps = NULL; 1084 1085 return QDF_STATUS_SUCCESS; 1086 } 1087 1088 qdf_export_symbol(init_deinit_scan_radio_cap_free); 1089 1090 int init_deinit_populate_msdu_idx_qtype_map_ext2(wmi_unified_t wmi_handle, 1091 uint8_t *event, 1092 struct tgt_info *info) 1093 { 1094 uint8_t *msdu_qtype; 1095 uint32_t num_msdu_idx_qtype_map; 1096 uint8_t msdu_idx; 1097 QDF_STATUS status; 1098 1099 if (!event) { 1100 target_if_err("Invalid event buffer"); 1101 return -EINVAL; 1102 } 1103 1104 num_msdu_idx_qtype_map = 1105 info->service_ext2_param.num_msdu_idx_qtype_map; 1106 target_if_debug("num msdu_idx to qtype map = %d", 1107 num_msdu_idx_qtype_map); 1108 1109 if (!num_msdu_idx_qtype_map) 1110 return 0; 1111 1112 info->msdu_idx_qtype_map = qdf_mem_malloc(sizeof(uint8_t) * 1113 num_msdu_idx_qtype_map); 1114 1115 if (!info->msdu_idx_qtype_map) { 1116 target_if_err("Failed to allocate memory for msdu idx qtype map"); 1117 return -EINVAL; 1118 } 1119 1120 for (msdu_idx = 0; msdu_idx < num_msdu_idx_qtype_map; msdu_idx++) { 1121 msdu_qtype = &info->msdu_idx_qtype_map[msdu_idx]; 1122 status = wmi_extract_msdu_idx_qtype_map_service_ready_ext2( 1123 wmi_handle, event, msdu_idx, msdu_qtype); 1124 if (QDF_IS_STATUS_ERROR(status)) { 1125 target_if_err("Extraction of msdu idx qtype map failed"); 1126 goto free_and_return; 1127 } 1128 } 1129 1130 return 0; 1131 1132 free_and_return: 1133 qdf_mem_free(info->msdu_idx_qtype_map); 1134 info->msdu_idx_qtype_map = NULL; 1135 1136 return qdf_status_to_os_return(status); 1137 } 1138 1139 QDF_STATUS init_deinit_msdu_idx_qtype_map_free( 1140 struct target_psoc_info *tgt_psoc_info) 1141 { 1142 qdf_mem_free(tgt_psoc_info->info.msdu_idx_qtype_map); 1143 tgt_psoc_info->info.msdu_idx_qtype_map = NULL; 1144 1145 return QDF_STATUS_SUCCESS; 1146 } 1147 1148 qdf_export_symbol(init_deinit_msdu_idx_qtype_map_free); 1149 1150 static bool init_deinit_regdmn_160mhz_support( 1151 struct wlan_psoc_host_hal_reg_capabilities_ext *hal_cap) 1152 { 1153 return ((hal_cap->wireless_modes & 1154 HOST_REGDMN_MODE_11AC_VHT160) != 0); 1155 } 1156 1157 static bool init_deinit_regdmn_80p80mhz_support( 1158 struct wlan_psoc_host_hal_reg_capabilities_ext *hal_cap) 1159 { 1160 return ((hal_cap->wireless_modes & 1161 HOST_REGDMN_MODE_11AC_VHT80_80) != 0); 1162 } 1163 1164 static bool init_deinit_vht_160mhz_is_supported(uint32_t vhtcap) 1165 { 1166 return ((vhtcap & WLAN_VHTCAP_SUP_CHAN_WIDTH_160) != 0); 1167 } 1168 1169 static bool init_deinit_vht_80p80mhz_is_supported(uint32_t vhtcap) 1170 { 1171 return ((vhtcap & WLAN_VHTCAP_SUP_CHAN_WIDTH_80_160) != 0); 1172 } 1173 1174 static bool init_deinit_vht_160mhz_shortgi_is_supported(uint32_t vhtcap) 1175 { 1176 return ((vhtcap & WLAN_VHTCAP_SHORTGI_160) != 0); 1177 } 1178 1179 QDF_STATUS init_deinit_validate_160_80p80_fw_caps( 1180 struct wlan_objmgr_psoc *psoc, 1181 struct target_psoc_info *tgt_hdl) 1182 { 1183 bool wireless_mode_160mhz = false; 1184 bool wireless_mode_80p80mhz = false; 1185 bool vhtcap_160mhz = false; 1186 bool vhtcap_80p80_160mhz = false; 1187 bool vhtcap_160mhz_sgi = false; 1188 bool valid = false; 1189 struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap; 1190 struct wmi_unified *wmi_handle; 1191 1192 if (!tgt_hdl) { 1193 target_if_err( 1194 "target_psoc_info is null in validate 160n80p80 cap check"); 1195 return QDF_STATUS_E_INVAL; 1196 } 1197 1198 wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl); 1199 1200 if ((tgt_hdl->info.target_type == TARGET_TYPE_QCA8074) || 1201 (tgt_hdl->info.target_type == TARGET_TYPE_QCA8074V2) || 1202 (tgt_hdl->info.target_type == TARGET_TYPE_QCN6122) || 1203 (tgt_hdl->info.target_type == TARGET_TYPE_QCN9160) || 1204 (tgt_hdl->info.target_type == TARGET_TYPE_QCA6290) || 1205 (tgt_hdl->info.target_type == TARGET_TYPE_QCN6432)) { 1206 /** 1207 * Return true for now. This is not available in 1208 * qca8074 fw yet 1209 */ 1210 return QDF_STATUS_SUCCESS; 1211 } 1212 1213 reg_cap = ucfg_reg_get_hal_reg_cap(psoc); 1214 if (!reg_cap) { 1215 target_if_err("reg cap is NULL"); 1216 return QDF_STATUS_E_FAILURE; 1217 } 1218 1219 /* NOTE: Host driver gets vht capability and supported channel 1220 * width / channel frequency range from FW/HALPHY and obeys it. 1221 * Host driver is unaware of any physical filters or any other 1222 * hardware factors that can impact these capabilities. 1223 * These need to be correctly determined by firmware. 1224 */ 1225 1226 /*This table lists all valid and invalid combinations 1227 * WMODE160 WMODE80_80 VHTCAP_160 VHTCAP_80+80_160 IsCombinationvalid? 1228 * 0 0 0 0 YES 1229 * 0 0 0 1 NO 1230 * 0 0 1 0 NO 1231 * 0 0 1 1 NO 1232 * 0 1 0 0 NO 1233 * 0 1 0 1 NO 1234 * 0 1 1 0 NO 1235 * 0 1 1 1 NO 1236 * 1 0 0 0 NO 1237 * 1 0 0 1 NO 1238 * 1 0 1 0 YES 1239 * 1 0 1 1 NO 1240 * 1 1 0 0 NO 1241 * 1 1 0 1 YES 1242 * 1 1 1 0 NO 1243 * 1 1 1 1 NO 1244 */ 1245 1246 /* NOTE: Last row in above table is invalid because value corresponding 1247 * to both VHTCAP_160 and VHTCAP_80+80_160 being set is reserved as per 1248 * 802.11ac. Only one of them can be set at a time. 1249 */ 1250 1251 wireless_mode_160mhz = init_deinit_regdmn_160mhz_support(reg_cap); 1252 wireless_mode_80p80mhz = init_deinit_regdmn_80p80mhz_support(reg_cap); 1253 vhtcap_160mhz = init_deinit_vht_160mhz_is_supported( 1254 tgt_hdl->info.target_caps.vht_cap_info); 1255 vhtcap_80p80_160mhz = init_deinit_vht_80p80mhz_is_supported( 1256 tgt_hdl->info.target_caps.vht_cap_info); 1257 vhtcap_160mhz_sgi = init_deinit_vht_160mhz_shortgi_is_supported( 1258 tgt_hdl->info.target_caps.vht_cap_info); 1259 1260 if (!(wireless_mode_160mhz || wireless_mode_80p80mhz || 1261 vhtcap_160mhz || vhtcap_80p80_160mhz)) { 1262 valid = QDF_STATUS_SUCCESS; 1263 } else if (wireless_mode_160mhz && !wireless_mode_80p80mhz && 1264 vhtcap_160mhz && !vhtcap_80p80_160mhz) { 1265 valid = QDF_STATUS_SUCCESS; 1266 } else if (wireless_mode_160mhz && wireless_mode_80p80mhz && 1267 !vhtcap_160mhz && vhtcap_160mhz_sgi) { 1268 valid = QDF_STATUS_SUCCESS; 1269 } 1270 1271 if (valid == QDF_STATUS_SUCCESS) { 1272 /* 1273 * Ensure short GI for 160 MHz is enabled 1274 * only if 160/80+80 is supported. 1275 */ 1276 if (vhtcap_160mhz_sgi && 1277 !(vhtcap_160mhz || vhtcap_80p80_160mhz)) { 1278 valid = QDF_STATUS_E_FAILURE; 1279 } 1280 } 1281 1282 /* Invalid config specified by FW */ 1283 if (valid != QDF_STATUS_SUCCESS) { 1284 target_if_err("Invalid 160/80+80 MHz config specified by FW. Take care of it first"); 1285 target_if_err("wireless_mode_160mhz: %d, wireless_mode_80p80mhz: %d", 1286 wireless_mode_160mhz, wireless_mode_80p80mhz); 1287 target_if_err("vhtcap_160mhz: %d, vhtcap_80p80_160mhz: %d,vhtcap_160mhz_sgi: %d", 1288 vhtcap_160mhz, vhtcap_80p80_160mhz, 1289 vhtcap_160mhz_sgi); 1290 } 1291 return valid; 1292 } 1293 1294 void init_deinit_chainmask_config( 1295 struct wlan_objmgr_psoc *psoc, 1296 struct target_psoc_info *tgt_hdl) 1297 { 1298 tgt_hdl->info.wlan_res_cfg.tx_chain_mask = 1299 ((1 << tgt_hdl->info.target_caps.num_rf_chains) - 1); 1300 tgt_hdl->info.wlan_res_cfg.rx_chain_mask = 1301 ((1 << tgt_hdl->info.target_caps.num_rf_chains) - 1); 1302 } 1303 1304 QDF_STATUS init_deinit_is_service_ext_msg( 1305 struct wlan_objmgr_psoc *psoc, 1306 struct target_psoc_info *tgt_hdl) 1307 { 1308 struct wmi_unified *wmi_handle; 1309 1310 if (!tgt_hdl) { 1311 target_if_err( 1312 "psoc target_psoc_info is null in service ext msg"); 1313 return QDF_STATUS_E_INVAL; 1314 } 1315 1316 wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl); 1317 1318 if (wmi_service_enabled(wmi_handle, wmi_service_ext_msg)) 1319 return QDF_STATUS_SUCCESS; 1320 else 1321 return QDF_STATUS_E_FAILURE; 1322 } 1323 1324 bool init_deinit_is_preferred_hw_mode_supported( 1325 struct wlan_objmgr_psoc *psoc, 1326 struct target_psoc_info *tgt_hdl) 1327 { 1328 uint16_t i; 1329 struct tgt_info *info; 1330 1331 if (!tgt_hdl) { 1332 target_if_err( 1333 "psoc target_psoc_info is null in service ext msg"); 1334 return FALSE; 1335 } 1336 1337 info = &tgt_hdl->info; 1338 1339 if (info->preferred_hw_mode == WMI_HOST_HW_MODE_MAX) 1340 return TRUE; 1341 1342 if (wlan_psoc_nif_feat_cap_get(psoc, WLAN_SOC_F_DYNAMIC_HW_MODE)) { 1343 if (!wlan_psoc_nif_fw_ext_cap_get(psoc, 1344 WLAN_SOC_CEXT_DYNAMIC_HW_MODE)) { 1345 target_if_err( 1346 "WMI service bit for DYNAMIC HW mode is not set!"); 1347 return FALSE; 1348 } 1349 } 1350 1351 for (i = 0; i < target_psoc_get_total_mac_phy_cnt(tgt_hdl); i++) { 1352 if (info->mac_phy_cap[i].hw_mode_id == info->preferred_hw_mode) 1353 return TRUE; 1354 } 1355 1356 return FALSE; 1357 } 1358 1359 void init_deinit_wakeup_host_wait( 1360 struct wlan_objmgr_psoc *psoc, 1361 struct target_psoc_info *tgt_hdl) 1362 { 1363 if (!tgt_hdl) { 1364 target_if_err("psoc target_psoc_info is null in target ready"); 1365 return; 1366 } 1367 qdf_event_set(&tgt_hdl->info.event); 1368 } 1369