As promised. This needs lots of testing so apply, test and reply to jordan and me please.
----- Forwarded message from Jordan Hargrave <[email protected]> ----- Date: Wed, 15 Dec 2010 19:06:26 -0700 (MST) From: Jordan Hargrave <[email protected]> To: [email protected] Subject: ACPI new fulltask diff This is a modified acpitask patch that adds all the power/sleep functionality to the task queue. It gets rid of all the unecessary state variables in the acpi softc. This works on the VAIO box that has the infinite wait in the startup AML Index: acpi.c =================================================================== RCS file: /cvs/src/sys/dev/acpi/acpi.c,v retrieving revision 1.221 diff -u -p -b -r1.221 acpi.c --- acpi.c 31 Oct 2010 21:52:46 -0000 1.221 +++ acpi.c 2 Dec 2010 00:29:23 -0000 @@ -86,6 +86,10 @@ struct acpi_q *acpi_maptable(struct acpi 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 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; Index: acpibtn.c =================================================================== RCS file: /cvs/src/sys/dev/acpi/acpibtn.c,v retrieving revision 1.33 diff -u -p -b -r1.33 acpibtn.c --- acpibtn.c 7 Aug 2010 16:21:20 -0000 1.33 +++ acpibtn.c 2 Dec 2010 00:29:23 -0000 @@ -167,6 +167,8 @@ acpibtn_notify(struct aml_node *node, in int64_t lid; #endif + printf("acpibtn notify: %s %x\n", aml_nodename(sc->sc_devnode), + notify_type); dnprintf(10, "acpibtn_notify: %.2x %s\n", notify_type, sc->sc_devnode->name); @@ -198,14 +200,16 @@ acpibtn_notify(struct aml_node *node, in 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), Index: acpisony.c =================================================================== RCS file: /cvs/src/sys/dev/acpi/acpisony.c,v retrieving revision 1.3 diff -u -p -b -r1.3 acpisony.c --- acpisony.c 7 Aug 2010 16:21:20 -0000 1.3 +++ acpisony.c 2 Dec 2010 00:29:23 -0000 @@ -198,7 +198,8 @@ acpisony_notify(struct aml_node *node, i 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: Index: acpithinkpad.c =================================================================== RCS file: /cvs/src/sys/dev/acpi/acpithinkpad.c,v retrieving revision 1.24 diff -u -p -b -r1.24 acpithinkpad.c --- acpithinkpad.c 7 Aug 2010 16:21:20 -0000 1.24 +++ acpithinkpad.c 2 Dec 2010 00:29:23 -0000 @@ -284,7 +284,8 @@ thinkpad_hotkey(struct aml_node *node, i 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; Index: acpivar.h =================================================================== RCS file: /cvs/src/sys/dev/acpi/acpivar.h,v retrieving revision 1.68 diff -u -p -b -r1.68 acpivar.h --- acpivar.h 31 Oct 2010 21:52:46 -0000 1.68 +++ acpivar.h 2 Dec 2010 00:29:23 -0000 @@ -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; @@ -332,6 +332,12 @@ void acpi_sleep(int, char *); 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 Index: dsdt.c =================================================================== RCS file: /cvs/src/sys/dev/acpi/dsdt.c,v retrieving revision 1.180 diff -u -p -b -r1.180 dsdt.c --- dsdt.c 31 Oct 2010 21:52:46 -0000 1.180 +++ dsdt.c 2 Dec 2010 00:29:25 -0000 @@ -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 */ @@ -521,7 +524,7 @@ 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); @@ -530,6 +533,17 @@ acpi_poll(void *arg) } 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, int (*proc)(struct aml_node *, int, void *), void *arg, int poll) { @@ -557,14 +571,11 @@ aml_register_notify(struct aml_node *nod 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 +593,7 @@ aml_notify_dev(const char *pnpid, int no } void -acpi_poll_notify(void) +acpi_poll_notify_task(void *arg0, int arg1) { struct aml_notify_data *pdata = NULL; @@ -2472,6 +2483,14 @@ acpi_xmutex_release(struct aml_scope *sc 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); Index: dsdt.h =================================================================== RCS file: /cvs/src/sys/dev/acpi/dsdt.h,v retrieving revision 1.55 diff -u -p -b -r1.55 dsdt.h --- dsdt.h 4 Aug 2010 18:11:56 -0000 1.55 +++ dsdt.h 2 Dec 2010 00:29:25 -0000 @@ -274,7 +274,6 @@ int aml_rdpciaddr(struct aml_node *pci #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 ----- End forwarded message -----
