> Date: Tue, 8 Jan 2019 17:46:37 +0100 (CET)
> From: Mark Kettenis <mark.kette...@xs4all.nl>
> 
> I have a Shuttle NC02U "nano" PC that ends up with the the acpi0
> kernel thread blocked on the "acpievt" wait channel.  I tracked this
> down to an incorrect implementation of the Signal() and Wait()
> operations.
> 
> This changes the implementation to be a proper semaphore.  It also
> releases the acpi interpreter lock.  This is necessary because the
> acpivout(4) implementation directly executes AML code from the calling
> thread instead of using an acpi task.  Maybe that should be fixed
> instead but it is non-trivial and the current code results in a hard
> hang during the initial mode setting stage.
> 
> ok?

Better diff.  We shouldn't call delay() if we ran a task.

ok?

Index: dev/acpi/dsdt.c
===================================================================
RCS file: /cvs/src/sys/dev/acpi/dsdt.c,v
retrieving revision 1.243
diff -u -p -r1.243 dsdt.c
--- dev/acpi/dsdt.c     19 Aug 2018 08:23:47 -0000      1.243
+++ dev/acpi/dsdt.c     8 Jan 2019 17:01:50 -0000
@@ -2905,29 +2905,34 @@ int
 acpi_event_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);
+       while (evt->v_evt.state == 0 && timeout >= 0) {
+               if (acpi_dotask(acpi_softc))
+                   continue;
+               if (!cold) {
+                       rw_exit_write(&acpi_softc->sc_lck);
+                       if (tsleep(evt, PWAIT, "acpievt", 1) == EWOULDBLOCK) {
+                               if (timeout < 0xffff)
+                                       timeout -= (1000 / hz);
+                       }
+                       rw_enter_write(&acpi_softc->sc_lck);
+               } else {
+                       delay(1000);
+                       if (timeout < 0xffff)
+                               timeout--;
+               }
        }
-       if (evt->v_evt.state == 1) {
-               /* Object is signaled */
-               return (0);
-       } else if (timeout == 0) {
-               /* Zero timeout */
+       if (evt->v_evt.state == 0)
                return (-1);
-       }
-       /* Wait for timeout or signal */
+       evt->v_evt.state--;
        return (0);
 }
 
 void
 acpi_event_signal(struct aml_scope *scope, struct aml_value *evt)
 {
-       evt->v_evt.state = 1;
-       /* Wakeup waiters */
+       evt->v_evt.state++;
+       if (evt->v_evt.state > 0)
+               wakeup_one(evt);
 }
 
 void
@@ -4215,7 +4220,7 @@ aml_parse(struct aml_scope *scope, int r
        case AMLOP_EVENT:
                /* Event: N */
                rv = _aml_setvalue(opargs[0], AML_OBJTYPE_EVENT, 0, 0);
-               rv->v_integer = 0;
+               rv->v_evt.state = 0;
                break;
        case AMLOP_MUTEX:
                /* Mutex: Nw */

Reply via email to