]>
Commit | Line | Data |
---|---|---|
d9b1f36d GKH |
1 | From 557d58687dcdee6bc00c1a8f1fd4e0eac8fefce9 Mon Sep 17 00:00:00 2001 |
2 | From: Zhang Rui <rui.zhang@intel.com> | |
3 | Date: Fri, 22 Oct 2010 10:02:06 +0800 | |
4 | Subject: ACPI battery: support percentage battery remaining capacity | |
5 | ||
6 | From: Zhang Rui <rui.zhang@intel.com> | |
7 | ||
8 | commit 557d58687dcdee6bc00c1a8f1fd4e0eac8fefce9 upstream. | |
9 | ||
10 | According to the ACPI spec, some kinds of primary battery can | |
11 | report percentage battery remaining capacity directly to OS. | |
12 | ||
13 | In this case, it reports the LastFullChargedCapacity == 100, | |
14 | BatteryPresentRate = 0xFFFFFFFF, and BatteryRemaingCapacity a | |
15 | percentage value, which actually means RemainingBatteryPercentage. | |
16 | ||
17 | Now we found some battery follows this rule even if it's a rechargeable. | |
18 | https://bugzilla.kernel.org/show_bug.cgi?id=15979 | |
19 | ||
20 | Handle these batteries correctly in ACPI battery driver | |
21 | so that they won't break userspace. | |
22 | ||
23 | Signed-off-by: Zhang Rui <rui.zhang@intel.com> | |
24 | Tested-by: Sitsofe Wheeler <sitsofe@yahoo.com> | |
25 | Signed-off-by: Len Brown <len.brown@intel.com> | |
26 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | |
27 | ||
28 | --- | |
29 | drivers/acpi/battery.c | 38 +++++++++++++++++++++++++++++++++++++- | |
30 | 1 file changed, 37 insertions(+), 1 deletion(-) | |
31 | ||
32 | --- a/drivers/acpi/battery.c | |
33 | +++ b/drivers/acpi/battery.c | |
34 | @@ -98,6 +98,7 @@ enum { | |
35 | * due to bad math. | |
36 | */ | |
37 | ACPI_BATTERY_QUIRK_SIGNED16_CURRENT, | |
38 | + ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, | |
39 | }; | |
40 | ||
41 | struct acpi_battery { | |
42 | @@ -412,6 +413,8 @@ static int acpi_battery_get_info(struct | |
43 | result = extract_package(battery, buffer.pointer, | |
44 | info_offsets, ARRAY_SIZE(info_offsets)); | |
45 | kfree(buffer.pointer); | |
46 | + if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)) | |
47 | + battery->full_charge_capacity = battery->design_capacity; | |
48 | return result; | |
49 | } | |
50 | ||
51 | @@ -448,6 +451,10 @@ static int acpi_battery_get_state(struct | |
52 | battery->rate_now != -1) | |
53 | battery->rate_now = abs((s16)battery->rate_now); | |
54 | ||
55 | + if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags) | |
56 | + && battery->capacity_now >= 0 && battery->capacity_now <= 100) | |
57 | + battery->capacity_now = (battery->capacity_now * | |
58 | + battery->full_charge_capacity) / 100; | |
59 | return result; | |
60 | } | |
61 | ||
62 | @@ -561,6 +568,33 @@ static void acpi_battery_quirks(struct a | |
63 | } | |
64 | } | |
65 | ||
66 | +/* | |
67 | + * According to the ACPI spec, some kinds of primary batteries can | |
68 | + * report percentage battery remaining capacity directly to OS. | |
69 | + * In this case, it reports the Last Full Charged Capacity == 100 | |
70 | + * and BatteryPresentRate == 0xFFFFFFFF. | |
71 | + * | |
72 | + * Now we found some battery reports percentage remaining capacity | |
73 | + * even if it's rechargeable. | |
74 | + * https://bugzilla.kernel.org/show_bug.cgi?id=15979 | |
75 | + * | |
76 | + * Handle this correctly so that they won't break userspace. | |
77 | + */ | |
78 | +static void acpi_battery_quirks2(struct acpi_battery *battery) | |
79 | +{ | |
80 | + if (test_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags)) | |
81 | + return ; | |
82 | + | |
83 | + if (battery->full_charge_capacity == 100 && | |
84 | + battery->rate_now == ACPI_BATTERY_VALUE_UNKNOWN && | |
85 | + battery->capacity_now >=0 && battery->capacity_now <= 100) { | |
86 | + set_bit(ACPI_BATTERY_QUIRK_PERCENTAGE_CAPACITY, &battery->flags); | |
87 | + battery->full_charge_capacity = battery->design_capacity; | |
88 | + battery->capacity_now = (battery->capacity_now * | |
89 | + battery->full_charge_capacity) / 100; | |
90 | + } | |
91 | +} | |
92 | + | |
93 | static int acpi_battery_update(struct acpi_battery *battery) | |
94 | { | |
95 | int result, old_present = acpi_battery_present(battery); | |
96 | @@ -586,7 +620,9 @@ static int acpi_battery_update(struct ac | |
97 | if (!battery->bat.dev) | |
98 | sysfs_add_battery(battery); | |
99 | #endif | |
100 | - return acpi_battery_get_state(battery); | |
101 | + result = acpi_battery_get_state(battery); | |
102 | + acpi_battery_quirks2(battery); | |
103 | + return result; | |
104 | } | |
105 | ||
106 | /* -------------------------------------------------------------------------- |