diff options
author | iwasaki <iwasaki@FreeBSD.org> | 2002-11-03 10:49:24 +0000 |
---|---|---|
committer | iwasaki <iwasaki@FreeBSD.org> | 2002-11-03 10:49:24 +0000 |
commit | d9788486227b0e8d3ca3f9538e8689742e19c592 (patch) | |
tree | 0364af86aac1f458e1106c83143eaf9dff085b7b /sys/dev/acpica | |
parent | f83a3fa3ad21dc6517182b1d2684f2b8e8f794d5 (diff) | |
download | FreeBSD-src-d9788486227b0e8d3ca3f9538e8689742e19c592.zip FreeBSD-src-d9788486227b0e8d3ca3f9538e8689742e19c592.tar.gz |
Add status initialization code for acpi_cmbat and acpi_acad,
acpi_cmbat_init_battery() and acpi_cmbat_init_acline() respectively.
Call acpi_cmbat_init_battery() from acpi_cmbat_resume() too just in
case.
This is a workaround for embedded controller operations which is
unstable for about a minute (typically 30 or 40 sec.) at boot time.
Diffstat (limited to 'sys/dev/acpica')
-rw-r--r-- | sys/dev/acpica/acpi_acad.c | 38 | ||||
-rw-r--r-- | sys/dev/acpica/acpi_cmbat.c | 89 |
2 files changed, 120 insertions, 7 deletions
diff --git a/sys/dev/acpica/acpi_acad.c b/sys/dev/acpica/acpi_acad.c index 2c9daf9..d7e8ebd 100644 --- a/sys/dev/acpica/acpi_acad.c +++ b/sys/dev/acpica/acpi_acad.c @@ -59,9 +59,12 @@ static int acpi_acad_probe(device_t); static int acpi_acad_attach(device_t); static int acpi_acad_ioctl(u_long, caddr_t, void *); static int acpi_acad_sysctl(SYSCTL_HANDLER_ARGS); +static void acpi_acad_init_acline(void *arg); struct acpi_acad_softc { int status; + + int initializing; }; static void @@ -157,7 +160,9 @@ acpi_acad_attach(device_t dev) /* Get initial status after whole system is up. */ sc->status = -1; - AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_acad_get_status, dev); + sc->initializing = 0; + + AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_acad_init_acline, dev); return(0); } @@ -215,6 +220,37 @@ acpi_acad_sysctl(SYSCTL_HANDLER_ARGS) return (error); } +static void +acpi_acad_init_acline(void *arg) +{ + int retry; + int status; + device_t dev = (device_t)arg; + struct acpi_acad_softc *sc = device_get_softc(dev); +#define ACPI_ACAD_RETRY_MAX 6 + + if (sc->initializing) { + return; + } + + sc->initializing = 1; + + ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), + "acline initialization start\n"); + + status = 0; + for (retry = 0; retry < ACPI_ACAD_RETRY_MAX; retry++, AcpiOsSleep(10, 0)) { + acpi_acad_get_status(dev); + if (status != sc->status) + break; + } + + ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), + "acline initialization done, tried %d times\n", retry+1); + + sc->initializing = 0; +} + /* * Public interfaces. */ diff --git a/sys/dev/acpica/acpi_cmbat.c b/sys/dev/acpica/acpi_cmbat.c index 86a650e..804614c 100644 --- a/sys/dev/acpica/acpi_cmbat.c +++ b/sys/dev/acpica/acpi_cmbat.c @@ -113,6 +113,7 @@ struct acpi_cmbat_softc { int cap; int min; int full_charge_time; + int initializing; }; static struct timespec acpi_cmbat_info_lastupdated; @@ -129,7 +130,10 @@ static int acpi_cmbat_probe(device_t); static int acpi_cmbat_attach(device_t); static int acpi_cmbat_resume(device_t); static int acpi_cmbat_ioctl(u_long, caddr_t, void *); +static int acpi_cmbat_is_bst_valid(struct acpi_bst*); +static int acpi_cmbat_is_bif_valid(struct acpi_bif*); static int acpi_cmbat_get_total_battinfo(struct acpi_battinfo *); +static void acpi_cmbat_init_battery(void *); static __inline int acpi_cmbat_info_expired(struct timespec *lastupdated) @@ -350,8 +354,9 @@ acpi_cmbat_attach(device_t dev) acpi_cmbat_units++; timespecclear(&acpi_cmbat_info_lastupdated); + sc->initializing = 0; - AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_cmbat_get_bif, dev); + AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_cmbat_init_battery, dev); return (0); } @@ -359,7 +364,7 @@ static int acpi_cmbat_resume(device_t dev) { - AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_cmbat_get_bif, dev); + AcpiOsQueueForExecution(OSD_PRIORITY_LO, acpi_cmbat_init_battery, dev); return (0); } @@ -435,6 +440,28 @@ acpi_cmbat_ioctl(u_long cmd, caddr_t addr, void *arg) return (0); } +static __inline int +acpi_cmbat_is_bst_valid(struct acpi_bst *bst) +{ + if (bst->state >= ACPI_BATT_STAT_MAX || + bst->cap == 0xffffffff || + bst->volt == 0xffffffff) { + return (0); + } + + return (1); +} + +static __inline int +acpi_cmbat_is_bif_valid(struct acpi_bif *bif) +{ + if (bif->lfcap == 0) { + return (0); + } + + return (1); +} + static int acpi_cmbat_get_total_battinfo(struct acpi_battinfo *battinfo) { @@ -496,10 +523,8 @@ acpi_cmbat_get_total_battinfo(struct acpi_battinfo *battinfo) acpi_cmbat_get_bst(bat[i]->dev); /* If battey not installed, we get strange values */ - if (bat[i]->bst.state >= ACPI_BATT_STAT_MAX || - bat[i]->bst.cap == 0xffffffff || - bat[i]->bst.volt == 0xffffffff || - bat[i]->bif.lfcap == 0) { + if (!acpi_cmbat_is_bst_valid(&(bat[i]->bst)) || + !acpi_cmbat_is_bif_valid(&(bat[i]->bif))) { bat[i]->present = 0; continue; } @@ -580,6 +605,58 @@ out: return (error); } +static void +acpi_cmbat_init_battery(void *arg) +{ + int retry; + device_t dev = (device_t)arg; + struct acpi_cmbat_softc *sc = device_get_softc(dev); +#define ACPI_CMBAT_RETRY_MAX 6 + + if (sc->initializing) { + return; + } + + sc->initializing = 1; + + ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), + "battery initialization start\n"); + + for (retry = 0; retry < ACPI_CMBAT_RETRY_MAX; retry++, AcpiOsSleep(10, 0)) { + sc->present = acpi_BatteryIsPresent(dev); + if (!sc->present) { + continue; + } + + timespecclear(&sc->bst_lastupdated); + timespecclear(&sc->bif_lastupdated); + + acpi_cmbat_get_bst(dev); + + if (!acpi_cmbat_is_bst_valid(&sc->bst)) { + continue; + } + + acpi_cmbat_get_bif(dev); + + if (!acpi_cmbat_is_bif_valid(&sc->bif)) { + continue; + } + + break; + } + + if (retry == ACPI_CMBAT_RETRY_MAX) + ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), + "battery initialization failed, giving up\n"); + else + ACPI_VPRINT(dev, acpi_device_get_parent_softc(dev), + "battery initialization done, tried %d times\n", + retry+1); + + sc->initializing = 0; +} + /* * Public interfaces. */ |