summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorJordan Hargrave <jordan@cvs.openbsd.org>2011-01-02 04:56:58 +0000
committerJordan Hargrave <jordan@cvs.openbsd.org>2011-01-02 04:56:58 +0000
commit3ec6aa883c28c24f24dc786655ed0b7f3213a870 (patch)
tree68e4149630b26b2976ad38f7b53f7c1bb6cf820a /sys
parent4ca44bef3da389cc4556166e0c99ec18a7dca17a (diff)
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')
-rw-r--r--sys/dev/acpi/acpi.c215
-rw-r--r--sys/dev/acpi/acpibtn.c8
-rw-r--r--sys/dev/acpi/acpisony.c5
-rw-r--r--sys/dev/acpi/acpithinkpad.c5
-rw-r--r--sys/dev/acpi/acpivar.h22
-rw-r--r--sys/dev/acpi/dsdt.c37
-rw-r--r--sys/dev/acpi/dsdt.h3
7 files changed, 194 insertions, 101 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;
diff --git a/sys/dev/acpi/acpibtn.c b/sys/dev/acpi/acpibtn.c
index 20cc016d540..b7b1f617b97 100644
--- a/sys/dev/acpi/acpibtn.c
+++ b/sys/dev/acpi/acpibtn.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpibtn.c,v 1.33 2010/08/07 16:21:20 deraadt Exp $ */
+/* $OpenBSD: acpibtn.c,v 1.34 2011/01/02 04:56:57 jordan Exp $ */
/*
* Copyright (c) 2005 Marco Peereboom <marco@openbsd.org>
*
@@ -198,14 +198,16 @@ acpibtn_notify(struct aml_node *node, int notify_type, void *arg)
sleep:
/* Request to go to sleep */
if (acpi_record_event(sc->sc_acpi, APM_USER_SUSPEND_REQ))
- sc->sc_acpi->sc_sleepmode = ACPI_STATE_S3;
+ acpi_addtask(sc->sc_acpi, acpi_sleep_task,
+ sc->sc_acpi, ACPI_STATE_S3);
break;
}
#endif /* SMALL_KERNEL */
break;
case ACPIBTN_POWER:
if (notify_type == 0x80)
- sc->sc_acpi->sc_powerdown = 1;
+ acpi_addtask(sc->sc_acpi, acpi_powerdown_task,
+ sc->sc_acpi, 0);
break;
default:
printf("%s: spurious acpi button interrupt %i\n", DEVNAME(sc),
diff --git a/sys/dev/acpi/acpisony.c b/sys/dev/acpi/acpisony.c
index 716db37130c..e6bede881ed 100644
--- a/sys/dev/acpi/acpisony.c
+++ b/sys/dev/acpi/acpisony.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpisony.c,v 1.3 2010/08/07 16:21:20 deraadt Exp $ */
+/* $OpenBSD: acpisony.c,v 1.4 2011/01/02 04:56:57 jordan Exp $ */
/*
* Copyright (c) 2010 Paul Irofti <pirofti@openbsd.org>
*
@@ -198,7 +198,8 @@ acpisony_notify(struct aml_node *node, int notify, void *arg)
DPRINTF(("suspend-pressed\n"));
#ifndef SMALL_KERNEL
if (acpi_record_event(sc->sc_acpi, APM_USER_SUSPEND_REQ))
- sc->sc_acpi->sc_sleepmode = ACPI_STATE_S3;
+ acpi_addtask(sc->sc_acpi, acpi_sleep_task,
+ sc->sc_acpi, ACPI_STATE_S3);
#endif
break;
case SONY_NOTIFY_SUSPEND_RELEASED:
diff --git a/sys/dev/acpi/acpithinkpad.c b/sys/dev/acpi/acpithinkpad.c
index bfff2073eda..8e7d2173499 100644
--- a/sys/dev/acpi/acpithinkpad.c
+++ b/sys/dev/acpi/acpithinkpad.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpithinkpad.c,v 1.24 2010/08/07 16:21:20 deraadt Exp $ */
+/* $OpenBSD: acpithinkpad.c,v 1.25 2011/01/02 04:56:57 jordan Exp $ */
/*
* Copyright (c) 2008 joshua stein <jcs@openbsd.org>
*
@@ -284,7 +284,8 @@ thinkpad_hotkey(struct aml_node *node, int notify_type, void *arg)
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_addtask(sc->sc_acpi, acpi_sleep_task,
+ sc->sc_acpi, ACPI_STATE_S3);
#endif
handled = 1;
break;
diff --git a/sys/dev/acpi/acpivar.h b/sys/dev/acpi/acpivar.h
index 1e4752d3407..e9a172b5681 100644
--- a/sys/dev/acpi/acpivar.h
+++ b/sys/dev/acpi/acpivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpivar.h,v 1.68 2010/10/31 21:52:46 guenther Exp $ */
+/* $OpenBSD: acpivar.h,v 1.69 2011/01/02 04:56:57 jordan Exp $ */
/*
* Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
*
@@ -82,6 +82,13 @@ struct acpi_q {
u_int8_t q_data[0];
};
+struct acpi_taskq {
+ SIMPLEQ_ENTRY(acpi_taskq) next;
+ void (*handler)(void *, int);
+ void *arg0;
+ int arg1;
+};
+
struct acpi_wakeq {
SIMPLEQ_ENTRY(acpi_wakeq) q_next;
struct aml_node *q_node;
@@ -206,12 +213,6 @@ struct acpi_softc {
void *sc_interrupt;
- int sc_powerbtn;
- int sc_sleepbtn;
-
- int sc_sleepmode;
- int sc_powerdown;
-
struct rwlock sc_lck;
struct {
@@ -241,7 +242,6 @@ struct acpi_softc {
struct acpi_bat_head sc_bat;
struct timeout sc_dev_timeout;
- int sc_poll;
int sc_revision;
@@ -333,6 +333,12 @@ int acpi_matchhids(struct acpi_attach_args *, const char *[], const char *);
int acpi_record_event(struct acpi_softc *, u_int);
+void acpi_addtask(struct acpi_softc *, void (*)(void *, int), void *, int);
+int acpi_dotask(struct acpi_softc *);
+
+void acpi_powerdown_task(void *, int);
+void acpi_sleep_task(void *, int);
+
#endif
#endif /* !_ACPI_WAKECODE */
diff --git a/sys/dev/acpi/dsdt.c b/sys/dev/acpi/dsdt.c
index c41ecf6d47e..3c18fbe947d 100644
--- a/sys/dev/acpi/dsdt.c
+++ b/sys/dev/acpi/dsdt.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: dsdt.c,v 1.180 2010/10/31 21:52:46 guenther Exp $ */
+/* $OpenBSD: dsdt.c,v 1.181 2011/01/02 04:56:57 jordan Exp $ */
/*
* Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
*
@@ -104,6 +104,9 @@ void aml_dump(int, u_int8_t *);
void _aml_die(const char *fn, int line, const char *fmt, ...);
#define aml_die(x...) _aml_die(__FUNCTION__, __LINE__, x)
+void aml_notify_task(void *, int);
+void acpi_poll_notify_task(void *, int);
+
/*
* @@@: Global variables
*/
@@ -515,19 +518,32 @@ aml_setbit(u_int8_t *pb, int bit, int val)
/*
* @@@: Notify functions
*/
+#ifndef SMALL_KERNEL
void
acpi_poll(void *arg)
{
int s;
s = spltty();
- acpi_softc->sc_poll = 1;
+ acpi_addtask(acpi_softc, acpi_poll_notify_task, NULL, 0);
acpi_softc->sc_threadwaiting = 0;
wakeup(acpi_softc);
splx(s);
timeout_add_sec(&acpi_softc->sc_dev_timeout, 10);
}
+#endif
+
+void
+aml_notify_task(void *node, int notify_value)
+{
+ struct aml_notify_data *pdata = NULL;
+
+ dnprintf(10,"run notify: %s %x\n", aml_nodename(node), notify_value);
+ SLIST_FOREACH(pdata, &aml_notify_list, link)
+ if (pdata->node == node)
+ pdata->cbproc(pdata->node, notify_value, pdata->cbarg);
+}
void
aml_register_notify(struct aml_node *node, const char *pnpid,
@@ -557,14 +573,11 @@ aml_register_notify(struct aml_node *node, const char *pnpid,
void
aml_notify(struct aml_node *node, int notify_value)
{
- struct aml_notify_data *pdata = NULL;
-
if (node == NULL)
return;
- SLIST_FOREACH(pdata, &aml_notify_list, link)
- if (pdata->node == node)
- pdata->cbproc(pdata->node, notify_value, pdata->cbarg);
+ dnprintf(10,"queue notify: %s %x\n", aml_nodename(node), notify_value);
+ acpi_addtask(acpi_softc, aml_notify_task, node, notify_value);
}
#ifndef SMALL_KERNEL
@@ -582,7 +595,7 @@ aml_notify_dev(const char *pnpid, int notify_value)
}
void
-acpi_poll_notify(void)
+acpi_poll_notify_task(void *arg0, int arg1)
{
struct aml_notify_data *pdata = NULL;
@@ -2472,6 +2485,14 @@ acpi_xmutex_release(struct aml_scope *scope, struct aml_value *mtx)
int
acpi_xevent_wait(struct aml_scope *scope, struct aml_value *evt, int timeout)
{
+ /* Wait for event to occur; do work in meantime */
+ evt->v_evt.state = 0;
+ while (!evt->v_evt.state) {
+ if (!acpi_dotask(acpi_softc) && !cold)
+ tsleep(evt, PWAIT, "acpievt", 1);
+ else
+ delay(100);
+ }
if (evt->v_evt.state == 1) {
/* Object is signaled */
return (0);
diff --git a/sys/dev/acpi/dsdt.h b/sys/dev/acpi/dsdt.h
index 0c58b1cccf8..aef42b43ded 100644
--- a/sys/dev/acpi/dsdt.h
+++ b/sys/dev/acpi/dsdt.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: dsdt.h,v 1.55 2010/08/04 18:11:56 jordan Exp $ */
+/* $OpenBSD: dsdt.h,v 1.56 2011/01/02 04:56:57 jordan Exp $ */
/*
* Copyright (c) 2005 Marco Peereboom <marco@openbsd.org>
*
@@ -274,7 +274,6 @@ int aml_rdpciaddr(struct aml_node *pcidev,
#ifndef SMALL_KERNEL
void acpi_getdevlist(struct acpi_devlist_head *,
struct aml_node *, struct aml_value *, int);
-void acpi_poll_notify(void);
void aml_notify_dev(const char *, int);
#endif