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