Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 5 Jun 2019 20:31:09 +0000 (UTC)
From:      Allan Jude <allanjude@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-12@freebsd.org
Subject:   svn commit: r348703 - stable/12/sys/dev/acpica
Message-ID:  <201906052031.x55KV9uk045615@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: allanjude
Date: Wed Jun  5 20:31:09 2019
New Revision: 348703
URL: https://svnweb.freebsd.org/changeset/base/348703

Log:
  MFC r348065:
  
  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>
  Sponsored by:	Klara Systems
  Event:		Waterloo Hackathon 2019

Modified:
  stable/12/sys/dev/acpica/acpi_battery.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/dev/acpica/acpi_battery.c
==============================================================================
--- stable/12/sys/dev/acpica/acpi_battery.c	Wed Jun  5 20:27:26 2019	(r348702)
+++ stable/12/sys/dev/acpica/acpi_battery.c	Wed Jun  5 20:31:09 2019	(r348703)
@@ -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_ba
      */
     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]);
@@ -213,17 +214,23 @@ acpi_battery_get_battinfo(device_t dev, struct acpi_ba
 	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
 	 * sequentially, thus bst.rate may only signify the one currently
@@ -244,7 +251,7 @@ acpi_battery_get_battinfo(device_t dev, struct acpi_ba
     }
 
     /* 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
@@ -256,10 +263,6 @@ acpi_battery_get_battinfo(device_t dev, struct acpi_ba
 	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;
     }
 
     /*
@@ -268,7 +271,7 @@ acpi_battery_get_battinfo(device_t dev, struct acpi_ba
      */
     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;



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201906052031.x55KV9uk045615>