summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2010-08-06 14:20:15 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2010-08-06 14:20:15 +0000
commitc1f00f4f76dd0e3d2195b25bf859a2350f12c416 (patch)
tree2b7ec9f4d5adcc63c3b51fae134f8d34deda65fc
parentf95c05f286b01e37607284a13bacb98d0a3d9e34 (diff)
As part of a revamp of the PM1/GPE code, I write this diff to look for
unmanaged EN & STS bits in the PM1 register at interrupt time and report them. As a side effect this splits the STS acknowledgement into two writes (for power, and sleep) instead of one. The printf that is added (to spot unmanaged STS bits) has not yet been triggered as far as we know. Before the "write to PM1 registers at the right offset" diff went in, this was not neccessary. But newer thinkpads do not have a working soft power button without this diff. We have no idea why. ok mlarkin kettenis
-rw-r--r--sys/dev/acpi/acpi.c18
1 files changed, 16 insertions, 2 deletions
diff --git a/sys/dev/acpi/acpi.c b/sys/dev/acpi/acpi.c
index b460ffd402b..273a35c8f0c 100644
--- a/sys/dev/acpi/acpi.c
+++ b/sys/dev/acpi/acpi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpi.c,v 1.203 2010/08/05 17:26:57 deraadt Exp $ */
+/* $OpenBSD: acpi.c,v 1.204 2010/08/06 14:20:14 deraadt Exp $ */
/*
* Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
* Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
@@ -1354,17 +1354,31 @@ acpi_interrupt(void *arg)
en = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0);
if (sts & en) {
dnprintf(10,"GEN interrupt: %.4x\n", sts & en);
- acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en & ~sts);
+ sts &= en;
if (sts & ACPI_PM1_PWRBTN_STS) {
+ /* Mask and acknowledge */
+ en &= ~ACPI_PM1_PWRBTN_EN;
+ acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en);
acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0,
ACPI_PM1_PWRBTN_STS);
+ sts &= ~ACPI_PM1_PWRBTN_STS;
sc->sc_powerbtn = 1;
}
if (sts & ACPI_PM1_SLPBTN_STS) {
+ /* Mask and acknowledge */
+ en &= ~ACPI_PM1_SLPBTN_EN;
+ acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en);
acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0,
ACPI_PM1_SLPBTN_STS);
+ sts &= ~ACPI_PM1_SLPBTN_STS;
sc->sc_sleepbtn = 1;
}
+ if (sts) {
+ printf("%s: PM1 stuck (en 0x%x st 0x%x), clearing\n",
+ sc->sc_dev.dv_xname, en, sts);
+ acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en & ~sts);
+ acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, sts);
+ }
processed = 1;
}