diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2010-08-06 14:20:15 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2010-08-06 14:20:15 +0000 |
commit | c1f00f4f76dd0e3d2195b25bf859a2350f12c416 (patch) | |
tree | 2b7ec9f4d5adcc63c3b51fae134f8d34deda65fc /sys/dev/acpi | |
parent | f95c05f286b01e37607284a13bacb98d0a3d9e34 (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
Diffstat (limited to 'sys/dev/acpi')
-rw-r--r-- | sys/dev/acpi/acpi.c | 18 |
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; } |