Module Name: src Committed By: jruoho Date: Sat Feb 19 09:52:32 UTC 2011
Modified Files: src/sys/dev/acpi: acpi.c acpi_wakedev.c acpi_wakedev.h Log Message: 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). To generate a diff of this commit: cvs rdiff -u -r1.236 -r1.237 src/sys/dev/acpi/acpi.c cvs rdiff -u -r1.23 -r1.24 src/sys/dev/acpi/acpi_wakedev.c cvs rdiff -u -r1.5 -r1.6 src/sys/dev/acpi/acpi_wakedev.h Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/acpi/acpi.c diff -u src/sys/dev/acpi/acpi.c:1.236 src/sys/dev/acpi/acpi.c:1.237 --- src/sys/dev/acpi/acpi.c:1.236 Thu Feb 17 19:36:49 2011 +++ src/sys/dev/acpi/acpi.c Sat Feb 19 09:52:32 2011 @@ -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: Index: src/sys/dev/acpi/acpi_wakedev.c diff -u src/sys/dev/acpi/acpi_wakedev.c:1.23 src/sys/dev/acpi/acpi_wakedev.c:1.24 --- src/sys/dev/acpi/acpi_wakedev.c:1.23 Fri Feb 18 13:56:03 2011 +++ src/sys/dev/acpi/acpi_wakedev.c Sat Feb 19 09:52:32 2011 @@ -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 <jmcne...@invisible.ca> @@ -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,77 +292,39 @@ 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); - 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 (state > ad->ad_wakedev->aw_state) + continue; - if (aw->aw_power[i] == NULL) - continue; + hdl = ad->ad_wakedev->aw_handle; + val = ad->ad_wakedev->aw_number; - (void)acpi_power_res(aw->aw_power[i], hdl, true); + if (state == ACPI_STATE_S0) { + (void)AcpiSetGpeWakeMask(hdl, val, ACPI_GPE_DISABLE); + continue; } - } -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); + (void)AcpiSetGpeWakeMask(hdl, val, ACPI_GPE_ENABLE); - 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)); + acpi_wakedev_power_set(ad, true); + acpi_wakedev_method(ad, state); + } } static void Index: src/sys/dev/acpi/acpi_wakedev.h diff -u src/sys/dev/acpi/acpi_wakedev.h:1.5 src/sys/dev/acpi/acpi_wakedev.h:1.6 --- src/sys/dev/acpi/acpi_wakedev.h:1.5 Thu Feb 17 19:36:49 2011 +++ src/sys/dev/acpi/acpi_wakedev.h Sat Feb 19 09:52:32 2011 @@ -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 <jmcne...@invisible.ca> @@ -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 *);