Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'acpi-6.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull ACPI updates from Rafael Wysocki:
"These include an ACPICA update (upstream revision 20250807 with a few
fixes on top), fixes and cleanups of the ACPI processor driver, fixes
and cleanups of the ACPI properties management code, one more ACPI IRQ
resource management quirk, one more ACPI backlight quirk, an ACPI
device enumeration quirk related to _DEP, a power resource quirk
related to WWAN modem for HP EliteBook 855 G7, ACPI SPCR table parser
extensions, an ACPI APEI EINJ driver update allowing it to handle more
address types, and several assorted cleanups of ACPI drivers and PNP
code.

Specifics:

- Add SoundWire File Table (SWFT) signature to ACPICA (Maciej
Strozek)

- Rearrange local variable definition involving #ifdef in ACPICA to
avoid using uninitialized variables (Zhe Qiao)

- Allow ACPICA to skip Global Lock initialization (Huacai Chen)

- Apply ACPI_NONSTRING in more places in ACPICA and fix two
regressions related to incorrect ACPI_NONSTRING usage (Ahmed Salem)

- Fix printing CDAT table header when dissasebling CDAT AML (Ahmed
Salem)

- Use acpi_ds_clear_operands() in acpi_ds_call_control_method() in
ACPICA (Hans de Goede)

- Update dsmethod.c in ACPICA to address unused variable warning
(Saket Dumbre)

- Print error messages in ACPICA for too few or too many control
method arguments (Saket Dumbre)

- Update ACPICA version to 20250807 (Saket Dumbre)

- Fix largest possible resource descriptor index in ACPICA (Dmitry
Antipov)

- Add Back-Invalidate restriction to CXL Window for CEDT in ACPICA
(Davidlohr Bueso)

- Add the package type to acceptable Arg3 types for _DSM in ACPICA
because ACPI_TYPE_ANY does not cover it (Saket Dumbre)

- Fix return values in ap_is_valid_checksum() in the acpidump utility
in ACPICA (Kaushlendra Kumar)

- Add Intel CVS ACPI HIDs to acpi_ignore_dep_ids[] so it is not
regarded as real dependency (Hans de Goede)

- Use ACPI_FREE() for freeing an ACPI object in description_show() in
the ACPI sysfs-related code (Kaushlendra Kumar)

- Fix memory leak in the ACPI processor idle driver registration
error code path and optimize ACPI idle driver registration (Huisong
Li, Rafael Wysocki)

- Add module import namespace to the ACPI processor idle driver
(Rafael Wysocki)

- Eliminate static variable flat_state_cnt from the ACPI processor
idle driver (Rafael Wysocki)

- Release cpufreq policy references using __free() in the ACPI
processor thremal driver (Zihuan Zhang)

- Remove unused empty stubs of some functions and rearrange function
declarations in a header file in the ACPI processor driver (Huisong
Li)

- Redefine two functions as void in the ACPI processor driver (Rafael
Wysocki)

- Stop exposing global variable acpi_idle_driver in the ACPI
processor driver (Huisong Li)

- Fix ACPI buffer properties extraction for data-only subnodes
represented as _DSD-equivalent packages (Rafael Wysocki)

- Fix handling of ACPI data-only subnodes represented as
_DSD-equivalent packages in the case when they are embedded in
larger _DSD-equivalent packages and clean up
acpi_nondev_subnode_extract() (Rafael Wysocki)

- Skip ACPI IRQ override on ASUS Vivobook Pro N6506CU (Sam van
Kampen)

- Add power resource init function and use it for introducing an HP
EliteBook 855 G7 WWAN modem power resource quirk (Maciej Szmigiero)

- Add support for DBG2 RISC-V SBI port subtype and Precise Baud Rate
field to the ACPI SPCR table parser (Chen Pei)

- Eliminate a dummy local variable from the ACPI thermal driver
(Rafael Wysocki)

- Fold two simple functions into their only caller in the ACPI fan
driver (Rafael Wysocki)

- Force native backlight on Lenovo 82K8 in the ACPI backlight (video)
driver (Mario Limonciello)

- Add missing sysfs_remove_group() for ACPI_TAD_RT (Daniel Tang)

- Skip PRM handlers with NULL handler_address or NULL VA in the ACPI
PRM driver (Shang song)

- Remove redundant assignments in erst_dbg_{ioctl|write}() in the
ACPI APEI driver (Thorsten Blum)

- Allow the ACPI APEI EINJ to handle more types of addresses than
just MMIO (Jiaqi Yan)

- Use str_low_high() helper in two places in the ACPI code (Chelsy
Ratnawat)

- Use str_plural() to simplify the PNP code (Xichao Zhao)

- Fix signedness issues in read/write helpers in the ACPI AML
debugger interface (Amir Mohammad)"

* tag 'acpi-6.18-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm: (50 commits)
ACPI: debug: fix signedness issues in read/write helpers
ACPI: processor: Do not expose global variable acpi_idle_driver
ACPI: SPCR: Support Precise Baud Rate field
ACPI: processor: idle: Redefine two functions as void
ACPI: processor: Update cpuidle driver check in __acpi_processor_start()
ACPI: processor: idle: Rearrange declarations in header file
ACPI: processor: Remove unused empty stubs of some functions
ACPI: property: Adjust failure handling in acpi_nondev_subnode_extract()
ACPI: property: Do not pass NULL handles to acpi_attach_data()
ACPI: property: Add code comments explaining what is going on
ACPI: property: Disregard references in data-only subnode lists
ACPI: property: Fix buffer properties extraction for subnodes
ACPI: SPCR: Add support for DBG2 RISC-V SBI port subtype
ACPI: APEI: EINJ: Allow more types of addresses except MMIO
ACPI: APEI: Remove redundant assignments in erst_dbg_{ioctl|write}()
ACPICA: acpidump: fix return values in ap_is_valid_checksum()
ACPICA: ACPI_TYPE_ANY does not include the package type
ACPICA: CEDT: Add Back-Invalidate restriction to CXL Window
ACPICA: Fix largest possible resource descriptor index
ACPICA: Update version to 20250807
...

