summaryrefslogtreecommitdiffstats
path: root/sys/dev/acpi/acpi.c
diff options
context:
space:
mode:
authorjordan <jordan@openbsd.org>2011-01-02 04:56:57 +0000
committerjordan <jordan@openbsd.org>2011-01-02 04:56:57 +0000
commit90680e5d36a330e5bfeed9a83ce91c174383de28 (patch)
tree8a7c629b58e0d0503f0dd7d7d3183611a2f5a6ce /sys/dev/acpi/acpi.c
parentUse the session ID passed to use by the virtual disk client, and pass back (diff)
downloadwireguard-openbsd-90680e5d36a330e5bfeed9a83ce91c174383de28.tar.xz
wireguard-openbsd-90680e5d36a330e5bfeed9a83ce91c174383de28.zip
Re-add code for ACPI taskqueue, eliminates need for state vars in acpi softc
Serialize processing ACPI tasks for sleep/powerdown/GPE event ok deraadt@
Diffstat (limited to 'sys/dev/acpi/acpi.c')
-rw-r--r--sys/dev/acpi/acpi.c215
1 files changed, 139 insertions, 76 deletions
diff --git a/sys/dev/acpi/acpi.c b/sys/dev/acpi/acpi.c
index 55d17e39a29..116a123e563 100644
--- a/sys/dev/acpi/acpi.c
+++ b/sys/dev/acpi/acpi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpi.c,v 1.221 2010/10/31 21:52:46 guenther Exp $ */
+/* $OpenBSD: acpi.c,v 1.222 2011/01/02 04:56:57 jordan Exp $ */
/*
* Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
* Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
@@ -86,6 +86,10 @@ struct acpi_q *acpi_maptable(struct acpi_softc *, paddr_t, const char *,
void acpi_init_states(struct acpi_softc *);
+void acpi_gpe_task(void *, int);
+void acpi_sbtn_task(void *, int);
+void acpi_pbtn_task(void *, int);
+
#ifndef SMALL_KERNEL
int acpi_thinkpad_enabled;
@@ -1204,6 +1208,54 @@ acpi_init_states(struct acpi_softc *sc)
}
}
+/* ACPI Workqueue support */
+SIMPLEQ_HEAD(,acpi_taskq) acpi_taskq =
+ SIMPLEQ_HEAD_INITIALIZER(acpi_taskq);
+
+void
+acpi_addtask(struct acpi_softc *sc, void (*handler)(void *, int),
+ void *arg0, int arg1)
+{
+ struct acpi_taskq *wq;
+ int s;
+
+ wq = malloc(sizeof(*wq), M_DEVBUF, M_ZERO | M_NOWAIT);
+ if (wq == NULL)
+ return;
+ wq->handler = handler;
+ wq->arg0 = arg0;
+ wq->arg1 = arg1;
+
+ s = spltty();
+ SIMPLEQ_INSERT_TAIL(&acpi_taskq, wq, next);
+ splx(s);
+}
+
+int
+acpi_dotask(struct acpi_softc *sc)
+{
+ struct acpi_taskq *wq;
+ int s;
+
+ s = spltty();
+ if (SIMPLEQ_EMPTY(&acpi_taskq)) {
+ splx(s);
+
+ /* we don't have anything to do */
+ return (0);
+ }
+ wq = SIMPLEQ_FIRST(&acpi_taskq);
+ SIMPLEQ_REMOVE_HEAD(&acpi_taskq, next);
+ splx(s);
+
+ wq->handler(wq->arg0, wq->arg1);
+
+ free(wq, M_DEVBUF);
+
+ /* We did something */
+ return (1);
+}
+
#ifndef SMALL_KERNEL
int
is_ata(struct aml_node *node)
@@ -1346,6 +1398,82 @@ acpi_reset(void)
delay(100000);
}
+void
+acpi_gpe_task(void *arg0, int gpe)
+{
+ struct acpi_softc *sc = acpi_softc;
+ struct gpe_block *pgpe = &sc->gpe_table[gpe];
+
+ dnprintf(10, "handle gpe: %x\n", gpe);
+ if (pgpe->handler && pgpe->active) {
+ pgpe->active = 0;
+ pgpe->handler(sc, gpe, pgpe->arg);
+ }
+}
+
+void
+acpi_pbtn_task(void *arg0, int dummy)
+{
+ struct acpi_softc *sc = arg0;
+ uint16_t en;
+ int s;
+
+ dnprintf(1,"power button pressed\n");
+
+ /* Reset the latch and re-enable the GPE */
+ s = spltty();
+ en = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0);
+ acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0,
+ en | ACPI_PM1_PWRBTN_EN);
+ splx(s);
+
+ acpi_addtask(sc, acpi_powerdown_task, sc, 0);
+}
+
+void
+acpi_sbtn_task(void *arg0, int dummy)
+{
+ struct acpi_softc *sc = arg0;
+ uint16_t en;
+ int s;
+
+ dnprintf(1,"sleep button pressed\n");
+ aml_notify_dev(ACPI_DEV_SBD, 0x80);
+
+ /* Reset the latch and re-enable the GPE */
+ s = spltty();
+ en = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0);
+ acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0,
+ en | ACPI_PM1_SLPBTN_EN);
+ splx(s);
+}
+
+void
+acpi_powerdown_task(void *arg0, int dummy)
+{
+ /* XXX put a knob in front of this */
+ psignal(initproc, SIGUSR2);
+}
+
+void
+acpi_sleep_task(void *arg0, int sleepmode)
+{
+ struct acpi_softc *sc = arg0;
+ struct acpi_ac *ac;
+ struct acpi_bat *bat;
+
+ /* System goes to sleep here.. */
+ acpi_sleep_state(sc, sleepmode);
+
+ /* AC and battery information needs refreshing */
+ SLIST_FOREACH(ac, &sc->sc_ac, aac_link)
+ aml_notify(ac->aac_softc->sc_devnode,
+ 0x80);
+ SLIST_FOREACH(bat, &sc->sc_bat, aba_link)
+ aml_notify(bat->aba_softc->sc_devnode,
+ 0x80);
+}
+
int
acpi_interrupt(void *arg)
{
@@ -1366,6 +1494,8 @@ acpi_interrupt(void *arg)
if (en & sts & (1L << jdx)) {
/* Signal this GPE */
sc->gpe_table[idx+jdx].active = 1;
+ dnprintf(10, "queue gpe: %x\n", idx+jdx);
+ acpi_addtask(sc, acpi_gpe_task, NULL, idx+jdx);
/*
* Edge interrupts need their STS bits
@@ -1395,7 +1525,8 @@ acpi_interrupt(void *arg)
acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0,
ACPI_PM1_PWRBTN_STS);
sts &= ~ACPI_PM1_PWRBTN_STS;
- sc->sc_powerbtn = 1;
+
+ acpi_addtask(sc, acpi_pbtn_task, sc, 0);
}
if (sts & ACPI_PM1_SLPBTN_STS) {
/* Mask and acknowledge */
@@ -1404,7 +1535,8 @@ acpi_interrupt(void *arg)
acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0,
ACPI_PM1_SLPBTN_STS);
sts &= ~ACPI_PM1_SLPBTN_STS;
- sc->sc_sleepbtn = 1;
+
+ acpi_addtask(sc, acpi_sbtn_task, sc, 0);
}
if (sts) {
printf("%s: PM1 stuck (en 0x%x st 0x%x), clearing\n",
@@ -2017,7 +2149,6 @@ acpi_thread(void *arg)
struct acpi_thread *thread = arg;
struct acpi_softc *sc = thread->sc;
extern int aml_busy;
- u_int32_t gpe;
int s;
rw_enter_write(&sc->sc_lck);
@@ -2065,77 +2196,9 @@ acpi_thread(void *arg)
continue;
}
- for (gpe = 0; gpe < sc->sc_lastgpe; gpe++) {
- struct gpe_block *pgpe = &sc->gpe_table[gpe];
-
- if (pgpe->active) {
- pgpe->active = 0;
- dnprintf(50, "softgpe: %.2x\n", gpe);
- if (pgpe->handler)
- pgpe->handler(sc, gpe, pgpe->arg);
- }
- }
- if (sc->sc_powerbtn) {
- uint16_t en;
-
- sc->sc_powerbtn = 0;
- dnprintf(1,"power button pressed\n");
- sc->sc_powerdown = 1;
-
- /* Reset the latch and re-enable the GPE */
- s = spltty();
- en = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0);
- acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0,
- en | ACPI_PM1_PWRBTN_EN);
- splx(s);
-
- }
- if (sc->sc_sleepbtn) {
- uint16_t en;
-
- sc->sc_sleepbtn = 0;
- dnprintf(1,"sleep button pressed\n");
- aml_notify_dev(ACPI_DEV_SBD, 0x80);
-
- /* Reset the latch and re-enable the GPE */
- s = spltty();
- en = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0);
- acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0,
- en | ACPI_PM1_SLPBTN_EN);
- splx(s);
- }
-
- /* handle polling here to keep code non-concurrent*/
- if (sc->sc_poll) {
- sc->sc_poll = 0;
- acpi_poll_notify();
- }
-
- if (sc->sc_powerdown) {
- sc->sc_powerdown = 0;
-
- /* XXX put a knob in front of this */
- psignal(initproc, SIGUSR2);
- }
-
- if (sc->sc_sleepmode) {
- struct acpi_ac *ac;
- struct acpi_bat *bat;
- int sleepmode = sc->sc_sleepmode;
-
- sc->sc_sleepmode = 0;
- acpi_sleep_state(sc, sleepmode);
-
- /* AC and battery information needs refreshing */
- SLIST_FOREACH(ac, &sc->sc_ac, aac_link)
- aml_notify(ac->aac_softc->sc_devnode,
- 0x80);
- SLIST_FOREACH(bat, &sc->sc_bat, aba_link)
- aml_notify(bat->aba_softc->sc_devnode,
- 0x80);
-
- continue;
- }
+ /* Run ACPI taskqueue */
+ while(acpi_dotask(acpi_softc))
+ ;
}
free(thread, M_DEVBUF);
@@ -2425,7 +2488,7 @@ acpiioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
if ((flag & FWRITE) == 0) {
error = EBADF;
} else {
- sc->sc_sleepmode = ACPI_STATE_S3;
+ acpi_addtask(sc, acpi_sleep_task, sc, ACPI_STATE_S3);
acpi_wakeup(sc);
}
break;