diff options
-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 7b8787b490f6..0b2707ee094b 100644 --- a/drivers/acpi/battery.c +++ b/drivers/acpi/battery.c | |||
@@ -95,6 +95,7 @@ enum { | |||
95 | * due to bad math. | 95 | * due to bad math. |
96 | */ | 96 | */ |
97 | ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, | 97 | ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, |
98 | ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, | ||
98 | }; | 99 | }; |
99 | 100 | ||
100 | struct acpi_battery { | 101 | struct acpi_battery { |
@@ -405,6 +406,8 @@ static int acpi_battery_get_info(struct acpi_battery *battery) | |||
405 | result = extract_package(battery, buffer.pointer, | 406 | result = extract_package(battery, buffer.pointer, |
406 | info_offsets, ARRAY_SIZE(info_offsets)); | 407 | info_offsets, ARRAY_SIZE(info_offsets)); |
407 | kfree(buffer.pointer); | 408 | kfree(buffer.pointer); |
409 | if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)) | ||
410 | battery->full_charge_capacity = battery->design_capacity; | ||
408 | return result; | 411 | return result; |
409 | } | 412 | } |
410 | 413 | ||
@@ -441,6 +444,10 @@ static int acpi_battery_get_state(struct acpi_battery *battery) | |||
441 | battery->rate_now != -1) | 444 | battery->rate_now != -1) |
442 | battery->rate_now = abs((s16)battery->rate_now); | 445 | battery->rate_now = abs((s16)battery->rate_now); |
443 | 446 | ||
447 | if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags) | ||
448 | && battery->capacity_now >= 0 && battery->capacity_now <= 100) | ||
449 | battery->capacity_now = (battery->capacity_now * | ||
450 | battery->full_charge_capacity) / 100; | ||
444 | return result; | 451 | return result; |
445 | } | 452 | } |
446 | 453 | ||
@@ -552,6 +559,33 @@ static void acpi_battery_quirks(struct acpi_battery *battery) | |||
552 | } | 559 | } |
553 | } | 560 | } |
554 | 561 | ||
562 | /* | ||
563 | * According to the ACPI spec, some kinds of primary batteries can | ||
564 | * report percentage battery remaining capacity directly to OS. | ||
565 | * In this case, it reports the Last Full Charged Capacity == 100 | ||
566 | * and BatteryPresentRate == 0xFFFFFFFF. | ||
567 | * | ||
568 | * Now we found some battery reports percentage remaining capacity | ||
569 | * even if it's rechargeable. | ||
570 | * https://bugzilla.kernel.org/show_bug.cgi?id=15979 | ||
571 | * | ||
572 | * Handle this correctly so that they won't break userspace. | ||
573 | */ | ||
574 | static void acpi_battery_quirks2(struct acpi_battery *battery) | ||
575 | { | ||
576 | if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)) | ||
577 | return ; | ||
578 | |||
579 | if (battery->full_charge_capacity == 100 && | ||
580 | battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN && | ||
581 | battery->capacity_now >=0 && battery->capacity_now <= 100) { | ||
582 | set_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags); | ||
583 | battery->full_charge_capacity = battery->design_capacity; | ||
584 | battery->capacity_now = (battery->capacity_now * | ||
585 | battery->full_charge_capacity) / 100; | ||
586 | } | ||
587 | } | ||
588 | |||
555 | static int acpi_battery_update(struct acpi_battery *battery) | 589 | static int acpi_battery_update(struct acpi_battery *battery) |
556 | { | 590 | { |
557 | int result, old_present = acpi_battery_present(battery); | 591 | int result, old_present = acpi_battery_present(battery); |
@@ -573,7 +607,9 @@ static int acpi_battery_update(struct acpi_battery *battery) | |||
573 | } | 607 | } |
574 | if (!battery->bat.dev) | 608 | if (!battery->bat.dev) |
575 | sysfs_add_battery(battery); | 609 | sysfs_add_battery(battery); |
576 | return acpi_battery_get_state(battery); | 610 | result = acpi_battery_get_state(battery); |
611 | acpi_battery_quirks2(battery); | ||
612 | return result; | ||
577 | } | 613 | } |
578 | 614 | ||
579 | /* -------------------------------------------------------------------------- | 615 | /* -------------------------------------------------------------------------- |