ACPI / battery: Add handling for devices which wrongly report discharging state
authorHans de Goede <hdegoede@redhat.com>
Thu, 12 Apr 2018 10:01:59 +0000 (12:01 +0200)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Wed, 2 May 2018 11:06:59 +0000 (13:06 +0200)
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
fuel-gauge.

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>
drivers/acpi/battery.c

index 338432cbef09a26005ad37ff8f19e32b37e89cab..bd36cb5c3fe1d91b6c13c6f19a1dd31e6c074e7b 100644 (file)
@@ -215,6 +215,19 @@ static bool acpi_battery_is_degraded(struct acpi_battery *battery)
                battery->full_charge_capacity < battery->design_capacity;
 }
 
+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)
+               return POWER_SUPPLY_STATUS_NOT_CHARGING;
+
+       return POWER_SUPPLY_STATUS_DISCHARGING;
+}
+
 static int acpi_battery_get_property(struct power_supply *psy,
                                     enum power_supply_property psp,
                                     union power_supply_propval *val)
@@ -230,7 +243,7 @@ static int acpi_battery_get_property(struct power_supply *psy,
        switch (psp) {
        case POWER_SUPPLY_PROP_STATUS:
                if (battery->state & ACPI_BATTERY_STATE_DISCHARGING)
-                       val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+                       val->intval = acpi_battery_handle_discharging(battery);
                else if (battery->state & ACPI_BATTERY_STATE_CHARGING)
                        val->intval = POWER_SUPPLY_STATUS_CHARGING;
                else if (acpi_battery_is_charged(battery))