summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authorume <ume@FreeBSD.org>2005-11-22 03:34:09 +0000
committerume <ume@FreeBSD.org>2005-11-22 03:34:09 +0000
commit3db092e2baccaa2eb0e8f9f1c8d7d7e812d081e3 (patch)
treef91348ecc69831ec3c0f35156950e7762ec79d94 /sys
parent9032fdcdd03f63174ba41e7d86ff25c502b2c093 (diff)
downloadFreeBSD-src-3db092e2baccaa2eb0e8f9f1c8d7d7e812d081e3.zip
FreeBSD-src-3db092e2baccaa2eb0e8f9f1c8d7d7e812d081e3.tar.gz
Cache the result of battery info retrieval from smbat as well
as cmbat. Reviewed by: njl MFC after: 3 days
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/acpica/acpi_smbat.c99
1 files changed, 77 insertions, 22 deletions
diff --git a/sys/dev/acpica/acpi_smbat.c b/sys/dev/acpica/acpi_smbat.c
index b88668f..37216e1 100644
--- a/sys/dev/acpica/acpi_smbat.c
+++ b/sys/dev/acpica/acpi_smbat.c
@@ -44,11 +44,18 @@ __FBSDID("$FreeBSD$");
struct acpi_smbat_softc {
uint8_t sb_base_addr;
device_t ec_dev;
+
+ struct acpi_bif bif;
+ struct acpi_bst bst;
+ struct timespec bif_lastupdated;
+ struct timespec bst_lastupdated;
};
static int acpi_smbat_probe(device_t dev);
static int acpi_smbat_attach(device_t dev);
static int acpi_smbat_shutdown(device_t dev);
+static int acpi_smbat_info_expired(struct timespec *lastupdated);
+static void acpi_smbat_info_updated(struct timespec *lastupdated);
static int acpi_smbat_get_bif(device_t dev, struct acpi_bif *bif);
static int acpi_smbat_get_bst(device_t dev, struct acpi_bst *bst);
@@ -114,6 +121,9 @@ acpi_smbat_attach(device_t dev)
return (ENXIO);
}
+ timespecclear(&sc->bif_lastupdated);
+ timespecclear(&sc->bst_lastupdated);
+
if (acpi_battery_register(dev) != 0) {
device_printf(dev, "cannot register battery\n");
return (ENXIO);
@@ -132,6 +142,34 @@ acpi_smbat_shutdown(device_t dev)
}
static int
+acpi_smbat_info_expired(struct timespec *lastupdated)
+{
+ struct timespec curtime;
+
+ ACPI_SERIAL_ASSERT(smbat);
+
+ if (lastupdated == NULL)
+ return (TRUE);
+ if (!timespecisset(lastupdated))
+ return (TRUE);
+
+ getnanotime(&curtime);
+ timespecsub(&curtime, lastupdated);
+ return (curtime.tv_sec < 0 ||
+ curtime.tv_sec > acpi_battery_get_info_expire());
+}
+
+static void
+acpi_smbat_info_updated(struct timespec *lastupdated)
+{
+
+ ACPI_SERIAL_ASSERT(smbat);
+
+ if (lastupdated != NULL)
+ getnanotime(lastupdated);
+}
+
+static int
acpi_smbus_read_2(struct acpi_smbat_softc *sc, uint8_t addr, uint8_t cmd,
uint16_t *ptr)
{
@@ -284,6 +322,11 @@ acpi_smbat_get_bst(device_t dev, struct acpi_bst *bst)
error = ENXIO;
sc = device_get_softc(dev);
+ if (!acpi_smbat_info_expired(&sc->bst_lastupdated)) {
+ error = 0;
+ goto out;
+ }
+
if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_BATTERY_MODE, &val))
goto out;
if (val & SMBATT_BM_CAPACITY_MODE) {
@@ -299,7 +342,7 @@ acpi_smbat_get_bst(device_t dev, struct acpi_bst *bst)
goto out;
if (val & SMBATT_BS_DISCHARGING) {
- bst->state |= ACPI_BATT_STAT_DISCHARG;
+ sc->bst.state |= ACPI_BATT_STAT_DISCHARG;
/*
* If the rate is negative, it is discharging. Otherwise,
@@ -308,27 +351,31 @@ acpi_smbat_get_bst(device_t dev, struct acpi_bst *bst)
if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_AT_RATE, &val))
goto out;
if (val < 0)
- bst->rate = (-val) * factor;
+ sc->bst.rate = (-val) * factor;
else
- bst->rate = -1;
+ sc->bst.rate = -1;
} else {
- bst->state |= ACPI_BATT_STAT_CHARGING;
- bst->rate = -1;
+ sc->bst.state |= ACPI_BATT_STAT_CHARGING;
+ sc->bst.rate = -1;
}
if (val & SMBATT_BS_REMAINING_CAPACITY_ALARM)
- bst->state |= ACPI_BATT_STAT_CRITICAL;
+ sc->bst.state |= ACPI_BATT_STAT_CRITICAL;
if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_REMAINING_CAPACITY, &val))
goto out;
- bst->cap = val * factor;
+ sc->bst.cap = val * factor;
if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_VOLTAGE, &val))
goto out;
- bst->volt = val;
+ sc->bst.volt = val;
+
+ acpi_smbat_info_updated(&sc->bst_lastupdated);
+
error = 0;
out:
+ memcpy(bst, &sc->bst, sizeof(sc->bst));
ACPI_SERIAL_END(smbat);
return (error);
}
@@ -348,55 +395,63 @@ acpi_smbat_get_bif(device_t dev, struct acpi_bif *bif)
error = ENXIO;
sc = device_get_softc(dev);
+ if (!acpi_smbat_info_expired(&sc->bif_lastupdated)) {
+ error = 0;
+ goto out;
+ }
+
if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_BATTERY_MODE, &val))
goto out;
if (val & SMBATT_BM_CAPACITY_MODE) {
factor = 10;
- bif->units = ACPI_BIF_UNITS_MW;
+ sc->bif.units = ACPI_BIF_UNITS_MW;
} else {
factor = 1;
- bif->units = ACPI_BIF_UNITS_MA;
+ sc->bif.units = ACPI_BIF_UNITS_MA;
}
if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_DESIGN_CAPACITY, &val))
goto out;
- bif->dcap = val * factor;
+ sc->bif.dcap = val * factor;
if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_FULL_CHARGE_CAPACITY, &val))
goto out;
- bif->lfcap = val * factor;
- bif->btech = 1; /* secondary (rechargeable) */
+ sc->bif.lfcap = val * factor;
+ sc->bif.btech = 1; /* secondary (rechargeable) */
if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_DESIGN_VOLTAGE, &val))
goto out;
- bif->dvol = val;
+ sc->bif.dvol = val;
- bif->wcap = bif->dcap / 10;
- bif->lcap = bif->dcap / 10;
+ sc->bif.wcap = sc->bif.dcap / 10;
+ sc->bif.lcap = sc->bif.dcap / 10;
- bif->gra1 = factor; /* not supported */
- bif->gra2 = factor; /* not supported */
+ sc->bif.gra1 = factor; /* not supported */
+ sc->bif.gra2 = factor; /* not supported */
if (acpi_smbus_read_multi_1(sc, addr, SMBATT_CMD_DEVICE_NAME,
- bif->model, sizeof(bif->model)))
+ sc->bif.model, sizeof(sc->bif.model)))
goto out;
if (acpi_smbus_read_2(sc, addr, SMBATT_CMD_SERIAL_NUMBER, &val))
goto out;
- snprintf(bif->serial, sizeof(bif->serial), "0x%04x", val);
+ snprintf(sc->bif.serial, sizeof(sc->bif.serial), "0x%04x", val);
if (acpi_smbus_read_multi_1(sc, addr, SMBATT_CMD_DEVICE_CHEMISTRY,
- bif->type, sizeof(bif->type)))
+ sc->bif.type, sizeof(sc->bif.type)))
goto out;
if (acpi_smbus_read_multi_1(sc, addr, SMBATT_CMD_MANUFACTURER_DATA,
- bif->oeminfo, sizeof(bif->oeminfo)))
+ sc->bif.oeminfo, sizeof(sc->bif.oeminfo)))
goto out;
+ acpi_smbat_info_updated(&sc->bif_lastupdated);
+
/* XXX check if device was replugged during read? */
error = 0;
out:
+ memcpy(bif, &sc->bif, sizeof(sc->bif));
ACPI_SERIAL_END(smbat);
return (error);
}
OpenPOWER on IntegriCloud