summaryrefslogtreecommitdiff
path: root/drivers/acpi/battery.c
diff options
context:
space:
mode:
authorHans de Goede <hdegoede@redhat.com>2018-04-12 13:01:59 +0300
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2018-05-02 14:06:59 +0300
commit19fffc8450d4378580a8f019b195c4617083176f (patch)
treea88adf5ea1530d8a46ff1a28dfa8e41cabe250b5 /drivers/acpi/battery.c
parent91afa07664a8d26f51fb59b13fd5fa3592b728bc (diff)
downloadlinux-19fffc8450d4378580a8f019b195c4617083176f.tar.xz
ACPI / battery: Add handling for devices which wrongly report discharging state
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>
Diffstat (limited to 'drivers/acpi/battery.c')
-rw-r--r--drivers/acpi/battery.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index 338432cbef09..bd36cb5c3fe1 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -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))