aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/acpica/acpi.c
diff options
context:
space:
mode:
authorAndriy Gapon <avg@FreeBSD.org>2009-04-28 11:56:54 +0000
committerAndriy Gapon <avg@FreeBSD.org>2009-04-28 11:56:54 +0000
commit33c70d417ea93fb3dea40fbf9dd20336ccb6a6e1 (patch)
tree4ec34c6c43f15daa04b643a6c968d2341f3fad4b /sys/dev/acpica/acpi.c
parent7981aa2431ce1833d334dcd85a2694dee71145c8 (diff)
downloadsrc-33c70d417ea93fb3dea40fbf9dd20336ccb6a6e1.tar.gz
src-33c70d417ea93fb3dea40fbf9dd20336ccb6a6e1.zip
acpi: do not run resume/backout code when entering S0/S5 states
This change adds (possibly redundant) early check for invalid state input parameter (including S0). Handling of S5 request is reduced to simply calling shutdown_nice(). As a result control flow of acpi_EnterSleepState is somewhat simplified and resume/backout half of the function is not executed for S5 (soft poweroff) request and invalid state requests. Note: it seems that shutdown_nice may act as nop when initproc is already initialized (to grab pid of 1), but init process is in "pre-natal" state. Tested by: Fabian Keil <fk@fabiankeil.de> Reviewed by: njl, jkim Approved by: rpaulo
Notes
Notes: svn path=/head/; revision=191627
Diffstat (limited to 'sys/dev/acpica/acpi.c')
-rw-r--r--sys/dev/acpica/acpi.c139
1 files changed, 66 insertions, 73 deletions
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index 50b84a5b5bcd..d8626b435690 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -2482,6 +2482,18 @@ acpi_EnterSleepState(struct acpi_softc *sc, int state)
ACPI_FUNCTION_TRACE_U32((char *)(uintptr_t)__func__, state);
+ if (state < ACPI_STATE_S1 || state > ACPI_STATE_S5)
+ return_ACPI_STATUS (AE_BAD_PARAMETER);
+
+ if (state == ACPI_STATE_S5) {
+ /*
+ * Shut down cleanly and power off. This will call us back through the
+ * shutdown handlers.
+ */
+ shutdown_nice(RB_POWEROFF);
+ return_ACPI_STATUS (AE_OK);
+ }
+
/* Re-entry once we're suspending is not allowed. */
status = acpi_sleep_disable(sc);
if (ACPI_FAILURE(status)) {
@@ -2502,92 +2514,74 @@ acpi_EnterSleepState(struct acpi_softc *sc, int state)
mtx_lock(&Giant);
slp_state = ACPI_SS_NONE;
- switch (state) {
- case ACPI_STATE_S1:
- case ACPI_STATE_S2:
- case ACPI_STATE_S3:
- case ACPI_STATE_S4:
- status = AcpiGetSleepTypeData(state, &TypeA, &TypeB);
- if (status == AE_NOT_FOUND) {
- device_printf(sc->acpi_dev,
- "Sleep state S%d not supported by BIOS\n", state);
- break;
- } else if (ACPI_FAILURE(status)) {
- device_printf(sc->acpi_dev, "AcpiGetSleepTypeData failed - %s\n",
- AcpiFormatException(status));
- break;
- }
+ status = AcpiGetSleepTypeData(state, &TypeA, &TypeB);
+ if (status == AE_NOT_FOUND) {
+ device_printf(sc->acpi_dev,
+ "Sleep state S%d not supported by BIOS\n", state);
+ goto backout;
+ } else if (ACPI_FAILURE(status)) {
+ device_printf(sc->acpi_dev, "AcpiGetSleepTypeData failed - %s\n",
+ AcpiFormatException(status));
+ goto backout;
+ }
- sc->acpi_sstate = state;
+ sc->acpi_sstate = state;
- /* Enable any GPEs as appropriate and requested by the user. */
- acpi_wake_prep_walk(state);
- slp_state = ACPI_SS_GPE_SET;
+ /* Enable any GPEs as appropriate and requested by the user. */
+ acpi_wake_prep_walk(state);
+ slp_state = ACPI_SS_GPE_SET;
- /*
- * Inform all devices that we are going to sleep. If at least one
- * device fails, DEVICE_SUSPEND() automatically resumes the tree.
- *
- * XXX Note that a better two-pass approach with a 'veto' pass
- * followed by a "real thing" pass would be better, but the current
- * bus interface does not provide for this.
- */
- if (DEVICE_SUSPEND(root_bus) != 0) {
- device_printf(sc->acpi_dev, "device_suspend failed\n");
- break;
- }
- slp_state = ACPI_SS_DEV_SUSPEND;
+ /*
+ * Inform all devices that we are going to sleep. If at least one
+ * device fails, DEVICE_SUSPEND() automatically resumes the tree.
+ *
+ * XXX Note that a better two-pass approach with a 'veto' pass
+ * followed by a "real thing" pass would be better, but the current
+ * bus interface does not provide for this.
+ */
+ if (DEVICE_SUSPEND(root_bus) != 0) {
+ device_printf(sc->acpi_dev, "device_suspend failed\n");
+ goto backout;
+ }
+ slp_state = ACPI_SS_DEV_SUSPEND;
- /* If testing device suspend only, back out of everything here. */
- if (acpi_susp_bounce)
- break;
+ /* If testing device suspend only, back out of everything here. */
+ if (acpi_susp_bounce)
+ goto backout;
- status = AcpiEnterSleepStatePrep(state);
- if (ACPI_FAILURE(status)) {
- device_printf(sc->acpi_dev, "AcpiEnterSleepStatePrep failed - %s\n",
- AcpiFormatException(status));
- break;
- }
- slp_state = ACPI_SS_SLP_PREP;
+ status = AcpiEnterSleepStatePrep(state);
+ if (ACPI_FAILURE(status)) {
+ device_printf(sc->acpi_dev, "AcpiEnterSleepStatePrep failed - %s\n",
+ AcpiFormatException(status));
+ goto backout;
+ }
+ slp_state = ACPI_SS_SLP_PREP;
- if (sc->acpi_sleep_delay > 0)
- DELAY(sc->acpi_sleep_delay * 1000000);
+ if (sc->acpi_sleep_delay > 0)
+ DELAY(sc->acpi_sleep_delay * 1000000);
- if (state != ACPI_STATE_S1) {
- acpi_sleep_machdep(sc, state);
+ if (state != ACPI_STATE_S1) {
+ acpi_sleep_machdep(sc, state);
- /* Re-enable ACPI hardware on wakeup from sleep state 4. */
- if (state == ACPI_STATE_S4)
- AcpiEnable();
- } else {
- ACPI_DISABLE_IRQS();
- status = AcpiEnterSleepState(state);
- if (ACPI_FAILURE(status)) {
- device_printf(sc->acpi_dev, "AcpiEnterSleepState failed - %s\n",
- AcpiFormatException(status));
- break;
- }
+ /* Re-enable ACPI hardware on wakeup from sleep state 4. */
+ if (state == ACPI_STATE_S4)
+ AcpiEnable();
+ } else {
+ ACPI_DISABLE_IRQS();
+ status = AcpiEnterSleepState(state);
+ if (ACPI_FAILURE(status)) {
+ device_printf(sc->acpi_dev, "AcpiEnterSleepState failed - %s\n",
+ AcpiFormatException(status));
+ goto backout;
}
- slp_state = ACPI_SS_SLEPT;
- break;
- case ACPI_STATE_S5:
- /*
- * Shut down cleanly and power off. This will call us back through the
- * shutdown handlers.
- */
- shutdown_nice(RB_POWEROFF);
- status = AE_OK;
- break;
- case ACPI_STATE_S0:
- default:
- status = AE_BAD_PARAMETER;
- break;
}
+ slp_state = ACPI_SS_SLEPT;
/*
* Back out state according to how far along we got in the suspend
* process. This handles both the error and success cases.
*/
+backout:
sc->acpi_next_sstate = 0;
if (slp_state >= ACPI_SS_GPE_SET) {
acpi_wake_prep_walk(state);
@@ -2609,8 +2603,7 @@ acpi_EnterSleepState(struct acpi_softc *sc, int state)
#endif
/* Allow another sleep request after a while. */
- if (state != ACPI_STATE_S5)
- timeout(acpi_sleep_enable, sc, hz * ACPI_MINIMUM_AWAKETIME);
+ timeout(acpi_sleep_enable, sc, hz * ACPI_MINIMUM_AWAKETIME);
/* Run /etc/rc.resume after we are back. */
if (devctl_process_running())