summaryrefslogtreecommitdiffstats
path: root/sys/dev/acpica/acpi.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/acpica/acpi.c')
-rw-r--r--sys/dev/acpica/acpi.c60
1 files changed, 37 insertions, 23 deletions
diff --git a/sys/dev/acpica/acpi.c b/sys/dev/acpica/acpi.c
index 7edb687..54426f4 100644
--- a/sys/dev/acpica/acpi.c
+++ b/sys/dev/acpica/acpi.c
@@ -262,6 +262,8 @@ acpi_attach(device_t dev)
bzero(sc, sizeof(*sc));
sc->acpi_dev = dev;
+ acpi_install_wakeup_handler(sc);
+
#ifdef ENABLE_DEBUGGER
if (debugpoint && !strcmp(debugpoint, "spaces"))
acpi_EnterDebugger();
@@ -959,7 +961,6 @@ acpi_FindIndexedResource(ACPI_RESOURCE *resbuf, int index, ACPI_RESOURCE **resp)
static ACPI_STATUS __inline
acpi_wakeup(UINT8 state)
{
- UINT16 Count;
ACPI_STATUS Status;
ACPI_OBJECT_LIST Arg_list;
ACPI_OBJECT Arg;
@@ -968,21 +969,6 @@ acpi_wakeup(UINT8 state)
FUNCTION_TRACE_U32(__func__, state);
ACPI_ASSERTLOCK;
-
- /* wait for the WAK_STS bit */
- Count = 0;
- while (!(AcpiHwRegisterBitAccess(ACPI_READ, ACPI_MTX_LOCK, WAK_STS))) {
- AcpiOsSleepUsec(1000);
- /*
- * Some BIOSes don't set WAK_STS at all,
- * give up waiting for wakeup if we time out.
- */
- if (Count > 1000) {
- printf("ACPI: timed out waiting for WAK_STS, continuing\n");
- break; /* giving up */
- }
- Count++;
- }
/*
* Evaluate the _WAK method
@@ -1056,6 +1042,7 @@ ACPI_STATUS
acpi_SetSleepState(struct acpi_softc *sc, int state)
{
ACPI_STATUS status = AE_OK;
+ UINT16 Count;
FUNCTION_TRACE_U32(__func__, state);
ACPI_ASSERTLOCK;
@@ -1069,6 +1056,9 @@ acpi_SetSleepState(struct acpi_softc *sc, int state)
break;
case ACPI_STATE_S1:
+ case ACPI_STATE_S2:
+ case ACPI_STATE_S3:
+ case ACPI_STATE_S4:
/*
* Inform all devices that we are going to sleep.
*/
@@ -1084,10 +1074,37 @@ acpi_SetSleepState(struct acpi_softc *sc, int state)
return_ACPI_STATUS(AE_ERROR);
}
sc->acpi_sstate = state;
- status = AcpiEnterSleepState((UINT8)state);
- if (status != AE_OK) {
- device_printf(sc->acpi_dev, "AcpiEnterSleepState failed - %s\n", acpi_strerror(status));
- break;
+
+ if (state != ACPI_STATE_S1) {
+ acpi_sleep_machdep(sc, state);
+
+ /* AcpiEnterSleepState() maybe incompleted, unlock here. */
+ AcpiUtReleaseMutex(ACPI_MTX_HARDWARE);
+
+ /* Re-enable ACPI hardware on wakeup from sleep state 4. */
+ if (state >= ACPI_STATE_S4) {
+ acpi_Disable(sc);
+ acpi_Enable(sc);
+ }
+ } else {
+ status = AcpiEnterSleepState((UINT8)state);
+ if (status != AE_OK) {
+ device_printf(sc->acpi_dev, "AcpiEnterSleepState failed - %s\n", acpi_strerror(status));
+ break;
+ }
+ /* wait for the WAK_STS bit */
+ Count = 0;
+ while (!(AcpiHwRegisterBitAccess(ACPI_READ, ACPI_MTX_LOCK, WAK_STS))) {
+ AcpiOsSleepUsec(1000);
+ /*
+ * Some BIOSes don't set WAK_STS at all,
+ * give up waiting for wakeup if we time out.
+ */
+ if (Count > 1000) {
+ break; /* giving up */
+ }
+ Count++;
+ }
}
acpi_wakeup((UINT8)state);
DEVICE_RESUME(root_bus);
@@ -1095,9 +1112,6 @@ acpi_SetSleepState(struct acpi_softc *sc, int state)
acpi_enable_fixed_events(sc);
break;
- case ACPI_STATE_S3:
- acpi_off_state = ACPI_STATE_S3;
- /* FALLTHROUGH */
case ACPI_STATE_S5:
/*
* Shut down cleanly and power off. This will call us back through the
OpenPOWER on IntegriCloud