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 251 if (current_hw_mode > WMI_HOST_HW_MODE_MAX || 252 new_hw_mode > WMI_HOST_HW_MODE_MAX) 253 return false; 254 255 /* Above precedence is defined by low to high, lower the value 256 * higher the precedence 257 */ 258 if (hw_mode_id_precedence[current_hw_mode] > 259 hw_mode_id_precedence[new_hw_mode]) 260 return true; 261 262 return false; 263 } 264 265 /** 266 * select_preferred_mode() - Select preferred hw mode based on current mode. 267 * @tgt_hdl: target_psoc_info object 268 * @hw_mode_caps: HW mode caps of new mode id that needs to checked for 269 * selection. 270 * @current_mode: Current mode. 271 * 272 * API to select preferred hw mode based on the current config. 273 * Based on host config for preferred mode, final mode selected as follows- 274 * 1) If preferred_mode == WMI_HOST_HW_MODE_DETECT, Then select mode from FW 275 * supported modes such that it is a super set of all modes FW advertises. 276 * For e.g., If FW supports DBS(2 radio) and DBS_SBS(3 radio)- Choose DBS_SBS 277 * 2) If preferred_mode == WMI_HOST_HW_MODE_MAX, Then do not select any mode 278 * from FW advertised modes. Host needs to maintain all modes supported in FW 279 * and can switch dynamically. 280 * 3) Else, A valid preferred_mode is set, Hence check if this is part of FW 281 * supported modes. If it is found, then use it to bring up the device. 282 * 283 * Return: selected_mode based on the above criteria. 284 */ 285 static uint32_t 286 select_preferred_hw_mode(struct target_psoc_info *tgt_hdl, 287 struct wlan_psoc_host_hw_mode_caps *hw_mode_caps, 288 uint32_t current_mode) 289 { 290 uint32_t preferred_mode, selected_mode = current_mode; 291 struct tgt_info *info; 292 293 info = &tgt_hdl->info; 294 preferred_mode = target_psoc_get_preferred_hw_mode(tgt_hdl); 295 if (preferred_mode == WMI_HOST_HW_MODE_DETECT) { 296 uint32_t new_mode = hw_mode_caps->hw_mode_id; 297 298 /* Choose hw_mode_id based on precedence */ 299 if (new_hw_mode_preferred(selected_mode, new_mode)) { 300 selected_mode = new_mode; 301 qdf_mem_copy(&info->hw_mode_cap, hw_mode_caps, 302 sizeof(info->hw_mode_cap)); 303 } 304 } else if ((preferred_mode != WMI_HOST_HW_MODE_MAX) && 305 (preferred_mode == hw_mode_caps->hw_mode_id)) { 306 selected_mode = preferred_mode; 307 qdf_mem_copy(&info->hw_mode_cap, hw_mode_caps, 308 sizeof(info->hw_mode_cap)); 309 } 310 311 return selected_mode; 312 } 313 314 #ifdef FEATURE_NO_DBS_INTRABAND_MCC_SUPPORT 315 static void init_deinit_change_def_hw_mode(struct target_psoc_info *tgt_hdl, 316 struct wmi_unified *wmi_handle) 317 { 318 struct tgt_info *info = &tgt_hdl->info; 319 320 if ((info->hw_modes.num_modes == 1) && 321 (info->hw_modes.hw_mode_ids[0] == WMI_HOST_HW_MODE_DBS) && 322 !wmi_service_enabled(wmi_handle, 323 wmi_service_dual_band_simultaneous_support)) 324 target_psoc_set_preferred_hw_mode(tgt_hdl, 325 WMI_HOST_HW_MODE_DETECT); 326 } 327 #else 328 static void init_deinit_change_def_hw_mode(struct target_psoc_info *tgt_hdl, 329 struct wmi_unified *wmi_handle) 330 { 331 } 332 #endif 333 334 int init_deinit_populate_hw_mode_capability( 335 wmi_unified_t wmi_handle, uint8_t *event, 336 struct target_psoc_info *tgt_hdl) 337 { 338 QDF_STATUS status = QDF_STATUS_SUCCESS; 339 uint8_t hw_idx; 340 uint32_t num_hw_modes; 341 struct wlan_psoc_host_hw_mode_caps hw_mode_caps[PSOC_MAX_HW_MODE]; 342 uint32_t preferred_mode, selected_mode = WMI_HOST_HW_MODE_MAX; 343 struct tgt_info *info; 344 345 info = &tgt_hdl->info; 346 num_hw_modes = info->service_ext_param.num_hw_modes; 347 if (num_hw_modes > PSOC_MAX_HW_MODE) { 348 target_if_err("invalid num_hw_modes %d", num_hw_modes); 349 return -EINVAL; 350 } 351 target_if_debug("num_hw_modes %d", num_hw_modes); 352 353 qdf_mem_zero(&hw_mode_caps, sizeof(hw_mode_caps)); 354 info->hw_modes.num_modes = 0; 355 info->hw_mode_cap.hw_mode_id = WMI_HOST_HW_MODE_MAX; 356 357 for (hw_idx = 0; hw_idx < num_hw_modes; hw_idx++) { 358 status = get_hw_mode(wmi_handle, event, hw_idx, 359 &hw_mode_caps[hw_idx]); 360 if (status) 361 goto return_exit; 362 363 if (hw_idx < WMI_HOST_HW_MODE_MAX) { 364 info->hw_modes.hw_mode_ids[hw_idx] = 365 hw_mode_caps[hw_idx].hw_mode_id; 366 info->hw_modes.phy_bit_map[hw_idx] = 367 hw_mode_caps[hw_idx].phy_id_map; 368 info->hw_modes.num_modes++; 369 } 370 371 status = init_deinit_populate_mac_phy_capability(wmi_handle, 372 event, &hw_mode_caps[hw_idx], info); 373 if (status) 374 goto return_exit; 375 376 if (num_hw_modes == 1) 377 init_deinit_change_def_hw_mode(tgt_hdl, wmi_handle); 378 379 selected_mode = select_preferred_hw_mode(tgt_hdl, 380 &hw_mode_caps[hw_idx], 381 selected_mode); 382 } 383 384 preferred_mode = target_psoc_get_preferred_hw_mode(tgt_hdl); 385 if (preferred_mode == WMI_HOST_HW_MODE_DETECT) { 386 target_if_info("Preferred mode is not set, use mode id %d\n", 387 selected_mode); 388 target_psoc_set_preferred_hw_mode(tgt_hdl, selected_mode); 389 390 /* Change default DBS hw mode as per selected one */ 391 info->target_caps.default_dbs_hw_mode_index = selected_mode; 392 } 393 394 status = get_sar_version(wmi_handle, event, &info->service_ext_param); 395 target_if_debug("sar version %d", info->service_ext_param.sar_version); 396 397 return_exit: 398 return qdf_status_to_os_return(status); 399 } 400 401 int init_deinit_populate_dbr_ring_cap(struct wlan_objmgr_psoc *psoc, 402 wmi_unified_t handle, uint8_t *event, 403 struct tgt_info *info) 404 405 { 406 uint8_t cap_idx; 407 uint32_t num_dbr_ring_caps; 408 QDF_STATUS status = QDF_STATUS_SUCCESS; 409 410 num_dbr_ring_caps = info->service_ext_param.num_dbr_ring_caps; 411 target_if_debug("Num DMA Capabilities = %d", num_dbr_ring_caps); 412 413 if (!num_dbr_ring_caps) 414 return 0; 415 416 info->dbr_ring_cap = qdf_mem_malloc( 417 sizeof(struct wlan_psoc_host_dbr_ring_caps) * 418 num_dbr_ring_caps); 419 420 if (!info->dbr_ring_cap) 421 return -EINVAL; 422 423 for (cap_idx = 0; cap_idx < num_dbr_ring_caps; cap_idx++) { 424 status = wmi_extract_dbr_ring_cap_service_ready_ext(handle, 425 event, cap_idx, 426 &(info->dbr_ring_cap[cap_idx])); 427 if (QDF_IS_STATUS_ERROR(status)) { 428 target_if_err("Extraction of DMA cap failed"); 429 goto free_and_return; 430 } 431 } 432 433 return 0; 434 435 free_and_return: 436 qdf_mem_free(info->dbr_ring_cap); 437 info->dbr_ring_cap = NULL; 438 439 return qdf_status_to_os_return(status); 440 } 441 442 int init_deinit_populate_dbr_ring_cap_ext2(struct wlan_objmgr_psoc *psoc, 443 wmi_unified_t handle, uint8_t *event, 444 struct tgt_info *info) 445 446 { 447 uint8_t cap_idx; 448 uint32_t num_dbr_ring_caps; 449 QDF_STATUS status = QDF_STATUS_SUCCESS; 450 struct wlan_psoc_host_dbr_ring_caps *param; 451 452 /* 453 * If FW had already sent this info as part of EXT event, 454 * we need to discard the same and use the info from EXT2. 455 */ 456 if (info->service_ext_param.num_dbr_ring_caps) { 457 target_if_debug("dbr_ring_caps already populated"); 458 info->service_ext_param.num_dbr_ring_caps = 0; 459 qdf_mem_free(info->dbr_ring_cap); 460 info->dbr_ring_cap = NULL; 461 } 462 463 num_dbr_ring_caps = info->service_ext2_param.num_dbr_ring_caps; 464 target_if_debug("Num DMA Capabilities = %d", num_dbr_ring_caps); 465 466 if (!num_dbr_ring_caps) 467 return 0; 468 469 info->dbr_ring_cap = qdf_mem_malloc( 470 sizeof(struct wlan_psoc_host_dbr_ring_caps) * 471 num_dbr_ring_caps); 472 473 if (!info->dbr_ring_cap) 474 return -EINVAL; 475 476 for (cap_idx = 0; cap_idx < num_dbr_ring_caps; cap_idx++) { 477 param = &info->dbr_ring_cap[cap_idx]; 478 status = wmi_extract_dbr_ring_cap_service_ready_ext2(handle, 479 event, 480 cap_idx, 481 param); 482 if (QDF_IS_STATUS_ERROR(status)) { 483 target_if_err("Extraction of DMA cap failed"); 484 goto free_and_return; 485 } 486 } 487 488 return 0; 489 490 free_and_return: 491 qdf_mem_free(info->dbr_ring_cap); 492 info->dbr_ring_cap = NULL; 493 494 return qdf_status_to_os_return(status); 495 } 496 int init_deinit_populate_spectral_bin_scale_params( 497 struct wlan_objmgr_psoc *psoc, wmi_unified_t handle, 498 uint8_t *event, struct tgt_info *info) 499 500 { 501 uint8_t param_idx; 502 uint32_t num_bin_scaling_params; 503 QDF_STATUS status = QDF_STATUS_SUCCESS; 504 505 num_bin_scaling_params = info->service_ext_param.num_bin_scaling_params; 506 507 if (!num_bin_scaling_params) 508 return 0; 509 510 info->scaling_params = qdf_mem_malloc( 511 sizeof(struct wlan_psoc_host_spectral_scaling_params) * 512 num_bin_scaling_params); 513 514 if (!info->scaling_params) { 515 target_if_err("Mem alloc for bin scaling params failed"); 516 return -EINVAL; 517 } 518 519 for (param_idx = 0; param_idx < num_bin_scaling_params; param_idx++) { 520 status = wmi_extract_spectral_scaling_params_service_ready_ext( 521 handle, 522 event, param_idx, 523 &info->scaling_params[param_idx]); 524 if (QDF_IS_STATUS_ERROR(status)) { 525 target_if_err("Extraction of scaling params failed"); 526 goto free_and_return; 527 } 528 } 529 530 return 0; 531 532 free_and_return: 533 qdf_mem_free(info->scaling_params); 534 info->scaling_params = NULL; 535 536 return qdf_status_to_os_return(status); 537 } 538 539 #ifdef WLAN_SUPPORT_TWT 540 int init_deinit_populate_twt_cap_ext2(struct wlan_objmgr_psoc *psoc, 541 wmi_unified_t handle, uint8_t *event, 542 struct tgt_info *info) 543 { 544 struct wmi_twt_cap_bitmap_params param; 545 struct target_psoc_info *psoc_info; 546 QDF_STATUS status = QDF_STATUS_SUCCESS; 547 548 status = wmi_extract_twt_cap_service_ready_ext2(handle, event, 549 ¶m); 550 if (QDF_IS_STATUS_ERROR(status)) { 551 target_if_err("Extraction of twt capability failed"); 552 goto exit; 553 } 554 555 psoc_info = wlan_psoc_get_tgt_if_handle(psoc); 556 557 target_psoc_set_twt_ack_cap(psoc_info, param.twt_ack_support_cap); 558 559 exit: 560 return qdf_status_to_os_return(status); 561 } 562 #endif 563 564 int init_deinit_populate_dbs_or_sbs_cap_ext2(struct wlan_objmgr_psoc *psoc, 565 wmi_unified_t handle, 566 uint8_t *event, 567 struct tgt_info *info) 568 { 569 uint32_t sbs_lower_band_end_freq; 570 struct target_psoc_info *psoc_info; 571 QDF_STATUS status = QDF_STATUS_SUCCESS; 572 573 status = wmi_extract_dbs_or_sbs_cap_service_ready_ext2(handle, event, 574 &sbs_lower_band_end_freq); 575 if (QDF_IS_STATUS_ERROR(status)) { 576 target_if_err("Extraction of twt capability failed"); 577 goto exit; 578 } 579 psoc_info = wlan_psoc_get_tgt_if_handle(psoc); 580 target_psoc_set_sbs_lower_band_end(psoc_info, sbs_lower_band_end_freq); 581 582 exit: 583 return qdf_status_to_os_return(status); 584 } 585 586 int init_deinit_populate_sap_coex_capability(struct wlan_objmgr_psoc *psoc, 587 wmi_unified_t handle, 588 uint8_t *event) 589 { 590 struct wmi_host_coex_fix_chan_cap sap_coex_fixed_chan_cap; 591 struct target_psoc_info *psoc_info; 592 QDF_STATUS status; 593 594 qdf_mem_zero(&sap_coex_fixed_chan_cap, 595 sizeof(struct wmi_host_coex_fix_chan_cap)); 596 597 status = wmi_extract_sap_coex_cap_service_ready_ext2(handle, event, 598 &sap_coex_fixed_chan_cap); 599 if (QDF_IS_STATUS_ERROR(status)) { 600 target_if_err("Extraction of sap_coex_chan_pref cap failed"); 601 goto exit; 602 } 603 psoc_info = wlan_psoc_get_tgt_if_handle(psoc); 604 target_psoc_set_sap_coex_fixed_chan_cap(psoc_info, 605 !!sap_coex_fixed_chan_cap.fix_chan_priority); 606 exit: 607 return qdf_status_to_os_return(status); 608 } 609 610 QDF_STATUS init_deinit_dbr_ring_cap_free( 611 struct target_psoc_info *tgt_psoc_info) 612 { 613 QDF_STATUS status = QDF_STATUS_SUCCESS; 614 615 if (tgt_psoc_info->info.dbr_ring_cap) { 616 qdf_mem_free(tgt_psoc_info->info.dbr_ring_cap); 617 tgt_psoc_info->info.dbr_ring_cap = NULL; 618 } 619 620 return status; 621 } 622 qdf_export_symbol(init_deinit_dbr_ring_cap_free); 623 624 QDF_STATUS init_deinit_spectral_scaling_params_free( 625 struct target_psoc_info *tgt_psoc_info) 626 { 627 QDF_STATUS status = QDF_STATUS_E_FAILURE; 628 629 if (tgt_psoc_info->info.scaling_params) { 630 qdf_mem_free(tgt_psoc_info->info.scaling_params); 631 tgt_psoc_info->info.scaling_params = NULL; 632 status = QDF_STATUS_SUCCESS; 633 } 634 635 return status; 636 } 637 638 qdf_export_symbol(init_deinit_spectral_scaling_params_free); 639 640 #ifdef DBS_SBS_BAND_LIMITATION_WAR 641 #define phy0 0 642 #define phy2 2 643 #define NUM_RF_MODES 2 /* (DBS + DBS_SBS) */ 644 /** 645 * init_deinit_update_phy_reg_cap() - Update the low/high frequency for phy0. 646 * @psoc: PSOC common object 647 * @info: FW or lower layer related info 648 * @wlan_psoc_host_hal_reg_capabilities_ext: Reg caps per PHY 649 * 650 * For the DBS_SBS capable board, update the low or high frequency 651 * for phy0 by leveraging the frequency populated for phy2 652 * depending on whether it is mapped to upper or lower 5G band by 653 * FW/HAL-PHY. 654 */ 655 static void init_deinit_update_phy_reg_cap(struct wlan_objmgr_psoc *psoc, 656 struct tgt_info *info, 657 struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap) 658 { 659 struct target_psoc_info *tgt_hdl; 660 enum wmi_host_hw_mode_config_type mode; 661 uint32_t num_hw_modes; 662 uint8_t idx; 663 664 tgt_hdl = (struct target_psoc_info *)wlan_psoc_get_tgt_if_handle( 665 psoc); 666 if (!tgt_hdl) { 667 target_if_err("target_psoc_info is null in service ready ev"); 668 return; 669 } 670 671 mode = target_psoc_get_preferred_hw_mode(tgt_hdl); 672 673 num_hw_modes = info->hw_modes.num_modes; 674 675 if ((mode != WMI_HOST_HW_MODE_DBS) || (num_hw_modes < NUM_RF_MODES)) 676 return; 677 678 for (idx = 0; idx < num_hw_modes; idx++) 679 if (info->hw_modes.hw_mode_ids[idx] == 680 WMI_HOST_HW_MODE_DBS_SBS) { 681 if (reg_cap[phy0].low_5ghz_chan > 682 reg_cap[phy2].low_5ghz_chan) 683 reg_cap[phy0].low_5ghz_chan = 684 reg_cap[phy2].low_5ghz_chan; 685 else if (reg_cap[phy0].high_5ghz_chan < 686 reg_cap[phy2].high_5ghz_chan) 687 reg_cap[phy0].high_5ghz_chan = 688 reg_cap[phy2].high_5ghz_chan; 689 break; 690 } 691 } 692 #else 693 static void init_deinit_update_phy_reg_cap(struct wlan_objmgr_psoc *psoc, 694 struct tgt_info *info, 695 struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap) 696 { 697 } 698 #endif 699 700 /** 701 * init_deinit_fill_host_reg_cap() - Fill the host regulatory cap 702 * with target hal reg capabilities. 703 * @cap: Pointer to wlan_psoc_hal_reg_capability where FW capabilities 704 * are extracted. 705 * @reg_cap: Pointer to wlan_psoc_host_hal_reg_capabilities_ext, host reg 706 * capabilities to be filled. 707 * 708 * Return - None 709 */ 710 static void 711 init_deinit_fill_host_reg_cap(struct wlan_psoc_hal_reg_capability *cap, 712 struct wlan_psoc_host_hal_reg_capabilities_ext 713 *reg_cap) 714 { 715 reg_cap->phy_id = 0; 716 reg_cap->eeprom_reg_domain = cap->eeprom_rd; 717 reg_cap->eeprom_reg_domain_ext = cap->eeprom_rd_ext; 718 reg_cap->regcap1 = cap->regcap1; 719 reg_cap->regcap2 = cap->regcap2; 720 reg_cap->wireless_modes = (uint64_t)cap->wireless_modes; 721 reg_cap->low_2ghz_chan = cap->low_2ghz_chan; 722 reg_cap->high_2ghz_chan = cap->high_2ghz_chan; 723 reg_cap->low_5ghz_chan = cap->low_5ghz_chan; 724 reg_cap->high_5ghz_chan = cap->high_5ghz_chan; 725 } 726 727 int init_deinit_populate_phy_reg_cap(struct wlan_objmgr_psoc *psoc, 728 wmi_unified_t handle, uint8_t *event, 729 struct tgt_info *info, 730 bool service_ready) 731 { 732 uint8_t reg_idx; 733 uint32_t num_phy_reg_cap; 734 QDF_STATUS status = QDF_STATUS_SUCCESS; 735 struct wlan_psoc_hal_reg_capability cap; 736 struct wlan_psoc_host_hal_reg_capabilities_ext 737 reg_cap[PSOC_MAX_PHY_REG_CAP] = {{0} }; 738 739 if (service_ready) { 740 status = wmi_extract_hal_reg_cap(handle, event, &cap); 741 if (QDF_IS_STATUS_ERROR(status)) { 742 target_if_err("failed to parse hal reg cap"); 743 return qdf_status_to_os_return(status); 744 } 745 info->service_ext_param.num_phy = 1; 746 num_phy_reg_cap = 1; 747 init_deinit_fill_host_reg_cap(&cap, ®_cap[0]); 748 target_if_debug("FW wireless modes 0x%llx", 749 reg_cap[0].wireless_modes); 750 } else { 751 num_phy_reg_cap = info->service_ext_param.num_phy; 752 if (num_phy_reg_cap > PSOC_MAX_PHY_REG_CAP) { 753 target_if_err("Invalid num_phy_reg_cap %d", 754 num_phy_reg_cap); 755 return -EINVAL; 756 } 757 target_if_debug("num_phy_reg_cap %d", num_phy_reg_cap); 758 759 for (reg_idx = 0; reg_idx < num_phy_reg_cap; reg_idx++) { 760 status = wmi_extract_reg_cap_service_ready_ext(handle, 761 event, reg_idx, &(reg_cap[reg_idx])); 762 if (QDF_IS_STATUS_ERROR(status)) { 763 target_if_err("failed to parse reg cap"); 764 return qdf_status_to_os_return(status); 765 } 766 } 767 } 768 769 init_deinit_update_phy_reg_cap(psoc, info, reg_cap); 770 status = ucfg_reg_set_hal_reg_cap(psoc, reg_cap, num_phy_reg_cap); 771 772 return qdf_status_to_os_return(status); 773 } 774 775 int init_deinit_populate_mac_phy_cap_ext2(wmi_unified_t wmi_handle, 776 uint8_t *event, 777 struct tgt_info *info) 778 { 779 uint32_t num_hw_modes; 780 uint8_t hw_idx; 781 uint32_t hw_mode_id; 782 uint32_t phy_bit_map; 783 uint8_t phy_id; 784 uint8_t mac_phy_count = 0; 785 QDF_STATUS status = QDF_STATUS_SUCCESS; 786 struct wlan_psoc_host_mac_phy_caps *mac_phy_cap; 787 struct wlan_psoc_host_mac_phy_caps_ext2 *mac_phy_caps_ext2; 788 789 if (!event) 790 return -EINVAL; 791 792 num_hw_modes = info->hw_modes.num_modes; 793 794 for (hw_idx = 0; hw_idx < num_hw_modes; hw_idx++) { 795 hw_mode_id = info->hw_modes.hw_mode_ids[hw_idx]; 796 phy_bit_map = info->hw_modes.phy_bit_map[hw_idx]; 797 798 phy_id = info->mac_phy_cap[mac_phy_count].phy_id; 799 while (phy_bit_map) { 800 if (mac_phy_count >= info->total_mac_phy_cnt) { 801 target_if_err("total MAC PHY count exceeds max limit %d, mac_phy_count = %d", 802 info->total_mac_phy_cnt, 803 mac_phy_count); 804 return -EINVAL; 805 } 806 807 mac_phy_cap = &info->mac_phy_cap[mac_phy_count]; 808 mac_phy_caps_ext2 = 809 &info->mac_phy_caps_ext2[mac_phy_count]; 810 status = wmi_extract_mac_phy_cap_service_ready_ext2( 811 wmi_handle, event, hw_mode_id, phy_id, 812 mac_phy_cap->phy_idx, 813 mac_phy_caps_ext2); 814 815 if (QDF_IS_STATUS_ERROR(status)) { 816 target_if_err("failed to parse mac phy capability ext2"); 817 return qdf_status_to_os_return(status); 818 } 819 820 mac_phy_cap->reg_cap_ext.wireless_modes |= 821 mac_phy_caps_ext2[phy_id].wireless_modes_ext; 822 823 mac_phy_count++; 824 phy_bit_map &= (phy_bit_map - 1); 825 phy_id++; 826 } 827 } 828 829 return 0; 830 } 831 832 int init_deinit_populate_hal_reg_cap_ext2(wmi_unified_t wmi_handle, 833 uint8_t *event, 834 struct tgt_info *info) 835 { 836 struct wlan_psoc_host_hal_reg_capabilities_ext2 837 reg_cap[PSOC_MAX_PHY_REG_CAP] = {{0} }; 838 struct wlan_objmgr_psoc *psoc; 839 uint32_t num_phy_reg_cap; 840 uint8_t reg_idx; 841 QDF_STATUS status = QDF_STATUS_SUCCESS; 842 843 if (!event) { 844 target_if_err("event buffer is null"); 845 return -EINVAL; 846 } 847 848 psoc = target_if_get_psoc_from_scn_hdl(wmi_handle->scn_handle); 849 if (!psoc) { 850 target_if_err("psoc is null"); 851 return -EINVAL; 852 } 853 854 num_phy_reg_cap = info->service_ext_param.num_phy; 855 if (num_phy_reg_cap > PSOC_MAX_PHY_REG_CAP) { 856 target_if_err("Invalid num_phy_reg_cap %d", num_phy_reg_cap); 857 return -EINVAL; 858 } 859 860 for (reg_idx = 0; reg_idx < num_phy_reg_cap; reg_idx++) { 861 status = wmi_extract_hal_reg_cap_ext2( 862 wmi_handle, event, reg_idx, ®_cap[reg_idx]); 863 if (QDF_IS_STATUS_ERROR(status)) { 864 target_if_err("failed to parse hal reg cap ext2"); 865 return qdf_status_to_os_return(status); 866 } 867 868 status = ucfg_reg_update_hal_reg_cap( 869 psoc, reg_cap[reg_idx].wireless_modes_ext, 870 reg_idx); 871 if (QDF_IS_STATUS_ERROR(status)) { 872 target_if_err("Failed to update hal reg cap"); 873 return qdf_status_to_os_return(status); 874 } 875 } 876 877 return 0; 878 } 879 880 int init_deinit_populate_scan_radio_cap_ext2(wmi_unified_t wmi_handle, 881 uint8_t *event, 882 struct tgt_info *info) 883 { 884 struct wlan_psoc_host_scan_radio_caps *param; 885 uint32_t num_scan_radio_caps; 886 uint8_t cap_idx; 887 QDF_STATUS status; 888 889 if (!event) { 890 target_if_err("Invalid event buffer"); 891 return -EINVAL; 892 } 893 894 num_scan_radio_caps = info->service_ext2_param.num_scan_radio_caps; 895 target_if_debug("num scan radio capabilities = %d", 896 num_scan_radio_caps); 897 898 if (!num_scan_radio_caps) 899 return 0; 900 901 info->scan_radio_caps = qdf_mem_malloc( 902 sizeof(struct wlan_psoc_host_scan_radio_caps) * 903 num_scan_radio_caps); 904 905 if (!info->scan_radio_caps) { 906 target_if_err("Failed to allocate memory for scan radio caps"); 907 return -EINVAL; 908 } 909 910 for (cap_idx = 0; cap_idx < num_scan_radio_caps; cap_idx++) { 911 param = &info->scan_radio_caps[cap_idx]; 912 status = wmi_extract_scan_radio_cap_service_ready_ext2( 913 wmi_handle, event, cap_idx, param); 914 if (QDF_IS_STATUS_ERROR(status)) { 915 target_if_err("Extraction of scan radio cap failed"); 916 goto free_and_return; 917 } 918 } 919 920 return 0; 921 922 free_and_return: 923 qdf_mem_free(info->scan_radio_caps); 924 info->scan_radio_caps = NULL; 925 926 return qdf_status_to_os_return(status); 927 } 928 929 QDF_STATUS init_deinit_scan_radio_cap_free( 930 struct target_psoc_info *tgt_psoc_info) 931 { 932 qdf_mem_free(tgt_psoc_info->info.scan_radio_caps); 933 tgt_psoc_info->info.scan_radio_caps = NULL; 934 935 return QDF_STATUS_SUCCESS; 936 } 937 938 qdf_export_symbol(init_deinit_scan_radio_cap_free); 939 940 static bool init_deinit_regdmn_160mhz_support( 941 struct wlan_psoc_host_hal_reg_capabilities_ext *hal_cap) 942 { 943 return ((hal_cap->wireless_modes & 944 HOST_REGDMN_MODE_11AC_VHT160) != 0); 945 } 946 947 static bool init_deinit_regdmn_80p80mhz_support( 948 struct wlan_psoc_host_hal_reg_capabilities_ext *hal_cap) 949 { 950 return ((hal_cap->wireless_modes & 951 HOST_REGDMN_MODE_11AC_VHT80_80) != 0); 952 } 953 954 static bool init_deinit_vht_160mhz_is_supported(uint32_t vhtcap) 955 { 956 return ((vhtcap & WLAN_VHTCAP_SUP_CHAN_WIDTH_160) != 0); 957 } 958 959 static bool init_deinit_vht_80p80mhz_is_supported(uint32_t vhtcap) 960 { 961 return ((vhtcap & WLAN_VHTCAP_SUP_CHAN_WIDTH_80_160) != 0); 962 } 963 964 static bool init_deinit_vht_160mhz_shortgi_is_supported(uint32_t vhtcap) 965 { 966 return ((vhtcap & WLAN_VHTCAP_SHORTGI_160) != 0); 967 } 968 969 QDF_STATUS init_deinit_validate_160_80p80_fw_caps( 970 struct wlan_objmgr_psoc *psoc, 971 struct target_psoc_info *tgt_hdl) 972 { 973 bool wireless_mode_160mhz = false; 974 bool wireless_mode_80p80mhz = false; 975 bool vhtcap_160mhz = false; 976 bool vhtcap_80p80_160mhz = false; 977 bool vhtcap_160mhz_sgi = false; 978 bool valid = false; 979 struct wlan_psoc_host_hal_reg_capabilities_ext *reg_cap; 980 struct wmi_unified *wmi_handle; 981 982 if (!tgt_hdl) { 983 target_if_err( 984 "target_psoc_info is null in validate 160n80p80 cap check"); 985 return QDF_STATUS_E_INVAL; 986 } 987 988 wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl); 989 990 if ((tgt_hdl->info.target_type == TARGET_TYPE_QCA8074) || 991 (tgt_hdl->info.target_type == TARGET_TYPE_QCA8074V2) || 992 (tgt_hdl->info.target_type == TARGET_TYPE_QCN6122) || 993 (tgt_hdl->info.target_type == TARGET_TYPE_QCN9160) || 994 (tgt_hdl->info.target_type == TARGET_TYPE_QCA6290)) { 995 /** 996 * Return true for now. This is not available in 997 * qca8074 fw yet 998 */ 999 return QDF_STATUS_SUCCESS; 1000 } 1001 1002 reg_cap = ucfg_reg_get_hal_reg_cap(psoc); 1003 if (!reg_cap) { 1004 target_if_err("reg cap is NULL"); 1005 return QDF_STATUS_E_FAILURE; 1006 } 1007 1008 /* NOTE: Host driver gets vht capability and supported channel 1009 * width / channel frequency range from FW/HALPHY and obeys it. 1010 * Host driver is unaware of any physical filters or any other 1011 * hardware factors that can impact these capabilities. 1012 * These need to be correctly determined by firmware. 1013 */ 1014 1015 /*This table lists all valid and invalid combinations 1016 * WMODE160 WMODE80_80 VHTCAP_160 VHTCAP_80+80_160 IsCombinationvalid? 1017 * 0 0 0 0 YES 1018 * 0 0 0 1 NO 1019 * 0 0 1 0 NO 1020 * 0 0 1 1 NO 1021 * 0 1 0 0 NO 1022 * 0 1 0 1 NO 1023 * 0 1 1 0 NO 1024 * 0 1 1 1 NO 1025 * 1 0 0 0 NO 1026 * 1 0 0 1 NO 1027 * 1 0 1 0 YES 1028 * 1 0 1 1 NO 1029 * 1 1 0 0 NO 1030 * 1 1 0 1 YES 1031 * 1 1 1 0 NO 1032 * 1 1 1 1 NO 1033 */ 1034 1035 /* NOTE: Last row in above table is invalid because value corresponding 1036 * to both VHTCAP_160 and VHTCAP_80+80_160 being set is reserved as per 1037 * 802.11ac. Only one of them can be set at a time. 1038 */ 1039 1040 wireless_mode_160mhz = init_deinit_regdmn_160mhz_support(reg_cap); 1041 wireless_mode_80p80mhz = init_deinit_regdmn_80p80mhz_support(reg_cap); 1042 vhtcap_160mhz = init_deinit_vht_160mhz_is_supported( 1043 tgt_hdl->info.target_caps.vht_cap_info); 1044 vhtcap_80p80_160mhz = init_deinit_vht_80p80mhz_is_supported( 1045 tgt_hdl->info.target_caps.vht_cap_info); 1046 vhtcap_160mhz_sgi = init_deinit_vht_160mhz_shortgi_is_supported( 1047 tgt_hdl->info.target_caps.vht_cap_info); 1048 1049 if (!(wireless_mode_160mhz || wireless_mode_80p80mhz || 1050 vhtcap_160mhz || vhtcap_80p80_160mhz)) { 1051 valid = QDF_STATUS_SUCCESS; 1052 } else if (wireless_mode_160mhz && !wireless_mode_80p80mhz && 1053 vhtcap_160mhz && !vhtcap_80p80_160mhz) { 1054 valid = QDF_STATUS_SUCCESS; 1055 } else if (wireless_mode_160mhz && wireless_mode_80p80mhz && 1056 !vhtcap_160mhz && vhtcap_160mhz_sgi) { 1057 valid = QDF_STATUS_SUCCESS; 1058 } 1059 1060 if (valid == QDF_STATUS_SUCCESS) { 1061 /* 1062 * Ensure short GI for 160 MHz is enabled 1063 * only if 160/80+80 is supported. 1064 */ 1065 if (vhtcap_160mhz_sgi && 1066 !(vhtcap_160mhz || vhtcap_80p80_160mhz)) { 1067 valid = QDF_STATUS_E_FAILURE; 1068 } 1069 } 1070 1071 /* Invalid config specified by FW */ 1072 if (valid != QDF_STATUS_SUCCESS) { 1073 target_if_err("Invalid 160/80+80 MHz config specified by FW. Take care of it first"); 1074 target_if_err("wireless_mode_160mhz: %d, wireless_mode_80p80mhz: %d", 1075 wireless_mode_160mhz, wireless_mode_80p80mhz); 1076 target_if_err("vhtcap_160mhz: %d, vhtcap_80p80_160mhz: %d,vhtcap_160mhz_sgi: %d", 1077 vhtcap_160mhz, vhtcap_80p80_160mhz, 1078 vhtcap_160mhz_sgi); 1079 } 1080 return valid; 1081 } 1082 1083 void init_deinit_chainmask_config( 1084 struct wlan_objmgr_psoc *psoc, 1085 struct target_psoc_info *tgt_hdl) 1086 { 1087 tgt_hdl->info.wlan_res_cfg.tx_chain_mask = 1088 ((1 << tgt_hdl->info.target_caps.num_rf_chains) - 1); 1089 tgt_hdl->info.wlan_res_cfg.rx_chain_mask = 1090 ((1 << tgt_hdl->info.target_caps.num_rf_chains) - 1); 1091 } 1092 1093 QDF_STATUS init_deinit_is_service_ext_msg( 1094 struct wlan_objmgr_psoc *psoc, 1095 struct target_psoc_info *tgt_hdl) 1096 { 1097 struct wmi_unified *wmi_handle; 1098 1099 if (!tgt_hdl) { 1100 target_if_err( 1101 "psoc target_psoc_info is null in service ext msg"); 1102 return QDF_STATUS_E_INVAL; 1103 } 1104 1105 wmi_handle = target_psoc_get_wmi_hdl(tgt_hdl); 1106 1107 if (wmi_service_enabled(wmi_handle, wmi_service_ext_msg)) 1108 return QDF_STATUS_SUCCESS; 1109 else 1110 return QDF_STATUS_E_FAILURE; 1111 } 1112 1113 bool init_deinit_is_preferred_hw_mode_supported( 1114 struct wlan_objmgr_psoc *psoc, 1115 struct target_psoc_info *tgt_hdl) 1116 { 1117 uint16_t i; 1118 struct tgt_info *info; 1119 1120 if (!tgt_hdl) { 1121 target_if_err( 1122 "psoc target_psoc_info is null in service ext msg"); 1123 return FALSE; 1124 } 1125 1126 info = &tgt_hdl->info; 1127 1128 if (info->preferred_hw_mode == WMI_HOST_HW_MODE_MAX) 1129 return TRUE; 1130 1131 if (wlan_psoc_nif_feat_cap_get(psoc, WLAN_SOC_F_DYNAMIC_HW_MODE)) { 1132 if (!wlan_psoc_nif_fw_ext_cap_get(psoc, 1133 WLAN_SOC_CEXT_DYNAMIC_HW_MODE)) { 1134 target_if_err( 1135 "WMI service bit for DYNAMIC HW mode is not set!"); 1136 return FALSE; 1137 } 1138 } 1139 1140 for (i = 0; i < target_psoc_get_total_mac_phy_cnt(tgt_hdl); i++) { 1141 if (info->mac_phy_cap[i].hw_mode_id == info->preferred_hw_mode) 1142 return TRUE; 1143 } 1144 1145 return FALSE; 1146 } 1147 1148 void init_deinit_wakeup_host_wait( 1149 struct wlan_objmgr_psoc *psoc, 1150 struct target_psoc_info *tgt_hdl) 1151 { 1152 if (!tgt_hdl) { 1153 target_if_err("psoc target_psoc_info is null in target ready"); 1154 return; 1155 } 1156 qdf_event_set(&tgt_hdl->info.event); 1157 } 1158