[4/5] ACPI / battery: Add handling for devices which wrongly report discharging state

Message ID 20190202153757.26990-5-kai.heng.feng@canonical.com
State New
Headers show
  • [1/5] Revert "ACPI / battery: Add quirk for Asus GL502VSK and UX305LA"
Related show

Commit Message

Kai-Heng Feng Feb. 2, 2019, 3:37 p.m.
From: Hans de Goede <hdegoede@redhat.com>

BugLink: https://bugs.launchpad.net/bugs/1745032

On quite a few devices the battery code in the ACPI tables is buggy and
first checks the charging status bits of the charger-IC, and if those
report not charging it will report discharging, without looking at the
presence of AC power or at the battery dis(charge) current from the

This causes the wrong status to be reported for the battery in the
following quite common scenario:

1) Plug in charger while battery is say half full, battery starts
charging, charging state bits indicate: pre-charge or fast-charge,
ACPI reported battery status is ok

2) When fully charged charging state bits indicate: end-of-charge,
ACPI reported battery status is ok

3) unplug the charger, wait 1 minute, replug. Now the battery voltage is
still above the start-charging threshold, so the charger will not start
charging to avoid wrecking the battery by repeatedly recharging the last 1%
capacity. The charger IC charging state bits now are all 0 (not-charging)
and the broken ACPI code wrongly translate this to "discharging" and ends
up setting the ACPI_BATTERY_STATE_DISCHARGING bit in its state field.

Reporting this "not charging" state as discharging is confusing for users,
making the user think his adapter/power-brick is broken or not properly
plugged in.

This commit adds a helper for handling the ACPI_BATTERY_STATE_DISCHARGING
state. This helper checks if we're an AC and the current going out of the
battery is 0 and in that case reports a status of "not charging" to
userspace rather then "discharging".

This replaces commit c68f0676ef7d ("ACPI / battery: Add quirk for Asus
GL502VSK and UX305LA"), a previous fix for this which was reverted.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Reviewed-by: Daniel Drake <drake@endlessm.com>
Reviewed-by: Sebastian Reichel <sebastian.reichel@collabora.co.uk>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
(backported from commit 19fffc8450d4378580a8f019b195c4617083176f)
Signed-off-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
 drivers/acpi/battery.c | 15 ++++++++++++++-
 1 file changed, 14 insertions(+), 1 deletion(-)


diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 6fe6b2e37334..5b4e0a49ddc4 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -200,6 +200,19 @@  static int acpi_battery_is_charged(struct acpi_battery *battery)
 	return 0;
+static int acpi_battery_handle_discharging(struct acpi_battery *battery)
+	/*
+	 * Some devices wrongly report discharging if the battery's charge level
+	 * was above the device's start charging threshold atm the AC adapter
+	 * was plugged in and the device thus did not start a new charge cycle.
+	 */
+	if (power_supply_is_system_supplied() && battery->rate_now == 0)
 static int acpi_battery_get_property(struct power_supply *psy,
 				     enum power_supply_property psp,
 				     union power_supply_propval *val)
@@ -215,7 +228,7 @@  static int acpi_battery_get_property(struct power_supply *psy,
 	switch (psp) {
 		if (battery->state & ACPI_BATTERY_STATE_DISCHARGING)
+			val->intval = acpi_battery_handle_discharging(battery);
 		else if (battery->state & ACPI_BATTERY_STATE_CHARGING)
 		else if (acpi_battery_is_charged(battery))