1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* 3 * Copyright (C) 2017 Intel Deutschland GmbH 4 * Copyright (C) 2019-2020 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 static const guid_t intel_wifi_guid = GUID_INIT(0xF21202BF, 0x8F78, 0x4DC6, 13 0xA5, 0xB3, 0x1F, 0x73, 14 0x8E, 0x28, 0x5A, 0xDE); 15 16 static int iwl_acpi_get_handle(struct device *dev, acpi_string method, 17 acpi_handle *ret_handle) 18 { 19 acpi_handle root_handle; 20 acpi_status status; 21 22 root_handle = ACPI_HANDLE(dev); 23 if (!root_handle) { 24 IWL_DEBUG_DEV_RADIO(dev, 25 "ACPI: Could not retrieve root port handle\n"); 26 return -ENOENT; 27 } 28 29 status = acpi_get_handle(root_handle, method, ret_handle); 30 if (ACPI_FAILURE(status)) { 31 IWL_DEBUG_DEV_RADIO(dev, 32 "ACPI: %s method not found\n", method); 33 return -ENOENT; 34 } 35 return 0; 36 } 37 38 void *iwl_acpi_get_object(struct device *dev, acpi_string method) 39 { 40 struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL}; 41 acpi_handle handle; 42 acpi_status status; 43 int ret; 44 45 ret = iwl_acpi_get_handle(dev, method, &handle); 46 if (ret) 47 return ERR_PTR(-ENOENT); 48 49 /* Call the method with no arguments */ 50 status = acpi_evaluate_object(handle, NULL, NULL, &buf); 51 if (ACPI_FAILURE(status)) { 52 IWL_DEBUG_DEV_RADIO(dev, 53 "ACPI: %s method invocation failed (status: 0x%x)\n", 54 method, status); 55 return ERR_PTR(-ENOENT); 56 } 57 return buf.pointer; 58 } 59 IWL_EXPORT_SYMBOL(iwl_acpi_get_object); 60 61 /* 62 * Generic function for evaluating a method defined in the device specific 63 * method (DSM) interface. The returned acpi object must be freed by calling 64 * function. 65 */ 66 static void *iwl_acpi_get_dsm_object(struct device *dev, int rev, int func, 67 union acpi_object *args) 68 { 69 union acpi_object *obj; 70 71 obj = acpi_evaluate_dsm(ACPI_HANDLE(dev), &intel_wifi_guid, rev, func, 72 args); 73 if (!obj) { 74 IWL_DEBUG_DEV_RADIO(dev, 75 "ACPI: DSM method invocation failed (rev: %d, func:%d)\n", 76 rev, func); 77 return ERR_PTR(-ENOENT); 78 } 79 return obj; 80 } 81 82 /* 83 * Evaluate a DSM with no arguments and a single u8 return value (inside a 84 * buffer object), verify and return that value. 85 */ 86 int iwl_acpi_get_dsm_u8(struct device *dev, int rev, int func) 87 { 88 union acpi_object *obj; 89 int ret; 90 91 obj = iwl_acpi_get_dsm_object(dev, rev, func, NULL); 92 if (IS_ERR(obj)) 93 return -ENOENT; 94 95 if (obj->type != ACPI_TYPE_BUFFER) { 96 IWL_DEBUG_DEV_RADIO(dev, 97 "ACPI: DSM method did not return a valid object, type=%d\n", 98 obj->type); 99 ret = -EINVAL; 100 goto out; 101 } 102 103 if (obj->buffer.length != sizeof(u8)) { 104 IWL_DEBUG_DEV_RADIO(dev, 105 "ACPI: DSM method returned invalid buffer, length=%d\n", 106 obj->buffer.length); 107 ret = -EINVAL; 108 goto out; 109 } 110 111 ret = obj->buffer.pointer[0]; 112 IWL_DEBUG_DEV_RADIO(dev, 113 "ACPI: DSM method evaluated: func=%d, ret=%d\n", 114 func, ret); 115 out: 116 ACPI_FREE(obj); 117 return ret; 118 } 119 IWL_EXPORT_SYMBOL(iwl_acpi_get_dsm_u8); 120 121 union acpi_object *iwl_acpi_get_wifi_pkg(struct device *dev, 122 union acpi_object *data, 123 int data_size, int *tbl_rev) 124 { 125 int i; 126 union acpi_object *wifi_pkg; 127 128 /* 129 * We need at least one entry in the wifi package that 130 * describes the domain, and one more entry, otherwise there's 131 * no point in reading it. 132 */ 133 if (WARN_ON_ONCE(data_size < 2)) 134 return ERR_PTR(-EINVAL); 135 136 /* 137 * We need at least two packages, one for the revision and one 138 * for the data itself. Also check that the revision is valid 139 * (i.e. it is an integer smaller than 2, as we currently support only 140 * 2 revisions). 141 */ 142 if (data->type != ACPI_TYPE_PACKAGE || 143 data->package.count < 2 || 144 data->package.elements[0].type != ACPI_TYPE_INTEGER || 145 data->package.elements[0].integer.value > 1) { 146 IWL_DEBUG_DEV_RADIO(dev, "Unsupported packages structure\n"); 147 return ERR_PTR(-EINVAL); 148 } 149 150 *tbl_rev = data->package.elements[0].integer.value; 151 152 /* loop through all the packages to find the one for WiFi */ 153 for (i = 1; i < data->package.count; i++) { 154 union acpi_object *domain; 155 156 wifi_pkg = &data->package.elements[i]; 157 158 /* skip entries that are not a package with the right size */ 159 if (wifi_pkg->type != ACPI_TYPE_PACKAGE || 160 wifi_pkg->package.count != data_size) 161 continue; 162 163 domain = &wifi_pkg->package.elements[0]; 164 if (domain->type == ACPI_TYPE_INTEGER && 165 domain->integer.value == ACPI_WIFI_DOMAIN) 166 goto found; 167 } 168 169 return ERR_PTR(-ENOENT); 170 171 found: 172 return wifi_pkg; 173 } 174 IWL_EXPORT_SYMBOL(iwl_acpi_get_wifi_pkg); 175 176 int iwl_acpi_get_tas(struct iwl_fw_runtime *fwrt, 177 __le32 *block_list_array, 178 int *block_list_size) 179 { 180 union acpi_object *wifi_pkg, *data; 181 int ret, tbl_rev, i; 182 bool enabled; 183 184 data = iwl_acpi_get_object(fwrt->dev, ACPI_WTAS_METHOD); 185 if (IS_ERR(data)) 186 return PTR_ERR(data); 187 188 wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data, 189 ACPI_WTAS_WIFI_DATA_SIZE, 190 &tbl_rev); 191 if (IS_ERR(wifi_pkg)) { 192 ret = PTR_ERR(wifi_pkg); 193 goto out_free; 194 } 195 196 if (wifi_pkg->package.elements[0].type != ACPI_TYPE_INTEGER || 197 tbl_rev != 0) { 198 ret = -EINVAL; 199 goto out_free; 200 } 201 202 enabled = !!wifi_pkg->package.elements[0].integer.value; 203 204 if (!enabled) { 205 *block_list_size = -1; 206 IWL_DEBUG_RADIO(fwrt, "TAS not enabled\n"); 207 ret = 0; 208 goto out_free; 209 } 210 211 if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER || 212 wifi_pkg->package.elements[1].integer.value > 213 APCI_WTAS_BLACK_LIST_MAX) { 214 IWL_DEBUG_RADIO(fwrt, "TAS invalid array size %llu\n", 215 wifi_pkg->package.elements[1].integer.value); 216 ret = -EINVAL; 217 goto out_free; 218 } 219 *block_list_size = wifi_pkg->package.elements[1].integer.value; 220 221 IWL_DEBUG_RADIO(fwrt, "TAS array size %d\n", *block_list_size); 222 if (*block_list_size > APCI_WTAS_BLACK_LIST_MAX) { 223 IWL_DEBUG_RADIO(fwrt, "TAS invalid array size value %u\n", 224 *block_list_size); 225 ret = -EINVAL; 226 goto out_free; 227 } 228 229 for (i = 0; i < *block_list_size; i++) { 230 u32 country; 231 232 if (wifi_pkg->package.elements[2 + i].type != 233 ACPI_TYPE_INTEGER) { 234 IWL_DEBUG_RADIO(fwrt, 235 "TAS invalid array elem %d\n", 2 + i); 236 ret = -EINVAL; 237 goto out_free; 238 } 239 240 country = wifi_pkg->package.elements[2 + i].integer.value; 241 block_list_array[i] = cpu_to_le32(country); 242 IWL_DEBUG_RADIO(fwrt, "TAS block list country %d\n", country); 243 } 244 245 ret = 0; 246 out_free: 247 kfree(data); 248 return ret; 249 } 250 IWL_EXPORT_SYMBOL(iwl_acpi_get_tas); 251 252 int iwl_acpi_get_mcc(struct device *dev, char *mcc) 253 { 254 union acpi_object *wifi_pkg, *data; 255 u32 mcc_val; 256 int ret, tbl_rev; 257 258 data = iwl_acpi_get_object(dev, ACPI_WRDD_METHOD); 259 if (IS_ERR(data)) 260 return PTR_ERR(data); 261 262 wifi_pkg = iwl_acpi_get_wifi_pkg(dev, data, ACPI_WRDD_WIFI_DATA_SIZE, 263 &tbl_rev); 264 if (IS_ERR(wifi_pkg)) { 265 ret = PTR_ERR(wifi_pkg); 266 goto out_free; 267 } 268 269 if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER || 270 tbl_rev != 0) { 271 ret = -EINVAL; 272 goto out_free; 273 } 274 275 mcc_val = wifi_pkg->package.elements[1].integer.value; 276 277 mcc[0] = (mcc_val >> 8) & 0xff; 278 mcc[1] = mcc_val & 0xff; 279 mcc[2] = '\0'; 280 281 ret = 0; 282 out_free: 283 kfree(data); 284 return ret; 285 } 286 IWL_EXPORT_SYMBOL(iwl_acpi_get_mcc); 287 288 u64 iwl_acpi_get_pwr_limit(struct device *dev) 289 { 290 union acpi_object *data, *wifi_pkg; 291 u64 dflt_pwr_limit; 292 int tbl_rev; 293 294 data = iwl_acpi_get_object(dev, ACPI_SPLC_METHOD); 295 if (IS_ERR(data)) { 296 dflt_pwr_limit = 0; 297 goto out; 298 } 299 300 wifi_pkg = iwl_acpi_get_wifi_pkg(dev, data, 301 ACPI_SPLC_WIFI_DATA_SIZE, &tbl_rev); 302 if (IS_ERR(wifi_pkg) || tbl_rev != 0 || 303 wifi_pkg->package.elements[1].integer.value != ACPI_TYPE_INTEGER) { 304 dflt_pwr_limit = 0; 305 goto out_free; 306 } 307 308 dflt_pwr_limit = wifi_pkg->package.elements[1].integer.value; 309 out_free: 310 kfree(data); 311 out: 312 return dflt_pwr_limit; 313 } 314 IWL_EXPORT_SYMBOL(iwl_acpi_get_pwr_limit); 315 316 int iwl_acpi_get_eckv(struct device *dev, u32 *extl_clk) 317 { 318 union acpi_object *wifi_pkg, *data; 319 int ret, tbl_rev; 320 321 data = iwl_acpi_get_object(dev, ACPI_ECKV_METHOD); 322 if (IS_ERR(data)) 323 return PTR_ERR(data); 324 325 wifi_pkg = iwl_acpi_get_wifi_pkg(dev, data, ACPI_ECKV_WIFI_DATA_SIZE, 326 &tbl_rev); 327 if (IS_ERR(wifi_pkg)) { 328 ret = PTR_ERR(wifi_pkg); 329 goto out_free; 330 } 331 332 if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER || 333 tbl_rev != 0) { 334 ret = -EINVAL; 335 goto out_free; 336 } 337 338 *extl_clk = wifi_pkg->package.elements[1].integer.value; 339 340 ret = 0; 341 342 out_free: 343 kfree(data); 344 return ret; 345 } 346 IWL_EXPORT_SYMBOL(iwl_acpi_get_eckv); 347 348 static int iwl_sar_set_profile(union acpi_object *table, 349 struct iwl_sar_profile *profile, 350 bool enabled) 351 { 352 int i; 353 354 profile->enabled = enabled; 355 356 for (i = 0; i < ACPI_SAR_TABLE_SIZE; i++) { 357 if (table[i].type != ACPI_TYPE_INTEGER || 358 table[i].integer.value > U8_MAX) 359 return -EINVAL; 360 361 profile->table[i] = table[i].integer.value; 362 } 363 364 return 0; 365 } 366 367 static int iwl_sar_fill_table(struct iwl_fw_runtime *fwrt, 368 __le16 *per_chain, u32 n_subbands, 369 int prof_a, int prof_b) 370 { 371 int profs[ACPI_SAR_NUM_CHAIN_LIMITS] = { prof_a, prof_b }; 372 int i, j, idx; 373 374 for (i = 0; i < ACPI_SAR_NUM_CHAIN_LIMITS; i++) { 375 struct iwl_sar_profile *prof; 376 377 /* don't allow SAR to be disabled (profile 0 means disable) */ 378 if (profs[i] == 0) 379 return -EPERM; 380 381 /* we are off by one, so allow up to ACPI_SAR_PROFILE_NUM */ 382 if (profs[i] > ACPI_SAR_PROFILE_NUM) 383 return -EINVAL; 384 385 /* profiles go from 1 to 4, so decrement to access the array */ 386 prof = &fwrt->sar_profiles[profs[i] - 1]; 387 388 /* if the profile is disabled, do nothing */ 389 if (!prof->enabled) { 390 IWL_DEBUG_RADIO(fwrt, "SAR profile %d is disabled.\n", 391 profs[i]); 392 /* 393 * if one of the profiles is disabled, we 394 * ignore all of them and return 1 to 395 * differentiate disabled from other failures. 396 */ 397 return 1; 398 } 399 400 IWL_DEBUG_INFO(fwrt, 401 "SAR EWRD: chain %d profile index %d\n", 402 i, profs[i]); 403 IWL_DEBUG_RADIO(fwrt, " Chain[%d]:\n", i); 404 for (j = 0; j < n_subbands; j++) { 405 idx = i * ACPI_SAR_NUM_SUB_BANDS + j; 406 per_chain[i * n_subbands + j] = 407 cpu_to_le16(prof->table[idx]); 408 IWL_DEBUG_RADIO(fwrt, " Band[%d] = %d * .125dBm\n", 409 j, prof->table[idx]); 410 } 411 } 412 413 return 0; 414 } 415 416 int iwl_sar_select_profile(struct iwl_fw_runtime *fwrt, 417 __le16 *per_chain, u32 n_tables, u32 n_subbands, 418 int prof_a, int prof_b) 419 { 420 int i, ret = 0; 421 422 for (i = 0; i < n_tables; i++) { 423 ret = iwl_sar_fill_table(fwrt, 424 &per_chain[i * n_subbands * ACPI_SAR_NUM_CHAIN_LIMITS], 425 n_subbands, prof_a, prof_b); 426 if (ret) 427 break; 428 } 429 430 return ret; 431 } 432 IWL_EXPORT_SYMBOL(iwl_sar_select_profile); 433 434 int iwl_sar_get_wrds_table(struct iwl_fw_runtime *fwrt) 435 { 436 union acpi_object *wifi_pkg, *table, *data; 437 bool enabled; 438 int ret, tbl_rev; 439 440 data = iwl_acpi_get_object(fwrt->dev, ACPI_WRDS_METHOD); 441 if (IS_ERR(data)) 442 return PTR_ERR(data); 443 444 wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data, 445 ACPI_WRDS_WIFI_DATA_SIZE, &tbl_rev); 446 if (IS_ERR(wifi_pkg) || tbl_rev != 0) { 447 ret = PTR_ERR(wifi_pkg); 448 goto out_free; 449 } 450 451 if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER) { 452 ret = -EINVAL; 453 goto out_free; 454 } 455 456 enabled = !!(wifi_pkg->package.elements[1].integer.value); 457 458 /* position of the actual table */ 459 table = &wifi_pkg->package.elements[2]; 460 461 /* The profile from WRDS is officially profile 1, but goes 462 * into sar_profiles[0] (because we don't have a profile 0). 463 */ 464 ret = iwl_sar_set_profile(table, &fwrt->sar_profiles[0], enabled); 465 out_free: 466 kfree(data); 467 return ret; 468 } 469 IWL_EXPORT_SYMBOL(iwl_sar_get_wrds_table); 470 471 int iwl_sar_get_ewrd_table(struct iwl_fw_runtime *fwrt) 472 { 473 union acpi_object *wifi_pkg, *data; 474 bool enabled; 475 int i, n_profiles, tbl_rev, pos; 476 int ret = 0; 477 478 data = iwl_acpi_get_object(fwrt->dev, ACPI_EWRD_METHOD); 479 if (IS_ERR(data)) 480 return PTR_ERR(data); 481 482 wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data, 483 ACPI_EWRD_WIFI_DATA_SIZE, &tbl_rev); 484 if (IS_ERR(wifi_pkg) || tbl_rev != 0) { 485 ret = PTR_ERR(wifi_pkg); 486 goto out_free; 487 } 488 489 if (wifi_pkg->package.elements[1].type != ACPI_TYPE_INTEGER || 490 wifi_pkg->package.elements[2].type != ACPI_TYPE_INTEGER) { 491 ret = -EINVAL; 492 goto out_free; 493 } 494 495 enabled = !!(wifi_pkg->package.elements[1].integer.value); 496 n_profiles = wifi_pkg->package.elements[2].integer.value; 497 498 /* 499 * Check the validity of n_profiles. The EWRD profiles start 500 * from index 1, so the maximum value allowed here is 501 * ACPI_SAR_PROFILES_NUM - 1. 502 */ 503 if (n_profiles <= 0 || n_profiles >= ACPI_SAR_PROFILE_NUM) { 504 ret = -EINVAL; 505 goto out_free; 506 } 507 508 /* the tables start at element 3 */ 509 pos = 3; 510 511 for (i = 0; i < n_profiles; i++) { 512 /* The EWRD profiles officially go from 2 to 4, but we 513 * save them in sar_profiles[1-3] (because we don't 514 * have profile 0). So in the array we start from 1. 515 */ 516 ret = iwl_sar_set_profile(&wifi_pkg->package.elements[pos], 517 &fwrt->sar_profiles[i + 1], 518 enabled); 519 if (ret < 0) 520 break; 521 522 /* go to the next table */ 523 pos += ACPI_SAR_TABLE_SIZE; 524 } 525 526 out_free: 527 kfree(data); 528 return ret; 529 } 530 IWL_EXPORT_SYMBOL(iwl_sar_get_ewrd_table); 531 532 int iwl_sar_get_wgds_table(struct iwl_fw_runtime *fwrt) 533 { 534 union acpi_object *wifi_pkg, *data; 535 int i, j, ret, tbl_rev; 536 int idx = 1; 537 538 data = iwl_acpi_get_object(fwrt->dev, ACPI_WGDS_METHOD); 539 if (IS_ERR(data)) 540 return PTR_ERR(data); 541 542 wifi_pkg = iwl_acpi_get_wifi_pkg(fwrt->dev, data, 543 ACPI_WGDS_WIFI_DATA_SIZE, &tbl_rev); 544 if (IS_ERR(wifi_pkg) || tbl_rev > 1) { 545 ret = PTR_ERR(wifi_pkg); 546 goto out_free; 547 } 548 549 fwrt->geo_rev = tbl_rev; 550 for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) { 551 for (j = 0; j < ACPI_GEO_TABLE_SIZE; j++) { 552 union acpi_object *entry; 553 554 entry = &wifi_pkg->package.elements[idx++]; 555 if (entry->type != ACPI_TYPE_INTEGER || 556 entry->integer.value > U8_MAX) { 557 ret = -EINVAL; 558 goto out_free; 559 } 560 561 fwrt->geo_profiles[i].values[j] = entry->integer.value; 562 } 563 } 564 ret = 0; 565 out_free: 566 kfree(data); 567 return ret; 568 } 569 IWL_EXPORT_SYMBOL(iwl_sar_get_wgds_table); 570 571 bool iwl_sar_geo_support(struct iwl_fw_runtime *fwrt) 572 { 573 /* 574 * The GEO_TX_POWER_LIMIT command is not supported on earlier 575 * firmware versions. Unfortunately, we don't have a TLV API 576 * flag to rely on, so rely on the major version which is in 577 * the first byte of ucode_ver. This was implemented 578 * initially on version 38 and then backported to 17. It was 579 * also backported to 29, but only for 7265D devices. The 580 * intention was to have it in 36 as well, but not all 8000 581 * family got this feature enabled. The 8000 family is the 582 * only one using version 36, so skip this version entirely. 583 */ 584 return IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) >= 38 || 585 IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) == 17 || 586 (IWL_UCODE_SERIAL(fwrt->fw->ucode_ver) == 29 && 587 ((fwrt->trans->hw_rev & CSR_HW_REV_TYPE_MSK) == 588 CSR_HW_REV_TYPE_7265D)); 589 } 590 IWL_EXPORT_SYMBOL(iwl_sar_geo_support); 591 592 int iwl_sar_geo_init(struct iwl_fw_runtime *fwrt, 593 struct iwl_per_chain_offset *table, u32 n_bands) 594 { 595 int ret, i, j; 596 597 if (!iwl_sar_geo_support(fwrt)) 598 return -EOPNOTSUPP; 599 600 ret = iwl_sar_get_wgds_table(fwrt); 601 if (ret < 0) { 602 IWL_DEBUG_RADIO(fwrt, 603 "Geo SAR BIOS table invalid or unavailable. (%d)\n", 604 ret); 605 /* we don't fail if the table is not available */ 606 return -ENOENT; 607 } 608 609 for (i = 0; i < ACPI_NUM_GEO_PROFILES; i++) { 610 for (j = 0; j < n_bands; j++) { 611 struct iwl_per_chain_offset *chain = 612 &table[i * n_bands + j]; 613 u8 *value; 614 615 if (j * ACPI_GEO_PER_CHAIN_SIZE >= 616 ARRAY_SIZE(fwrt->geo_profiles[0].values)) 617 /* 618 * Currently we only store lb an hb values, and 619 * don't have any special ones for uhb. So leave 620 * those empty for the time being 621 */ 622 break; 623 624 value = &fwrt->geo_profiles[i].values[j * 625 ACPI_GEO_PER_CHAIN_SIZE]; 626 chain->max_tx_power = cpu_to_le16(value[0]); 627 chain->chain_a = value[1]; 628 chain->chain_b = value[2]; 629 IWL_DEBUG_RADIO(fwrt, 630 "SAR geographic profile[%d] Band[%d]: chain A = %d chain B = %d max_tx_power = %d\n", 631 i, j, value[1], value[2], value[0]); 632 } 633 } 634 635 return 0; 636 } 637 IWL_EXPORT_SYMBOL(iwl_sar_geo_init); 638