From 08b54fd577825d922a2263f3dcf8481e3720d606 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 15 Dec 2025 15:01:53 +0100 Subject: [PATCH 1/5] ACPI: battery: Adjust event notification routine Adjust acpi_battery_notify() to cast its "data" argument to a struct acpi_battery pointer istead of a struct acpi_device one, which allows the use of acpi_driver_data() to be limited and will facilitate subsequent changes. No intentional functional impact. Signed-off-by: Rafael J. Wysocki Link: https://patch.msgid.link/4344406.1IzOArtZ34@rafael.j.wysocki --- drivers/acpi/battery.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 34181fa52e93..582c35fc8d03 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -1054,8 +1054,8 @@ static void acpi_battery_refresh(struct acpi_battery *battery) /* Driver Interface */ static void acpi_battery_notify(acpi_handle handle, u32 event, void *data) { - struct acpi_device *device = data; - struct acpi_battery *battery = acpi_driver_data(device); + struct acpi_battery *battery = data; + struct acpi_device *device = battery->device; struct power_supply *old; if (!battery) @@ -1249,7 +1249,7 @@ static int acpi_battery_add(struct acpi_device *device) device_init_wakeup(&device->dev, 1); result = acpi_dev_install_notify_handler(device, ACPI_ALL_NOTIFY, - acpi_battery_notify, device); + acpi_battery_notify, battery); if (result) goto fail_pm; From 0d17aafa79c6c5693a740a5b6c2693203e4043ee Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 15 Dec 2025 15:02:37 +0100 Subject: [PATCH 2/5] ACPI: battery: Reduce code duplication related to cleanup Notice that sysfs_battery_cleanup() calls sysfs_remove_battery() under battery->update_lock which is also done in acpi_battery_remove(), so adjust the latter to use it. No intentional functional impact. Signed-off-by: Rafael J. Wysocki Link: https://patch.msgid.link/1866517.TLkxdtWsSY@rafael.j.wysocki --- drivers/acpi/battery.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 582c35fc8d03..4a66c6291102 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -1279,9 +1279,7 @@ static void acpi_battery_remove(struct acpi_device *device) device_init_wakeup(&device->dev, 0); unregister_pm_notifier(&battery->pm_nb); - guard(mutex)(&battery->update_lock); - - sysfs_remove_battery(battery); + sysfs_battery_cleanup(battery); } /* this is needed to learn about changes made in suspended state */ From 0a869409a981112565fac055739e9e2fd8575ade Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 15 Dec 2025 15:03:28 +0100 Subject: [PATCH 3/5] ACPI: battery: Convert the driver to a platform one While binding drivers directly to struct acpi_device objects allows basic functionality to be provided, at least in the majority of cases, there are some problems with it, related to general consistency, sysfs layout, power management operation ordering, and code cleanliness. Overall, it is better to bind drivers to platform devices than to their ACPI companions, so convert the ACPI battery driver to a platform one. While this is not expected to alter functionality, it changes sysfs layout and so it will be visible to user space. Signed-off-by: Rafael J. Wysocki Link: https://patch.msgid.link/3187448.CbtlEUcBR6@rafael.j.wysocki --- drivers/acpi/battery.c | 61 +++++++++++++++++++----------------------- 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 4a66c6291102..151a9f645511 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -17,6 +17,7 @@ #include #include #include +#include #include #include #include @@ -1208,26 +1209,26 @@ static void sysfs_battery_cleanup(struct acpi_battery *battery) sysfs_remove_battery(battery); } -static int acpi_battery_add(struct acpi_device *device) +static int acpi_battery_probe(struct platform_device *pdev) { - int result = 0; + struct acpi_device *device = ACPI_COMPANION(&pdev->dev); struct acpi_battery *battery; - - if (!device) - return -EINVAL; + int result; if (device->dep_unmet) return -EPROBE_DEFER; - battery = devm_kzalloc(&device->dev, sizeof(*battery), GFP_KERNEL); + battery = devm_kzalloc(&pdev->dev, sizeof(*battery), GFP_KERNEL); if (!battery) return -ENOMEM; + + platform_set_drvdata(pdev, battery); + battery->device = device; strscpy(acpi_device_name(device), ACPI_BATTERY_DEVICE_NAME); strscpy(acpi_device_class(device), ACPI_BATTERY_CLASS); - device->driver_data = battery; - result = devm_mutex_init(&device->dev, &battery->update_lock); + result = devm_mutex_init(&pdev->dev, &battery->update_lock); if (result) return result; @@ -1246,7 +1247,7 @@ static int acpi_battery_add(struct acpi_device *device) if (result) goto fail; - device_init_wakeup(&device->dev, 1); + device_init_wakeup(&pdev->dev, true); result = acpi_dev_install_notify_handler(device, ACPI_ALL_NOTIFY, acpi_battery_notify, battery); @@ -1256,7 +1257,7 @@ static int acpi_battery_add(struct acpi_device *device) return 0; fail_pm: - device_init_wakeup(&device->dev, 0); + device_init_wakeup(&pdev->dev, false); unregister_pm_notifier(&battery->pm_nb); fail: sysfs_battery_cleanup(battery); @@ -1264,19 +1265,18 @@ static int acpi_battery_add(struct acpi_device *device) return result; } -static void acpi_battery_remove(struct acpi_device *device) +static void acpi_battery_remove(struct platform_device *pdev) { - struct acpi_battery *battery; + struct acpi_device *device = ACPI_COMPANION(&pdev->dev); + struct acpi_battery *battery = platform_get_drvdata(pdev); - if (!device || !acpi_driver_data(device)) + if (!device || !battery) return; - battery = acpi_driver_data(device); - acpi_dev_remove_notify_handler(device, ACPI_ALL_NOTIFY, acpi_battery_notify); - device_init_wakeup(&device->dev, 0); + device_init_wakeup(&pdev->dev, false); unregister_pm_notifier(&battery->pm_nb); sysfs_battery_cleanup(battery); @@ -1285,12 +1285,8 @@ static void acpi_battery_remove(struct acpi_device *device) /* this is needed to learn about changes made in suspended state */ static int acpi_battery_resume(struct device *dev) { - struct acpi_battery *battery; + struct acpi_battery *battery = dev_get_drvdata(dev); - if (!dev) - return -EINVAL; - - battery = acpi_driver_data(to_acpi_device(dev)); if (!battery) return -EINVAL; @@ -1304,16 +1300,15 @@ static int acpi_battery_resume(struct device *dev) static DEFINE_SIMPLE_DEV_PM_OPS(acpi_battery_pm, NULL, acpi_battery_resume); -static struct acpi_driver acpi_battery_driver = { - .name = "battery", - .class = ACPI_BATTERY_CLASS, - .ids = battery_device_ids, - .ops = { - .add = acpi_battery_add, - .remove = acpi_battery_remove, - }, - .drv.pm = pm_sleep_ptr(&acpi_battery_pm), - .drv.probe_type = PROBE_PREFER_ASYNCHRONOUS, +static struct platform_driver acpi_battery_driver = { + .probe = acpi_battery_probe, + .remove = acpi_battery_remove, + .driver = { + .name = "acpi-battery", + .acpi_match_table = battery_device_ids, + .pm = pm_sleep_ptr(&acpi_battery_pm), + .probe_type = PROBE_PREFER_ASYNCHRONOUS, + }, }; static int __init acpi_battery_init(void) @@ -1323,12 +1318,12 @@ static int __init acpi_battery_init(void) dmi_check_system(bat_dmi_table); - return acpi_bus_register_driver(&acpi_battery_driver); + return platform_driver_register(&acpi_battery_driver); } static void __exit acpi_battery_exit(void) { - acpi_bus_unregister_driver(&acpi_battery_driver); + platform_driver_unregister(&acpi_battery_driver); battery_hook_exit(); } From b0c8ac52da5a1c00bb9ffdc231cbf2222297688d Mon Sep 17 00:00:00 2001 From: Can Peng Date: Tue, 9 Dec 2025 15:27:57 +0800 Subject: [PATCH 4/5] ACPI: acpi_watchdog: use LIST_HEAD for stack-allocated list Replace the separate declaration of 'resource_list' and subsequent INIT_LIST_HEAD() call with LIST_HEAD(), which declares and initializes the list head in one idiomatic step. This reduces code verbosity and aligns with common kernel coding patterns, without functional change. Signed-off-by: Can Peng [ rjw: Subject edits ] Link: https://patch.msgid.link/20251209072757.3110467-1-pengcan@kylinos.cn Signed-off-by: Rafael J. Wysocki --- drivers/acpi/acpi_watchdog.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/drivers/acpi/acpi_watchdog.c b/drivers/acpi/acpi_watchdog.c index 14b24157799c..709993c535d1 100644 --- a/drivers/acpi/acpi_watchdog.c +++ b/drivers/acpi/acpi_watchdog.c @@ -103,7 +103,7 @@ void __init acpi_watchdog_init(void) { const struct acpi_wdat_entry *entries; const struct acpi_table_wdat *wdat; - struct list_head resource_list; + LIST_HEAD(resource_list); struct resource_entry *rentry; struct platform_device *pdev; struct resource *resources; @@ -125,8 +125,6 @@ void __init acpi_watchdog_init(void) wdat->pci_device != 0xff || wdat->pci_function != 0xff) goto fail_put_wdat; - INIT_LIST_HEAD(&resource_list); - entries = (struct acpi_wdat_entry *)(wdat + 1); for (i = 0; i < wdat->entries; i++) { const struct acpi_generic_address *gas; From bb1256e0ddc7e9e406164319769b9f8d8389f056 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ata=20=C4=B0lhan=20K=C3=B6kt=C3=BCrk?= Date: Thu, 29 Jan 2026 17:48:56 +0300 Subject: [PATCH 5/5] ACPI: battery: fix incorrect charging status when current is zero MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On some laptops, such as the Huawei Matebook series, the embedded controller continues to report "Charging" status even when the charge threshold is reached and no current is being drawn. This incorrect reporting prevents the system from switching to battery power profiles, leading to significantly higher power (e.g., 18W instead of 7W during browsing) and missed remaining battery time estimation. Validate the "Charging" state by checking if rate_now is zero. If the hardware reports charging but the current is zero, report "Not Charging" to user space. Signed-off-by: Ata İlhan Köktürk [ rjw: Whitespace fix, braces added to an inner if (), new comment rewrite ] [ rjw: Changelog edits ] Link: https://patch.msgid.link/20260129144856.43058-1-atailhan2006@gmail.com Signed-off-by: Rafael J. Wysocki --- drivers/acpi/battery.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 151a9f645511..3bbddd6f622c 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -212,7 +212,14 @@ static int acpi_battery_get_property(struct power_supply *psy, if (battery->state & ACPI_BATTERY_STATE_DISCHARGING) val->intval = acpi_battery_handle_discharging(battery); else if (battery->state & ACPI_BATTERY_STATE_CHARGING) - val->intval = POWER_SUPPLY_STATUS_CHARGING; + /* Validate the status by checking the current. */ + if (battery->rate_now != ACPI_BATTERY_VALUE_UNKNOWN && + battery->rate_now == 0) { + /* On charge but no current (0W/0mA). */ + val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; + } else { + val->intval = POWER_SUPPLY_STATUS_CHARGING; + } else if (battery->state & ACPI_BATTERY_STATE_CHARGE_LIMITING) val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING; else if (acpi_battery_is_charged(battery))