Correct the way remaining battery life is calculated

Previously, if a system had multiple batteries, the remaining life
percentage was calculated as the average of each battery's percent
remaining. This results in rather incorrect values when you consider the
case of the Thinkpad X270 that has a small 3 cell internally battery, and
a hot-swappable 9 cell battery that is used first. Battery 0 is at 100%,
but battery 1 is at 10%, you do not infact have 55% of your capacity
remaining.

The new method calculates the percentage based on remaining capacity
out of total capacity, giving a much more accurate reading.

PR:		229818
Submitted by:	Keegan Drake H.P. <kd-dev@pm.me>
MFC after:	2 weeks
Sponsored by:	Klara Systems
Event:		Waterloo Hackathon 2019
This commit is contained in:
allanjude 2019-05-21 21:14:22 +00:00
parent 3038f1af7b
commit e7fc15972b

View File

@ -119,7 +119,7 @@ int
acpi_battery_get_battinfo(device_t dev, struct acpi_battinfo *battinfo)
{
int batt_stat, devcount, dev_idx, error, i;
int total_cap, total_min, valid_rate, valid_units;
int total_cap, total_lfcap, total_min, valid_rate, valid_units;
devclass_t batt_dc;
device_t batt_dev;
struct acpi_bst *bst;
@ -152,6 +152,7 @@ acpi_battery_get_battinfo(device_t dev, struct acpi_battinfo *battinfo)
*/
dev_idx = -1;
batt_stat = valid_rate = valid_units = 0;
total_cap = total_lfcap = 0;
for (i = 0; i < devcount; i++) {
/* Default info for every battery is "not present". */
acpi_reset_battinfo(&bi[i]);
@ -210,16 +211,22 @@ acpi_battery_get_battinfo(device_t dev, struct acpi_battinfo *battinfo)
if (!acpi_battery_bif_valid(bif))
continue;
/* Calculate percent capacity remaining. */
bi[i].cap = (100 * bst[i].cap) / bif->lfcap;
/*
* Some laptops report the "design-capacity" instead of the
* "real-capacity" when the battery is fully charged. That breaks
* the above arithmetic as it needs to be 100% maximum.
*/
if (bi[i].cap > 100)
bi[i].cap = 100;
if (bst[i].cap > bif->lfcap)
bst[i].cap = bif->lfcap;
/* Calculate percent capacity remaining. */
bi[i].cap = (100 * bst[i].cap) / bif->lfcap;
/* If this battery is not present, don't use its capacity. */
if (bi[i].cap != -1) {
total_cap += bst[i].cap;
total_lfcap += bif->lfcap;
}
/*
* On systems with more than one battery, they may get used
@ -241,7 +248,7 @@ acpi_battery_get_battinfo(device_t dev, struct acpi_battinfo *battinfo)
}
/* Pass 2: calculate capacity and remaining time for all batteries. */
total_cap = total_min = 0;
total_min = 0;
for (i = 0; i < devcount; i++) {
/*
* If any batteries are discharging, use the sum of the bst.rate
@ -253,10 +260,6 @@ acpi_battery_get_battinfo(device_t dev, struct acpi_battinfo *battinfo)
else
bi[i].min = 0;
total_min += bi[i].min;
/* If this battery is not present, don't use its capacity. */
if (bi[i].cap != -1)
total_cap += bi[i].cap;
}
/*
@ -265,7 +268,7 @@ acpi_battery_get_battinfo(device_t dev, struct acpi_battinfo *battinfo)
*/
if (valid_units > 0) {
if (dev == NULL) {
battinfo->cap = total_cap / valid_units;
battinfo->cap = (total_cap * 100) / total_lfcap;
battinfo->min = total_min;
battinfo->state = batt_stat;
battinfo->rate = valid_rate;