summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorTheo de Raadt <deraadt@cvs.openbsd.org>2010-07-06 20:14:18 +0000
committerTheo de Raadt <deraadt@cvs.openbsd.org>2010-07-06 20:14:18 +0000
commit34742b972dd39d67dd2490891c0236fa4c793c6c (patch)
tree8a5c4ca588f678111198519b60d0e471b596a0b4 /sys
parent04ca5b42a1294c87014c29bb6dc82d41cb3ca3d2 (diff)
Don't use a workq to do the suspend, because it races aginst the acpi
thread. Instead, just tell the acpi thread to do the suspend for us. This makes apmd & zzz work correctly. While here, have acpithinkpad attempt to post the event to apm before prompting the suspend itself. ok kettenis marco mlarkin
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/acpi/acpi.c28
-rw-r--r--sys/dev/acpi/acpibtn.c27
-rw-r--r--sys/dev/acpi/acpithinkpad.c12
-rw-r--r--sys/dev/acpi/acpivar.h6
4 files changed, 51 insertions, 22 deletions
diff --git a/sys/dev/acpi/acpi.c b/sys/dev/acpi/acpi.c
index e37c649e452..dffb5aa0d8c 100644
--- a/sys/dev/acpi/acpi.c
+++ b/sys/dev/acpi/acpi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpi.c,v 1.170 2010/07/05 05:59:01 mlarkin Exp $ */
+/* $OpenBSD: acpi.c,v 1.171 2010/07/06 20:14:17 deraadt Exp $ */
/*
* Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
* Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
@@ -978,13 +978,8 @@ acpiioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
switch (cmd) {
case APM_IOC_SUSPEND:
case APM_IOC_STANDBY:
- /*
- * Must use a workq to get out of this process's address
- * space and into a kernel thread which has the kernel
- * address space (with the ACPI trampoline way low).
- */
- workq_add_task(NULL, 0, (workq_fn)acpi_sleep_state,
- acpi_softc, (void *)ACPI_STATE_S3);
+ sc->sc_sleepmode = ACPI_STATE_S3;
+ acpi_wakeup(sc);
break;
case APM_IOC_GETPOWER:
/* A/C */
@@ -2122,7 +2117,14 @@ fail:
return (error);
}
+void
+acpi_wakeup(void *arg)
+{
+ struct acpi_softc *sc = (struct acpi_softc *)arg;
+ sc->sc_wakeup = 0;
+ wakeup(sc);
+}
void
acpi_powerdown(void)
@@ -2216,6 +2218,16 @@ acpi_isr_thread(void *arg)
sc->sc_poll = 0;
acpi_poll_notify();
}
+
+#ifndef SMALL_KERNEL
+ if (sc->sc_sleepmode) {
+ int sleepmode = sc->sc_sleepmode;
+
+ sc->sc_sleepmode = 0;
+ acpi_sleep_state(sc, sleepmode);
+ continue;
+ }
+#endif /* SMALL_KERNEL */
}
free(thread, M_DEVBUF);
diff --git a/sys/dev/acpi/acpibtn.c b/sys/dev/acpi/acpibtn.c
index 548dd3c800d..cba0cafed74 100644
--- a/sys/dev/acpi/acpibtn.c
+++ b/sys/dev/acpi/acpibtn.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpibtn.c,v 1.26 2010/03/31 19:21:19 kettenis Exp $ */
+/* $OpenBSD: acpibtn.c,v 1.27 2010/07/06 20:14:17 deraadt Exp $ */
/*
* Copyright (c) 2005 Marco Peereboom <marco@openbsd.org>
*
@@ -112,6 +112,9 @@ acpibtn_getsta(struct acpibtn_softc *sc)
return (0);
}
+/* XXX tie this to a sysctl later */
+int acpi_lid_suspend = 0;
+
int
acpibtn_notify(struct aml_node *node, int notify_type, void *arg)
{
@@ -125,24 +128,24 @@ acpibtn_notify(struct aml_node *node, int notify_type, void *arg)
switch (sc->sc_btn_type) {
case ACPIBTN_LID:
+#ifndef SMALL_KERNEL
/*
* Notification of 0x80 for lid opens or closes. We
* need to check the current status by calling the
- * _LID method. Zero means the lid is closed and we
+ * _LID method. 0 means the lid is closed and we
* should go to sleep.
*/
-#ifndef SMALL_KERNEL
if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode,
"_LID", 0, NULL, &lid))
return (0);
-#if 0
- if (lid == 0) {
- if (acpi_record_event(sc->sc_acpi, APM_USER_SUSPEND_REQ))
- acpi_sleep_state(sc->sc_acpi, ACPI_STATE_S3);
+ if (acpi_lid_suspend && lid == 0) {
+ if (acpi_record_event(sc->sc_acpi, APM_USER_SUSPEND_REQ)) {
+ sc->sc_acpi->sc_sleepmode = ACPI_STATE_S3;
+ acpi_wakeup(sc->sc_acpi);
+ }
}
-#endif
- break;
#endif /* SMALL_KERNEL */
+ break;
case ACPIBTN_SLEEP:
#ifndef SMALL_KERNEL
switch (notify_type) {
@@ -151,8 +154,10 @@ acpibtn_notify(struct aml_node *node, int notify_type, void *arg)
break;
case 0x80:
/* Request to go to sleep */
- if (acpi_record_event(sc->sc_acpi, APM_USER_SUSPEND_REQ))
- acpi_sleep_state(sc->sc_acpi, ACPI_STATE_S3);
+ if (acpi_record_event(sc->sc_acpi, APM_USER_SUSPEND_REQ)) {
+ sc->sc_acpi->sc_sleepmode = ACPI_STATE_S3;
+ acpi_wakeup(sc->sc_acpi);
+ }
break;
}
#endif /* SMALL_KERNEL */
diff --git a/sys/dev/acpi/acpithinkpad.c b/sys/dev/acpi/acpithinkpad.c
index b8f0ca6b54a..e91b0ac6514 100644
--- a/sys/dev/acpi/acpithinkpad.c
+++ b/sys/dev/acpi/acpithinkpad.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpithinkpad.c,v 1.22 2009/11/25 18:57:02 deraadt Exp $ */
+/* $OpenBSD: acpithinkpad.c,v 1.23 2010/07/06 20:14:17 deraadt Exp $ */
/*
* Copyright (c) 2008 joshua stein <jcs@openbsd.org>
*
@@ -17,6 +17,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/proc.h>
#include <dev/acpi/acpireg.h>
#include <dev/acpi/acpivar.h>
@@ -24,6 +25,8 @@
#include <dev/acpi/amltypes.h>
#include <dev/acpi/dsdt.h>
+#include <machine/apmvar.h>
+
#define THINKPAD_HKEY_VERSION 0x0100
#define THINKPAD_CMOS_VOLUME_DOWN 0x00
@@ -279,8 +282,13 @@ thinkpad_hotkey(struct aml_node *node, int notify_type, void *arg)
handled = 1;
break;
case THINKPAD_BUTTON_SUSPEND:
+#ifndef SMALL_KERNEL
+ if (acpi_record_event(sc->sc_acpi, APM_USER_SUSPEND_REQ)) {
+ sc->sc_acpi->sc_sleepmode = ACPI_STATE_S3;
+ acpi_wakeup(sc->sc_acpi);
+ }
+#endif
handled = 1;
- acpi_sleep_state(sc->sc_acpi, ACPI_STATE_S3);
break;
case THINKPAD_BUTTON_HIBERNATE:
case THINKPAD_BUTTON_FN_F1:
diff --git a/sys/dev/acpi/acpivar.h b/sys/dev/acpi/acpivar.h
index af31e3240cc..9016af5c36e 100644
--- a/sys/dev/acpi/acpivar.h
+++ b/sys/dev/acpi/acpivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpivar.h,v 1.57 2010/04/07 06:33:06 kettenis Exp $ */
+/* $OpenBSD: acpivar.h,v 1.58 2010/07/06 20:14:17 deraadt Exp $ */
/*
* Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
*
@@ -207,6 +207,8 @@ struct acpi_softc {
int sc_powerbtn;
int sc_sleepbtn;
+ int sc_sleepmode;
+
struct {
int slp_typa;
int slp_typb;
@@ -302,6 +304,8 @@ void acpi_sleep_walk(struct acpi_softc *, int);
#define ACPI_IOWRITE 1
void acpi_delay(struct acpi_softc *, int64_t);
+void acpi_wakeup(void *);
+
int acpi_gasio(struct acpi_softc *, int, int, uint64_t, int, int, void *);
int acpi_set_gpehandler(struct acpi_softc *, int,