summaryrefslogtreecommitdiffstats
path: root/sys/dev/acpica
diff options
context:
space:
mode:
authornjl <njl@FreeBSD.org>2004-05-28 07:04:09 +0000
committernjl <njl@FreeBSD.org>2004-05-28 07:04:09 +0000
commit61d1e128a80566ea69193f0ae2c2ea5e68301c9d (patch)
treed559ed5835dc0c9c7e8169840b6c2a9ea1505b66 /sys/dev/acpica
parent41bb6f98ab690ebf69ea3c6126c7dc11175d4f5e (diff)
downloadFreeBSD-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.c78
-rw-r--r--sys/dev/acpica/acpi_button.c1
-rw-r--r--sys/dev/acpica/acpi_lid.c1
-rw-r--r--sys/dev/acpica/acpivar.h1
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);
OpenPOWER on IntegriCloud