From 5e44538fcd0b9fa083642ab257ef021e79e8d9c0 Mon Sep 17 00:00:00 2001 From: Sascha Wildner Date: Sat, 13 Sep 2014 00:42:14 +0200 Subject: [PATCH] kernel/acpi: Sync acpi_battery and acpi_cmbat with FreeBSD. --- sys/dev/acpica/acpi_battery.c | 14 +++++++++++--- sys/dev/acpica/acpi_cmbat.c | 8 +++++++- sys/dev/acpica/acpiio.h | 15 +++++++++++++-- 3 files changed, 31 insertions(+), 6 deletions(-) diff --git a/sys/dev/acpica/acpi_battery.c b/sys/dev/acpica/acpi_battery.c index a23a66409c..e9602b1e5d 100644 --- a/sys/dev/acpica/acpi_battery.c +++ b/sys/dev/acpica/acpi_battery.c @@ -24,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/sys/dev/acpica/acpi_battery.c,v 1.30 2009/08/20 19:17:53 jhb + * $FreeBSD: head/sys/dev/acpica/acpi_battery.c 227992 2011-11-26 13:43:50Z dumbbell $ */ #include "opt_acpi.h" @@ -101,8 +101,8 @@ acpi_battery_get_info_expire(void) int acpi_battery_bst_valid(struct acpi_bst *bst) { - return (bst->state < ACPI_BATT_STAT_MAX && bst->cap != ACPI_BATT_UNKNOWN && - bst->volt != ACPI_BATT_UNKNOWN); + return (bst->state != ACPI_BATT_STAT_NOT_PRESENT && + bst->cap != ACPI_BATT_UNKNOWN && bst->volt != ACPI_BATT_UNKNOWN); } /* Check _BIF results for validity. */ @@ -203,6 +203,14 @@ acpi_battery_get_battinfo(device_t dev, struct acpi_battinfo *battinfo) bif->lfcap = (bif->lfcap * bif->dvol) / 1000; } + /* + * The calculation above may set bif->lfcap to zero. This was + * seen on a laptop with a broken battery. The result of the + * division was rounded to zero. + */ + if (!acpi_battery_bif_valid(bif)) + continue; + /* Calculate percent capacity remaining. */ bi[i].cap = (100 * bst[i].cap) / bif->lfcap; diff --git a/sys/dev/acpica/acpi_cmbat.c b/sys/dev/acpica/acpi_cmbat.c index 28f2b6fa1f..401a908487 100644 --- a/sys/dev/acpica/acpi_cmbat.c +++ b/sys/dev/acpica/acpi_cmbat.c @@ -26,7 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/sys/dev/acpica/acpi_cmbat.c,v 1.46.8.1 2009/04/15 03:14:26 kensmith Exp $ + * $FreeBSD: head/sys/dev/acpica/acpi_cmbat.c 246128 2013-01-30 18:01:20Z sbz $ */ #include "opt_acpi.h" @@ -274,6 +274,12 @@ acpi_cmbat_get_bst(void *arg) goto end; acpi_cmbat_info_updated(&sc->bst_lastupdated); + /* Clear out undefined/extended bits that might be set by hardware. */ + sc->bst.state &= ACPI_BATT_STAT_BST_MASK; + if ((sc->bst.state & ACPI_BATT_STAT_INVALID) == ACPI_BATT_STAT_INVALID) + ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), + "battery reports simultaneous charging and discharging\n"); + /* XXX If all batteries are critical, perhaps we should suspend. */ if (sc->bst.state & ACPI_BATT_STAT_CRITICAL) { if ((sc->flags & ACPI_BATT_STAT_CRITICAL) == 0) { diff --git a/sys/dev/acpica/acpiio.h b/sys/dev/acpica/acpiio.h index 0b4bba25ee..7829438182 100644 --- a/sys/dev/acpica/acpiio.h +++ b/sys/dev/acpica/acpiio.h @@ -76,11 +76,22 @@ struct acpi_bst { uint32_t volt; /* Present Voltage */ }; +/* + * Note that the following definitions represent status bits for internal + * driver state. The first three of them (charging, discharging and critical) + * conveninetly conform to ACPI specification of status returned by _BST + * method. Other definitions (not present, etc) are synthetic. + * Also note that according to the specification the charging and discharging + * status bits must not be set at the same time. + */ #define ACPI_BATT_STAT_DISCHARG 0x0001 #define ACPI_BATT_STAT_CHARGING 0x0002 #define ACPI_BATT_STAT_CRITICAL 0x0004 -#define ACPI_BATT_STAT_NOT_PRESENT 0x0007 -#define ACPI_BATT_STAT_MAX 0x0007 +#define ACPI_BATT_STAT_INVALID \ + (ACPI_BATT_STAT_DISCHARG | ACPI_BATT_STAT_CHARGING) +#define ACPI_BATT_STAT_BST_MASK \ + (ACPI_BATT_STAT_INVALID | ACPI_BATT_STAT_CRITICAL) +#define ACPI_BATT_STAT_NOT_PRESENT ACPI_BATT_STAT_BST_MASK union acpi_battery_ioctl_arg { int unit; /* Device unit or ACPI_BATTERY_ALL_UNITS. */ -- 2.41.0