1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* 3 * Copyright (C) 2017 Intel Deutschland GmbH 4 * Copyright (C) 2019-2021 Intel Corporation 5 */ 6 #include <linux/uuid.h> 7 #include "iwl-drv.h" 8 #include "iwl-debug.h" 9 #include "acpi.h" 10 #include "fw/runtime.h" 11 12 const guid_t iwl_guid = GUID_INIT(0xF21202BF, 0x8F78, 0x4DC6, 13 0xA5, 0xB3, 0x1F, 0x73, 14 0x8E, 0x28, 0x5A, 0xDE); 15 IWL_EXPORT_SYMBOL(iwl_guid); 16 17 const guid_t iwl_rfi_guid = GUID_INIT(0x7266172C, 0x220B, 0x4B29, 18 0x81, 0x4F, 0x75, 0xE4, 19 0xDD, 0x26, 0xB5, 0xFD); 20 IWL_EXPORT_SYMBOL(iwl_rfi_guid); 21 22 static int iwl_acpi_get_handle(struct device *dev, acpi_string method, 23 acpi_handle *ret_handle) 24 { 25 acpi_handle root_handle; 26 acpi_status status; 27 28 root_handle = ACPI_HANDLE(dev); 29 if (!root_handle) { 30 IWL_DEBUG_DEV_RADIO(dev, 31 "ACPI: Could not retrieve root port handle\n"); 32 return -ENOENT; 33 } 34 35 status = acpi_get_handle(root_handle, method, ret_handle); 36 if (ACPI_FAILURE(status)) { 37 IWL_DEBUG_DEV_RADIO(dev, 38 "ACPI: %s method not found\n", method); 39 return -ENOENT; 40 } 41 return 0; 42 } 43 44 void *iwl_acpi_get_object(struct device *dev, acpi_string method) 45 { 46 struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL}; 47 acpi_handle handle; 48 acpi_status status; 49 int ret; 50 51 ret = iwl_acpi_get_handle(dev, method, &handle); 52 if (ret) 53 return ERR_PTR(-ENOENT); 54 55 /* Call the method with no arguments */ 56 status = acpi_evaluate_object(handle, NULL, NULL, &buf); 57 if (ACPI_FAILURE(status)) { 58 IWL_DEBUG_DEV_RADIO(dev, 59 "ACPI: %s method invocation failed (status: 0x%x)\n", 60 method, status); 61 return ERR_PTR(-ENOENT); 62 } 63 return buf.pointer; 64 } 65 IWL_EXPORT_SYMBOL(iwl_acpi_get_object); 66 67 /* 68 * Generic function for evaluating a method defined in the device specific 69 * method (DSM) interface. The returned acpi object must be freed by calling 70 * function. 71 */ 72 static void *iwl_acpi_get_dsm_object(struct device *dev, int rev, int func, 73 union acpi_object *args, 74 const guid_t *guid) 75 { 76 union acpi_object *obj; 77 78 obj = acpi_evaluate_dsm(ACPI_HANDLE(dev), guid, rev, func, 79 args); 80 if (!obj) { 81 IWL_DEBUG_DEV_RADIO(dev, 82 "ACPI: DSM method invocation failed (rev: %d, func:%d)\n", 83 rev, func); 84 return ERR_PTR(-ENOENT); 85 } 86 return obj; 87 } 88 89 /* 90 * Generic function to evaluate a DSM with no arguments 91 * and an integer return value, 92 * (as an integer object or inside a buffer object), 93 * verify and assign the value in the "value" parameter. 94 * return 0 in success and the appropriate errno otherwise. 95 */ 96 static int iwl_acpi_get_dsm_integer(struct device *dev, int rev, int func, 97 const guid_t *guid, u64 *value, 98 size_t expected_size) 99 { 100 union acpi_object *obj; 101 int ret = 0; 102 103 obj = iwl_acpi_get_dsm_object(dev, rev, func, NULL, guid); 104 if (IS_ERR(obj)) { 105 IWL_DEBUG_DEV_RADIO(dev, 106 "Failed to get DSM object. func= %d\n", 107 func); 108 return -ENOENT; 109 } 110 111 if (obj->type == ACPI_TYPE_INTEGER) { 112 *value = obj->integer.value; 113 } else if (obj->type == ACPI_TYPE_BUFFER) { 114 __le64 le_value = 0; 115 116 if (WARN_ON_ONCE(expected_size > sizeof(le_value))) 117 return -EINVAL; 118 119 /* if the buffer size doesn't match the expected size */ 120 if (obj->buffer.length != expected_size) 121 IWL_DEBUG_DEV_RADIO(dev, 122 "ACPI: DSM invalid buffer size, padding or truncating (%d)\n", 123 obj->buffer.length); 124 125 /* assuming LE from Intel BIOS spec */ 126 memcpy(&le_value, obj->buffer.pointer, 127 min_t(size_t, expected_size, (size_t)obj->buffer.length)); 128 *value = le64_to_cpu(le_value); 129 } else { 130 IWL_DEBUG_DEV_RADIO(dev, 131 "ACPI: DSM method did not return a valid object, type=%d\n", 132 obj->type); 133 ret = -EINVAL; 134 goto out; 135 } 136 137 IWL_DEBUG_DEV_RADIO(dev, 138 "ACPI: DSM method evaluated: func=%d, ret=%d\n", 139 func, ret); 140 out: 141 ACPI_FREE(obj); 142 return ret; 143 } 144 145 /* 146 * Evaluate a DSM with no arguments and a u8 return value, 147 */ 148 int iwl_acpi_get_dsm_u8(struct device *dev, int rev, int func, 149 const guid_t *guid, u8 *value) 150 { 151 int ret; 152 u64 val; 153 154 ret = iwl_acpi_get_dsm_integer(dev, rev, func, 155 guid, &val, sizeof(u8)); 156 157 if (ret < 0) 158 return ret; 159 160 /* cast val (u64) to be u8 */ 161 *value = (u8)val; 162 return 0; 163 } 164 IWL_EXPORT_SYMBOL(iwl_acpi_get_dsm_u8); 165 166 /* 167 * Evaluate a DSM with no arguments and a u32 return value, 168 */ 169 int iwl_acpi_get_dsm_u32(struct device *dev, int rev, int func, 170 const guid_t *guid, u32 *value) 171 { 172 int ret; 173 u64 val; 174 175 ret = iwl_acpi_get_dsm_integer(dev, rev, func, 176 guid, &val, sizeof(u32)); 177 178 if (ret < 0) 179 return ret; 180 181 /* cast val (u64) to be u32 */ 182 *value = (u32)val; 183 return 0; 184 } 185 IWL_EXPORT_SYMBOL(iwl_acpi_get_dsm_u32); 186 187 union acpi_object *iwl_acpi_get_wifi_pkg_range(struct device *dev, 188 union acpi_object *data, 189 int min_data_size, 190 int max_data_size, 191 int *tbl_rev) 192 { 193 int i; 194 union acpi_object *wifi_pkg; 195 196 /* 197 * We need at least one entry in the wifi package that 198 * describes the domain, and one more entry, otherwise there's 199 * no point in reading it. 200 */ 201 if (WARN_ON_ONCE(min_data_size < 2 || min_data_size > max_data_size)) 202 return ERR_PTR(-EINVAL); 203 204 /* 205 * We need at least two packages, one for the revision and one 206 * for the data itself. Also check that the revision is valid 207 * (i.e. it is an integer (each caller has to check by itself 208 * if the returned revision is supported)). 209 */ 210 if (data->type != ACPI_TYPE_PACKAGE || 211 data->package.count < 2 || 212 data->package.elements[0].type != ACPI_TYPE_INTEGER) { 213 IWL_DEBUG_DEV_RADIO(dev, "Invalid packages structure\n"); 214 return ERR_PTR(-EINVAL); 215 } 216 217 *tbl_rev = data->package.elements[0].integer.value; 218 219 /* loop through all the packages to find the one for WiFi */ 220 for (i = 1; i < data->package.count; i++) { 221 union acpi_object *domain; 222 223 wifi_pkg = &data->package.elements[i]; 224 225 /* skip entries that are not a package with the right size */ 226 if (wifi_pkg->type != ACPI_TYPE_PACKAGE || 227 wifi_pkg->package.count < min_data_size || 228 wifi_pkg->package.count > max_data_size) 229 continue; 230 231 domain = &wifi_pkg->package.elements[0]; 232 if (domain->type == ACPI_TYPE_INTEGER && 233 domain->integer.value == ACPI_WIFI_DOMAIN) 234 goto found; 235 } 236 237 return ERR_PTR(-ENOENT); 238 239 found: 240 return wifi_pkg; 241 } 242 IWL_EXPORT_SYMBOL(iwl_acpi_get_wifi_pkg_range); 243 244 int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt, 245 struct iwl_tas_config_cmd_v3 *cmd) 246 { 247 union acpi_object *wifi_pkg, *data; 248 int ret, tbl_rev, i, block_list_size, enabled; 249 250 data = iwl_acpi_get_object(fwrt->dev, ACPI_WTAS_METHOD); 251 if (IS_ERR(data)) 252 return PTR_ERR(data); 253 254 /* try to read wtas table revision 1 or revision 0*/ 255 wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data, 256 ACPI_WTAS_WIFI_DATA_SIZE, 257 &tbl_rev); 258 if (IS_ERR(wifi_pkg)) { 259 ret = PTR_ERR(wifi_pkg); 260 goto out_free; 261 } 262 263 if (tbl_rev == 1 && wifi_pkg->package.elements[1].type == 264 ACPI_TYPE_INTEGER) { 265 u32 tas_selection = 266 (u32)wifi_pkg->package.elements[1].integer.value; 267 u16 override_iec = 268 (tas_selection & ACPI_WTAS_OVERRIDE_IEC_MSK) >> ACPI_WTAS_OVERRIDE_IEC_POS; 269 u16 enabled_iec = (tas_selection & ACPI_WTAS_ENABLE_IEC_MSK) >> 270 ACPI_WTAS_ENABLE_IEC_POS; 271 272 enabled = tas_selection & ACPI_WTAS_ENABLED_MSK; 273 cmd->override_tas_iec = cpu_to_le16(override_iec); 274 cmd->enable_tas_iec = cpu_to_le16(enabled_iec); 275 276 } else if (tbl_rev == 0 && 277 wifi_pkg->package.elements[1].type == ACPI_TYPE_INTEGER) { 278 enabled = !!wifi_pkg->package.elements[1].integer.value; 279 } else { 280 ret = -EINVAL; 281 goto out_free; 282 } 283 284 if (!enabled) { 285 IWL_DEBUG_RADIO(fwrt, "TAS not enabled\n"); 286 ret = 0; 287 goto out_free; 288 } 289 290 IWL_DEBUG_RADIO(fwrt, "Reading TAS table revision %d\n", tbl_rev); 291 if (wifi_pkg->package.elements[2].type != ACPI_TYPE_INTEGER || 292 wifi_pkg->package.elements[2].integer.value > 293 APCI_WTAS_BLACK_LIST_MAX) { 294 IWL_DEBUG_RADIO(fwrt, "TAS invalid array size %llu\n", 295 wifi_pkg->package.elements[2].integer.value); 296 ret = -EINVAL; 297 goto out_free; 298 } 299 block_list_size = wifi_pkg->package.elements[2].integer.value; 300 cmd->block_list_size = cpu_to_le32(block_list_size); 301 302 IWL_DEBUG_RADIO(fwrt, "TAS array size %u\n", block_list_size); 303 if (block_list_size > APCI_WTAS_BLACK_LIST_MAX) { 304 IWL_DEBUG_RADIO(fwrt, "TAS invalid array size value %u\n", 305 block_list_size); 306 ret = -EINVAL; 307 goto out_free; 308 } 309 310 for (i = 0; i < block_list_size; i++) { 311 u32 country; 312 313 if (wifi_pkg->package.elements[3 + i].type != 314 ACPI_TYPE_INTEGER) { 315 IWL_DEBUG_RADIO(fwrt, 316 "TAS invalid array elem %d\n", 3 + i); 317 ret = -EINVAL; 318 goto out_free; 319 } 320 321 country = wifi_pkg->package.elements[3 + i].integer.value; 322 cmd->block_list_array[i] = cpu_to_le32(country); 323 IWL_DEBUG_RADIO(fwrt, "TAS block list country %d\n", country); 324 } 325 326 ret = 1; 327 out_free: 328 kfree(data); 329 return ret; 330 } 331 IWL_EXPORT_SYMBOL(iwl_acpi_get_tas); 332 333 int iwl_acpi_get_mcc(struct device *dev, char *mcc) 334 { 335 union acpi_object *wifi_pkg, *data; 336 u32 mcc_val; 337 int ret, tbl_rev; 338 339 data = iwl_acpi_get_object(dev, ACPI_WRDD_METHOD); 340 if (IS_ERR(data)) 341 return PTR_ERR(data); 342 343 wifi_pkg = iwl_acpi_get_wifi_pkg(dev, data, ACPI_WRDD_WIFI_DATA_SIZE, 344 &tbl_rev); 345 if (IS_ERR(wifi_pkg)) { 346 ret = PTR_ERR(wifi_pkg); 347 goto out_free; 348 } 349 350 if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER || 351 tbl_rev != 0) { 352 ret = -EINVAL; 353 goto out_free; 354 } 355 356 mcc_val = wifi_pkg->package.elements[1].integer.value; 357 358 mcc[0] = (mcc_val >> 8) & 0xff; 359 mcc[1] = mcc_val & 0xff; 360 mcc[2] = '\0'; 361 362 ret = 0; 363 out_free: 364 kfree(data); 365 return ret; 366 } 367 IWL_EXPORT_SYMBOL(iwl_acpi_get_mcc); 368 369 u64 iwl_acpi_get_pwr_limit(struct device *dev) 370 { 371 union acpi_object *data, *wifi_pkg; 372 u64 dflt_pwr_limit; 373 int tbl_rev; 374 375 data = iwl_acpi_get_object(dev, ACPI_SPLC_METHOD); 376 if (IS_ERR(data)) { 377 dflt_pwr_limit = 0; 378 goto out; 379 } 380 381 wifi_pkg = iwl_acpi_get_wifi_pkg(dev, data, 382 ACPI_SPLC_WIFI_DATA_SIZE, &tbl_rev); 383 if (IS_ERR(wifi_pkg) || tbl_rev != 0 || 384 wifi_pkg->package.elements[1].integer.value != ACPI_TYPE_INTEGER) { 385 dflt_pwr_limit = 0; 386 goto out_free; 387 } 388 389 dflt_pwr_limit = wifi_pkg->package.elements[1].integer.value; 390 out_free: 391 kfree(data); 392 out: 393 return dflt_pwr_limit; 394 } 395 IWL_EXPORT_SYMBOL(iwl_acpi_get_pwr_limit); 396 397 int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk) 398 { 399 union acpi_object *wifi_pkg, *data; 400 int ret, tbl_rev; 401 402 data = iwl_acpi_get_object(dev, ACPI_ECKV_METHOD); 403 if (IS_ERR(data)) 404 return PTR_ERR(data); 405 406 wifi_pkg = iwl_acpi_get_wifi_pkg(dev, data, ACPI_ECKV_WIFI_DATA_SIZE, 407 &tbl_rev); 408 if (IS_ERR(wifi_pkg)) { 409 ret = PTR_ERR(wifi_pkg); 410 goto out_free; 411 } 412 413 if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER || 414 tbl_rev != 0) { 415 ret = -EINVAL; 416 goto out_free; 417 } 418 419 *extl_clk = wifi_pkg->package.elements[1].integer.value; 420 421 ret = 0; 422 423 out_free: 424 kfree(data); 425 return ret; 426 } 427 IWL_EXPORT_SYMBOL(iwl_acpi_get_eckv); 428 429 static int iwl_sar_set_profile(union acpi_object *table, 430 struct iwl_sar_profile *profile, 431 bool enabled, u8 num_chains, u8 num_sub_bands) 432 { 433 int i, j, idx = 0; 434 435 /* 436 * The table from ACPI is flat, but we store it in a 437 * structured array. 438 */ 439 for (i = 0; i < ACPI_SAR_NUM_CHAINS_REV2; i++) { 440 for (j = 0; j < ACPI_SAR_NUM_SUB_BANDS_REV2; j++) { 441 /* if we don't have the values, use the default */ 442 if (i >= num_chains || j >= num_sub_bands) { 443 profile->chains[i].subbands[j] = 0; 444 } else { 445 if (table[idx].type != ACPI_TYPE_INTEGER || 446 table[idx].integer.value > U8_MAX) 447 return -EINVAL; 448 449 profile->chains[i].subbands[j] = 450 table[idx].integer.value; 451 452 idx++; 453 } 454 } 455 } 456 457 /* Only if all values were valid can the profile be enabled */ 458 profile->enabled = enabled; 459 460 return 0; 461 } 462 463 static int iwl_sar_fill_table(struct iwl_fw_runtime *fwrt, 464 __le16 *per_chain, u32 n_subbands, 465 int prof_a, int prof_b) 466 { 467 int profs[ACPI_SAR_NUM_CHAINS_REV0] = { prof_a, prof_b }; 468 int i, j; 469 470 for (i = 0; i < ACPI_SAR_NUM_CHAINS_REV0; i++) { 471 struct iwl_sar_profile *prof; 472 473 /* don't allow SAR to be disabled (profile 0 means disable) */ 474 if (profs[i] == 0) 475 return -EPERM; 476 477 /* we are off by one, so allow up to ACPI_SAR_PROFILE_NUM */ 478 if (profs[i] > ACPI_SAR_PROFILE_NUM) 479 return -EINVAL; 480 481 /* profiles go from 1 to 4, so decrement to access the array */ 482 prof = &fwrt->sar_profiles[profs[i] - 1]; 483 484 /* if the profile is disabled, do nothing */ 485 if (!prof->enabled) { 486 IWL_DEBUG_RADIO(fwrt, "SAR profile %d is disabled.\n", 487 profs[i]); 488 /* 489 * if one of the profiles is disabled, we 490 * ignore all of them and return 1 to 491 * differentiate disabled from other failures. 492 */ 493 return 1; 494 } 495 496 IWL_DEBUG_INFO(fwrt, 497 "SAR EWRD: chain %d profile index %d\n", 498 i, profs[i]); 499 IWL_DEBUG_RADIO(fwrt, " Chain[%d]:\n", i); 500 for (j = 0; j < n_subbands; j++) { 501 per_chain[i * n_subbands + j] = 502 cpu_to_le16(prof->chains[i].subbands[j]); 503 IWL_DEBUG_RADIO(fwrt, " Band[%d] = %d * .125dBm\n", 504 j, prof->chains[i].subbands[j]); 505 } 506 } 507 508 return 0; 509 } 510 511 int iwl_sar_select_profile(struct iwl_fw_runtime *fwrt, 512 __le16 *per_chain, u32 n_tables, u32 n_subbands, 513 int prof_a, int prof_b) 514 { 515 int i, ret = 0; 516 517 for (i = 0; i < n_tables; i++) { 518 ret = iwl_sar_fill_table(fwrt, 519 &per_chain[i * n_subbands * ACPI_SAR_NUM_CHAINS_REV0], 520 n_subbands, prof_a, prof_b); 521 if (ret) 522 break; 523 } 524 525 return ret; 526 } 527 IWL_EXPORT_SYMBOL(iwl_sar_select_profile); 528 529 int iwl_sar_get_wrds_table(struct iwl_fw_runtime *fwrt) 530 { 531 union acpi_object *wifi_pkg, *table, *data; 532 bool enabled; 533 int ret, tbl_rev; 534 u8 num_chains, num_sub_bands; 535 536 data = iwl_acpi_get_object(fwrt->dev, ACPI_WRDS_METHOD); 537 if (IS_ERR(data)) 538 return PTR_ERR(data); 539 540 /* start by trying to read revision 2 */ 541 wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data, 542 ACPI_WRDS_WIFI_DATA_SIZE_REV2, 543 &tbl_rev); 544 if (!IS_ERR(wifi_pkg)) { 545 if (tbl_rev != 2) { 546 ret = PTR_ERR(wifi_pkg); 547 goto out_free; 548 } 549 550 num_chains = ACPI_SAR_NUM_CHAINS_REV2; 551 num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV2; 552 553 goto read_table; 554 } 555 556 /* then try revision 1 */ 557 wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data, 558 ACPI_WRDS_WIFI_DATA_SIZE_REV1, 559 &tbl_rev); 560 if (!IS_ERR(wifi_pkg)) { 561 if (tbl_rev != 1) { 562 ret = PTR_ERR(wifi_pkg); 563 goto out_free; 564 } 565 566 num_chains = ACPI_SAR_NUM_CHAINS_REV1; 567 num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV1; 568 569 goto read_table; 570 } 571 572 /* then finally revision 0 */ 573 wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data, 574 ACPI_WRDS_WIFI_DATA_SIZE_REV0, 575 &tbl_rev); 576 if (!IS_ERR(wifi_pkg)) { 577 if (tbl_rev != 0) { 578 ret = PTR_ERR(wifi_pkg); 579 goto out_free; 580 } 581 582 num_chains = ACPI_SAR_NUM_CHAINS_REV0; 583 num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV0; 584 585 goto read_table; 586 } 587 588 ret = PTR_ERR(wifi_pkg); 589 goto out_free; 590 591 read_table: 592 if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) { 593 ret = -EINVAL; 594 goto out_free; 595 } 596 597 IWL_DEBUG_RADIO(fwrt, "Reading WRDS tbl_rev=%d\n", tbl_rev); 598 599 enabled = !!(wifi_pkg->package.elements[1].integer.value); 600 601 /* position of the actual table */ 602 table = &wifi_pkg->package.elements[2]; 603 604 /* The profile from WRDS is officially profile 1, but goes 605 * into sar_profiles[0] (because we don't have a profile 0). 606 */ 607 ret = iwl_sar_set_profile(table, &fwrt->sar_profiles[0], enabled, 608 num_chains, num_sub_bands); 609 out_free: 610 kfree(data); 611 return ret; 612 } 613 IWL_EXPORT_SYMBOL(iwl_sar_get_wrds_table); 614 615 int iwl_sar_get_ewrd_table(struct iwl_fw_runtime *fwrt) 616 { 617 union acpi_object *wifi_pkg, *data; 618 bool enabled; 619 int i, n_profiles, tbl_rev, pos; 620 int ret = 0; 621 u8 num_chains, num_sub_bands; 622 623 data = iwl_acpi_get_object(fwrt->dev, ACPI_EWRD_METHOD); 624 if (IS_ERR(data)) 625 return PTR_ERR(data); 626 627 /* start by trying to read revision 2 */ 628 wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data, 629 ACPI_EWRD_WIFI_DATA_SIZE_REV2, 630 &tbl_rev); 631 if (!IS_ERR(wifi_pkg)) { 632 if (tbl_rev != 2) { 633 ret = PTR_ERR(wifi_pkg); 634 goto out_free; 635 } 636 637 num_chains = ACPI_SAR_NUM_CHAINS_REV2; 638 num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV2; 639 640 goto read_table; 641 } 642 643 /* then try revision 1 */ 644 wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data, 645 ACPI_EWRD_WIFI_DATA_SIZE_REV1, 646 &tbl_rev); 647 if (!IS_ERR(wifi_pkg)) { 648 if (tbl_rev != 1) { 649 ret = PTR_ERR(wifi_pkg); 650 goto out_free; 651 } 652 653 num_chains = ACPI_SAR_NUM_CHAINS_REV1; 654 num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV1; 655 656 goto read_table; 657 } 658 659 /* then finally revision 0 */ 660 wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data, 661 ACPI_EWRD_WIFI_DATA_SIZE_REV0, 662 &tbl_rev); 663 if (!IS_ERR(wifi_pkg)) { 664 if (tbl_rev != 0) { 665 ret = PTR_ERR(wifi_pkg); 666 goto out_free; 667 } 668 669 num_chains = ACPI_SAR_NUM_CHAINS_REV0; 670 num_sub_bands = ACPI_SAR_NUM_SUB_BANDS_REV0; 671 672 goto read_table; 673 } 674 675 ret = PTR_ERR(wifi_pkg); 676 goto out_free; 677 678 read_table: 679 if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER || 680 wifi_pkg->package.elements[2].type != ACPI_TYPE_INTEGER) { 681 ret = -EINVAL; 682 goto out_free; 683 } 684 685 enabled = !!(wifi_pkg->package.elements[1].integer.value); 686 n_profiles = wifi_pkg->package.elements[2].integer.value; 687 688 /* 689 * Check the validity of n_profiles. The EWRD profiles start 690 * from index 1, so the maximum value allowed here is 691 * ACPI_SAR_PROFILES_NUM - 1. 692 */ 693 if (n_profiles <= 0 || n_profiles >= ACPI_SAR_PROFILE_NUM) { 694 ret = -EINVAL; 695 goto out_free; 696 } 697 698 /* the tables start at element 3 */ 699 pos = 3; 700 701 for (i = 0; i < n_profiles; i++) { 702 /* The EWRD profiles officially go from 2 to 4, but we 703 * save them in sar_profiles[1-3] (because we don't 704 * have profile 0). So in the array we start from 1. 705 */ 706 ret = iwl_sar_set_profile(&wifi_pkg->package.elements[pos], 707 &fwrt->sar_profiles[i + 1], enabled, 708 num_chains, num_sub_bands); 709 if (ret < 0) 710 break; 711 712 /* go to the next table */ 713 pos += num_chains * num_sub_bands; 714 } 715 716 out_free: 717 kfree(data); 718 return ret; 719 } 720 IWL_EXPORT_SYMBOL(iwl_sar_get_ewrd_table); 721 722 int iwl_sar_get_wgds_table(struct iwl_fw_runtime *fwrt) 723 { 724 union acpi_object *wifi_pkg, *data; 725 int i, j, k, ret, tbl_rev; 726 u8 num_bands, num_profiles; 727 static const struct { 728 u8 revisions; 729 u8 bands; 730 u8 profiles; 731 u8 min_profiles; 732 } rev_data[] = { 733 { 734 .revisions = BIT(3), 735 .bands = ACPI_GEO_NUM_BANDS_REV2, 736 .profiles = ACPI_NUM_GEO_PROFILES_REV3, 737 .min_profiles = 3, 738 }, 739 { 740 .revisions = BIT(2), 741 .bands = ACPI_GEO_NUM_BANDS_REV2, 742 .profiles = ACPI_NUM_GEO_PROFILES, 743 }, 744 { 745 .revisions = BIT(0) | BIT(1), 746 .bands = ACPI_GEO_NUM_BANDS_REV0, 747 .profiles = ACPI_NUM_GEO_PROFILES, 748 }, 749 }; 750 int idx; 751 /* start from one to skip the domain */ 752 int entry_idx = 1; 753 754 BUILD_BUG_ON(ACPI_NUM_GEO_PROFILES_REV3 != IWL_NUM_GEO_PROFILES_V3); 755 BUILD_BUG_ON(ACPI_NUM_GEO_PROFILES != IWL_NUM_GEO_PROFILES); 756 757 data = iwl_acpi_get_object(fwrt->dev, ACPI_WGDS_METHOD); 758 if (IS_ERR(data)) 759 return PTR_ERR(data); 760 761 /* read the highest revision we understand first */ 762 for (idx = 0; idx < ARRAY_SIZE(rev_data); idx++) { 763 /* min_profiles != 0 requires num_profiles header */ 764 u32 hdr_size = 1 + !!rev_data[idx].min_profiles; 765 u32 profile_size = ACPI_GEO_PER_CHAIN_SIZE * 766 rev_data[idx].bands; 767 u32 max_size = hdr_size + profile_size * rev_data[idx].profiles; 768 u32 min_size; 769 770 if (!rev_data[idx].min_profiles) 771 min_size = max_size; 772 else 773 min_size = hdr_size + 774 profile_size * rev_data[idx].min_profiles; 775 776 wifi_pkg = iwl_acpi_get_wifi_pkg_range(fwrt->dev, data, 777 min_size, max_size, 778 &tbl_rev); 779 if (!IS_ERR(wifi_pkg)) { 780 if (!(BIT(tbl_rev) & rev_data[idx].revisions)) 781 continue; 782 783 num_bands = rev_data[idx].bands; 784 num_profiles = rev_data[idx].profiles; 785 786 if (rev_data[idx].min_profiles) { 787 /* read header that says # of profiles */ 788 union acpi_object *entry; 789 790 entry = &wifi_pkg->package.elements[entry_idx]; 791 entry_idx++; 792 if (entry->type != ACPI_TYPE_INTEGER || 793 entry->integer.value > num_profiles) { 794 ret = -EINVAL; 795 goto out_free; 796 } 797 num_profiles = entry->integer.value; 798 799 /* 800 * this also validates >= min_profiles since we 801 * otherwise wouldn't have gotten the data when 802 * looking up in ACPI 803 */ 804 if (wifi_pkg->package.count != 805 hdr_size + profile_size * num_profiles) { 806 ret = -EINVAL; 807 goto out_free; 808 } 809 } 810 goto read_table; 811 } 812 } 813 814 if (idx < ARRAY_SIZE(rev_data)) 815 ret = PTR_ERR(wifi_pkg); 816 else 817 ret = -ENOENT; 818 goto out_free; 819 820 read_table: 821 fwrt->geo_rev = tbl_rev; 822 for (i = 0; i < num_profiles; i++) { 823 for (j = 0; j < ACPI_GEO_NUM_BANDS_REV2; j++) { 824 union acpi_object *entry; 825 826 /* 827 * num_bands is either 2 or 3, if it's only 2 then 828 * fill the third band (6 GHz) with the values from 829 * 5 GHz (second band) 830 */ 831 if (j >= num_bands) { 832 fwrt->geo_profiles[i].bands[j].max = 833 fwrt->geo_profiles[i].bands[1].max; 834 } else { 835 entry = &wifi_pkg->package.elements[entry_idx]; 836 entry_idx++; 837 if (entry->type != ACPI_TYPE_INTEGER || 838 entry->integer.value > U8_MAX) { 839 ret = -EINVAL; 840 goto out_free; 841 } 842 843 fwrt->geo_profiles[i].bands[j].max = 844 entry->integer.value; 845 } 846 847 for (k = 0; k < ACPI_GEO_NUM_CHAINS; k++) { 848 /* same here as above */ 849 if (j >= num_bands) { 850 fwrt->geo_profiles[i].bands[j].chains[k] = 851 fwrt->geo_profiles[i].bands[1].chains[k]; 852 } else { 853 entry = &wifi_pkg->package.elements[entry_idx]; 854 entry_idx++; 855 if (entry->type != ACPI_TYPE_INTEGER || 856 entry->integer.value > U8_MAX) { 857 ret = -EINVAL; 858 goto out_free; 859 } 860 861 fwrt->geo_profiles[i].bands[j].chains[k] = 862 entry->integer.value; 863 } 864 } 865 } 866 } 867 868 fwrt->geo_num_profiles = num_profiles; 869 fwrt->geo_enabled = true; 870 ret = 0; 871 out_free: 872 kfree(data); 873 return ret; 874 } 875 IWL_EXPORT_SYMBOL(iwl_sar_get_wgds_table); 876 877 bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt) 878 { 879 /* 880 * The PER_CHAIN_LIMIT_OFFSET_CMD command is not supported on 881 * earlier firmware versions. Unfortunately, we don't have a 882 * TLV API flag to rely on, so rely on the major version which 883 * is in the first byte of ucode_ver. This was implemented 884 * initially on version 38 and then backported to 17. It was 885 * also backported to 29, but only for 7265D devices. The 886 * intention was to have it in 36 as well, but not all 8000 887 * family got this feature enabled. The 8000 family is the 888 * only one using version 36, so skip this version entirely. 889 */ 890 return IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) >= 38 || 891 IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) == 17 || 892 (IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) == 29 && 893 ((fwrt->trans->hw_rev & CSR_HW_REV_TYPE_MSK) == 894 CSR_HW_REV_TYPE_7265D)); 895 } 896 IWL_EXPORT_SYMBOL(iwl_sar_geo_support); 897 898 int iwl_sar_geo_init(struct iwl_fw_runtime *fwrt, 899 struct iwl_per_chain_offset *table, 900 u32 n_bands, u32 n_profiles) 901 { 902 int i, j; 903 904 if (!iwl_sar_geo_support(fwrt)) 905 return -EOPNOTSUPP; 906 907 for (i = 0; i < n_profiles; i++) { 908 for (j = 0; j < n_bands; j++) { 909 struct iwl_per_chain_offset *chain = 910 &table[i * n_bands + j]; 911 912 chain->max_tx_power = 913 cpu_to_le16(fwrt->geo_profiles[i].bands[j].max); 914 chain->chain_a = fwrt->geo_profiles[i].bands[j].chains[0]; 915 chain->chain_b = fwrt->geo_profiles[i].bands[j].chains[1]; 916 IWL_DEBUG_RADIO(fwrt, 917 "SAR geographic profile[%d] Band[%d]: chain A = %d chain B = %d max_tx_power = %d\n", 918 i, j, 919 fwrt->geo_profiles[i].bands[j].chains[0], 920 fwrt->geo_profiles[i].bands[j].chains[1], 921 fwrt->geo_profiles[i].bands[j].max); 922 } 923 } 924 925 return 0; 926 } 927 IWL_EXPORT_SYMBOL(iwl_sar_geo_init); 928 929 __le32 iwl_acpi_get_lari_config_bitmap(struct iwl_fw_runtime *fwrt) 930 { 931 int ret; 932 u8 value; 933 __le32 config_bitmap = 0; 934 935 /* 936 ** Evaluate func 'DSM_FUNC_ENABLE_INDONESIA_5G2' 937 */ 938 ret = iwl_acpi_get_dsm_u8(fwrt->dev, 0, 939 DSM_FUNC_ENABLE_INDONESIA_5G2, 940 &iwl_guid, &value); 941 942 if (!ret && value == DSM_VALUE_INDONESIA_ENABLE) 943 config_bitmap |= 944 cpu_to_le32(LARI_CONFIG_ENABLE_5G2_IN_INDONESIA_MSK); 945 946 /* 947 ** Evaluate func 'DSM_FUNC_DISABLE_SRD' 948 */ 949 ret = iwl_acpi_get_dsm_u8(fwrt->dev, 0, 950 DSM_FUNC_DISABLE_SRD, 951 &iwl_guid, &value); 952 if (!ret) { 953 if (value == DSM_VALUE_SRD_PASSIVE) 954 config_bitmap |= 955 cpu_to_le32(LARI_CONFIG_CHANGE_ETSI_TO_PASSIVE_MSK); 956 else if (value == DSM_VALUE_SRD_DISABLE) 957 config_bitmap |= 958 cpu_to_le32(LARI_CONFIG_CHANGE_ETSI_TO_DISABLED_MSK); 959 } 960 961 return config_bitmap; 962 } 963 IWL_EXPORT_SYMBOL(iwl_acpi_get_lari_config_bitmap); 964