From 7b7683c71a6c5af6a02a67d9768516cd22abfd2c Mon Sep 17 00:00:00 2001 From: marco Date: Fri, 6 Aug 2010 21:12:27 +0000 Subject: [PATCH] Always call _PSW on _LID devices that support it to enable lid open to resume the machine. Conversely disable it when the machine wakes up. Tested by several ok deraadt --- sys/dev/acpi/acpi.c | 11 ++++++- sys/dev/acpi/acpibtn.c | 68 ++++++++++++++++++++++++++++++++---------- sys/dev/acpi/acpidev.h | 4 ++- 3 files changed, 66 insertions(+), 17 deletions(-) diff --git a/sys/dev/acpi/acpi.c b/sys/dev/acpi/acpi.c index 273a35c8f0c..a90f2f81106 100644 --- a/sys/dev/acpi/acpi.c +++ b/sys/dev/acpi/acpi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpi.c,v 1.204 2010/08/06 14:20:14 deraadt Exp $ */ +/* $OpenBSD: acpi.c,v 1.205 2010/08/06 21:12:27 marco Exp $ */ /* * Copyright (c) 2005 Thorsten Lockert * Copyright (c) 2005 Jordan Hargrave @@ -1809,6 +1809,9 @@ acpi_resume(struct acpi_softc *sc, int state) } } + /* disable _LID for wakeup */ + acpibtn_disable_psw(); + /* Reset the indicator lights to "working" */ if (sc->sc_sst) { env.v_integer = ACPI_SST_WORKING; @@ -1850,6 +1853,9 @@ acpi_handle_suspend_failure(struct acpi_softc *sc) } } + /* disable _LID for wakeup */ + acpibtn_disable_psw(); + /* Reset the indicator lights to "working" */ if (sc->sc_sst) { env.v_integer = ACPI_SST_WORKING; @@ -1919,6 +1925,9 @@ acpi_prepare_sleep_state(struct acpi_softc *sc, int state) goto fail; } + /* enable _LID for wakeup */ + acpibtn_enable_psw(); + /* Reset the indicator lights to "sleeping" */ if (sc->sc_sst) { env.v_integer = ACPI_SST_SLEEPING; diff --git a/sys/dev/acpi/acpibtn.c b/sys/dev/acpi/acpibtn.c index 278e296cd4f..274c956ddad 100644 --- a/sys/dev/acpi/acpibtn.c +++ b/sys/dev/acpi/acpibtn.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpibtn.c,v 1.31 2010/08/05 21:10:06 deraadt Exp $ */ +/* $OpenBSD: acpibtn.c,v 1.32 2010/08/06 21:12:27 marco Exp $ */ /* * Copyright (c) 2005 Marco Peereboom * @@ -47,13 +47,21 @@ struct acpibtn_softc { struct aml_node *sc_devnode; int sc_btn_type; -#define ACPIBTN_UNKNOWN -1 -#define ACPIBTN_LID 0 -#define ACPIBTN_POWER 1 -#define ACPIBTN_SLEEP 2 +#define ACPIBTN_UNKNOWN 0 +#define ACPIBTN_LID 1 +#define ACPIBTN_POWER 2 +#define ACPIBTN_SLEEP 3 }; int acpibtn_getsta(struct acpibtn_softc *); +int acpibtn_setpsw(struct acpibtn_softc *, int); + +struct acpi_lid { + struct acpibtn_softc *abl_softc; + SLIST_ENTRY(acpi_lid) abl_link; +}; +SLIST_HEAD(acpi_lid_head, acpi_lid) acpibtn_lids = + SLIST_HEAD_INITIALIZER(acpibtn_lids); struct cfattach acpibtn_ca = { sizeof(struct acpibtn_softc), acpibtn_match, acpibtn_attach @@ -65,6 +73,40 @@ struct cfdriver acpibtn_cd = { const char *acpibtn_hids[] = { ACPI_DEV_LD, ACPI_DEV_PBD, ACPI_DEV_SBD, 0 }; +int +acpibtn_setpsw(struct acpibtn_softc *sc, int psw) +{ + struct aml_value val; + + bzero(&val, sizeof val); + val.type = AML_OBJTYPE_INTEGER; + val.v_integer = psw; + val.length = 1; + + return (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_PSW", 1, &val, + NULL)); +} + +void +acpibtn_disable_psw(void) +{ + struct acpi_lid *lid; + + /* disable _LID for wakeup */ + SLIST_FOREACH(lid, &acpibtn_lids, abl_link) + acpibtn_setpsw(lid->abl_softc, 0); +} + +void +acpibtn_enable_psw(void) +{ + struct acpi_lid *lid; + + /* enable _LID for wakeup */ + SLIST_FOREACH(lid, &acpibtn_lids, abl_link) + acpibtn_setpsw(lid->abl_softc, 1); +} + int acpibtn_match(struct device *parent, void *match, void *aux) { @@ -80,26 +122,22 @@ acpibtn_attach(struct device *parent, struct device *self, void *aux) { struct acpibtn_softc *sc = (struct acpibtn_softc *)self; struct acpi_attach_args *aa = aux; + struct acpi_lid *lid; sc->sc_acpi = (struct acpi_softc *)parent; sc->sc_devnode = aa->aaa_node; if (!strcmp(aa->aaa_dev, ACPI_DEV_LD)) { - struct aml_value val; - sc->sc_btn_type = ACPIBTN_LID; - bzero(&val, sizeof val); - val.type = AML_OBJTYPE_INTEGER; - val.v_integer = 1; - val.length = 1; - (void) aml_evalname(sc->sc_acpi, sc->sc_devnode, "_PSW", - 1, &val, NULL); + if (acpibtn_setpsw(sc, 0) == 0) { + lid = malloc(sizeof(*lid), M_DEVBUF, M_WAITOK | M_ZERO); + lid->abl_softc = sc; + SLIST_INSERT_HEAD(&acpibtn_lids, lid, abl_link); + } } else if (!strcmp(aa->aaa_dev, ACPI_DEV_PBD)) sc->sc_btn_type = ACPIBTN_POWER; else if (!strcmp(aa->aaa_dev, ACPI_DEV_SBD)) sc->sc_btn_type = ACPIBTN_SLEEP; - else - sc->sc_btn_type = ACPIBTN_UNKNOWN; acpibtn_getsta(sc); diff --git a/sys/dev/acpi/acpidev.h b/sys/dev/acpi/acpidev.h index b0e2d425a3e..c04d292d133 100644 --- a/sys/dev/acpi/acpidev.h +++ b/sys/dev/acpi/acpidev.h @@ -1,4 +1,4 @@ -/* $OpenBSD: acpidev.h,v 1.31 2010/08/03 16:55:06 marco Exp $ */ +/* $OpenBSD: acpidev.h,v 1.32 2010/08/06 21:12:27 marco Exp $ */ /* * Copyright (c) 2005 Marco Peereboom * Copyright (c) 2005 Thorsten Lockert @@ -334,4 +334,6 @@ struct acpiec_softc { int sc_gotsci; }; +void acpibtn_disable_psw(void); +void acpibtn_enable_psw(void); #endif /* __DEV_ACPI_ACPIDEV_H__ */ -- 2.20.1