From a414485ebc2aa50907d0ce97cde2b1a353696897 Mon Sep 17 00:00:00 2001 From: Hongyan Xu Date: Sat, 8 Aug 2026 16:59:42 +0800 Subject: [PATCH 1/3] ACPI: scan: fix bus ID cleanup on device_add() failures When device_add() fails after acpi_device_set_name() has allocated an instance ID and a new acpi_device_bus_id has been linked into acpi_bus_id_list, the rollback path only removes wakeup_list and detaches the ACPI handle data. That leaves the bus-ID bookkeeping behind and keeps the allocated instance number consumed. Move the bus-ID cleanup and wakeup-list removal into a single helper. Use it from both the normal device teardown path and the device_add() rollback path. The wakeup list node is initialized before registration, so it can be deleted without checking whether the device is wakeup- capable like in the original teardown path. Fixes: d783156ea384 ("ACPI / scan: Define non-empty device removal handler") Signed-off-by: Hongyan Xu [ rjw: Rename acpi_device_del_list() to acpi_device_cleanup() ] [ rjw: Subject and changelog edits ] Link: https://patch.msgid.link/20260808085943.526-1-getshell@seu.edu.cn Signed-off-by: Rafael J. Wysocki --- drivers/acpi/scan.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 9a7ac2eb9ce0..f8450f7ea097 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -524,12 +524,10 @@ static void acpi_device_release(struct device *dev) kfree(acpi_dev); } -static void acpi_device_del(struct acpi_device *device) +static void acpi_device_cleanup(struct acpi_device *device) { struct acpi_device_bus_id *acpi_device_bus_id; - mutex_lock(&acpi_device_lock); - list_for_each_entry(acpi_device_bus_id, &acpi_bus_id_list, node) if (!strcmp(acpi_device_bus_id->bus_id, acpi_device_hid(device))) { @@ -544,6 +542,13 @@ static void acpi_device_del(struct acpi_device *device) } list_del(&device->wakeup_list); +} + +static void acpi_device_del(struct acpi_device *device) +{ + mutex_lock(&acpi_device_lock); + + acpi_device_cleanup(device); mutex_unlock(&acpi_device_lock); @@ -803,7 +808,7 @@ int acpi_device_add(struct acpi_device *device) err: mutex_lock(&acpi_device_lock); - list_del(&device->wakeup_list); + acpi_device_cleanup(device); err_unlock: mutex_unlock(&acpi_device_lock); From dc948f8b384a516ac5c471eb9382959f838e02f4 Mon Sep 17 00:00:00 2001 From: Peixin Xie Date: Thu, 20 Aug 2026 13:56:27 +0800 Subject: [PATCH 2/3] ACPI: scan: Defer device power initialization acpi_bus_get_power_flags() initializes the device power state while the ACPI device object is being created, before checking whether the device is ready for enumeration. If enumeration is deferred, acpi_bus_attach() clears the initialized and power_manageable flags. When the dependency is later satisfied, acpi_bus_init_power() is called again and takes additional references to the power resources used by the device. These references prevent the resources from being turned off when the device enters D3. This issue was reproduced on a SpacemiT K3 RISC-V Pico-ITX. The affected device uses a power resource through _PR0 and has an automatically derived dependency on its interrupt controller. The initial power initialization acquires a power resource reference. The device is then deferred, but that reference is not dropped. When the dependency becomes available, power initialization acquires another reference. Consequently, entering D3 only drops the reference count from 2 to 1 and _OFF is not evaluated: [ 0.314611] ACPI Debug: "I2P2 _STA" [ 0.318260] ACPI: \_SB_.I2P2: ACPI: PM: Power resource is on [ 0.323998] ACPI: \_SB_.I2P2: New power resource [ 0.382108] ACPI Debug: "I2P2 _STA" [ 0.478964] ACPI Debug: "I2P2 _ON" [ 0.482498] ACPI: \_SB_.I2P2: ACPI: PM: Power resource turned on [ 0.488597] ACPI Debug: "I2C2, PS0" [ 0.863170] ACPI: \_SB_.I2P2: ACPI: PM: Power resource already on [ 0.873686] ACPI Debug: "I2C2, PS0" [ 2.416055] ACPI Debug: "I2C2, PS3" [ 2.423397] ACPI: \_SB_.I2P2: ACPI: PM: Power resource still in use To address this, remove the early acpi_bus_init_power() call and leave regular ACPI device objects uninitialized until acpi_bus_attach() runs after the device is ready for enumeration. Power resource objects are initialized through acpi_add_power_resource() and do not require the generic initialization in acpi_bus_attach(), so mark them as initialized there. After the change, device power state initialization is deferred until its dependency is met. Since no reference is acquired before then, the power resource left on by firmware is turned off as unused after the namespace scan. Once the dependency is met, the resource is turned on once for the device and is turned off normally when the device later enters D3: [ 0.314628] ACPI Debug: "I2P2 _STA" [ 0.318277] ACPI: \_SB_.I2P2: ACPI: PM: Power resource is on [ 0.324016] ACPI: \_SB_.I2P2: New power resource [ 0.382118] ACPI Debug: "I2P2 _STA" [ 0.496116] ACPI: \_SB_.I2P2: ACPI: PM: Turning OFF [ 0.501081] ACPI Debug: "I2P2 _OFF" [ 0.504705] ACPI: \_SB_.I2P2: ACPI: PM: Power resource turned off [ 1.415899] ACPI Debug: "I2P2 _ON" [ 1.418866] ACPI: \_SB_.I2P2: ACPI: PM: Power resource turned on [ 1.424947] ACPI Debug: "I2C2, PS0" [ 2.647655] ACPI Debug: "I2C2, PS3" [ 2.654856] ACPI Debug: "I2P2 _OFF" [ 2.654866] ACPI: \_SB_.I2P2: ACPI: PM: Power resource turned off This also avoids powering up devices before their dependencies are available. Signed-off-by: Peixin Xie [ rjw: Changelog edits ] Link: https://patch.msgid.link/20260820-acpi-power-resource-ref-fix-v2-1-29818173ea13@linux.spacemit.com Signed-off-by: Rafael J. Wysocki --- drivers/acpi/power.c | 1 + drivers/acpi/scan.c | 4 ---- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/acpi/power.c b/drivers/acpi/power.c index d4131c184be8..4f1479103bfe 100644 --- a/drivers/acpi/power.c +++ b/drivers/acpi/power.c @@ -955,6 +955,7 @@ struct acpi_device *acpi_add_power_resource(acpi_handle handle) INIT_LIST_HEAD(&resource->dependents); device->power.state = ACPI_STATE_UNKNOWN; device->flags.match_driver = true; + device->flags.initialized = true; /* Evaluate the object to get the system level and resource order. */ status = acpi_evaluate_object(handle, NULL, NULL, &buffer); diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index f8450f7ea097..cd7ab27ecdce 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1146,9 +1146,6 @@ static void acpi_bus_get_power_flags(struct acpi_device *device) if (!list_empty(&device->power.states[ACPI_STATE_D3_HOT].resources)) device->power.states[ACPI_STATE_D3_COLD].flags.valid = 1; } - - if (acpi_bus_init_power(device)) - device->flags.power_manageable = 0; } static void acpi_bus_get_flags(struct acpi_device *device) @@ -1827,7 +1824,6 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, acpi_init_properties(device); acpi_bus_get_flags(device); device->flags.match_driver = false; - device->flags.initialized = true; device->flags.enumeration_by_parent = acpi_device_enumeration_by_parent(device); acpi_device_clear_enumerated(device); From 7617cc05df28dcae967cca109de74084321eaa62 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 20 Aug 2026 21:11:14 +0200 Subject: [PATCH 3/3] ACPI: scan: Do not combine resources that overlap completely Commit f234fdaae1ca ("ACPI: scan: Avoid registering platform devices with resource overlaps") attempted to avoid platform device registration errors due to overlaps of resources of the same type returned by the same _CRS object in the ACPI tables. It did that by combining two or more overlapping resources into one, but it went too far and also caused resources that overlap completely to be combined which broke the arm-cmn driver that expects two MMIO resources to be present for each device it binds to and it expects those two resources to overlap completely. Address this issue by adding checks for completely overlapping resources to acpi_platform_adjust_resources() and add a comment explaining what is done there. Fixes: f234fdaae1ca ("ACPI: scan: Avoid registering platform devices with resource overlaps") Reported-by: Nathan Chancellor Tested-by: Nathan Chancellor Closes: https://lore.kernel.org/linux-acpi/20260819003752.GA3063251@ax162/ Signed-off-by: Rafael J. Wysocki Reviewed-by: Jarkko Sakkinen Link: https://patch.msgid.link/12955564.O9o76ZdvQC@rafael.j.wysocki --- drivers/acpi/acpi_platform.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/acpi_platform.c b/drivers/acpi/acpi_platform.c index 373c94de7590..e3c77a65f61c 100644 --- a/drivers/acpi/acpi_platform.c +++ b/drivers/acpi/acpi_platform.c @@ -85,7 +85,13 @@ static unsigned int acpi_platform_adjust_resources(struct acpi_device *adev, for (i = 0; i < count; ) { struct resource *res = &resources[i]; - if (resource_type(new_res) != resource_type(res) || + /* + * Look for overlaps of resources of the same type that would + * cause resource insertion to fail down the road. + */ + if (__resource_contains_unbound(res, new_res) || + __resource_contains_unbound(new_res, res) || + resource_type(new_res) != resource_type(res) || !resource_union(new_res, res, new_res)) { i++; continue;