diff options
Diffstat (limited to 'drivers/acpi/battery.c')
-rw-r--r-- | drivers/acpi/battery.c | 38 |
1 files changed, 37 insertions, 1 deletions
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c index 7b8787b490f..0b2707ee094 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c @@ -95,6 +95,7 @@ enum { * due to bad math. */ ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, + ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, }; struct acpi_battery { @@ -405,6 +406,8 @@ static int acpi_battery_get_info(struct acpi_battery *battery) result = extract_package(battery, buffer.pointer, info_offsets, ARRAY_SIZE(info_offsets)); kfree(buffer.pointer); + if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)) + battery->full_charge_capacity = battery->design_capacity; return result; } @@ -441,6 +444,10 @@ static int acpi_battery_get_state(struct acpi_battery *battery) battery->rate_now != -1) battery->rate_now = abs((s16)battery->rate_now); + if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags) + && battery->capacity_now >= 0 && battery->capacity_now <= 100) + battery->capacity_now = (battery->capacity_now * + battery->full_charge_capacity) / 100; return result; } @@ -552,6 +559,33 @@ static void acpi_battery_quirks(struct acpi_battery *battery) } } +/* + * According to the ACPI spec, some kinds of primary batteries can + * report percentage battery remaining capacity directly to OS. + * In this case, it reports the Last Full Charged Capacity == 100 + * and BatteryPresentRate == 0xFFFFFFFF. + * + * Now we found some battery reports percentage remaining capacity + * even if it's rechargeable. + * https://bugzilla.kernel.org/show_bug.cgi?id=15979 + * + * Handle this correctly so that they won't break userspace. + */ +static void acpi_battery_quirks2(struct acpi_battery *battery) +{ + if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)) + return ; + + if (battery->full_charge_capacity == 100 && + battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN && + battery->capacity_now >=0 && battery->capacity_now <= 100) { + set_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags); + battery->full_charge_capacity = battery->design_capacity; + battery->capacity_now = (battery->capacity_now * + battery->full_charge_capacity) / 100; + } +} + static int acpi_battery_update(struct acpi_battery *battery) { int result, old_present = acpi_battery_present(battery); @@ -573,7 +607,9 @@ static int acpi_battery_update(struct acpi_battery *battery) } if (!battery->bat.dev) sysfs_add_battery(battery); - return acpi_battery_get_state(battery); + result = acpi_battery_get_state(battery); + acpi_battery_quirks2(battery); + return result; } /* -------------------------------------------------------------------------- |