summaryrefslogtreecommitdiffstats
path: root/sys/dev/acpica
diff options
context:
space:
mode:
authoriwasaki <iwasaki@FreeBSD.org>2002-11-03 10:49:24 +0000
committeriwasaki <iwasaki@FreeBSD.org>2002-11-03 10:49:24 +0000
commitd9788486227b0e8d3ca3f9538e8689742e19c592 (patch)
tree0364af86aac1f458e1106c83143eaf9dff085b7b /sys/dev/acpica
parentf83a3fa3ad21dc6517182b1d2684f2b8e8f794d5 (diff)
downloadFreeBSD-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.c38
-rw-r--r--sys/dev/acpica/acpi_cmbat.c89
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.
*/
OpenPOWER on IntegriCloud