> Date: Wed, 3 Aug 2016 13:22:33 +0300
> From: Paul Irofti <p...@irofti.net>
> 
> Hi,
> 
> I was looking at fixing powerdown on the x260 Skylake machine and ran
> into the EC XXX comment from acpi_powerdown().
> 
> I think that grabbing the global lock before doing the AML calls is a
> good start.
> 
> What we are missing now is incrementing the global_lock_count variable
> from the ACPI thread so that calls to acpi_glk_leave() take into account
> our hold of the lock.
> 
> Should we make that a global variable and protect increments and
> decrements from acpi_glk_{enter,leave}? This way we could also increment
> it from acpi_powerdown() and that would put an end to this issue.

Where in the acpi spec does it say you have to grab the acpi global lock?

Unless it explicitly says that, we defenitely shouldn't grab it.  The
global lock is all about locking out the firmware, not the acpi
thread.  And by locking out the firmware when we shouldn't, we will
probably cause hangs on some machines.

I don't think that XXX is a big issue by the way.  By the time
acpi_powerdown() runs we've halted the secondary CPUs and are running
on the primary CPU anyway.  As long as the acpi_powerdown() doesn't
sleep, the acpi thread shouldn't interfere.  And from a firmware
perspective this is indistinguishable from running the code in the
acpi thread.

Mike Larkin was talking recently about moving the S5 transition
handling into acpi_sleep_state().  If that happens it would be trivial
to run from the acpi thread.  That is probably a better strategy to
get rid of that XXX.

Cheers,

Mark


> Index: acpi.c
> ===================================================================
> RCS file: /cvs/src/sys/dev/acpi/acpi.c,v
> retrieving revision 1.313
> diff -u -p -u -p -r1.313 acpi.c
> --- acpi.c    28 Jul 2016 21:57:56 -0000      1.313
> +++ acpi.c    3 Aug 2016 10:12:15 -0000
> @@ -2497,27 +2497,31 @@ fail_tts:
>       return (error);
>  }
>  
> -/* XXX
> - * We are going to do AML execution but are not in the acpi thread.
> - * We do not know if the acpi thread is sleeping on acpiec in some
> - * intermediate context.  Wish us luck.
> - */
>  void
>  acpi_powerdown(void)
>  {
>       int state = ACPI_STATE_S5, s;
>       struct acpi_softc *sc = acpi_softc;
> +     int st = 0;
>  
>       if (acpi_enabled == 0)
>               return;
>  
> +     /*
> +      * We are going to do AML execution but are not in the acpi thread.
> +      * Grab the global lock to make sure that the acpi thread is not
> +      * sleeping on acpiec in some intermediate context.
> +      */
> +     while (!st)
> +             st = acpi_acquire_glk(&sc->sc_facs->global_lock);
> +
>       s = splhigh();
>       disable_intr();
>       cold = 1;
>  
>       /* 1st powerdown AML step: _PTS(tostate) */
>       aml_node_setval(sc, sc->sc_pts, state);
> -     
> +
>       acpi_disable_allgpes(sc);
>       acpi_enable_wakegpes(sc, state);
>  
> 
> 

Reply via email to