1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* 3 * Copyright (C) 2023, 2025 Intel Corporation 4 */ 5 #include <linux/dmi.h> 6 #include "iwl-drv.h" 7 #include "iwl-debug.h" 8 #include "regulatory.h" 9 #include "fw/runtime.h" 10 #include "fw/uefi.h" 11 12 #define GET_BIOS_TABLE(__name, ...) \ 13 do { \ 14 int ret = -ENOENT; \ 15 if (fwrt->uefi_tables_lock_status > UEFI_WIFI_GUID_UNLOCKED) \ 16 ret = iwl_uefi_get_ ## __name(__VA_ARGS__); \ 17 if (ret < 0) \ 18 ret = iwl_acpi_get_ ## __name(__VA_ARGS__); \ 19 return ret; \ 20 } while (0) 21 22 #define IWL_BIOS_TABLE_LOADER(__name) \ 23 int iwl_bios_get_ ## __name(struct iwl_fw_runtime *fwrt) \ 24 {GET_BIOS_TABLE(__name, fwrt); } \ 25 IWL_EXPORT_SYMBOL(iwl_bios_get_ ## __name) 26 27 #define IWL_BIOS_TABLE_LOADER_DATA(__name, data_type) \ 28 int iwl_bios_get_ ## __name(struct iwl_fw_runtime *fwrt, \ 29 data_type * data) \ 30 {GET_BIOS_TABLE(__name, fwrt, data); } \ 31 IWL_EXPORT_SYMBOL(iwl_bios_get_ ## __name) 32 33 IWL_BIOS_TABLE_LOADER(wrds_table); 34 IWL_BIOS_TABLE_LOADER(ewrd_table); 35 IWL_BIOS_TABLE_LOADER(wgds_table); 36 IWL_BIOS_TABLE_LOADER(ppag_table); 37 IWL_BIOS_TABLE_LOADER(phy_filters); 38 IWL_BIOS_TABLE_LOADER_DATA(tas_table, struct iwl_tas_data); 39 IWL_BIOS_TABLE_LOADER_DATA(pwr_limit, u64); 40 IWL_BIOS_TABLE_LOADER_DATA(mcc, char); 41 IWL_BIOS_TABLE_LOADER_DATA(eckv, u32); 42 IWL_BIOS_TABLE_LOADER_DATA(wbem, u32); 43 IWL_BIOS_TABLE_LOADER_DATA(dsbr, u32); 44 45 46 static const struct dmi_system_id dmi_ppag_approved_list[] = { 47 { .ident = "HP", 48 .matches = { 49 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 50 }, 51 }, 52 { .ident = "SAMSUNG", 53 .matches = { 54 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD"), 55 }, 56 }, 57 { .ident = "MSFT", 58 .matches = { 59 DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), 60 }, 61 }, 62 { .ident = "ASUS", 63 .matches = { 64 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 65 }, 66 }, 67 { .ident = "GOOGLE-HP", 68 .matches = { 69 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 70 DMI_MATCH(DMI_BOARD_VENDOR, "HP"), 71 }, 72 }, 73 { .ident = "GOOGLE-ASUS", 74 .matches = { 75 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 76 DMI_MATCH(DMI_BOARD_VENDOR, "ASUSTek COMPUTER INC."), 77 }, 78 }, 79 { .ident = "GOOGLE-SAMSUNG", 80 .matches = { 81 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 82 DMI_MATCH(DMI_BOARD_VENDOR, "SAMSUNG ELECTRONICS CO., LTD"), 83 }, 84 }, 85 { .ident = "DELL", 86 .matches = { 87 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 88 }, 89 }, 90 { .ident = "DELL", 91 .matches = { 92 DMI_MATCH(DMI_SYS_VENDOR, "Alienware"), 93 }, 94 }, 95 { .ident = "RAZER", 96 .matches = { 97 DMI_MATCH(DMI_SYS_VENDOR, "Razer"), 98 }, 99 }, 100 { .ident = "Honor", 101 .matches = { 102 DMI_MATCH(DMI_SYS_VENDOR, "HONOR"), 103 }, 104 }, 105 { .ident = "WIKO", 106 .matches = { 107 DMI_MATCH(DMI_SYS_VENDOR, "WIKO"), 108 }, 109 }, 110 {} 111 }; 112 113 static const struct dmi_system_id dmi_tas_approved_list[] = { 114 { .ident = "HP", 115 .matches = { 116 DMI_MATCH(DMI_SYS_VENDOR, "HP"), 117 }, 118 }, 119 { .ident = "SAMSUNG", 120 .matches = { 121 DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD"), 122 }, 123 }, 124 { .ident = "LENOVO", 125 .matches = { 126 DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 127 }, 128 }, 129 { .ident = "DELL", 130 .matches = { 131 DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), 132 }, 133 }, 134 { .ident = "MSFT", 135 .matches = { 136 DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"), 137 }, 138 }, 139 { .ident = "Acer", 140 .matches = { 141 DMI_MATCH(DMI_SYS_VENDOR, "Acer"), 142 }, 143 }, 144 { .ident = "ASUS", 145 .matches = { 146 DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 147 }, 148 }, 149 { .ident = "GOOGLE-HP", 150 .matches = { 151 DMI_MATCH(DMI_SYS_VENDOR, "Google"), 152 DMI_MATCH(DMI_BOARD_VENDOR, "HP"), 153 }, 154 }, 155 { .ident = "MSI", 156 .matches = { 157 DMI_MATCH(DMI_SYS_VENDOR, "Micro-Star International Co., Ltd."), 158 }, 159 }, 160 { .ident = "Honor", 161 .matches = { 162 DMI_MATCH(DMI_SYS_VENDOR, "HONOR"), 163 }, 164 }, 165 /* keep last */ 166 {} 167 }; 168 169 bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt) 170 { 171 /* 172 * The PER_CHAIN_LIMIT_OFFSET_CMD command is not supported on 173 * earlier firmware versions. Unfortunately, we don't have a 174 * TLV API flag to rely on, so rely on the major version which 175 * is in the first byte of ucode_ver. This was implemented 176 * initially on version 38 and then backported to 17. It was 177 * also backported to 29, but only for 7265D devices. The 178 * intention was to have it in 36 as well, but not all 8000 179 * family got this feature enabled. The 8000 family is the 180 * only one using version 36, so skip this version entirely. 181 */ 182 return IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) >= 38 || 183 (IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) == 17 && 184 fwrt->trans->hw_rev != CSR_HW_REV_TYPE_3160) || 185 (IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) == 29 && 186 ((fwrt->trans->hw_rev & CSR_HW_REV_TYPE_MSK) == 187 CSR_HW_REV_TYPE_7265D)); 188 } 189 IWL_EXPORT_SYMBOL(iwl_sar_geo_support); 190 191 int iwl_sar_geo_fill_table(struct iwl_fw_runtime *fwrt, 192 struct iwl_per_chain_offset *table, 193 u32 n_bands, u32 n_profiles) 194 { 195 int i, j; 196 197 if (!fwrt->geo_enabled) 198 return -ENODATA; 199 200 if (!iwl_sar_geo_support(fwrt)) 201 return -EOPNOTSUPP; 202 203 for (i = 0; i < n_profiles; i++) { 204 for (j = 0; j < n_bands; j++) { 205 struct iwl_per_chain_offset *chain = 206 &table[i * n_bands + j]; 207 208 chain->max_tx_power = 209 cpu_to_le16(fwrt->geo_profiles[i].bands[j].max); 210 chain->chain_a = 211 fwrt->geo_profiles[i].bands[j].chains[0]; 212 chain->chain_b = 213 fwrt->geo_profiles[i].bands[j].chains[1]; 214 IWL_DEBUG_RADIO(fwrt, 215 "SAR geographic profile[%d] Band[%d]: chain A = %d chain B = %d max_tx_power = %d\n", 216 i, j, 217 fwrt->geo_profiles[i].bands[j].chains[0], 218 fwrt->geo_profiles[i].bands[j].chains[1], 219 fwrt->geo_profiles[i].bands[j].max); 220 } 221 } 222 223 return 0; 224 } 225 IWL_EXPORT_SYMBOL(iwl_sar_geo_fill_table); 226 227 static int iwl_sar_fill_table(struct iwl_fw_runtime *fwrt, 228 __le16 *per_chain, u32 n_subbands, 229 int prof_a, int prof_b) 230 { 231 int profs[BIOS_SAR_NUM_CHAINS] = { prof_a, prof_b }; 232 int i, j; 233 234 for (i = 0; i < BIOS_SAR_NUM_CHAINS; i++) { 235 struct iwl_sar_profile *prof; 236 237 /* don't allow SAR to be disabled (profile 0 means disable) */ 238 if (profs[i] == 0) 239 return -EPERM; 240 241 /* we are off by one, so allow up to BIOS_SAR_MAX_PROFILE_NUM */ 242 if (profs[i] > BIOS_SAR_MAX_PROFILE_NUM) 243 return -EINVAL; 244 245 /* profiles go from 1 to 4, so decrement to access the array */ 246 prof = &fwrt->sar_profiles[profs[i] - 1]; 247 248 /* if the profile is disabled, do nothing */ 249 if (!prof->enabled) { 250 IWL_DEBUG_RADIO(fwrt, "SAR profile %d is disabled.\n", 251 profs[i]); 252 /* 253 * if one of the profiles is disabled, we 254 * ignore all of them and return 1 to 255 * differentiate disabled from other failures. 256 */ 257 return 1; 258 } 259 260 IWL_DEBUG_INFO(fwrt, 261 "SAR EWRD: chain %d profile index %d\n", 262 i, profs[i]); 263 IWL_DEBUG_RADIO(fwrt, " Chain[%d]:\n", i); 264 for (j = 0; j < n_subbands; j++) { 265 per_chain[i * n_subbands + j] = 266 cpu_to_le16(prof->chains[i].subbands[j]); 267 IWL_DEBUG_RADIO(fwrt, " Band[%d] = %d * .125dBm\n", 268 j, prof->chains[i].subbands[j]); 269 } 270 } 271 272 return 0; 273 } 274 275 int iwl_sar_fill_profile(struct iwl_fw_runtime *fwrt, 276 __le16 *per_chain, u32 n_tables, u32 n_subbands, 277 int prof_a, int prof_b) 278 { 279 int i, ret = 0; 280 281 for (i = 0; i < n_tables; i++) { 282 ret = iwl_sar_fill_table(fwrt, 283 &per_chain[i * n_subbands * BIOS_SAR_NUM_CHAINS], 284 n_subbands, prof_a, prof_b); 285 if (ret) 286 break; 287 } 288 289 return ret; 290 } 291 IWL_EXPORT_SYMBOL(iwl_sar_fill_profile); 292 293 static bool iwl_ppag_value_valid(struct iwl_fw_runtime *fwrt, int chain, 294 int subband) 295 { 296 s8 ppag_val = fwrt->ppag_chains[chain].subbands[subband]; 297 298 if ((subband == 0 && 299 (ppag_val > IWL_PPAG_MAX_LB || ppag_val < IWL_PPAG_MIN_LB)) || 300 (subband != 0 && 301 (ppag_val > IWL_PPAG_MAX_HB || ppag_val < IWL_PPAG_MIN_HB))) { 302 IWL_DEBUG_RADIO(fwrt, "Invalid PPAG value: %d\n", ppag_val); 303 return false; 304 } 305 return true; 306 } 307 308 int iwl_fill_ppag_table(struct iwl_fw_runtime *fwrt, 309 union iwl_ppag_table_cmd *cmd, int *cmd_size) 310 { 311 u8 cmd_ver; 312 int i, j, num_sub_bands; 313 s8 *gain; 314 bool send_ppag_always; 315 316 /* many firmware images for JF lie about this */ 317 if (CSR_HW_RFID_TYPE(fwrt->trans->hw_rf_id) == 318 CSR_HW_RFID_TYPE(CSR_HW_RF_ID_TYPE_JF)) 319 return -EOPNOTSUPP; 320 321 if (!fw_has_capa(&fwrt->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SET_PPAG)) { 322 IWL_DEBUG_RADIO(fwrt, 323 "PPAG capability not supported by FW, command not sent.\n"); 324 return -EINVAL; 325 } 326 327 cmd_ver = iwl_fw_lookup_cmd_ver(fwrt->fw, 328 WIDE_ID(PHY_OPS_GROUP, 329 PER_PLATFORM_ANT_GAIN_CMD), 1); 330 /* 331 * Starting from ver 4, driver needs to send the PPAG CMD regardless 332 * if PPAG is enabled/disabled or valid/invalid. 333 */ 334 send_ppag_always = cmd_ver > 3; 335 336 /* Don't send PPAG if it is disabled */ 337 if (!send_ppag_always && !fwrt->ppag_flags) { 338 IWL_DEBUG_RADIO(fwrt, "PPAG not enabled, command not sent.\n"); 339 return -EINVAL; 340 } 341 342 /* The 'flags' field is the same in v1 and in v2 so we can just 343 * use v1 to access it. 344 */ 345 cmd->v1.flags = cpu_to_le32(fwrt->ppag_flags); 346 347 IWL_DEBUG_RADIO(fwrt, "PPAG cmd ver is %d\n", cmd_ver); 348 if (cmd_ver == 1) { 349 num_sub_bands = IWL_NUM_SUB_BANDS_V1; 350 gain = cmd->v1.gain[0]; 351 *cmd_size = sizeof(cmd->v1); 352 if (fwrt->ppag_ver >= 1) { 353 /* in this case FW supports revision 0 */ 354 IWL_DEBUG_RADIO(fwrt, 355 "PPAG table rev is %d, send truncated table\n", 356 fwrt->ppag_ver); 357 } 358 } else if (cmd_ver >= 2 && cmd_ver <= 6) { 359 num_sub_bands = IWL_NUM_SUB_BANDS_V2; 360 gain = cmd->v2.gain[0]; 361 *cmd_size = sizeof(cmd->v2); 362 if (fwrt->ppag_ver == 0) { 363 /* in this case FW supports revisions 1,2 or 3 */ 364 IWL_DEBUG_RADIO(fwrt, 365 "PPAG table rev is 0, send padded table\n"); 366 } 367 } else { 368 IWL_DEBUG_RADIO(fwrt, "Unsupported PPAG command version\n"); 369 return -EINVAL; 370 } 371 372 /* ppag mode */ 373 IWL_DEBUG_RADIO(fwrt, 374 "PPAG MODE bits were read from bios: %d\n", 375 le32_to_cpu(cmd->v1.flags)); 376 377 if (cmd_ver == 5) 378 cmd->v1.flags &= cpu_to_le32(IWL_PPAG_CMD_V5_MASK); 379 else if (cmd_ver < 5) 380 cmd->v1.flags &= cpu_to_le32(IWL_PPAG_CMD_V4_MASK); 381 382 if ((cmd_ver == 1 && 383 !fw_has_capa(&fwrt->fw->ucode_capa, 384 IWL_UCODE_TLV_CAPA_PPAG_CHINA_BIOS_SUPPORT)) || 385 (cmd_ver == 2 && fwrt->ppag_ver >= 2)) { 386 cmd->v1.flags &= cpu_to_le32(IWL_PPAG_ETSI_MASK); 387 IWL_DEBUG_RADIO(fwrt, "masking ppag China bit\n"); 388 } else { 389 IWL_DEBUG_RADIO(fwrt, "isn't masking ppag China bit\n"); 390 } 391 392 IWL_DEBUG_RADIO(fwrt, 393 "PPAG MODE bits going to be sent: %d\n", 394 le32_to_cpu(cmd->v1.flags)); 395 396 for (i = 0; i < IWL_NUM_CHAIN_LIMITS; i++) { 397 for (j = 0; j < num_sub_bands; j++) { 398 if (!send_ppag_always && 399 !iwl_ppag_value_valid(fwrt, i, j)) 400 return -EINVAL; 401 402 gain[i * num_sub_bands + j] = 403 fwrt->ppag_chains[i].subbands[j]; 404 IWL_DEBUG_RADIO(fwrt, 405 "PPAG table: chain[%d] band[%d]: gain = %d\n", 406 i, j, gain[i * num_sub_bands + j]); 407 } 408 } 409 410 return 0; 411 } 412 IWL_EXPORT_SYMBOL(iwl_fill_ppag_table); 413 414 bool iwl_is_ppag_approved(struct iwl_fw_runtime *fwrt) 415 { 416 if (!dmi_check_system(dmi_ppag_approved_list)) { 417 IWL_DEBUG_RADIO(fwrt, 418 "System vendor '%s' is not in the approved list, disabling PPAG.\n", 419 dmi_get_system_info(DMI_SYS_VENDOR) ?: "<unknown>"); 420 fwrt->ppag_flags = 0; 421 return false; 422 } 423 424 return true; 425 } 426 IWL_EXPORT_SYMBOL(iwl_is_ppag_approved); 427 428 bool iwl_is_tas_approved(void) 429 { 430 return dmi_check_system(dmi_tas_approved_list); 431 } 432 IWL_EXPORT_SYMBOL(iwl_is_tas_approved); 433 434 struct iwl_tas_selection_data 435 iwl_parse_tas_selection(const u32 tas_selection_in, const u8 tbl_rev) 436 { 437 struct iwl_tas_selection_data tas_selection_out = {}; 438 u8 override_iec = u32_get_bits(tas_selection_in, 439 IWL_WTAS_OVERRIDE_IEC_MSK); 440 u8 canada_tas_uhb = u32_get_bits(tas_selection_in, 441 IWL_WTAS_CANADA_UHB_MSK); 442 u8 enabled_iec = u32_get_bits(tas_selection_in, 443 IWL_WTAS_ENABLE_IEC_MSK); 444 u8 usa_tas_uhb = u32_get_bits(tas_selection_in, 445 IWL_WTAS_USA_UHB_MSK); 446 447 if (tbl_rev > 0) { 448 tas_selection_out.usa_tas_uhb_allowed = usa_tas_uhb; 449 tas_selection_out.override_tas_iec = override_iec; 450 tas_selection_out.enable_tas_iec = enabled_iec; 451 } 452 453 if (tbl_rev > 1) 454 tas_selection_out.canada_tas_uhb_allowed = canada_tas_uhb; 455 456 return tas_selection_out; 457 } 458 IWL_EXPORT_SYMBOL(iwl_parse_tas_selection); 459 460 bool iwl_add_mcc_to_tas_block_list(u16 *list, u8 *size, u16 mcc) 461 { 462 for (int i = 0; i < *size; i++) { 463 if (list[i] == mcc) 464 return true; 465 } 466 467 /* Verify that there is room for another country 468 * If *size == IWL_WTAS_BLACK_LIST_MAX, then the table is full. 469 */ 470 if (*size >= IWL_WTAS_BLACK_LIST_MAX) 471 return false; 472 473 list[*size++] = mcc; 474 return true; 475 } 476 IWL_EXPORT_SYMBOL(iwl_add_mcc_to_tas_block_list); 477 478 __le32 iwl_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt) 479 { 480 int ret; 481 u32 val; 482 __le32 config_bitmap = 0; 483 484 switch (CSR_HW_RFID_TYPE(fwrt->trans->hw_rf_id)) { 485 case IWL_CFG_RF_TYPE_HR1: 486 case IWL_CFG_RF_TYPE_HR2: 487 case IWL_CFG_RF_TYPE_JF1: 488 case IWL_CFG_RF_TYPE_JF2: 489 ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_INDONESIA_5G2, 490 &val); 491 492 if (!ret && val == DSM_VALUE_INDONESIA_ENABLE) 493 config_bitmap |= 494 cpu_to_le32(LARI_CONFIG_ENABLE_5G2_IN_INDONESIA_MSK); 495 break; 496 default: 497 break; 498 } 499 500 ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_DISABLE_SRD, &val); 501 if (!ret) { 502 if (val == DSM_VALUE_SRD_PASSIVE) 503 config_bitmap |= 504 cpu_to_le32(LARI_CONFIG_CHANGE_ETSI_TO_PASSIVE_MSK); 505 else if (val == DSM_VALUE_SRD_DISABLE) 506 config_bitmap |= 507 cpu_to_le32(LARI_CONFIG_CHANGE_ETSI_TO_DISABLED_MSK); 508 } 509 510 if (fw_has_capa(&fwrt->fw->ucode_capa, 511 IWL_UCODE_TLV_CAPA_CHINA_22_REG_SUPPORT)) { 512 ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_REGULATORY_CONFIG, 513 &val); 514 /* 515 * China 2022 enable if the BIOS object does not exist or 516 * if it is enabled in BIOS. 517 */ 518 if (ret < 0 || val & DSM_MASK_CHINA_22_REG) 519 config_bitmap |= 520 cpu_to_le32(LARI_CONFIG_ENABLE_CHINA_22_REG_SUPPORT_MSK); 521 } 522 523 return config_bitmap; 524 } 525 IWL_EXPORT_SYMBOL(iwl_get_lari_config_bitmap); 526 527 static size_t iwl_get_lari_config_cmd_size(u8 cmd_ver) 528 { 529 size_t cmd_size; 530 531 switch (cmd_ver) { 532 case 12: 533 case 11: 534 cmd_size = sizeof(struct iwl_lari_config_change_cmd); 535 break; 536 case 10: 537 cmd_size = sizeof(struct iwl_lari_config_change_cmd_v10); 538 break; 539 case 9: 540 case 8: 541 case 7: 542 cmd_size = sizeof(struct iwl_lari_config_change_cmd_v7); 543 break; 544 case 6: 545 cmd_size = sizeof(struct iwl_lari_config_change_cmd_v6); 546 break; 547 case 5: 548 cmd_size = sizeof(struct iwl_lari_config_change_cmd_v5); 549 break; 550 case 4: 551 cmd_size = sizeof(struct iwl_lari_config_change_cmd_v4); 552 break; 553 case 3: 554 cmd_size = sizeof(struct iwl_lari_config_change_cmd_v3); 555 break; 556 case 2: 557 cmd_size = sizeof(struct iwl_lari_config_change_cmd_v2); 558 break; 559 default: 560 cmd_size = sizeof(struct iwl_lari_config_change_cmd_v1); 561 break; 562 } 563 return cmd_size; 564 } 565 566 int iwl_fill_lari_config(struct iwl_fw_runtime *fwrt, 567 struct iwl_lari_config_change_cmd *cmd, 568 size_t *cmd_size) 569 { 570 int ret; 571 u32 value; 572 u8 cmd_ver = iwl_fw_lookup_cmd_ver(fwrt->fw, 573 WIDE_ID(REGULATORY_AND_NVM_GROUP, 574 LARI_CONFIG_CHANGE), 1); 575 576 if (WARN_ONCE(cmd_ver > 12, 577 "Don't add newer versions to this function\n")) 578 return -EINVAL; 579 580 memset(cmd, 0, sizeof(*cmd)); 581 *cmd_size = iwl_get_lari_config_cmd_size(cmd_ver); 582 583 cmd->config_bitmap = iwl_get_lari_config_bitmap(fwrt); 584 585 ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_11AX_ENABLEMENT, &value); 586 if (!ret) 587 cmd->oem_11ax_allow_bitmap = cpu_to_le32(value); 588 589 ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_UNII4_CHAN, &value); 590 if (!ret) { 591 value &= DSM_UNII4_ALLOW_BITMAP; 592 593 /* Since version 9, bits 4 and 5 are supported 594 * regardless of this capability. 595 */ 596 if (cmd_ver < 9 && 597 !fw_has_capa(&fwrt->fw->ucode_capa, 598 IWL_UCODE_TLV_CAPA_BIOS_OVERRIDE_5G9_FOR_CA)) 599 value &= ~(DSM_VALUE_UNII4_CANADA_OVERRIDE_MSK | 600 DSM_VALUE_UNII4_CANADA_EN_MSK); 601 602 cmd->oem_unii4_allow_bitmap = cpu_to_le32(value); 603 } 604 605 ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ACTIVATE_CHANNEL, &value); 606 if (!ret) { 607 if (cmd_ver < 8) 608 value &= ~ACTIVATE_5G2_IN_WW_MASK; 609 610 /* Since version 12, bits 5 and 6 are supported 611 * regardless of this capability. 612 */ 613 if (cmd_ver < 12 && 614 !fw_has_capa(&fwrt->fw->ucode_capa, 615 IWL_UCODE_TLV_CAPA_BIOS_OVERRIDE_UNII4_US_CA)) 616 value &= CHAN_STATE_ACTIVE_BITMAP_CMD_V11; 617 618 cmd->chan_state_active_bitmap = cpu_to_le32(value); 619 } 620 621 ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_6E, &value); 622 if (!ret) 623 cmd->oem_uhb_allow_bitmap = cpu_to_le32(value); 624 625 ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_FORCE_DISABLE_CHANNELS, &value); 626 if (!ret) 627 cmd->force_disable_channels_bitmap = cpu_to_le32(value); 628 629 ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENERGY_DETECTION_THRESHOLD, 630 &value); 631 if (!ret) 632 cmd->edt_bitmap = cpu_to_le32(value); 633 634 ret = iwl_bios_get_wbem(fwrt, &value); 635 if (!ret) 636 cmd->oem_320mhz_allow_bitmap = cpu_to_le32(value); 637 638 ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_ENABLE_11BE, &value); 639 if (!ret) 640 cmd->oem_11be_allow_bitmap = cpu_to_le32(value); 641 642 if (cmd->config_bitmap || 643 cmd->oem_uhb_allow_bitmap || 644 cmd->oem_11ax_allow_bitmap || 645 cmd->oem_unii4_allow_bitmap || 646 cmd->chan_state_active_bitmap || 647 cmd->force_disable_channels_bitmap || 648 cmd->edt_bitmap || 649 cmd->oem_320mhz_allow_bitmap || 650 cmd->oem_11be_allow_bitmap) { 651 IWL_DEBUG_RADIO(fwrt, 652 "sending LARI_CONFIG_CHANGE, config_bitmap=0x%x, oem_11ax_allow_bitmap=0x%x\n", 653 le32_to_cpu(cmd->config_bitmap), 654 le32_to_cpu(cmd->oem_11ax_allow_bitmap)); 655 IWL_DEBUG_RADIO(fwrt, 656 "sending LARI_CONFIG_CHANGE, oem_unii4_allow_bitmap=0x%x, chan_state_active_bitmap=0x%x, cmd_ver=%d\n", 657 le32_to_cpu(cmd->oem_unii4_allow_bitmap), 658 le32_to_cpu(cmd->chan_state_active_bitmap), 659 cmd_ver); 660 IWL_DEBUG_RADIO(fwrt, 661 "sending LARI_CONFIG_CHANGE, oem_uhb_allow_bitmap=0x%x, force_disable_channels_bitmap=0x%x\n", 662 le32_to_cpu(cmd->oem_uhb_allow_bitmap), 663 le32_to_cpu(cmd->force_disable_channels_bitmap)); 664 IWL_DEBUG_RADIO(fwrt, 665 "sending LARI_CONFIG_CHANGE, edt_bitmap=0x%x, oem_320mhz_allow_bitmap=0x%x\n", 666 le32_to_cpu(cmd->edt_bitmap), 667 le32_to_cpu(cmd->oem_320mhz_allow_bitmap)); 668 IWL_DEBUG_RADIO(fwrt, 669 "sending LARI_CONFIG_CHANGE, oem_11be_allow_bitmap=0x%x\n", 670 le32_to_cpu(cmd->oem_11be_allow_bitmap)); 671 } else { 672 return 1; 673 } 674 675 return 0; 676 } 677 IWL_EXPORT_SYMBOL(iwl_fill_lari_config); 678 679 int iwl_bios_get_dsm(struct iwl_fw_runtime *fwrt, enum iwl_dsm_funcs func, 680 u32 *value) 681 { 682 GET_BIOS_TABLE(dsm, fwrt, func, value); 683 } 684 IWL_EXPORT_SYMBOL(iwl_bios_get_dsm); 685 686 bool iwl_puncturing_is_allowed_in_bios(u32 puncturing, u16 mcc) 687 { 688 /* Some kind of regulatory mess means we need to currently disallow 689 * puncturing in the US and Canada unless enabled in BIOS. 690 */ 691 switch (mcc) { 692 case IWL_MCC_US: 693 return puncturing & IWL_UEFI_CNV_PUNCTURING_USA_EN_MSK; 694 case IWL_MCC_CANADA: 695 return puncturing & IWL_UEFI_CNV_PUNCTURING_CANADA_EN_MSK; 696 default: 697 return true; 698 } 699 } 700 IWL_EXPORT_SYMBOL(iwl_puncturing_is_allowed_in_bios); 701 702 bool iwl_rfi_is_enabled_in_bios(struct iwl_fw_runtime *fwrt) 703 { 704 /* default behaviour is disabled */ 705 u32 value = 0; 706 int ret = iwl_bios_get_dsm(fwrt, DSM_FUNC_RFI_CONFIG, &value); 707 708 if (ret < 0) { 709 IWL_DEBUG_RADIO(fwrt, "Failed to get DSM RFI, ret=%d\n", ret); 710 return false; 711 } 712 713 value &= DSM_VALUE_RFI_DISABLE; 714 /* RFI BIOS CONFIG value can be 0 or 3 only. 715 * i.e 0 means DDR and DLVR enabled. 3 means DDR and DLVR disabled. 716 * 1 and 2 are invalid BIOS configurations, So, it's not possible to 717 * disable ddr/dlvr separately. 718 */ 719 if (!value) { 720 IWL_DEBUG_RADIO(fwrt, "DSM RFI is evaluated to enable\n"); 721 return true; 722 } else if (value == DSM_VALUE_RFI_DISABLE) { 723 IWL_DEBUG_RADIO(fwrt, "DSM RFI is evaluated to disable\n"); 724 } else { 725 IWL_DEBUG_RADIO(fwrt, 726 "DSM RFI got invalid value, value=%d\n", value); 727 } 728 729 return false; 730 } 731 IWL_EXPORT_SYMBOL(iwl_rfi_is_enabled_in_bios); 732