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 -----

Reply via email to