As can be seen from PR 6508, the current implementation of the
acpibat(4) notify stuff causes infinite recursion. The AML for that
particular machine will execute a Notify(\_SC.BAT, 0x81) from the
_BST() method. Since we always execute both _BST() and _BIF() from
the \_SC.BAT notify handler it's easy to see that things go wrong.
The fix is to only call _BST() if the notify value is 0x80 (or 0x00
for the "poll" case) and only call _BIF() if the notify value is 0x81.
This diff also simplifies the battery presence detect logic, which was
unecessaryly complex.
ok?
Index: acpibat.c
===================================================================
RCS file: /cvs/src/sys/dev/acpi/acpibat.c,v
retrieving revision 1.57
diff -u -p -r1.57 acpibat.c
--- acpibat.c 7 Aug 2010 16:55:38 -0000 1.57
+++ acpibat.c 7 Nov 2010 21:04:36 -0000
@@ -186,13 +186,6 @@ acpibat_refresh(void *arg)
return;
}
- /*
- * XXX don't really need _BIF but keep it here in case we
- * miss an insertion/removal event
- */
- acpibat_getbif(sc);
- acpibat_getbst(sc);
-
/* _BIF values are static, sensor 0..3 */
if (sc->sc_bif.bif_last_capacity == BIF_UNKNOWN) {
sc->sc_sens[0].value = 0;
@@ -386,7 +379,8 @@ out:
return (rv);
}
-/* XXX it has been observed that some systems do not propagate battery
+/*
+ * XXX it has been observed that some systems do not propagate battery
* insertion events up to the driver. What seems to happen is that DSDT
* does receive an interrupt however the originator bit is not set.
* This seems to happen when one inserts a 100% full battery. Removal
@@ -400,23 +394,25 @@ acpibat_notify(struct aml_node *node, in
{
struct acpibat_softc *sc = arg;
int64_t sta;
- int present;
dnprintf(10, "acpibat_notify: %.2x %s\n", notify_type,
sc->sc_devnode->name);
/* Check if installed state of battery has changed */
if (aml_evalinteger(sc->sc_acpi, node, "_STA", 0, NULL, &sta) == 0) {
- present = sta & STA_BATTERY;
- if (!sc->sc_bat_present && present)
+ if (sta & STA_BATTERY)
sc->sc_bat_present = 1;
- else if (sc->sc_bat_present && !present)
+ else
sc->sc_bat_present = 0;
}
+
switch (notify_type) {
+ case 0x00: /* Poll sensors */
case 0x80: /* _BST changed */
+ acpibat_getbst(sc);
break;
case 0x81: /* _BIF changed */
+ acpibat_getbif(sc);
break;
default:
break;