Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/acpi Revisit the wake-device code once more.



details:   https://anonhg.NetBSD.org/src/rev/631f692596c5
branches:  trunk
changeset: 762318:631f692596c5
user:      jruoho <jruoho%NetBSD.org@localhost>
date:      Sat Feb 19 09:52:32 2011 +0000

description:
Revisit the wake-device code once more.

  1. Remove the AcpiEnableGpe() call. This was wrong.

  2. Only call _PSW or _DSW for devices that are scheduled for wake.
     This was an old bug.

  3. Only enable wake GPEs during suspend. Disabling these for
     devices not setup for wake was causing problems.

  4. No wake GPEs should be enabled at runtime.
     Unconditionally disable these during resume.

This should make the wake-device code work again. Note that waking via
pckbd(4) has always been unreliable; the _PRW object is not typically located
under the PC keyboard object, but in the parent of it (e.g. the LPC bridge).

diffstat:

 sys/dev/acpi/acpi.c         |    5 +-
 sys/dev/acpi/acpi_wakedev.c |  105 +++++++++++++++++--------------------------
 sys/dev/acpi/acpi_wakedev.h |    6 +-
 3 files changed, 47 insertions(+), 69 deletions(-)

diffs (222 lines):

diff -r 7b827803fbfd -r 631f692596c5 sys/dev/acpi/acpi.c
--- a/sys/dev/acpi/acpi.c       Sat Feb 19 08:46:41 2011 +0000
+++ b/sys/dev/acpi/acpi.c       Sat Feb 19 09:52:32 2011 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: acpi.c,v 1.236 2011/02/17 19:36:49 jruoho Exp $        */
+/*     $NetBSD: acpi.c,v 1.237 2011/02/19 09:52:32 jruoho Exp $        */
 
 /*-
  * Copyright (c) 2003, 2007 The NetBSD Foundation, Inc.
@@ -100,7 +100,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.236 2011/02/17 19:36:49 jruoho Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi.c,v 1.237 2011/02/19 09:52:32 jruoho Exp $");
 
 #include "opt_acpi.h"
 #include "opt_pcifixup.h"
@@ -1389,6 +1389,7 @@
                        (void)pmf_system_resume(PMF_Q_NONE);
                }
 
+               acpi_wakedev_commit(sc, ACPI_STATE_S0);
                break;
 
        case ACPI_STATE_S5:
diff -r 7b827803fbfd -r 631f692596c5 sys/dev/acpi/acpi_wakedev.c
--- a/sys/dev/acpi/acpi_wakedev.c       Sat Feb 19 08:46:41 2011 +0000
+++ b/sys/dev/acpi/acpi_wakedev.c       Sat Feb 19 09:52:32 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_wakedev.c,v 1.23 2011/02/18 13:56:03 jruoho Exp $ */
+/* $NetBSD: acpi_wakedev.c,v 1.24 2011/02/19 09:52:32 jruoho Exp $ */
 
 /*-
  * Copyright (c) 2009, 2010, 2011 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -27,7 +27,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: acpi_wakedev.c,v 1.23 2011/02/18 13:56:03 jruoho Exp $");
+__KERNEL_RCSID(0, "$NetBSD: acpi_wakedev.c,v 1.24 2011/02/19 09:52:32 jruoho Exp $");
 
 #include <sys/param.h>
 #include <sys/device.h>
@@ -54,8 +54,8 @@
 static int32_t acpi_wakedev_acpinode = CTL_EOL;
 static int32_t acpi_wakedev_wakenode = CTL_EOL;
 
-static void    acpi_wakedev_power(struct acpi_devnode *, ACPI_OBJECT *);
-static void    acpi_wakedev_set(struct acpi_devnode *, int);
+static void    acpi_wakedev_power_add(struct acpi_devnode *, ACPI_OBJECT *);
+static void    acpi_wakedev_power_set(struct acpi_devnode *, bool);
 static void    acpi_wakedev_method(struct acpi_devnode *, int);
 
 void
@@ -143,13 +143,13 @@
        elm = &obj->Package.Elements[1];
 
        if (elm->Type == ACPI_TYPE_INTEGER)
-               ad->ad_wakedev->aw_sleep = elm->Integer.Value;
+               ad->ad_wakedev->aw_state = elm->Integer.Value;
 
        /*
         * The rest of the elements are reference
         * handles to power resources. Store these.
         */