+502 -256
+13 -13
drivers/acpi/acpi_dbg.c
··· 569 569 return 0; 570 570 } 571 571 572 - static int acpi_aml_read_user(char __user *buf, int len) 572 + static ssize_t acpi_aml_read_user(char __user *buf, size_t len) 573 573 { 574 - int ret; 575 574 struct circ_buf *crc = &acpi_aml_io.out_crc; 576 - int n; 575 + ssize_t ret; 576 + size_t n; 577 577 char *p; 578 578 579 579 ret = acpi_aml_lock_read(crc, ACPI_AML_OUT_USER); ··· 582 582 /* sync head before removing logs */ 583 583 smp_rmb(); 584 584 p = &crc->buf[crc->tail]; 585 - n = min(len, circ_count_to_end(crc)); 585 + n = min_t(size_t, len, circ_count_to_end(crc)); 586 586 if (copy_to_user(buf, p, n)) { 587 587 ret = -EFAULT; 588 588 goto out; ··· 599 599 static ssize_t acpi_aml_read(struct file *file, char __user *buf, 600 600 size_t count, loff_t *ppos) 601 601 { 602 - int ret = 0; 603 - int size = 0; 602 + ssize_t ret = 0; 603 + ssize_t size = 0; 604 604 605 605 if (!count) 606 606 return 0; ··· 639 639 return size > 0 ? size : ret; 640 640 } 641 641 642 - static int acpi_aml_write_user(const char __user *buf, int len) 642 + static ssize_t acpi_aml_write_user(const char __user *buf, size_t len) 643 643 { 644 - int ret; 645 644 struct circ_buf *crc = &acpi_aml_io.in_crc; 646 - int n; 645 + ssize_t ret; 646 + size_t n; 647 647 char *p; 648 648 649 649 ret = acpi_aml_lock_write(crc, ACPI_AML_IN_USER); ··· 652 652 /* sync tail before inserting cmds */ 653 653 smp_mb(); 654 654 p = &crc->buf[crc->head]; 655 - n = min(len, circ_space_to_end(crc)); 655 + n = min_t(size_t, len, circ_space_to_end(crc)); 656 656 if (copy_from_user(p, buf, n)) { 657 657 ret = -EFAULT; 658 658 goto out; ··· 663 663 ret = n; 664 664 out: 665 665 acpi_aml_unlock_fifo(ACPI_AML_IN_USER, ret >= 0); 666 - return n; 666 + return ret; 667 667 } 668 668 669 669 static ssize_t acpi_aml_write(struct file *file, const char __user *buf, 670 670 size_t count, loff_t *ppos) 671 671 { 672 - int ret = 0; 673 - int size = 0; 672 + ssize_t ret = 0; 673 + ssize_t size = 0; 674 674 675 675 if (!count) 676 676 return 0;
+2 -2
drivers/acpi/acpi_processor.c
··· 815 815 cst_control_claimed = true; 816 816 return true; 817 817 } 818 - EXPORT_SYMBOL_GPL(acpi_processor_claim_cst_control); 818 + EXPORT_SYMBOL_NS_GPL(acpi_processor_claim_cst_control, "ACPI_PROCESSOR_IDLE"); 819 819 820 820 /** 821 821 * acpi_processor_evaluate_cst - Evaluate the processor _CST control method. ··· 994 994 995 995 return ret; 996 996 } 997 - EXPORT_SYMBOL_GPL(acpi_processor_evaluate_cst); 997 + EXPORT_SYMBOL_NS_GPL(acpi_processor_evaluate_cst, "ACPI_PROCESSOR_IDLE"); 998 998 #endif /* CONFIG_ACPI_PROCESSOR_CSTATE */
+3
drivers/acpi/acpi_tad.c
··· 565 565 566 566 pm_runtime_get_sync(dev); 567 567 568 + if (dd->capabilities & ACPI_TAD_RT) 569 + sysfs_remove_group(&dev->kobj, &acpi_tad_time_attr_group); 570 + 568 571 if (dd->capabilities & ACPI_TAD_DC_WAKE) 569 572 sysfs_remove_group(&dev->kobj, &acpi_tad_dc_attr_group); 570 573
+1 -1
drivers/acpi/acpica/acdebug.h
··· 37 37 struct acpi_db_execute_walk { 38 38 u32 count; 39 39 u32 max_count; 40 - char name_seg[ACPI_NAMESEG_SIZE + 1] ACPI_NONSTRING; 40 + char name_seg[ACPI_NAMESEG_SIZE + 1]; 41 41 }; 42 42 43 43 #define PARAM_LIST(pl) pl
+1 -1
drivers/acpi/acpica/aclocal.h
··· 1141 1141 #define ACPI_RESOURCE_NAME_PIN_GROUP_FUNCTION 0x91 1142 1142 #define ACPI_RESOURCE_NAME_PIN_GROUP_CONFIG 0x92 1143 1143 #define ACPI_RESOURCE_NAME_CLOCK_INPUT 0x93 1144 - #define ACPI_RESOURCE_NAME_LARGE_MAX 0x94 1144 + #define ACPI_RESOURCE_NAME_LARGE_MAX 0x93 1145 1145 1146 1146 /***************************************************************************** 1147 1147 *
+2 -1
drivers/acpi/acpica/acpredef.h
··· 450 450 451 451 {{"_DSM", 452 452 METHOD_4ARGS(ACPI_TYPE_BUFFER, ACPI_TYPE_INTEGER, ACPI_TYPE_INTEGER, 453 - ACPI_TYPE_ANY) | ARG_COUNT_IS_MINIMUM, 453 + ACPI_TYPE_ANY | ACPI_TYPE_PACKAGE) | 454 + ARG_COUNT_IS_MINIMUM, 454 455 METHOD_RETURNS(ACPI_RTYPE_ALL)}}, /* Must return a value, but it can be of any type */ 455 456 456 457 {{"_DSS", METHOD_1ARGS(ACPI_TYPE_INTEGER),
+10 -11
drivers/acpi/acpica/dsmethod.c
··· 462 462 struct acpi_walk_state *next_walk_state = NULL; 463 463 union acpi_operand_object *obj_desc; 464 464 struct acpi_evaluate_info *info; 465 - u32 i; 466 465 467 466 ACPI_FUNCTION_TRACE_PTR(ds_call_control_method, this_walk_state); 468 467 ··· 483 484 } 484 485 485 486 if (this_walk_state->num_operands < obj_desc->method.param_count) { 486 - ACPI_ERROR((AE_INFO, "Missing argument for method [%4.4s]", 487 + ACPI_ERROR((AE_INFO, "Missing argument(s) for method [%4.4s]", 487 488 acpi_ut_get_node_name(method_node))); 488 489 489 - return_ACPI_STATUS(AE_AML_UNINITIALIZED_ARG); 490 + return_ACPI_STATUS(AE_AML_TOO_FEW_ARGUMENTS); 491 + } 492 + 493 + else if (this_walk_state->num_operands > obj_desc->method.param_count) { 494 + ACPI_ERROR((AE_INFO, "Too many arguments for method [%4.4s]", 495 + acpi_ut_get_node_name(method_node))); 496 + 497 + return_ACPI_STATUS(AE_AML_TOO_MANY_ARGUMENTS); 490 498 } 491 499 492 500 /* Init for new method, possibly wait on method mutex */ ··· 552 546 * Delete the operands on the previous walkstate operand stack 553 547 * (they were copied to new objects) 554 548 */ 555 - for (i = 0; i < obj_desc->method.param_count; i++) { 556 - acpi_ut_remove_reference(this_walk_state->operands[i]); 557 - this_walk_state->operands[i] = NULL; 558 - } 559 - 560 - /* Clear the operand stack */ 561 - 562 - this_walk_state->num_operands = 0; 549 + acpi_ds_clear_operands(this_walk_state); 563 550 564 551 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, 565 552 "**** Begin nested execution of [%4.4s] **** WalkState=%p\n",
+4
drivers/acpi/acpica/evglock.c
··· 42 42 return_ACPI_STATUS(AE_OK); 43 43 } 44 44 45 + if (!acpi_gbl_use_global_lock) { 46 + return_ACPI_STATUS(AE_OK); 47 + } 48 + 45 49 /* Attempt installation of the global lock handler */ 46 50 47 51 status = acpi_install_fixed_event_handler(ACPI_EVENT_GLOBAL,
+2 -2
drivers/acpi/acpica/psopinfo.c
··· 34 34 35 35 const struct acpi_opcode_info *acpi_ps_get_opcode_info(u16 opcode) 36 36 { 37 - #ifdef ACPI_DEBUG_OUTPUT 37 + #if defined ACPI_ASL_COMPILER && defined ACPI_DEBUG_OUTPUT 38 38 const char *opcode_name = "Unknown AML opcode"; 39 39 #endif 40 40 ··· 102 102 default: 103 103 break; 104 104 } 105 - #endif 106 105 107 106 /* Unknown AML opcode */ 108 107 109 108 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%s [%4.4X]\n", opcode_name, opcode)); 109 + #endif 110 110 111 111 return (&acpi_gbl_aml_op_info[_UNK]); 112 112 }
+8
drivers/acpi/acpica/tbprint.c
··· 121 121 ACPI_CAST_PTR(struct acpi_table_rsdp, 122 122 header)->revision, 123 123 local_header.oem_id)); 124 + } else if (acpi_gbl_CDAT && !acpi_ut_valid_nameseg(header->signature)) { 125 + 126 + /* CDAT does not use the common ACPI table header */ 127 + 128 + ACPI_INFO(("%-4.4s 0x%8.8X%8.8X %06X", 129 + ACPI_SIG_CDAT, ACPI_FORMAT_UINT64(address), 130 + ACPI_CAST_PTR(struct acpi_table_cdat, 131 + header)->length)); 124 132 } else { 125 133 /* Standard ACPI table with full common header */ 126 134
+42 -9
drivers/acpi/apei/einj-core.c
··· 656 656 return rc; 657 657 } 658 658 659 + /* Allow almost all types of address except MMIO. */ 660 + static bool is_allowed_range(u64 base_addr, u64 size) 661 + { 662 + int i; 663 + /* 664 + * MMIO region is usually claimed with IORESOURCE_MEM + IORES_DESC_NONE. 665 + * However, IORES_DESC_NONE is treated like a wildcard when we check if 666 + * region intersects with known resource. So do an allow list check for 667 + * IORES_DESCs that definitely or most likely not MMIO. 668 + */ 669 + int non_mmio_desc[] = { 670 + IORES_DESC_CRASH_KERNEL, 671 + IORES_DESC_ACPI_TABLES, 672 + IORES_DESC_ACPI_NV_STORAGE, 673 + IORES_DESC_PERSISTENT_MEMORY, 674 + IORES_DESC_PERSISTENT_MEMORY_LEGACY, 675 + /* Treat IORES_DESC_DEVICE_PRIVATE_MEMORY as MMIO. */ 676 + IORES_DESC_RESERVED, 677 + IORES_DESC_SOFT_RESERVED, 678 + }; 679 + 680 + if (region_intersects(base_addr, size, IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE) 681 + == REGION_INTERSECTS) 682 + return true; 683 + 684 + for (i = 0; i < ARRAY_SIZE(non_mmio_desc); ++i) { 685 + if (region_intersects(base_addr, size, IORESOURCE_MEM, non_mmio_desc[i]) 686 + == REGION_INTERSECTS) 687 + return true; 688 + } 689 + 690 + if (arch_is_platform_page(base_addr)) 691 + return true; 692 + 693 + return false; 694 + } 695 + 659 696 /* Inject the specified hardware error */ 660 697 int einj_error_inject(u32 type, u32 flags, u64 param1, u64 param2, u64 param3, 661 698 u64 param4) ··· 739 702 * Disallow crazy address masks that give BIOS leeway to pick 740 703 * injection address almost anywhere. Insist on page or 741 704 * better granularity and that target address is normal RAM or 742 - * NVDIMM. 705 + * as long as is not MMIO. 743 706 */ 744 707 base_addr = param1 & param2; 745 708 size = ~param2 + 1; 746 709 747 - if (((param2 & PAGE_MASK) != PAGE_MASK) || 748 - ((region_intersects(base_addr, size, IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE) 749 - != REGION_INTERSECTS) && 750 - (region_intersects(base_addr, size, IORESOURCE_MEM, IORES_DESC_PERSISTENT_MEMORY) 751 - != REGION_INTERSECTS) && 752 - (region_intersects(base_addr, size, IORESOURCE_MEM, IORES_DESC_SOFT_RESERVED) 753 - != REGION_INTERSECTS) && 754 - !arch_is_platform_page(base_addr))) 710 + if ((param2 & PAGE_MASK) != PAGE_MASK) 711 + return -EINVAL; 712 + 713 + if (!is_allowed_range(base_addr, size)) 755 714 return -EINVAL; 756 715 757 716 if (is_zero_pfn(base_addr >> PAGE_SHIFT))
+3 -5
drivers/acpi/apei/erst-dbg.c
··· 60 60 61 61 switch (cmd) { 62 62 case APEI_ERST_CLEAR_RECORD: 63 - rc = copy_from_user(&record_id, (void __user *)arg, 64 - sizeof(record_id)); 65 - if (rc) 63 + if (copy_from_user(&record_id, (void __user *)arg, 64 + sizeof(record_id))) 66 65 return -EFAULT; 67 66 return erst_clear(record_id); 68 67 case APEI_ERST_GET_RECORD_COUNT: ··· 174 175 erst_dbg_buf = p; 175 176 erst_dbg_buf_len = usize; 176 177 } 177 - rc = copy_from_user(erst_dbg_buf, ubuf, usize); 178 - if (rc) { 178 + if (copy_from_user(erst_dbg_buf, ubuf, usize)) { 179 179 rc = -EFAULT; 180 180 goto out; 181 181 }
+1 -1
drivers/acpi/device_sysfs.c
··· 464 464 465 465 buf[result++] = '\n'; 466 466 467 - kfree(str_obj); 467 + ACPI_FREE(str_obj); 468 468 469 469 return result; 470 470 }
+4 -14
drivers/acpi/fan_core.c
··· 203 203 * -------------------------------------------------------------------------- 204 204 */ 205 205 206 - static bool acpi_fan_has_fst(struct acpi_device *device) 207 - { 208 - return acpi_has_method(device->handle, "_FST"); 209 - } 210 - 211 - static bool acpi_fan_is_acpi4(struct acpi_device *device) 212 - { 213 - return acpi_has_method(device->handle, "_FIF") && 214 - acpi_has_method(device->handle, "_FPS") && 215 - acpi_has_method(device->handle, "_FSL"); 216 - } 217 - 218 206 static int acpi_fan_get_fif(struct acpi_device *device) 219 207 { 220 208 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; ··· 319 331 device->driver_data = fan; 320 332 platform_set_drvdata(pdev, fan); 321 333 322 - if (acpi_fan_has_fst(device)) { 334 + if (acpi_has_method(device->handle, "_FST")) { 323 335 fan->has_fst = true; 324 - fan->acpi4 = acpi_fan_is_acpi4(device); 336 + fan->acpi4 = acpi_has_method(device->handle, "_FIF") && 337 + acpi_has_method(device->handle, "_FPS") && 338 + acpi_has_method(device->handle, "_FSL"); 325 339 } 326 340 327 341 if (fan->acpi4) {
+1
drivers/acpi/internal.h
··· 140 140 /* -------------------------------------------------------------------------- 141 141 Power Resource 142 142 -------------------------------------------------------------------------- */ 143 + void acpi_power_resources_init(void); 143 144 void acpi_power_resources_list_free(struct list_head *list); 144 145 int acpi_extract_power_resources(union acpi_object *package, unsigned int start, 145 146 struct list_head *list);
+2 -1
drivers/acpi/pci_irq.c
··· 22 22 #include <linux/acpi.h> 23 23 #include <linux/slab.h> 24 24 #include <linux/interrupt.h> 25 + #include <linux/string_choices.h> 25 26 26 27 struct acpi_prt_entry { 27 28 struct acpi_pci_id id; ··· 469 468 dev_dbg(&dev->dev, "PCI INT %c%s -> GSI %u (%s, %s) -> IRQ %d\n", 470 469 pin_name(pin), link_desc, gsi, 471 470 (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge", 472 - (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq); 471 + str_low_high(polarity == ACPI_ACTIVE_LOW), dev->irq); 473 472 474 473 kfree(entry); 475 474 return 0;
+87 -3
drivers/acpi/power.c
··· 23 23 24 24 #define pr_fmt(fmt) "ACPI: PM: " fmt 25 25 26 + #include <linux/delay.h> 26 27 #include <linux/dmi.h> 27 28 #include <linux/kernel.h> 28 29 #include <linux/module.h> ··· 63 62 struct list_head node; 64 63 struct acpi_power_resource *resource; 65 64 }; 65 + 66 + static bool hp_eb_gp12pxp_quirk; 67 + static bool unused_power_resources_quirk; 66 68 67 69 static LIST_HEAD(acpi_power_resource_list); 68 70 static DEFINE_MUTEX(power_resource_list_lock); ··· 996 992 } 997 993 998 994 #ifdef CONFIG_ACPI_SLEEP 995 + static bool resource_is_gp12pxp(acpi_handle handle) 996 + { 997 + const char *path; 998 + bool ret; 999 + 1000 + path = acpi_handle_path(handle); 1001 + ret = path && strcmp(path, "\\_SB_.PCI0.GP12.PXP_") == 0; 1002 + kfree(path); 1003 + 1004 + return ret; 1005 + } 1006 + 1007 + static void acpi_resume_on_eb_gp12pxp(struct acpi_power_resource *resource) 1008 + { 1009 + acpi_handle_notice(resource->device.handle, 1010 + "HP EB quirk - turning OFF then ON\n"); 1011 + 1012 + __acpi_power_off(resource); 1013 + __acpi_power_on(resource); 1014 + 1015 + /* 1016 + * Use the same delay as DSDT uses in modem _RST method. 1017 + * 1018 + * Otherwise we get "Unable to change power state from unknown to D0, 1019 + * device inaccessible" error for the modem PCI device after thaw. 1020 + * 1021 + * This power resource is normally being enabled only during thaw (once) 1022 + * so this wait is not a performance issue. 1023 + */ 1024 + msleep(200); 1025 + } 1026 + 999 1027 void acpi_resume_power_resources(void) 1000 1028 { 1001 1029 struct acpi_power_resource *resource; ··· 1049 1013 1050 1014 if (state == ACPI_POWER_RESOURCE_STATE_OFF 1051 1015 && resource->ref_count) { 1052 - acpi_handle_debug(resource->device.handle, "Turning ON\n"); 1053 - __acpi_power_on(resource); 1016 + if (hp_eb_gp12pxp_quirk && 1017 + resource_is_gp12pxp(resource->device.handle)) { 1018 + acpi_resume_on_eb_gp12pxp(resource); 1019 + } else { 1020 + acpi_handle_debug(resource->device.handle, 1021 + "Turning ON\n"); 1022 + __acpi_power_on(resource); 1023 + } 1054 1024 } 1055 1025 1056 1026 mutex_unlock(&resource->resource_lock); ··· 1065 1023 mutex_unlock(&power_resource_list_lock); 1066 1024 } 1067 1025 #endif 1026 + 1027 + static const struct dmi_system_id dmi_hp_elitebook_gp12pxp_quirk[] = { 1028 + /* 1029 + * This laptop (and possibly similar models too) has power resource called 1030 + * "GP12.PXP_" for its WWAN modem. 1031 + * 1032 + * For this power resource to turn ON power for the modem it needs certain 1033 + * internal flag called "ONEN" to be set. 1034 + * This flag only gets set from this power resource "_OFF" method, while the 1035 + * actual modem power gets turned off during suspend by "GP12.PTS" method 1036 + * called from the global "_PTS" (Prepare To Sleep) method. 1037 + * On the other hand, this power resource "_OFF" method implementation just 1038 + * sets the aforementioned flag without actually doing anything else (it 1039 + * doesn't contain any code to actually turn off power). 1040 + * 1041 + * The above means that when upon hibernation finish we try to set this 1042 + * power resource back ON since its "_STA" method returns 0 (while the resource 1043 + * is still considered in use) its "_ON" method won't do anything since 1044 + * that "ONEN" flag is not set. 1045 + * Overall, this means the modem is dead until laptop is rebooted since its 1046 + * power has been cut by "_PTS" and its PCI configuration was lost and not able 1047 + * to be restored. 1048 + * 1049 + * The easiest way to workaround the issue is to call this power resource 1050 + * "_OFF" method before calling the "_ON" method to make sure the "ONEN" 1051 + * flag gets properly set. 1052 + */ 1053 + { 1054 + .matches = { 1055 + DMI_MATCH(DMI_SYS_VENDOR, "HP"), 1056 + DMI_MATCH(DMI_PRODUCT_NAME, "HP EliteBook 855 G7 Notebook PC"), 1057 + }, 1058 + }, 1059 + {} 1060 + }; 1068 1061 1069 1062 static const struct dmi_system_id dmi_leave_unused_power_resources_on[] = { 1070 1063 { ··· 1123 1046 { 1124 1047 struct acpi_power_resource *resource; 1125 1048 1126 - if (dmi_check_system(dmi_leave_unused_power_resources_on)) 1049 + if (unused_power_resources_quirk) 1127 1050 return; 1128 1051 1129 1052 mutex_lock(&power_resource_list_lock); ··· 1141 1064 } 1142 1065 1143 1066 mutex_unlock(&power_resource_list_lock); 1067 + } 1068 + 1069 + void __init acpi_power_resources_init(void) 1070 + { 1071 + hp_eb_gp12pxp_quirk = dmi_check_system(dmi_hp_elitebook_gp12pxp_quirk); 1072 + unused_power_resources_quirk = 1073 + dmi_check_system(dmi_leave_unused_power_resources_on); 1144 1074 }
+16 -3
drivers/acpi/prmt.c
··· 150 150 th = &tm->handlers[cur_handler]; 151 151 152 152 guid_copy(&th->guid, (guid_t *)handler_info->handler_guid); 153 + 154 + /* 155 + * Print an error message if handler_address is NULL, the parse of VA also 156 + * can be skipped. 157 + */ 158 + if (unlikely(!handler_info->handler_address)) { 159 + pr_info("Skipping handler with NULL address for GUID: %pUL", 160 + (guid_t *)handler_info->handler_guid); 161 + continue; 162 + } 163 + 153 164 th->handler_addr = 154 165 (void *)efi_pa_va_lookup(&th->guid, handler_info->handler_address); 155 166 /* 156 - * Print a warning message if handler_addr is zero which is not expected to 157 - * ever happen. 167 + * Print a warning message and skip the parse of VA if handler_addr is zero 168 + * which is not expected to ever happen. 158 169 */ 159 - if (unlikely(!th->handler_addr)) 170 + if (unlikely(!th->handler_addr)) { 160 171 pr_warn("Failed to find VA of handler for GUID: %pUL, PA: 0x%llx", 161 172 &th->guid, handler_info->handler_address); 173 + continue; 174 + } 162 175 163 176 th->static_data_buffer_addr = 164 177 efi_pa_va_lookup(&th->guid, handler_info->static_data_buffer_address);
+4 -2
drivers/acpi/processor_driver.c
··· 166 166 if (result && !IS_ENABLED(CONFIG_ACPI_CPU_FREQ_PSS)) 167 167 dev_dbg(&device->dev, "CPPC data invalid or not present\n"); 168 168 169 - if (!cpuidle_get_driver() || cpuidle_get_driver() == &acpi_idle_driver) 170 - acpi_processor_power_init(pr); 169 + acpi_processor_power_init(pr); 171 170 172 171 acpi_pss_perf_init(pr); 173 172 ··· 262 263 if (result < 0) 263 264 return result; 264 265 266 + acpi_processor_register_idle_driver(); 267 + 265 268 result = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN, 266 269 "acpi/cpu-drv:online", 267 270 acpi_soft_cpu_online, NULL); ··· 302 301 303 302 cpuhp_remove_state_nocalls(hp_online); 304 303 cpuhp_remove_state_nocalls(CPUHP_ACPI_CPUDRV_DEAD); 304 + acpi_processor_unregister_idle_driver(); 305 305 driver_unregister(&acpi_processor_driver); 306 306 } 307 307
+84 -59
drivers/acpi/processor_idle.c
··· 51 51 52 52 static DEFINE_PER_CPU(struct cpuidle_device *, acpi_cpuidle_device); 53 53 54 - struct cpuidle_driver acpi_idle_driver = { 54 + static struct cpuidle_driver acpi_idle_driver = { 55 55 .name = "acpi_idle", 56 56 .owner = THIS_MODULE, 57 57 }; ··· 998 998 return ret; 999 999 } 1000 1000 1001 - /* 1002 - * flat_state_cnt - the number of composite LPI states after the process of flattening 1003 - */ 1004 - static int flat_state_cnt; 1005 - 1006 1001 /** 1007 1002 * combine_lpi_states - combine local and parent LPI states to form a composite LPI state 1008 1003 * ··· 1040 1045 curr_level->composite_states[curr_level->composite_states_size++] = t; 1041 1046 } 1042 1047 1043 - static int flatten_lpi_states(struct acpi_processor *pr, 1044 - struct acpi_lpi_states_array *curr_level, 1045 - struct acpi_lpi_states_array *prev_level) 1048 + static unsigned int flatten_lpi_states(struct acpi_processor *pr, 1049 + unsigned int flat_state_cnt, 1050 + struct acpi_lpi_states_array *curr_level, 1051 + struct acpi_lpi_states_array *prev_level) 1046 1052 { 1047 1053 int i, j, state_count = curr_level->size; 1048 1054 struct acpi_lpi_state *p, *t = curr_level->entries; ··· 1083 1087 } 1084 1088 1085 1089 kfree(curr_level->entries); 1086 - return 0; 1090 + return flat_state_cnt; 1087 1091 } 1088 1092 1089 1093 int __weak acpi_processor_ffh_lpi_probe(unsigned int cpu) ··· 1098 1102 acpi_handle handle = pr->handle, pr_ahandle; 1099 1103 struct acpi_device *d = NULL; 1100 1104 struct acpi_lpi_states_array info[2], *tmp, *prev, *curr; 1105 + unsigned int state_count; 1101 1106 1102 1107 /* make sure our architecture has support */ 1103 1108 ret = acpi_processor_ffh_lpi_probe(pr->id); ··· 1111 1114 if (!acpi_has_method(handle, "_LPI")) 1112 1115 return -EINVAL; 1113 1116 1114 - flat_state_cnt = 0; 1115 1117 prev = &info[0]; 1116 1118 curr = &info[1]; 1117 1119 handle = pr->handle; 1118 1120 ret = acpi_processor_evaluate_lpi(handle, prev); 1119 1121 if (ret) 1120 1122 return ret; 1121 - flatten_lpi_states(pr, prev, NULL); 1123 + state_count = flatten_lpi_states(pr, 0, prev, NULL); 1122 1124 1123 1125 status = acpi_get_parent(handle, &pr_ahandle); 1124 1126 while (ACPI_SUCCESS(status)) { ··· 1139 1143 break; 1140 1144 1141 1145 /* flatten all the LPI states in this level of hierarchy */ 1142 - flatten_lpi_states(pr, curr, prev); 1146 + state_count = flatten_lpi_states(pr, state_count, curr, prev); 1143 1147 1144 1148 tmp = prev, prev = curr, curr = tmp; 1145 1149 1146 1150 status = acpi_get_parent(handle, &pr_ahandle); 1147 1151 } 1148 1152 1149 - pr->power.count = flat_state_cnt; 1150 1153 /* reset the index after flattening */ 1151 - for (i = 0; i < pr->power.count; i++) 1154 + for (i = 0; i < state_count; i++) 1152 1155 pr->power.lpi_states[i].index = i; 1156 + 1157 + pr->power.count = state_count; 1153 1158 1154 1159 /* Tell driver that _LPI is supported. */ 1155 1160 pr->flags.has_lpi = 1; ··· 1357 1360 return 0; 1358 1361 } 1359 1362 1360 - static int acpi_processor_registered; 1361 - 1362 - int acpi_processor_power_init(struct acpi_processor *pr) 1363 + void acpi_processor_register_idle_driver(void) 1363 1364 { 1364 - int retval; 1365 + struct acpi_processor *pr; 1366 + int ret = -ENODEV; 1367 + int cpu; 1368 + 1369 + /* 1370 + * Acpi idle driver is used by all possible CPUs. 1371 + * Install the idle handler by the processor power info of one in them. 1372 + * Note that we use previously set idle handler will be used on 1373 + * platforms that only support C1. 1374 + */ 1375 + for_each_cpu(cpu, (struct cpumask *)cpu_possible_mask) { 1376 + pr = per_cpu(processors, cpu); 1377 + if (!pr) 1378 + continue; 1379 + 1380 + ret = acpi_processor_get_power_info(pr); 1381 + if (!ret) { 1382 + pr->flags.power_setup_done = 1; 1383 + acpi_processor_setup_cpuidle_states(pr); 1384 + break; 1385 + } 1386 + } 1387 + 1388 + if (ret) { 1389 + pr_debug("No ACPI power information from any CPUs.\n"); 1390 + return; 1391 + } 1392 + 1393 + ret = cpuidle_register_driver(&acpi_idle_driver); 1394 + if (ret) { 1395 + pr_debug("register %s failed.\n", acpi_idle_driver.name); 1396 + return; 1397 + } 1398 + pr_debug("%s registered with cpuidle.\n", acpi_idle_driver.name); 1399 + } 1400 + 1401 + void acpi_processor_unregister_idle_driver(void) 1402 + { 1403 + cpuidle_unregister_driver(&acpi_idle_driver); 1404 + } 1405 + 1406 + void acpi_processor_power_init(struct acpi_processor *pr) 1407 + { 1365 1408 struct cpuidle_device *dev; 1366 1409 1410 + /* 1411 + * The code below only works if the current cpuidle driver is the ACPI 1412 + * idle driver. 1413 + */ 1414 + if (cpuidle_get_driver() != &acpi_idle_driver) 1415 + return; 1416 + 1367 1417 if (disabled_by_idle_boot_param()) 1368 - return 0; 1418 + return; 1369 1419 1370 1420 acpi_processor_cstate_first_run_checks(); 1371 1421 1372 1422 if (!acpi_processor_get_power_info(pr)) 1373 1423 pr->flags.power_setup_done = 1; 1374 1424 1425 + if (!pr->flags.power) 1426 + return; 1427 + 1428 + dev = kzalloc(sizeof(*dev), GFP_KERNEL); 1429 + if (!dev) 1430 + return; 1431 + 1432 + per_cpu(acpi_cpuidle_device, pr->id) = dev; 1433 + 1434 + acpi_processor_setup_cpuidle_dev(pr, dev); 1435 + 1375 1436 /* 1376 - * Install the idle handler if processor power management is supported. 1377 - * Note that we use previously set idle handler will be used on 1378 - * platforms that only support C1. 1437 + * Register a cpuidle device for this CPU. The cpuidle driver using 1438 + * this device is expected to be registered. 1379 1439 */ 1380 - if (pr->flags.power) { 1381 - /* Register acpi_idle_driver if not already registered */ 1382 - if (!acpi_processor_registered) { 1383 - acpi_processor_setup_cpuidle_states(pr); 1384 - retval = cpuidle_register_driver(&acpi_idle_driver); 1385 - if (retval) 1386 - return retval; 1387 - pr_debug("%s registered with cpuidle\n", 1388 - acpi_idle_driver.name); 1389 - } 1390 - 1391 - dev = kzalloc(sizeof(*dev), GFP_KERNEL); 1392 - if (!dev) 1393 - return -ENOMEM; 1394 - per_cpu(acpi_cpuidle_device, pr->id) = dev; 1395 - 1396 - acpi_processor_setup_cpuidle_dev(pr, dev); 1397 - 1398 - /* Register per-cpu cpuidle_device. Cpuidle driver 1399 - * must already be registered before registering device 1400 - */ 1401 - retval = cpuidle_register_device(dev); 1402 - if (retval) { 1403 - if (acpi_processor_registered == 0) 1404 - cpuidle_unregister_driver(&acpi_idle_driver); 1405 - return retval; 1406 - } 1407 - acpi_processor_registered++; 1440 + if (cpuidle_register_device(dev)) { 1441 + per_cpu(acpi_cpuidle_device, pr->id) = NULL; 1442 + kfree(dev); 1408 1443 } 1409 - return 0; 1410 1444 } 1411 1445 1412 - int acpi_processor_power_exit(struct acpi_processor *pr) 1446 + void acpi_processor_power_exit(struct acpi_processor *pr) 1413 1447 { 1414 1448 struct cpuidle_device *dev = per_cpu(acpi_cpuidle_device, pr->id); 1415 1449 1416 1450 if (disabled_by_idle_boot_param()) 1417 - return 0; 1451 + return; 1418 1452 1419 1453 if (pr->flags.power) { 1420 1454 cpuidle_unregister_device(dev); 1421 - acpi_processor_registered--; 1422 - if (acpi_processor_registered == 0) 1423 - cpuidle_unregister_driver(&acpi_idle_driver); 1424 - 1425 1455 kfree(dev); 1426 1456 } 1427 1457 1428 1458 pr->flags.power_setup_done = 0; 1429 - return 0; 1430 1459 } 1460 + 1461 + MODULE_IMPORT_NS("ACPI_PROCESSOR_IDLE");
+27 -25
drivers/acpi/processor_thermal.c
··· 62 62 return 0; 63 63 } 64 64 65 - static int cpu_has_cpufreq(unsigned int cpu) 65 + static bool cpu_has_cpufreq(unsigned int cpu) 66 66 { 67 - struct cpufreq_policy *policy; 68 - 69 67 if (!acpi_processor_cpufreq_init) 70 68 return 0; 71 69 72 - policy = cpufreq_cpu_get(cpu); 73 - if (policy) { 74 - cpufreq_cpu_put(policy); 75 - return 1; 76 - } 77 - return 0; 70 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu); 71 + 72 + return policy != NULL; 78 73 } 79 74 80 75 static int cpufreq_get_max_state(unsigned int cpu) ··· 88 93 return reduction_step(cpu); 89 94 } 90 95 96 + static bool cpufreq_update_thermal_limit(unsigned int cpu, struct acpi_processor *pr) 97 + { 98 + unsigned long max_freq; 99 + int ret; 100 + 101 + struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu); 102 + if (!policy) 103 + return false; 104 + 105 + max_freq = (policy->cpuinfo.max_freq * 106 + (100 - reduction_step(cpu) * cpufreq_thermal_reduction_pctg)) / 100; 107 + 108 + ret = freq_qos_update_request(&pr->thermal_req, max_freq); 109 + if (ret < 0) { 110 + pr_warn("Failed to update thermal freq constraint: CPU%d (%d)\n", 111 + pr->id, ret); 112 + } 113 + 114 + return true; 115 + } 116 + 91 117 static int cpufreq_set_cur_state(unsigned int cpu, int state) 92 118 { 93 - struct cpufreq_policy *policy; 94 119 struct acpi_processor *pr; 95 - unsigned long max_freq; 96 - int i, ret; 120 + int i; 97 121 98 122 if (!cpu_has_cpufreq(cpu)) 99 123 return 0; ··· 134 120 if (unlikely(!freq_qos_request_active(&pr->thermal_req))) 135 121 continue; 136 122 137 - policy = cpufreq_cpu_get(i); 138 - if (!policy) 123 + if (!cpufreq_update_thermal_limit(i, pr)) 139 124 return -EINVAL; 140 - 141 - max_freq = (policy->cpuinfo.max_freq * 142 - (100 - reduction_step(i) * cpufreq_thermal_reduction_pctg)) / 100; 143 - 144 - cpufreq_cpu_put(policy); 145 - 146 - ret = freq_qos_update_request(&pr->thermal_req, max_freq); 147 - if (ret < 0) { 148 - pr_warn("Failed to update thermal freq constraint: CPU%d (%d)\n", 149 - pr->id, ret); 150 - } 151 125 } 152 126 return 0; 153 127 }
+98 -58
drivers/acpi/property.c
··· 83 83 struct fwnode_handle *parent) 84 84 { 85 85 struct acpi_data_node *dn; 86 + acpi_handle scope = NULL; 86 87 bool result; 87 88 88 89 if (acpi_graph_ignore_port(handle)) ··· 99 98 INIT_LIST_HEAD(&dn->data.properties); 100 99 INIT_LIST_HEAD(&dn->data.subnodes); 101 100 102 - result = acpi_extract_properties(handle, desc, &dn->data); 101 + /* 102 + * The scope for the completion of relative pathname segments and 103 + * subnode object lookup is the one of the namespace node (device) 104 + * containing the object that has returned the package. That is, it's 105 + * the scope of that object's parent device. 106 + */ 107 + if (handle) 108 + acpi_get_parent(handle, &scope); 103 109 104 - if (handle) { 105 - acpi_handle scope; 106 - acpi_status status; 107 - 108 - /* 109 - * The scope for the subnode object lookup is the one of the 110 - * namespace node (device) containing the object that has 111 - * returned the package. That is, it's the scope of that 112 - * object's parent. 113 - */ 114 - status = acpi_get_parent(handle, &scope); 115 - if (ACPI_SUCCESS(status) 116 - && acpi_enumerate_nondev_subnodes(scope, desc, &dn->data, 117 - &dn->fwnode)) 118 - result = true; 119 - } else if (acpi_enumerate_nondev_subnodes(NULL, desc, &dn->data, 120 - &dn->fwnode)) { 110 + /* 111 + * Extract properties from the _DSD-equivalent package pointed to by 112 + * desc and use scope (if not NULL) for the completion of relative 113 + * pathname segments. 114 + * 115 + * The extracted properties will be held in the new data node dn. 116 + */ 117 + result = acpi_extract_properties(scope, desc, &dn->data); 118 + /* 119 + * Look for subnodes in the _DSD-equivalent package pointed to by desc 120 + * and create child nodes of dn if there are any. 121 + */ 122 + if (acpi_enumerate_nondev_subnodes(scope, desc, &dn->data, &dn->fwnode)) 121 123 result = true; 124 + 125 + if (!result) { 126 + kfree(dn); 127 + acpi_handle_debug(handle, "Invalid properties/subnodes data, skipping\n"); 128 + return false; 122 129 } 123 130 124 - if (result) { 125 - dn->handle = handle; 126 - dn->data.pointer = desc; 127 - list_add_tail(&dn->sibling, list); 128 - return true; 129 - } 131 + /* 132 + * This will be NULL if the desc package is embedded in an outer 133 + * _DSD-equivalent package and its scope cannot be determined. 134 + */ 135 + dn->handle = handle; 136 + dn->data.pointer = desc; 137 + list_add_tail(&dn->sibling, list); 130 138 131 - kfree(dn); 132 - acpi_handle_debug(handle, "Invalid properties/subnodes data, skipping\n"); 133 - return false; 139 + return true; 134 140 } 135 141 136 - static bool acpi_nondev_subnode_data_ok(acpi_handle handle, 137 - const union acpi_object *link, 138 - struct list_head *list, 139 - struct fwnode_handle *parent) 142 + static bool acpi_nondev_subnode_ok(acpi_handle scope, 143 + const union acpi_object *link, 144 + struct list_head *list, 145 + struct fwnode_handle *parent) 140 146 { 141 147 struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER }; 148 + acpi_handle handle; 142 149 acpi_status status; 150 + 151 + /* 152 + * If the scope is unknown, the _DSD-equivalent package being parsed 153 + * was embedded in an outer _DSD-equivalent package as a result of 154 + * direct evaluation of an object pointed to by a reference. In that 155 + * case, using a pathname as the target object pointer is invalid. 156 + */ 157 + if (!scope) 158 + return false; 159 + 160 + status = acpi_get_handle(scope, link->package.elements[1].string.pointer, 161 + &handle); 162 + if (ACPI_FAILURE(status)) 163 + return false; 143 164 144 165 status = acpi_evaluate_object_typed(handle, NULL, NULL, &buf, 145 166 ACPI_TYPE_PACKAGE); ··· 176 153 return false; 177 154 } 178 155 179 - static bool acpi_nondev_subnode_ok(acpi_handle scope, 180 - const union acpi_object *link, 181 - struct list_head *list, 182 - struct fwnode_handle *parent) 183 - { 184 - acpi_handle handle; 185 - acpi_status status; 186 - 187 - if (!scope) 188 - return false; 189 - 190 - status = acpi_get_handle(scope, link->package.elements[1].string.pointer, 191 - &handle); 192 - if (ACPI_FAILURE(status)) 193 - return false; 194 - 195 - return acpi_nondev_subnode_data_ok(handle, link, list, parent); 196 - } 197 - 198 156 static bool acpi_add_nondev_subnodes(acpi_handle scope, 199 157 union acpi_object *links, 200 158 struct list_head *list, ··· 184 180 bool ret = false; 185 181 int i; 186 182 183 + /* 184 + * Every element in the links package is expected to represent a link 185 + * to a non-device node in a tree containing device-specific data. 186 + */ 187 187 for (i = 0; i < links->package.count; i++) { 188 188 union acpi_object *link, *desc; 189 - acpi_handle handle; 190 189 bool result; 191 190 192 191 link = &links->package.elements[i]; ··· 197 190 if (link->package.count != 2) 198 191 continue; 199 192 200 - /* The first one must be a string. */ 193 + /* The first one (the key) must be a string. */ 201 194 if (link->package.elements[0].type != ACPI_TYPE_STRING) 202 195 continue; 203 196 204 - /* The second one may be a string, a reference or a package. */ 197 + /* The second one (the target) may be a string or a package. */ 205 198 switch (link->package.elements[1].type) { 206 199 case ACPI_TYPE_STRING: 200 + /* 201 + * The string is expected to be a full pathname or a 202 + * pathname segment relative to the given scope. That 203 + * pathname is expected to point to an object returning 204 + * a package that contains _DSD-equivalent information. 205 + */ 207 206 result = acpi_nondev_subnode_ok(scope, link, list, 208 207 parent); 209 208 break; 210 - case ACPI_TYPE_LOCAL_REFERENCE: 211 - handle = link->package.elements[1].reference.handle; 212 - result = acpi_nondev_subnode_data_ok(handle, link, list, 213 - parent); 214 - break; 215 209 case ACPI_TYPE_PACKAGE: 210 + /* 211 + * This happens when a reference is used in AML to 212 + * point to the target. Since the target is expected 213 + * to be a named object, a reference to it will cause it 214 + * to be avaluated in place and its return package will 215 + * be embedded in the links package at the location of 216 + * the reference. 217 + * 218 + * The target package is expected to contain _DSD- 219 + * equivalent information, but the scope in which it 220 + * is located in the original AML is unknown. Thus 221 + * it cannot contain pathname segments represented as 222 + * strings because there is no way to build full 223 + * pathnames out of them. 224 + */ 225 + acpi_handle_debug(scope, "subnode %s: Unknown scope\n", 226 + link->package.elements[0].string.pointer); 216 227 desc = &link->package.elements[1]; 217 228 result = acpi_nondev_subnode_extract(desc, NULL, link, 218 229 list, parent); 219 230 break; 231 + case ACPI_TYPE_LOCAL_REFERENCE: 232 + /* 233 + * It is not expected to see any local references in 234 + * the links package because referencing a named object 235 + * should cause it to be evaluated in place. 236 + */ 237 + acpi_handle_info(scope, "subnode %s: Unexpected reference\n", 238 + link->package.elements[0].string.pointer); 239 + fallthrough; 220 240 default: 221 241 result = false; 222 242 break; ··· 403 369 struct acpi_data_node *dn; 404 370 405 371 list_for_each_entry(dn, &data->subnodes, sibling) { 372 + if (!dn->handle) 373 + continue; 374 + 406 375 acpi_detach_data(dn->handle, acpi_nondev_subnode_tag); 407 376 408 377 acpi_untie_nondev_subnodes(&dn->data); ··· 419 382 list_for_each_entry(dn, &data->subnodes, sibling) { 420 383 acpi_status status; 421 384 bool ret; 385 + 386 + if (!dn->handle) 387 + continue; 422 388 423 389 status = acpi_attach_data(dn->handle, acpi_nondev_subnode_tag, dn); 424 390 if (ACPI_FAILURE(status) && status != AE_ALREADY_EXISTS) {
+9 -1
drivers/acpi/resource.c
··· 17 17 #include <linux/slab.h> 18 18 #include <linux/irq.h> 19 19 #include <linux/dmi.h> 20 + #include <linux/string_choices.h> 20 21 21 22 #ifdef CONFIG_X86 22 23 #define valid_IRQ(i) (((i) != 0) && ((i) != 2)) ··· 512 511 }, 513 512 }, 514 513 { 514 + /* Asus Vivobook Pro N6506CU* */ 515 + .matches = { 516 + DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), 517 + DMI_MATCH(DMI_BOARD_NAME, "N6506CU"), 518 + }, 519 + }, 520 + { 515 521 /* LG Electronics 17U70P */ 516 522 .matches = { 517 523 DMI_MATCH(DMI_SYS_VENDOR, "LG Electronics"), ··· 781 773 pr_warn("ACPI: IRQ %d override to %s%s, %s%s\n", gsi, 782 774 t ? "level" : "edge", 783 775 trig == triggering ? "" : "(!)", 784 - p ? "low" : "high", 776 + str_low_high(p), 785 777 pol == polarity ? "" : "(!)"); 786 778 triggering = trig; 787 779 polarity = pol;
+3
drivers/acpi/scan.c
··· 845 845 static const char * const acpi_ignore_dep_ids[] = { 846 846 "PNP0D80", /* Windows-compatible System Power Management Controller */ 847 847 "INT33BD", /* Intel Baytrail Mailbox Device */ 848 + "INTC10DE", /* Intel CVS LNL */ 849 + "INTC10E0", /* Intel CVS ARL */ 848 850 "LATT2021", /* Lattice FW Update Client Driver */ 849 851 NULL 850 852 }; ··· 2704 2702 acpi_memory_hotplug_init(); 2705 2703 acpi_watchdog_init(); 2706 2704 acpi_pnp_init(); 2705 + acpi_power_resources_init(); 2707 2706 acpi_int340x_thermal_init(); 2708 2707 acpi_init_lpit(); 2709 2708
+12 -1
drivers/acpi/spcr.c
··· 141 141 case ACPI_DBG2_16550_NVIDIA: 142 142 uart = "uart"; 143 143 break; 144 + case ACPI_DBG2_RISCV_SBI_CON: 145 + uart = "sbi"; 146 + break; 144 147 default: 145 148 err = -ENOENT; 146 149 goto done; 147 150 } 148 151 149 - switch (table->baud_rate) { 152 + /* 153 + * SPCR 1.09 defines Precise Baud Rate Filed contains a specific 154 + * non-zero baud rate which overrides the value of the Configured 155 + * Baud Rate field. If this field is zero or not present, Configured 156 + * Baud Rate is used. 157 + */ 158 + if (table->precise_baudrate) 159 + baud_rate = table->precise_baudrate; 160 + else switch (table->baud_rate) { 150 161 case 0: 151 162 /* 152 163 * SPCR 1.04 defines 0 as a preconfigured state of UART.
+1 -1
drivers/acpi/tables.c
··· 408 408 ACPI_SIG_PSDT, ACPI_SIG_RSDT, ACPI_SIG_XSDT, ACPI_SIG_SSDT, 409 409 ACPI_SIG_IORT, ACPI_SIG_NFIT, ACPI_SIG_HMAT, ACPI_SIG_PPTT, 410 410 ACPI_SIG_NHLT, ACPI_SIG_AEST, ACPI_SIG_CEDT, ACPI_SIG_AGDI, 411 - ACPI_SIG_NBFT }; 411 + ACPI_SIG_NBFT, ACPI_SIG_SWFT}; 412 412 413 413 #define ACPI_HEADER_SIZE sizeof(struct acpi_table_header) 414 414
+3 -5
drivers/acpi/thermal.c
··· 924 924 static int acpi_thermal_resume(struct device *dev) 925 925 { 926 926 struct acpi_thermal *tz; 927 - int i, j, power_state; 927 + int i, j; 928 928 929 929 if (!dev) 930 930 return -EINVAL; ··· 939 939 if (!acpi_thermal_trip_valid(acpi_trip)) 940 940 break; 941 941 942 - for (j = 0; j < acpi_trip->devices.count; j++) { 943 - acpi_bus_update_power(acpi_trip->devices.handles[j], 944 - &power_state); 945 - } 942 + for (j = 0; j < acpi_trip->devices.count; j++) 943 + acpi_bus_update_power(acpi_trip->devices.handles[j], NULL); 946 944 } 947 945 948 946 acpi_queue_thermal_check(tz);
+8
drivers/acpi/video_detect.c
··· 948 948 DMI_MATCH(DMI_PRODUCT_NAME, "Mipad2"), 949 949 }, 950 950 }, 951 + /* https://gitlab.freedesktop.org/drm/amd/-/issues/4512 */ 952 + { 953 + .callback = video_detect_force_native, 954 + .matches = { 955 + DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), 956 + DMI_MATCH(DMI_PRODUCT_NAME, "82K8"), 957 + }, 958 + }, 951 959 { }, 952 960 }; 953 961
+2 -1
drivers/pnp/isapnp/core.c
··· 27 27 #include <linux/init.h> 28 28 #include <linux/isapnp.h> 29 29 #include <linux/mutex.h> 30 + #include <linux/string_choices.h> 30 31 #include <asm/io.h> 31 32 32 33 #include "../base.h" ··· 1038 1037 if (cards) 1039 1038 printk(KERN_INFO 1040 1039 "isapnp: %i Plug & Play card%s detected total\n", cards, 1041 - cards > 1 ? "s" : ""); 1040 + str_plural(cards)); 1042 1041 else 1043 1042 printk(KERN_INFO "isapnp: No Plug & Play card found\n"); 1044 1043
+8 -2
include/acpi/acexcep.h
··· 173 173 #define AE_AML_TARGET_TYPE EXCEP_AML (0x0023) 174 174 #define AE_AML_PROTOCOL EXCEP_AML (0x0024) 175 175 #define AE_AML_BUFFER_LENGTH EXCEP_AML (0x0025) 176 + #define AE_AML_TOO_FEW_ARGUMENTS EXCEP_AML (0x0026) 177 + #define AE_AML_TOO_MANY_ARGUMENTS EXCEP_AML (0x0027) 176 178 177 - #define AE_CODE_AML_MAX 0x0025 179 + #define AE_CODE_AML_MAX 0x0027 178 180 179 181 /* 180 182 * Internal exceptions used for control ··· 355 353 "A target operand of an incorrect type was encountered"), 356 354 EXCEP_TXT("AE_AML_PROTOCOL", "Violation of a fixed ACPI protocol"), 357 355 EXCEP_TXT("AE_AML_BUFFER_LENGTH", 358 - "The length of the buffer is invalid/incorrect") 356 + "The length of the buffer is invalid/incorrect"), 357 + EXCEP_TXT("AE_AML_TOO_FEW_ARGUMENTS", 358 + "There are fewer than expected method arguments"), 359 + EXCEP_TXT("AE_AML_TOO_MANY_ARGUMENTS", 360 + "There are too many arguments for this method") 359 361 }; 360 362 361 363 static const struct acpi_exception_info acpi_gbl_exception_names_ctrl[] = {
+7 -1
include/acpi/acpixf.h
··· 12 12 13 13 /* Current ACPICA subsystem version in YYYYMMDD format */ 14 14 15 - #define ACPI_CA_VERSION 0x20250404 15 + #define ACPI_CA_VERSION 0x20250807 16 16 17 17 #include <acpi/acconfig.h> 18 18 #include <acpi/actypes.h> ··· 212 212 * a reduced HW machine, and that flag is duplicated here for convenience. 213 213 */ 214 214 ACPI_INIT_GLOBAL(u8, acpi_gbl_reduced_hardware, FALSE); 215 + 216 + /* 217 + * ACPI Global Lock is mainly used for systems with SMM, so no-SMM systems 218 + * (such as loong_arch) may not have and not use Global Lock. 219 + */ 220 + ACPI_INIT_GLOBAL(u8, acpi_gbl_use_global_lock, TRUE); 215 221 216 222 /* 217 223 * Maximum timeout for While() loop iterations before forced method abort.
+1 -1
include/acpi/actbl.h
··· 73 73 char oem_id[ACPI_OEM_ID_SIZE] ACPI_NONSTRING; /* ASCII OEM identification */ 74 74 char oem_table_id[ACPI_OEM_TABLE_ID_SIZE] ACPI_NONSTRING; /* ASCII OEM table identification */ 75 75 u32 oem_revision; /* OEM revision number */ 76 - char asl_compiler_id[ACPI_NAMESEG_SIZE]; /* ASCII ASL compiler vendor ID */ 76 + char asl_compiler_id[ACPI_NAMESEG_SIZE] ACPI_NONSTRING; /* ASCII ASL compiler vendor ID */ 77 77 u32 asl_compiler_revision; /* ASL compiler version */ 78 78 }; 79 79
+1
include/acpi/actbl1.h
··· 565 565 #define ACPI_CEDT_CFMWS_RESTRICT_VOLATILE (1<<2) 566 566 #define ACPI_CEDT_CFMWS_RESTRICT_PMEM (1<<3) 567 567 #define ACPI_CEDT_CFMWS_RESTRICT_FIXED (1<<4) 568 + #define ACPI_CEDT_CFMWS_RESTRICT_BI (1<<5) 568 569 569 570 /* 2: CXL XOR Interleave Math Structure */ 570 571
+21
include/acpi/actbl2.h
··· 57 57 #define ACPI_SIG_SDEI "SDEI" /* Software Delegated Exception Interface Table */ 58 58 #define ACPI_SIG_SDEV "SDEV" /* Secure Devices table */ 59 59 #define ACPI_SIG_SVKL "SVKL" /* Storage Volume Key Location Table */ 60 + #define ACPI_SIG_SWFT "SWFT" /* SoundWire File Table */ 60 61 #define ACPI_SIG_TDEL "TDEL" /* TD Event Log Table */ 61 62 62 63 /* ··· 3477 3476 enum acpi_svkl_format { 3478 3477 ACPI_SVKL_FORMAT_RAW_BINARY = 0, 3479 3478 ACPI_SVKL_FORMAT_RESERVED = 1 /* 1 and greater are reserved */ 3479 + }; 3480 + 3481 + /******************************************************************************* 3482 + * SWFT - SoundWire File Table 3483 + * 3484 + * Conforms to "Discovery and Configuration (DisCo) Specification for SoundWire" 3485 + * Version 2.1, 2 October 2023 3486 + * 3487 + ******************************************************************************/ 3488 + struct acpi_sw_file { 3489 + u16 vendor_id; 3490 + u32 file_id; 3491 + u16 file_version; 3492 + u32 file_length; 3493 + u8 data[]; 3494 + }; 3495 + 3496 + struct acpi_table_swft { 3497 + struct acpi_table_header header; 3498 + struct acpi_sw_file files[]; 3480 3499 }; 3481 3500 3482 3501 /*******************************************************************************
+6 -28
include/acpi/processor.h
··· 417 417 #endif /* CONFIG_ACPI_CPU_FREQ_PSS */ 418 418 419 419 /* in processor_idle.c */ 420 - extern struct cpuidle_driver acpi_idle_driver; 421 420 #ifdef CONFIG_ACPI_PROCESSOR_IDLE 422 - int acpi_processor_power_init(struct acpi_processor *pr); 423 - int acpi_processor_power_exit(struct acpi_processor *pr); 421 + void acpi_processor_power_init(struct acpi_processor *pr); 422 + void acpi_processor_power_exit(struct acpi_processor *pr); 424 423 int acpi_processor_power_state_has_changed(struct acpi_processor *pr); 425 424 int acpi_processor_hotplug(struct acpi_processor *pr); 426 - #else 427 - static inline int acpi_processor_power_init(struct acpi_processor *pr) 428 - { 429 - return -ENODEV; 430 - } 431 - 432 - static inline int acpi_processor_power_exit(struct acpi_processor *pr) 433 - { 434 - return -ENODEV; 435 - } 436 - 437 - static inline int acpi_processor_power_state_has_changed(struct acpi_processor *pr) 438 - { 439 - return -ENODEV; 440 - } 441 - 442 - static inline int acpi_processor_hotplug(struct acpi_processor *pr) 443 - { 444 - return -ENODEV; 445 - } 425 + void acpi_processor_register_idle_driver(void); 426 + void acpi_processor_unregister_idle_driver(void); 427 + int acpi_processor_ffh_lpi_probe(unsigned int cpu); 428 + int acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi); 446 429 #endif /* CONFIG_ACPI_PROCESSOR_IDLE */ 447 430 448 431 /* in processor_thermal.c */ ··· 447 464 return; 448 465 } 449 466 #endif /* CONFIG_CPU_FREQ */ 450 - 451 - #ifdef CONFIG_ACPI_PROCESSOR_IDLE 452 - extern int acpi_processor_ffh_lpi_probe(unsigned int cpu); 453 - extern int acpi_processor_ffh_lpi_enter(struct acpi_lpi_state *lpi); 454 - #endif 455 467 456 468 void acpi_processor_init_invariance_cppc(void); 457 469
+2 -2
tools/power/acpi/os_specific/service_layers/oslinuxtbl.c
··· 995 995 { 996 996 void *table_dir; 997 997 u32 instance; 998 - char temp_name[ACPI_NAMESEG_SIZE]; 998 + char temp_name[ACPI_NAMESEG_SIZE] ACPI_NONSTRING; 999 999 char *filename; 1000 1000 acpi_status status = AE_OK; 1001 1001 ··· 1312 1312 { 1313 1313 void *table_dir; 1314 1314 u32 current_instance = 0; 1315 - char temp_name[ACPI_NAMESEG_SIZE]; 1315 + char temp_name[ACPI_NAMESEG_SIZE] ACPI_NONSTRING; 1316 1316 char table_filename[PATH_MAX]; 1317 1317 char *filename; 1318 1318 acpi_status status;
+2 -1
tools/power/acpi/tools/acpidump/apdump.c
··· 86 86 if (ACPI_FAILURE(status)) { 87 87 fprintf(stderr, "%4.4s: Warning: wrong checksum in table\n", 88 88 table->signature); 89 + return (FALSE); 89 90 } 90 91 91 - return (AE_OK); 92 + return (TRUE); 92 93 } 93 94 94 95 /******************************************************************************
+1 -1
tools/power/acpi/tools/acpidump/apfiles.c
··· 103 103 104 104 int ap_write_to_binary_file(struct acpi_table_header *table, u32 instance) 105 105 { 106 - char filename[ACPI_NAMESEG_SIZE + 16] ACPI_NONSTRING; 106 + char filename[ACPI_NAMESEG_SIZE + 16]; 107 107 char instance_str[16]; 108 108 ACPI_FILE file; 109 109 acpi_size actual;