From owner-svn-src-all@FreeBSD.ORG Tue Apr 28 11:56:56 2009 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 61DEF106564A; Tue, 28 Apr 2009 11:56:56 +0000 (UTC) (envelope-from avg@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 4FD728FC1C; Tue, 28 Apr 2009 11:56:56 +0000 (UTC) (envelope-from avg@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id n3SBusFV048950; Tue, 28 Apr 2009 11:56:54 GMT (envelope-from avg@svn.freebsd.org) Received: (from avg@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id n3SBusAb048949; Tue, 28 Apr 2009 11:56:54 GMT (envelope-from avg@svn.freebsd.org) Message-Id: <200904281156.n3SBusAb048949@svn.freebsd.org> From: Andriy Gapon Date: Tue, 28 Apr 2009 11:56:54 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r191627 - head/sys/dev/acpica X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 28 Apr 2009 11:56:56 -0000 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 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())