-       acpi_wakedev_power(ad, obj);
+       acpi_wakedev_power_add(ad, obj);
 
        /*
         * Last but not least, mark the GPE for wake.
@@ -166,7 +166,7 @@
 }
 
 static void
-acpi_wakedev_power(struct acpi_devnode *ad, ACPI_OBJECT *obj)
+acpi_wakedev_power_add(struct acpi_devnode *ad, ACPI_OBJECT *obj)
 {
        struct acpi_wakedev *aw = ad->ad_wakedev;
        uint32_t i, j, n;
@@ -194,6 +194,21 @@
        }
 }
 
+static void
+acpi_wakedev_power_set(struct acpi_devnode *ad, bool enable)
+{
+       struct acpi_wakedev *aw = ad->ad_wakedev;
+       uint8_t i;
+
+       for (i = 0; i < __arraycount(aw->aw_power); i++) {
+
+               if (aw->aw_power[i] == NULL)
+                       continue;
+
+               (void)acpi_power_res(aw->aw_power[i], ad->ad_handle, enable);
+       }
+}
+
 void
 acpi_wakedev_add(struct acpi_devnode *ad)
 {
@@ -277,80 +292,42 @@
 acpi_wakedev_commit(struct acpi_softc *sc, int state)
 {
        struct acpi_devnode *ad;
+       ACPI_INTEGER val;
+       ACPI_HANDLE hdl;
 
        /*
         * To prepare a device for wakeup:
         *
-        *  1.  Set appropriate GPEs.
+        *  1.  Set the wake GPE.
         *
-        *  2.  Enable all power resources in _PRW.
+        *  2.  Turn on power resources.
         *
-        *  3.  If present, execute _DSW/_PSW method.
+        *  3.  Execute _DSW or _PSW method.
         */
        SIMPLEQ_FOREACH(ad, &sc->ad_head, ad_list) {
 
                if (ad->ad_wakedev == NULL)
                        continue;
 
-               acpi_wakedev_set(ad, state);
+               if (state > ad->ad_wakedev->aw_state)
+                       continue;
+
+               hdl = ad->ad_wakedev->aw_handle;
+               val = ad->ad_wakedev->aw_number;
+
+               if (state == ACPI_STATE_S0) {
+                       (void)AcpiSetGpeWakeMask(hdl, val, ACPI_GPE_DISABLE);
+                       continue;
+               }
+
+               (void)AcpiSetGpeWakeMask(hdl, val, ACPI_GPE_ENABLE);
+
+               acpi_wakedev_power_set(ad, true);
                acpi_wakedev_method(ad, state);
        }
 }
 
 static void
-acpi_wakedev_set(struct acpi_devnode *ad, int state)
-{
-       struct acpi_wakedev *aw = ad->ad_wakedev;
-       ACPI_INTEGER val = aw->aw_number;
-       ACPI_HANDLE hdl = aw->aw_handle;
-       ACPI_STATUS rv;
-       uint8_t i;
-
-       /*
-        * Enable or disable wake GPEs.
-        */
-       if (aw->aw_enable != true)
-               rv = AcpiSetGpeWakeMask(hdl, val, ACPI_GPE_DISABLE);
-       else {
-               rv = AcpiSetGpeWakeMask(hdl, val, ACPI_GPE_ENABLE);
-
-               if (ACPI_FAILURE(rv))
-                       goto out;
-
-               rv = AcpiEnableGpe(hdl, val);
-
-               if (ACPI_FAILURE(rv))
-                       goto out;
-
-               /*
-                * Turn power resources on.
-                *
-                * XXX: We should also turn these off for devices
-                *      that are not allowed to wake the system.
-                *      However, as these are not yet integrated
-                *      with pmf(9), we can not risk devices to
-                *      possibly resume in a power-off state.
-                */
-               for (i = 0; i < __arraycount(aw->aw_power); i++) {
-
-                       if (aw->aw_power[i] == NULL)
-                               continue;
-
-                       (void)acpi_power_res(aw->aw_power[i], hdl, true);
-               }
-       }
-
-out:
-       if (state > aw->aw_sleep)
-               aprint_error_dev(ad->ad_root, "sleep state S%d "
-                   "loses wake for %s\n", state, ad->ad_name);
-
-       if (ACPI_FAILURE(rv) && rv != AE_NOT_FOUND)
-               aprint_error_dev(ad->ad_root, "failed to set wake GPE "
-                   "for %s: %s\n", ad->ad_name, AcpiFormatException(rv));
-}
-
-static void
 acpi_wakedev_method(struct acpi_devnode *ad, int state)
 {
        const bool enable = ad->ad_wakedev->aw_enable;
diff -r 7b827803fbfd -r 631f692596c5 sys/dev/acpi/acpi_wakedev.h
--- a/sys/dev/acpi/acpi_wakedev.h       Sat Feb 19 08:46:41 2011 +0000
+++ b/sys/dev/acpi/acpi_wakedev.h       Sat Feb 19 09:52:32 2011 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: acpi_wakedev.h,v 1.5 2011/02/17 19:36:49 jruoho Exp $ */
+/* $NetBSD: acpi_wakedev.h,v 1.6 2011/02/19 09:52:32 jruoho Exp $ */
 
 /*-
  * Copyright (c) 2009, 2011 Jared D. McNeill <jmcneill%invisible.ca@localhost>
@@ -33,8 +33,8 @@
        ACPI_HANDLE     aw_power[8];    /* Power resources */
        ACPI_HANDLE     aw_handle;      /* Wake GPE handle */
        ACPI_INTEGER    aw_number;      /* Wake GPE number */
-       ACPI_INTEGER    aw_sleep;       /* Highest sleep state for wake */
-       bool            aw_enable;      /* Wake enabled? */
+       ACPI_INTEGER    aw_state;       /* Highest sleep state for wake */
+       bool            aw_enable;      /* Wake enabled (sysctl)? */
 };
 
 void    acpi_wakedev_init(struct acpi_devnode *);



Home | Main Index | Thread Index | Old Index