From: Peter Marheine pmarheine@chromium.org
[ Upstream commit 234f71555019d308c6bc6f98c78c5551cb8cd56a ]
The ACPI specification requires that battery rate is always positive, but the kernel ABI for POWER_SUPPLY_PROP_CURRENT_NOW (Documentation/ABI/testing/sysfs-class-power) specifies that it should be negative when a battery is discharging. When reporting CURRENT_NOW, massage the value to match the documented ABI.
This only changes the sign of `current_now` and not `power_now` because documentation doesn't describe any particular meaning for `power_now` so leaving `power_now` unchanged is less likely to confuse userspace unnecessarily, whereas becoming consistent with the documented ABI is worth potentially confusing clients that read `current_now`.
Signed-off-by: Peter Marheine pmarheine@chromium.org Link: https://patch.msgid.link/20250508024146.1436129-1-pmarheine@chromium.org Signed-off-by: Rafael J. Wysocki rafael.j.wysocki@intel.com Signed-off-by: Sasha Levin sashal@kernel.org ---
Based on my analysis of the commit and examination of the kernel codebase, I can now provide my assessment: **YES** This commit should be backported to stable kernel trees because: 1. **Fixes a real user-facing bug**: The commit addresses an ABI inconsistency where ACPI battery drivers were reporting current_now with the wrong sign. According to the kernel's power supply ABI documentation (Documentation/ABI/testing/sysfs-class-power), `current_now` should be negative when discharging and positive when charging, but ACPI battery drivers were reporting positive values always. 2. **Small and contained fix**: The change is minimal and well-contained. It only affects the `POWER_SUPPLY_PROP_CURRENT_NOW` case in `acpi_battery_get_property()` function in `drivers/acpi/battery.c`. The code adds a simple check to negate the current value only when: - Property requested is `POWER_SUPPLY_PROP_CURRENT_NOW` (not power_now) - Battery is in discharging state - The `acpi_battery_handle_discharging()` function confirms it's actually discharging 3. **Follows stable rules**: This is an important bugfix that corrects userspace-visible behavior to match documented ABI. Applications and battery monitoring tools rely on the documented behavior that negative current indicates discharging. 4. **Minimal regression risk**: The change is very conservative: - Only affects `current_now`, not `power_now` (as noted in commit message) - Uses existing `acpi_battery_handle_discharging()` logic to double-check the discharging state - Leaves all other battery properties unchanged 5. **Similar pattern in similar drivers**: From the historical examples provided, commits like "power: supply: bq27xxx: fix polarity of current_now" and "power: supply: axp20x_battery: properly report current when discharging" were backported with YES status for exactly the same type of issue - fixing current sign during discharge. 6. **Affects critical subsystem**: Battery reporting is crucial for power management, and incorrect current direction can confuse userspace tools and potentially impact power management decisions. The commit carefully addresses the ABI compliance issue while minimizing risk by only changing the sign for `current_now` during confirmed discharging states, making it an ideal candidate for stable backporting.
drivers/acpi/battery.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 6760330a8af55..93bb1f7d90986 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -243,10 +243,23 @@ static int acpi_battery_get_property(struct power_supply *psy, break; case POWER_SUPPLY_PROP_CURRENT_NOW: case POWER_SUPPLY_PROP_POWER_NOW: - if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN) + if (battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN) { ret = -ENODEV; - else - val->intval = battery->rate_now * 1000; + break; + } + + val->intval = battery->rate_now * 1000; + /* + * When discharging, the current should be reported as a + * negative number as per the power supply class interface + * definition. + */ + if (psp == POWER_SUPPLY_PROP_CURRENT_NOW && + (battery->state & ACPI_BATTERY_STATE_DISCHARGING) && + acpi_battery_handle_discharging(battery) + == POWER_SUPPLY_STATUS_DISCHARGING) + val->intval = -val->intval; + break; case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN: case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN: