Author: avg
Date: Tue Apr 28 11:56:54 2009
New Revision: 191627
URL: http://svn.freebsd.org/changeset/base/191627

Log:
  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 <f...@fabiankeil.de>
  Reviewed by:  njl, jkim
  Approved by:  rpaulo

Modified:
  head/sys/dev/acpica/acpi.c

Modified: head/sys/dev/acpica/acpi.c
==============================================================================
--- head/sys/dev/acpica/acpi.c  Tue Apr 28 11:45:36 2009        (r191626)
+++ head/sys/dev/acpica/acpi.c  Tue Apr 28 11:56:54 2009        (r191627)
@@ -2482,6 +2482,18 @@ acpi_EnterSleepState(struct acpi_softc *
 
     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 *
     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;
+
+    /* Enable any GPEs as appropriate and requested by the user. */
+    acpi_wake_prep_walk(state);
+    slp_state = ACPI_SS_GPE_SET;
 
-       sc->acpi_sstate = state;
+    /*
+     * 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;
 
-       /* Enable any GPEs as appropriate and requested by the user. */
-       acpi_wake_prep_walk(state);
-       slp_state = ACPI_SS_GPE_SET;
+    /* If testing device suspend only, back out of everything here. */
+    if (acpi_susp_bounce)
+       goto backout;
 
-       /*
-        * 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;
+    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 testing device suspend only, back out of everything here. */
-       if (acpi_susp_bounce)
-           break;
+    if (sc->acpi_sleep_delay > 0)
+       DELAY(sc->acpi_sleep_delay * 1000000);
+
+    if (state != ACPI_STATE_S1) {
+       acpi_sleep_machdep(sc, state);
 
-       status = AcpiEnterSleepStatePrep(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, "AcpiEnterSleepStatePrep failed - %s\n",
+           device_printf(sc->acpi_dev, "AcpiEnterSleepState failed - %s\n",
                          AcpiFormatException(status));
-           break;
+           goto backout;
        }
-       slp_state = ACPI_SS_SLP_PREP;
-
-       if (sc->acpi_sleep_delay > 0)
-           DELAY(sc->acpi_sleep_delay * 1000000);
-
-       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;
-           }
-       }
-       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 *
 #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())
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to