diff options
author | njl <njl@FreeBSD.org> | 2004-05-28 07:04:09 +0000 |
---|---|---|
committer | njl <njl@FreeBSD.org> | 2004-05-28 07:04:09 +0000 |
commit | 61d1e128a80566ea69193f0ae2c2ea5e68301c9d (patch) | |
tree | d559ed5835dc0c9c7e8169840b6c2a9ea1505b66 /sys/dev/acpica | |
parent | 41bb6f98ab690ebf69ea3c6126c7dc11175d4f5e (diff) | |
download | FreeBSD-src-61d1e128a80566ea69193f0ae2c2ea5e68301c9d.zip FreeBSD-src-61d1e128a80566ea69193f0ae2c2ea5e68301c9d.tar.gz |
Update the new suspend/resume GPE methods to properly limit the GPE
based on the destination sleep state. Add a method to restore the old
state on resume. This is needed for the case of suspending to a very low
state disabling a GPE (i.e. S4), resuming, and then suspending to a higher
state (i.e. S3). This case should now keep the proper GPEs enabled.
Diffstat (limited to 'sys/dev/acpica')
-rw-r--r-- | sys/dev/acpica/acpi.c | 78 | ||||
-rw-r--r-- | sys/dev/acpica/acpi_button.c | 1 | ||||
-rw-r--r-- | sys/dev/acpica/acpi_lid.c | 1 | ||||
-rw-r--r-- | sys/dev/acpica/acpivar.h | 1 |
4 files changed, 65 insertions, 16 deletions
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c index 9262065..540a7ba 100644 --- a/sys/dev/acpica/acpi.c +++ b/sys/dev/acpica/acpi.c @@ -1836,39 +1836,85 @@ acpi_wake_sleep_prep(device_t dev, int sstate) { struct acpi_prw_data prw; ACPI_HANDLE handle; + int flags; /* Check that this is an ACPI device and get its GPE. */ + flags = device_get_flags(dev); handle = acpi_get_handle(dev); - if (handle == NULL) + if ((flags & ACPI_FLAG_WAKE_CAPABLE) == 0 || handle == NULL) return (ENXIO); + + /* Evaluate _PRW to find the GPE. */ if (acpi_parse_prw(handle, &prw) != 0) return (ENXIO); /* - * The sleeping state being entered must be less than (i.e., higher power) - * or equal to the value specified by _PRW. If not, disable this GPE. + * TBD: All Power Resources referenced by elements 2 through N + * of the _PRW object are put into the ON state. + */ + + /* + * If the user requested that this device wake the system and the next + * sleep state is valid for this GPE, enable it and the device's wake + * capability. The sleep state must be less than (i.e., higher power) + * or equal to the value specified by _PRW. Return early, leaving + * the appropriate power resources enabled. */ - if (sstate > prw.lowest_wake) { + if ((flags & ACPI_FLAG_WAKE_ENABLED) != 0 && + sstate <= prw.lowest_wake) { if (bootverbose) - device_printf(dev, "wake_prep disabled gpe %#x for state %d\n", + device_printf(dev, "wake_prep enabled gpe %#x for state %d\n", prw.gpe_bit, sstate); - AcpiDisableGpe(prw.gpe_handle, prw.gpe_bit, ACPI_NOT_ISR); - acpi_SetInteger(handle, "_PSW", 0); + AcpiEnableGpe(prw.gpe_handle, prw.gpe_bit, ACPI_NOT_ISR); + acpi_SetInteger(handle, "_PSW", 1); return (0); } /* - * If requested, enable the device's wake capability. - * + * If the device wake was disabled or this sleep state is too low for + * this device, disable its wake capability and GPE. + */ + AcpiDisableGpe(prw.gpe_handle, prw.gpe_bit, ACPI_NOT_ISR); + acpi_SetInteger(handle, "_PSW", 0); + if (bootverbose) + device_printf(dev, "wake_prep disabled gpe %#x for state %d\n", + prw.gpe_bit, sstate); + + /* * TBD: All Power Resources referenced by elements 2 through N - * of the _PRW object are put into the ON state. - */ - if ((device_get_flags(dev) & ACPI_FLAG_WAKE_ENABLED) != 0) { - if (bootverbose) - device_printf(dev, "wake_prep enabled _PSW for state %d\n", sstate); - acpi_SetInteger(handle, "_PSW", 1); - } + * of the _PRW object are put into the OFF state. + */ + + return (0); +} + +/* Re-enable GPEs after wake. */ +int +acpi_wake_run_prep(device_t dev) +{ + struct acpi_prw_data prw; + ACPI_HANDLE handle; + int flags; + + /* Check that this is an ACPI device and get its GPE. */ + flags = device_get_flags(dev); + handle = acpi_get_handle(dev); + if ((flags & ACPI_FLAG_WAKE_CAPABLE) == 0 || handle == NULL) + return (ENXIO); + + /* Evaluate _PRW to find the GPE. */ + if (acpi_parse_prw(handle, &prw) != 0) + return (ENXIO); + + /* + * TBD: Be sure all Power Resources referenced by elements 2 through N + * of the _PRW object are in the ON state. + */ + /* Disable wake capability and if the user requested, enable the GPE. */ + acpi_SetInteger(handle, "_PSW", 0); + if ((flags & ACPI_FLAG_WAKE_ENABLED) != 0) + AcpiEnableGpe(prw.gpe_handle, prw.gpe_bit, ACPI_NOT_ISR); return (0); } diff --git a/sys/dev/acpica/acpi_button.c b/sys/dev/acpica/acpi_button.c index b96c5fe..056c3d0 100644 --- a/sys/dev/acpica/acpi_button.c +++ b/sys/dev/acpica/acpi_button.c @@ -175,6 +175,7 @@ acpi_button_suspend(device_t dev) static int acpi_button_resume(device_t dev) { + acpi_wake_run_prep(dev); return (0); } diff --git a/sys/dev/acpica/acpi_lid.c b/sys/dev/acpica/acpi_lid.c index 7971001..4fc4491 100644 --- a/sys/dev/acpica/acpi_lid.c +++ b/sys/dev/acpica/acpi_lid.c @@ -128,6 +128,7 @@ acpi_lid_suspend(device_t dev) static int acpi_lid_resume(device_t dev) { + acpi_wake_run_prep(dev); return (0); } diff --git a/sys/dev/acpica/acpivar.h b/sys/dev/acpica/acpivar.h index 1be1ed8..6ed02e6 100644 --- a/sys/dev/acpica/acpivar.h +++ b/sys/dev/acpica/acpivar.h @@ -230,6 +230,7 @@ extern ACPI_STATUS acpi_SetSleepState(struct acpi_softc *sc, int state); int acpi_wake_init(device_t dev, int type); int acpi_wake_set_enable(device_t dev, int enable); int acpi_wake_sleep_prep(device_t dev, int sstate); +int acpi_wake_run_prep(device_t dev); extern ACPI_STATUS acpi_Startup(void); extern ACPI_STATUS acpi_Enable(struct acpi_softc *sc); extern ACPI_STATUS acpi_Disable(struct acpi_softc *sc); |