Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 28 Apr 2009 11:56:54 +0000 (UTC)
From:      Andriy Gapon <avg@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r191627 - head/sys/dev/acpica
Message-ID:  <200904281156.n3SBusAb048949@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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 <fk@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())



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200904281156.n3SBusAb048949>