summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/acpi/acpi.c125
1 files changed, 47 insertions, 78 deletions
diff --git a/sys/dev/acpi/acpi.c b/sys/dev/acpi/acpi.c
index 937223bb47f..d16dadf95a1 100644
--- a/sys/dev/acpi/acpi.c
+++ b/sys/dev/acpi/acpi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpi.c,v 1.143 2009/10/26 20:17:26 deraadt Exp $ */
+/* $OpenBSD: acpi.c,v 1.144 2009/11/23 15:04:41 mlarkin Exp $ */
/*
* Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
* Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
@@ -55,6 +55,7 @@ int acpi_enabled;
int acpi_poll_enabled;
int acpi_hasprocfvs;
int acpi_thinkpad_enabled;
+int acpi_saved_spl;
#define ACPIEN_RETRIES 15
@@ -84,9 +85,6 @@ void acpi_init_states(struct acpi_softc *);
void acpi_init_gpes(struct acpi_softc *);
void acpi_init_pm(struct acpi_softc *);
-void acpi_dev_sort(void);
-void acpi_dev_free(void);
-
int acpi_foundide(struct aml_node *node, void *arg);
int acpiide_notify(struct aml_node *, int, void *);
@@ -107,9 +105,10 @@ int is_ejectable_bay(struct aml_node *node);
int is_ata(struct aml_node *node);
int is_ejectable(struct aml_node *node);
-#ifdef ACPI_SLEEP_ENABLED
-void acpi_sleep_walk(struct acpi_softc *, int);
-#endif /* ACPI_SLEEP_ENABLED */
+#ifndef SMALL_KERNEL
+void acpi_resume(struct acpi_softc *, int);
+void acpi_susp_resume_gpewalk(struct acpi_softc *, int, int);
+#endif /* SMALL_KERNEL */
#ifndef SMALL_KERNEL
int acpi_add_device(struct aml_node *node, void *arg);
@@ -1775,14 +1774,17 @@ acpi_init_pm(struct acpi_softc *sc)
sc->sc_wak = aml_searchname(&aml_root, "_WAK");
sc->sc_bfs = aml_searchname(&aml_root, "_BFS");
sc->sc_gts = aml_searchname(&aml_root, "_GTS");
+ sc->sc_sst = aml_searchname(&aml_root, "_SST");
}
#ifndef SMALL_KERNEL
void
-acpi_sleep_walk(struct acpi_softc *sc, int state)
+acpi_susp_resume_gpewalk(struct acpi_softc *sc, int state,
+ int wake_gpe_state)
{
struct acpi_wakeq *wentry;
int idx;
+ u_int32_t gpe;
/* Clear GPE status */
for (idx = 0; idx < sc->sc_lastgpe; idx += 8) {
@@ -1795,8 +1797,18 @@ acpi_sleep_walk(struct acpi_softc *sc, int state)
wentry->q_state,
wentry->q_gpe);
- if (state <= wentry->q_state)
- acpi_enable_onegpe(sc, wentry->q_gpe, 1);
+ if (state <= wentry->q_state)
+ acpi_enable_onegpe(sc, wentry->q_gpe,
+ wake_gpe_state);
+ }
+
+ /* If we are resuming (disabling wake GPEs), enable other GPEs */
+
+ if (wake_gpe_state == 0) {
+ for (gpe = 0; gpe < sc->sc_lastgpe; gpe++) {
+ if (sc->gpe_table[gpe].handler)
+ acpi_enable_onegpe(sc, gpe, 1);
+ }
}
}
#endif /* ! SMALL_KERNEL */
@@ -1821,8 +1833,6 @@ acpi_sleep_state(struct acpi_softc *sc, int state)
return (EOPNOTSUPP);
}
- acpi_sleep_walk(sc, state);
-
if ((ret = acpi_prepare_sleep_state(sc, state)) != 0)
return (ret);
@@ -1831,9 +1841,10 @@ acpi_sleep_state(struct acpi_softc *sc, int state)
else
ret = acpi_enter_sleep_state(sc, state);
-#ifndef SMALL_KERNEL
- acpi_resume(sc);
-#endif /* ! SMALL_KERNEL */
+#ifdef ACPI_SLEEP_ENABLED
+ if (state == ACPI_STATE_S3)
+ acpi_resume(sc, state);
+#endif /* ACPI_SLEEP_ENABLED */
return (ret);
}
@@ -1871,6 +1882,7 @@ acpi_enter_sleep_state(struct acpi_softc *sc, int state)
acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, 0, rega);
acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, 0, regb);
+
/* Loop on WAK_STS */
for (retries = 1000; retries > 0; retries--) {
rega = acpi_read_pmreg(sc, ACPIREG_PM1A_STS, 0);
@@ -1886,7 +1898,7 @@ acpi_enter_sleep_state(struct acpi_softc *sc, int state)
#ifndef SMALL_KERNEL
void
-acpi_resume(struct acpi_softc *sc)
+acpi_resume(struct acpi_softc *sc, int state)
{
struct aml_value env;
@@ -1900,8 +1912,13 @@ acpi_resume(struct acpi_softc *sc)
DEVNAME(sc));
}
- dopowerhooks(PWR_RESUME);
- inittodr(0);
+ /* Disable wake GPEs */
+ acpi_susp_resume_gpewalk(sc, state, 0);
+
+ config_suspend(TAILQ_FIRST(&alldevs), DVACT_RESUME);
+
+ enable_intr();
+ splx(acpi_saved_spl);
if (sc->sc_wak)
if (aml_evalnode(sc, sc->sc_wak, 1, &env, NULL) != 0) {
@@ -1946,17 +1963,12 @@ acpi_prepare_sleep_state(struct acpi_softc *sc, int state)
return (ENXIO);
}
- switch (state) {
- case ACPI_STATE_S1:
- case ACPI_STATE_S2:
- resettodr();
- dopowerhooks(PWR_SUSPEND);
- break;
- case ACPI_STATE_S3:
- resettodr();
- dopowerhooks(PWR_STANDBY);
- break;
- }
+ acpi_saved_spl = splhigh();
+ disable_intr();
+#ifndef SMALL_KERNEL
+ if (state == ACPI_STATE_S3)
+ config_suspend(TAILQ_FIRST(&alldevs), DVACT_SUSPEND);
+#endif /* ! SMALL_KERNEL */
/* _PTS(state) */
if (sc->sc_pts)
@@ -1975,9 +1987,11 @@ acpi_prepare_sleep_state(struct acpi_softc *sc, int state)
return (ENXIO);
}
- disable_intr();
- aml_evalname(sc, &aml_root, "\\_SST", 1, &env, NULL);
- sc->sc_state = state;
+ if (sc->sc_sst)
+ aml_evalnode(sc, sc->sc_sst, 1, &env, NULL);
+
+ /* Enable wake GPEs */
+ acpi_susp_resume_gpewalk(sc, state, 1);
return (0);
}
@@ -1991,7 +2005,7 @@ acpi_powerdown(void)
* In case acpi_prepare_sleep fails, we shouldn't try to enter
* the sleep state. It might cost us the battery.
*/
- acpi_sleep_walk(acpi_softc, ACPI_STATE_S5);
+ acpi_susp_resume_gpewalk(acpi_softc, ACPI_STATE_S5, 1);
if (acpi_prepare_sleep_state(acpi_softc, ACPI_STATE_S5) == 0)
acpi_enter_sleep_state(acpi_softc, ACPI_STATE_S5);
}
@@ -2277,49 +2291,4 @@ acpi_foundvideo(struct aml_node *node, void *arg)
return (0);
}
-
-TAILQ_HEAD(acpi_dv_hn, acpi_dev_rank) acpi_dv_h;
-void
-acpi_dev_sort(void)
-{
- struct device *dev, *idev;
- struct acpi_dev_rank *rentry, *ientry;
- int rank;
-
- TAILQ_INIT(&acpi_dv_h);
-
- TAILQ_FOREACH(dev, &alldevs, dv_list) {
- for (rank = -1, idev = dev; idev != NULL;
- idev = idev->dv_parent, rank++)
- ; /* nothing */
-
- rentry = malloc(sizeof(*rentry), M_DEVBUF, M_WAITOK | M_ZERO);
- rentry->rank = rank;
- rentry->dev = dev;
-
- if (TAILQ_FIRST(&acpi_dv_h) == NULL)
- TAILQ_INSERT_HEAD(&acpi_dv_h, rentry, link);
- TAILQ_FOREACH_REVERSE(ientry, &acpi_dv_h, acpi_dv_hn, link) {
- if (rentry->rank > ientry->rank) {
- TAILQ_INSERT_AFTER(&acpi_dv_h, ientry, rentry,
- link);
- break;
- }
- }
- }
-}
-
-void
-acpi_dev_free(void)
-{
- struct acpi_dev_rank *dvr;
-
- while ((dvr = TAILQ_FIRST(&acpi_dv_h)) != NULL) {
- TAILQ_REMOVE(&acpi_dv_h, dvr, link);
- if (dvr != NULL) {
- free(dvr, M_DEVBUF);
- dvr = NULL;
- }
- }
-}
#endif /* SMALL_KERNEL */