From 72a35790da31acc12f05d35466e46254439d5dcd Mon Sep 17 00:00:00 2001 From: Sang-Heon Jeon Date: Fri, 21 Aug 2026 22:15:08 +0900 Subject: [PATCH 01/11] ACPI: MRRM: Use for_each_populated_zone() in get_node_num() get_node_num() iterates over the populated zones of every online node with a nested loop. for_each_populated_zone() iterates over the same zones in the same order. So use for_each_populated_zone() instead and remove the unused variable. No functional change. Signed-off-by: Sang-Heon Jeon Link: https://patch.msgid.link/20260821131530.3375820-1-ekffu200098@gmail.com Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_mrrm.c | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/drivers/acpi/acpi_mrrm.c b/drivers/acpi/acpi_mrrm.c index e99cbda83452..83934e2aa0d4 100644 --- a/drivers/acpi/acpi_mrrm.c +++ b/drivers/acpi/acpi_mrrm.c @@ -36,17 +36,11 @@ static u32 mrrm_mem_entry_num; static int get_node_num(struct mrrm_mem_range_entry *e) { - unsigned int nid; + struct zone *zone; - for_each_online_node(nid) { - for (int z = 0; z < MAX_NR_ZONES; z++) { - struct zone *zone = NODE_DATA(nid)->node_zones + z; - - if (!populated_zone(zone)) - continue; - if (zone_intersects(zone, PHYS_PFN(e->base), PHYS_PFN(e->length))) - return zone_to_nid(zone); - } + for_each_populated_zone(zone) { + if (zone_intersects(zone, PHYS_PFN(e->base), PHYS_PFN(e->length))) + return zone_to_nid(zone); } return -ENOENT; From 412746bb6652ddc6fa435bc11a9b1253d63bf8a6 Mon Sep 17 00:00:00 2001 From: Vlatko Kosturjak Date: Mon, 31 Aug 2026 06:51:04 +0200 Subject: [PATCH 02/11] ACPI: OSL: Use vsnprintf() in acpi_os_vprintf() acpi_os_vprintf() formats every ACPICA diagnostic into a 512-byte static buffer with an unbounded vsprintf(): static char buffer[512]; vsprintf(buffer, fmt, args); ACPICA interpolates table-derived namespace paths into its messages, so the length is driven by table content. A malformed ACPI table can therefore produce a diagnostic longer than the buffer and overwrite whatever follows it. From the System.map of an x86_64_defconfig build, acpi_ioremap_lock sits 624 bytes into that buffer - 112 bytes past its end - so bytes 624..631 of an over-long message land on the mutex's owner field, which __mutex_lock() then dereferences. The overwritten bytes are attacker-influenced but not attacker-controlled: they are printable ASCII from a NUL-terminated string, so the resulting pointer is always non-canonical and always faults. This is a reliable denial of service, not a demonstrated pointer-control primitive. Because acpi_tb_load_namespace() parses the DSDT and every SSDT during acpi_init(), a table supplied by firmware triggers this in PID 1 inside do_one_initcall(), panicking the kernel before userspace exists. Bound the write with vsnprintf(). Truncating a diagnostic is strictly better than corrupting adjacent kernel objects. Tested on pristine Linux 7.2.2 - tag: v7.2.2., Stock x86_64_defconfig (no KASAN, no debug options), table supplied by firmware via "qemu -acpitable": [ 0.022259] ACPI: SSDT 0x000000003FFE1C52 000640 (v01 _ASUS_ Notebook 00000005 MSFT 0100000D) [ 0.353684] Oops: general protection fault, probably for non-canonical address 0x41435f2e345f2e64: 0000 [#1] SMP NOPTI [ 0.353727] RIP: 0010:__mutex_lock.constprop.0+0xbd/0xa40 [ 0.353727] RAX: 41435f2e345f2e30 RBX: 00000000fed00000 [ 0.353727] R15: ffffffff8c248530 [ 0.353727] Call Trace: [ 0.353727] acpi_os_map_iomem [ 0.353727] acpi_ex_system_memory_space_handler [ 0.353727] acpi_ev_address_space_dispatch [ 0.353727] acpi_ex_access_region [ 0.353727] acpi_ex_read_data_from_field [ 0.353727] acpi_ex_resolve_node_to_value [ 0.353727] acpi_ds_evaluate_name_path [ 0.353727] acpi_ps_parse_loop [ 0.353727] acpi_ps_execute_method [ 0.354729] Kernel panic - not syncing: Attempted to kill init! exitcode=0x00000009 RAX is the corrupted owner; the faulting address is RAX + 0x34. R15 matches acpi_ioremap_lock. On a KASAN build the overflow is reported directly as: BUG: KASAN: global-out-of-bounds in string. Signed-off-by: Vlatko Kosturjak [ rjw: Subject tweak ] Link: https://patch.msgid.link/CAPAw8HEMdsNN6WhizHkv2Orp2pkQ2-g009XCGFnKnhXoRhcKZQ@mail.gmail.com Signed-off-by: Rafael J. Wysocki --- drivers/acpi/osl.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c index ed2162a97bd2..5b7aefb48eeb 100644 --- a/drivers/acpi/osl.c +++ b/drivers/acpi/osl.c @@ -159,7 +159,7 @@ void __printf(1, 0) acpi_os_vprintf(const char *fmt, va_list args) { static char buffer[512]; - vsprintf(buffer, fmt, args); + vsnprintf(buffer, sizeof(buffer), fmt, args); #ifdef ENABLE_DEBUGGER if (acpi_in_debugger) { From 78ddbfaa72d68acc98cd5ba12eca071d452702c4 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 6 Sep 2026 17:56:56 +0200 Subject: [PATCH 03/11] ACPI: utils: Adjust message printing macros for ACPI objects The majority of acpi_handle_() macros use neither pr_fmt() nor dev_fmt() and acpi_handle_debug() uses pr_fmt() like dev_fmt(), but only if dynamic debug is compiled in. For more consistency, redefine all of the macros in question to use dev_fmt() because they are more similar to the analogous dev_*() family of macros than to the pr_*() ones and make all of them use it in the same way. While at it, rephrase the comment documenting those macros for more clarity. Fixes: 45fef5b88d1f ("ACPI: add dynamic_debug support") Signed-off-by: Rafael J. Wysocki Reviewed-by: Andy Shevchenko Link: https://patch.msgid.link/2300525.irdbgypaU6@rafael.j.wysocki Signed-off-by: Rafael J. Wysocki --- include/linux/acpi.h | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/include/linux/acpi.h b/include/linux/acpi.h index ddacac812094..f7e3efd328f7 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -1305,34 +1305,34 @@ void __acpi_handle_debug(struct _ddebug *descriptor, acpi_handle handle, const c #endif /* - * acpi_handle_: Print message with ACPI prefix and object path + * acpi_handle_ - Print a message with ACPI prefix and object path * - * These interfaces acquire the global namespace mutex to obtain an object - * path. In interrupt context, it shows the object path as . + * In thread context, the global namespace mutex is acquired to obtain the + * object path. In interrupt context, the object path is shown as . */ #define acpi_handle_emerg(handle, fmt, ...) \ - acpi_handle_printk(KERN_EMERG, handle, fmt, ##__VA_ARGS__) + acpi_handle_printk(KERN_EMERG, handle, dev_fmt(fmt), ##__VA_ARGS__) #define acpi_handle_alert(handle, fmt, ...) \ - acpi_handle_printk(KERN_ALERT, handle, fmt, ##__VA_ARGS__) + acpi_handle_printk(KERN_ALERT, handle, dev_fmt(fmt), ##__VA_ARGS__) #define acpi_handle_crit(handle, fmt, ...) \ - acpi_handle_printk(KERN_CRIT, handle, fmt, ##__VA_ARGS__) + acpi_handle_printk(KERN_CRIT, handle, dev_fmt(fmt), ##__VA_ARGS__) #define acpi_handle_err(handle, fmt, ...) \ - acpi_handle_printk(KERN_ERR, handle, fmt, ##__VA_ARGS__) + acpi_handle_printk(KERN_ERR, handle, dev_fmt(fmt), ##__VA_ARGS__) #define acpi_handle_warn(handle, fmt, ...) \ - acpi_handle_printk(KERN_WARNING, handle, fmt, ##__VA_ARGS__) + acpi_handle_printk(KERN_WARNING, handle, dev_fmt(fmt), ##__VA_ARGS__) #define acpi_handle_notice(handle, fmt, ...) \ - acpi_handle_printk(KERN_NOTICE, handle, fmt, ##__VA_ARGS__) + acpi_handle_printk(KERN_NOTICE, handle, dev_fmt(fmt), ##__VA_ARGS__) #define acpi_handle_info(handle, fmt, ...) \ - acpi_handle_printk(KERN_INFO, handle, fmt, ##__VA_ARGS__) + acpi_handle_printk(KERN_INFO, handle, dev_fmt(fmt), ##__VA_ARGS__) #if defined(DEBUG) #define acpi_handle_debug(handle, fmt, ...) \ - acpi_handle_printk(KERN_DEBUG, handle, fmt, ##__VA_ARGS__) + acpi_handle_printk(KERN_DEBUG, handle, dev_fmt(fmt), ##__VA_ARGS__) #else #if defined(CONFIG_DYNAMIC_DEBUG) #define acpi_handle_debug(handle, fmt, ...) \ _dynamic_func_call(fmt, __acpi_handle_debug, \ - handle, pr_fmt(fmt), ##__VA_ARGS__) + handle, dev_fmt(fmt), ##__VA_ARGS__) #else #define acpi_handle_debug(handle, fmt, ...) \ ({ \ From 3107a9a3241d6b585cbc08c7035b03fa44e9fb94 Mon Sep 17 00:00:00 2001 From: Mario Limonciello Date: Tue, 8 Sep 2026 14:34:58 -0500 Subject: [PATCH 04/11] ACPI: utils: Ignore leading root scope prefix in string _UID match Firmware may express an ACPI namespace path used as a _UID with or without the leading root scope character ('\'). For example, an AMD IVRS IVHD ACPI HID device entry may carry a character UID of "\_SB.MHSP" while the corresponding device's _UID evaluates to "_SB.MHSP" (or vice versa). This semantic difference is due to how Windows PnP enumerates and uses devices. acpi_str_uid_match() compared the two strings verbatim, so such entries failed to match on the UID even though they refer to the same object. In the AMD IOMMU case (get_acpihid_device_id()) this caused the exact HID+UID match to be missed and the code to fall through to the HID-only path, spuriously raising a FW_BUG. Skip a single leading '\' on either string before comparing so that paths that differ only by the root scope prefix are treated as a match. The integer _UID path is unaffected. [ rjw: It is sad that making this change needed to be considered at all. That being said, it is also rather unlikely that someone will use a leading backslash as the only difference to distinguish one UID string from antother, so this change is unlikely to break anything. ] Signed-off-by: Mario Limonciello [ rjw: Added separator line to a kerneldoc comment ] [ rjw: Droppend Link: tag with a limited access target ] Signed-off-by: Rafael J. Wysocki --- include/acpi/acpi_bus.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h index a10a591c18b2..22be27e02682 100644 --- a/include/acpi/acpi_bus.h +++ b/include/acpi/acpi_bus.h @@ -830,7 +830,15 @@ static inline bool acpi_str_uid_match(struct acpi_device *adev, const char *uid2 { const char *uid1 = acpi_device_uid(adev); - return uid1 && uid2 && !strcmp(uid1, uid2); + if (!uid1 || !uid2) + return false; + + if (*uid1 == '\\' && uid1[1]) + uid1++; + if (*uid2 == '\\' && uid2[1]) + uid2++; + + return !strcmp(uid1, uid2); } static inline bool acpi_int_uid_match(struct acpi_device *adev, u64 uid2) @@ -857,6 +865,10 @@ static inline bool acpi_int_uid_match(struct acpi_device *adev, u64 uid2) * * Matches UID in @adev with given @uid2. * + * If both the UID in @adev and @uid2 are strings, they are compared + * after optionally skipping a leading backslash ('\') if the given + * string contains additional characters. + * * Returns: %true if matches, %false otherwise. */ #define acpi_dev_uid_match(adev, uid2) \ From 047c834d939df75386cfc0603c7ddeaa23a349a4 Mon Sep 17 00:00:00 2001 From: Slavin Liu Date: Sun, 13 Sep 2026 20:51:23 +0800 Subject: [PATCH 05/11] ACPI: tables: handle failed initrd override mappings The runtime AML table-loading path can invoke initrd override after permanent mappings are enabled. Mapping bookkeeping can then fail. Return AE_NO_MEMORY in that case to prevent a NULL pointer dereference when attempting to read the table length. Detected by static analysis and reviewed with AI-assisted source auditing. Fixes: b2a35003dfbc ("ACPI: Implement physical address table override") Assisted-by: LLM Signed-off-by: Slavin Liu [ rjw: Added empty code line after conditional, changelog edits ] Link: https://patch.msgid.link/20260913125123.109803-1-bolin.liu@seu.edu.cn Signed-off-by: Rafael J. Wysocki --- drivers/acpi/tables.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index eb93c060426f..aaa1de79bccf 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -560,6 +560,9 @@ acpi_table_initrd_override(struct acpi_table_header *existing_table, while (table_offset + ACPI_HEADER_SIZE <= all_tables_size) { table = acpi_os_map_memory(acpi_tables_addr + table_offset, ACPI_HEADER_SIZE); + if (!table) + return AE_NO_MEMORY; + if (table_offset + table->length > all_tables_size) { acpi_os_unmap_memory(table, ACPI_HEADER_SIZE); WARN_ON(1); From 46767b17fda3fba1ed91dd73d7d432b0bb6851c1 Mon Sep 17 00:00:00 2001 From: Saranya Gopal Date: Fri, 4 Sep 2026 13:08:44 +0530 Subject: [PATCH 06/11] ACPI: PM: s2idle: Add _Ixx GPE wake indicator support ACPI 6.6 defines _Ixx indicator objects under \_GPE to mark GPEs that should remain wake-enabled in s2idle without a _PRW association. To support them, add new function acpi_setup_ixx_gpes() that looks for _Ixx objects for all GPEs in the FADT 0/1 blocks and if it finds any, it marks the corresponding GPE as wake-capable, in which case the GPE is also enabled so long as it has a handler method because marking it as wake-capable causes acpi_update_all_gpes() to skip it. Since the above only needs to be done if suspend-to-idle is enabled, make acpi_s2idle_setup() call that new function. For now, this is limited to x86 systems and it assumes that the GPEs with _Ixx will not cause spurious wakeups to occur while the system is suspended. Signed-off-by: Saranya Gopal [ rjw: Added three empty code lines, subject tweak, changelog edits ] [ rjw: New debug message adjustment ] Link: https://patch.msgid.link/20260904073844.2740931-1-saranya.gopal@intel.com Signed-off-by: Rafael J. Wysocki --- drivers/acpi/x86/s2idle.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/drivers/acpi/x86/s2idle.c b/drivers/acpi/x86/s2idle.c index b6b1dd76a06b..c278ea14c0b3 100644 --- a/drivers/acpi/x86/s2idle.c +++ b/drivers/acpi/x86/s2idle.c @@ -24,6 +24,34 @@ #ifdef CONFIG_SUSPEND +static void acpi_setup_ixx_gpes(void) +{ + acpi_handle gpe_root; + unsigned int i; + char gpe_nr_str[5]; + + if (ACPI_FAILURE(acpi_get_handle(NULL, "\\_GPE", &gpe_root))) + return; + + for (i = 0; i <= 0xff; i++) { + scnprintf(gpe_nr_str, sizeof(gpe_nr_str), "_I%02X", i); + if (!acpi_has_method(gpe_root, gpe_nr_str)) + continue; + + /* + * Enable the GPE if it has a handler method because marking it + * as wake-capable causes acpi_update_all_gpes() to skip it. + */ + if (ACPI_FAILURE(acpi_enable_gpe_cond(NULL, i, ACPI_GPE_DISPATCH_METHOD))) + continue; + + acpi_mark_gpe_for_wake(NULL, i); + acpi_set_gpe_wake_mask(NULL, i, ACPI_GPE_ENABLE); + + pm_pr_dbg("ACPI: GPE0x%02x armed for wake via %s\n", i, gpe_nr_str); + } +} + static bool sleep_no_lps0 __read_mostly; module_param(sleep_no_lps0, bool, 0644); MODULE_PARM_DESC(sleep_no_lps0, "Do not use the special LPS0 device interface"); @@ -649,6 +677,7 @@ void __init acpi_s2idle_setup(void) { acpi_scan_add_handler(&lps0_handler); s2idle_set_ops(&acpi_s2idle_ops_lps0); + acpi_setup_ixx_gpes(); } int acpi_register_lps0_dev(struct acpi_s2idle_dev_ops *arg) From b1c75a77d494298b8dedf46062f2072239bbc33b Mon Sep 17 00:00:00 2001 From: Alejandro Lucero Date: Thu, 16 Jul 2026 19:11:14 +0100 Subject: [PATCH 07/11] ACPI: HMAT: preserve hmat_adist_nb notifier block Remove __meminitdata from hmat_adist_nb declaration preserving it even when CONFIG_MEMORY_HOTPLUG is not set. Otherwise further notifier registrations using register_mt_adistance_algorithm() will find a notifier chain likely corrupted. This is the case when cxl_region_probe() calls register_mt_adistance_algorithm() what can happen when CXL regions are dynamically created at any time from Type3 device(s) or when a Type2 device is initialized at its driver probe. Fixes: 3718c02dbd4c ("acpi, hmat: calculate abstract distance with HMAT") Signed-off-by: Alejandro Lucero Reviewed-by: Dave Jiang Reviewed-by: Jonathan Cameron [ rjw: Subject tweak ] Link: https://patch.msgid.link/20260716181114.35962-2-alejandro.lucero-palau@amd.com Signed-off-by: Rafael J. Wysocki --- drivers/acpi/numa/hmat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/acpi/numa/hmat.c b/drivers/acpi/numa/hmat.c index 9792dc394756..3006789ae31f 100644 --- a/drivers/acpi/numa/hmat.c +++ b/drivers/acpi/numa/hmat.c @@ -995,7 +995,7 @@ static int hmat_calculate_adistance(struct notifier_block *self, return NOTIFY_STOP; } -static struct notifier_block hmat_adist_nb __meminitdata = { +static struct notifier_block hmat_adist_nb = { .notifier_call = hmat_calculate_adistance, .priority = 100, }; From a0039113053d4d3f629ea1b9cd74130ca597f14a Mon Sep 17 00:00:00 2001 From: Matthias Dittrich Date: Mon, 7 Sep 2026 09:04:49 +0200 Subject: [PATCH 08/11] ACPI: PM: Add quirk for Acer Swift 3 SF314-56G (MX250) The Acer Swift 3 SF314-56G (with NVIDIA GeForce MX250) suffers from the same ACPI power resource regression as the Thunderobot ZERO. The power resource controlling the dGPU is incorrectly turned off during initialization, causing the GPU to fall off the bus (D3cold). This commit adds a DMI quirk to keep the power resource on for this model, similar to the existing Thunderobot quirk. Tested on Acer Swift 3 SF314-56G with NVIDIA MX250. Closes: https://bugzilla.kernel.org/show_bug.cgi?id=221087 Signed-off-by: Matthias Dittrich [ rjw: Changelog edits ] Signed-off-by: Rafael J. Wysocki --- drivers/acpi/power.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 23a4e207a01e..c6955d1ad29d 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -1120,6 +1120,19 @@ static const struct dmi_system_id dmi_leave_unused_power_resources_on[] = { DMI_MATCH(DMI_PRODUCT_NAME, "ZERO"), } + }, + { + /* + * Acer Swift 3 SF314-56G with NVIDIA MX250 suffers from the + * same ACPI power resource regression as the Thunderobot ZERO. + * The power resource controlling the dGPU is incorrectly turned off + * during initialization, causing the GPU to fall off the bus (D3cold). + */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Swift SF314-56G"), + } + }, {} }; From 23ec17231cc6a83bb11d8660db5bfc5336f53a0e Mon Sep 17 00:00:00 2001 From: Hakan Abay Date: Mon, 5 Oct 2026 20:49:39 +0300 Subject: [PATCH 09/11] ACPI: PM: Add unused power resource quirk for Casper Excalibur G900 On the Casper Excalibur G900, the NVIDIA discrete GPU and the second NVMe device become inaccessible when unused ACPI power resources are turned off during initialization. The failure is similar to the THUNDEROBOT ZERO case addressed by commit cd7ef20ba8c6 ("ACPI: PM: Add unused power resource quirk for THUNDEROBOT ZERO"). Without the quirk, the NVIDIA GPU and the second NVMe device are left inaccessible in D3cold and attempts to transition them back to D0 fail. Add a DMI quirk for the affected Casper Excalibur G900 with NLCC 001 mainboard to leave unused ACPI power resources on. With the quirk applied, the second NVMe device remains accessible. The NVIDIA GPU can enter D3cold while idle and subsequently return to D0 for accelerated rendering. Link: https://bugs.kali.org/view.php?id=9891 Signed-off-by: Hakan Abay Link: https://patch.msgid.link/20261005174939.53873-1-hakan.abay84@gmail.com Signed-off-by: Rafael J. Wysocki --- drivers/acpi/power.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index c6955d1ad29d..34b73f320b18 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -1134,6 +1134,18 @@ static const struct dmi_system_id dmi_leave_unused_power_resources_on[] = { } }, + { + /* + * CASPER EXCALIBUR G900 laptop: Keep unused ACPI power + * resources on to prevent the NVIDIA dGPU and NVMe #2 + * from becoming inaccessible. + */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "CASPER BILGISAYAR SISTEMLERI"), + DMI_MATCH(DMI_PRODUCT_NAME, "EXCALIBUR G900"), + DMI_MATCH(DMI_BOARD_NAME, "NLCC 001"), + }, + }, {} }; From f43cdd75b38a29c96896ed1f7bf9b3ec04a6c3b7 Mon Sep 17 00:00:00 2001 From: Riwen Lu Date: Thu, 8 Oct 2026 10:51:52 +0800 Subject: [PATCH 10/11] ACPI: PM: sleep: Drop unused sleep_no_lps0 define The sleep_no_lps0 stub define in the !CONFIG_ACPI_SLEEP branch of sleep.c has no users left in that file: the LPS0 code consuming it was moved to drivers/acpi/x86/s2idle.c by commit fef98671194b ("ACPI: PM: s2idle: Move x86-specific code to the x86 directory"), which has its own static module parameter of the same name, so the define is no longer used. Drop it. Signed-off-by: Riwen Lu Link: https://patch.msgid.link/20261008025152.153073-1-luriwen@kylinos.cn Signed-off-by: Rafael J. Wysocki --- drivers/acpi/sleep.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/acpi/sleep.c b/drivers/acpi/sleep.c index 132a9df98471..a94bac4422d4 100644 --- a/drivers/acpi/sleep.c +++ b/drivers/acpi/sleep.c @@ -548,7 +548,6 @@ static void acpi_pm_end(void) acpi_sleep_tts_switch(acpi_target_sleep_state); } #else /* !CONFIG_ACPI_SLEEP */ -#define sleep_no_lps0 (1) #define acpi_target_sleep_state ACPI_STATE_S0 #define acpi_sleep_default_s3 (1) static inline void acpi_sleep_dmi_check(void) {} From 8eb2754ef96d77d870d6b1ef1e0e8470c892b6b4 Mon Sep 17 00:00:00 2001 From: Krittikun Wongnin Date: Tue, 13 Oct 2026 14:42:45 +0700 Subject: [PATCH 11/11] ACPI: PM: Add Acer Aspire A515-53G to dmi_leave_unused_power_resources_on[] On the Acer Aspire A515-53G (Whiskey Lake + NVIDIA GeForce MX230), the dGPU behind root port RP05 (00:1c.4) falls off the bus during boot and is unusable until the next power cycle: nvidia 0000:02:00.0: Unable to change power state from D3cold to D0, device inaccessible NVRM: The NVIDIA GPU 0000:02:00.0 ... has fallen off the bus The firmware ships two SSDTs which both provide power management for the dGPU: - One SSDT defines \_SB.PCI0.RP05.PC01 together with RP05._PR0/_PR2/_PR3 = { PC01 }. - A second SSDT defines \_SB.PCI0.RP05.PCRP (_STA initially One, _OFF calls \_SB.PCI0.HGOF, which puts the link into L2/L3 and drops the dGPU power enable GPIO) and its own RP05._PR0/_PR2/_PR3/_S0W. The latter fail to load: ACPI BIOS Error (bug): Failure creating named object [\_SB.PCI0.RP05._PR0], AE_ALREADY_EXISTS As a result PCRP is not referenced by any device and acpi_turn_off_unused_power_resources() turns it off right after the ACPI namespace scan. This cuts power to the dGPU, but PC01 still believes it is on, so its _ON method is a no-op when the PCI core later tries to bring the GPU back to D0. Windows does not turn off unused power resources, so the dGPU works there. Add the machine to dmi_leave_unused_power_resources_on[], like the THUNDEROBOT ZERO which has a similar SSDT bug. With this change the dGPU stays on the bus and the nvidia driver binds. Runtime PM of the dGPU is unaffected, as it is handled through PC01: with no driver bound and power/control set to auto, RP05 reaches D3cold and the GPU comes back to D0 on resume. Link: https://lore.kernel.org/r/CADS-TgDQ1G8vrTQLJeQ3RTBVFTyMe0C+5p2=UBKS=EFCDFuaxw@mail.gmail.com/ Signed-off-by: Krittikun Wongnin [ rjw: Subject and changelog tweaks ] Link: https://patch.msgid.link/20261013074245.4327-1-krittikunwongnin@gmail.com Signed-off-by: Rafael J. Wysocki --- drivers/acpi/power.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index 34b73f320b18..c77342a584f0 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -1146,6 +1146,19 @@ static const struct dmi_system_id dmi_leave_unused_power_resources_on[] = { DMI_MATCH(DMI_BOARD_NAME, "NLCC 001"), }, }, + { + /* + * Acer Aspire A515-53G: Two SSDTs both define power resources + * for the dGPU root port RP05 ('PC01' and 'PCRP'). Only PC01 ends + * up in RP05's _PR0/_PR3, so 'PCRP' is shut down on + * initialization, cutting power to the NVIDIA dGPU behind the + * back of 'PC01' and making the dGPU unavailable. + */ + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Acer"), + DMI_MATCH(DMI_PRODUCT_NAME, "Aspire A515-53G"), + }, + }, {} };