diff options
author | Jeremie Courreges-Anglas <jca@cvs.openbsd.org> | 2020-06-10 22:26:41 +0000 |
---|---|---|
committer | Jeremie Courreges-Anglas <jca@cvs.openbsd.org> | 2020-06-10 22:26:41 +0000 |
commit | 436fa7e69f0eb41c4f58b0c798bc619f4dcd6a38 (patch) | |
tree | 67a1ef862504a3da7bf9b4519f2c8b16c33ebf15 | |
parent | 966e090892aa0bea26580f682af56b01950adbf7 (diff) |
Give userland a consistent battery and A/C state after resume
Previously we refreshed the state of acpiac(4) and acpibat(4)/acpisbs(4)
by queueing fake ACPI events to be processed by the acpi thread.
acpibat(4) using ACPIDEV_POLL meant that its status could be refreshed
first, resulting in an APM_POWER_CHANGE event sent to userland before
the state of acpiac(4) was up to date. Because of this, apmd(8) could
see A/C unplugged when it was in fact plugged, possibly leading to
a wrong decision.
Instead of using fake ACPI events, refresh the status of acpiac(4) and
acpibat(4)/acpisbs(4) right away at DVACT_WAKEUP time. To reuse the
existing refresh code of those drivers, make their ACPI *_notify()
handlers responsible for sending APM_POWER_CHANGE events instead. Also
queue an APM_POWER_CHANGE event right after resume to retain existing
behavior.
This fixes the consistency of data shown to userland, and makes those
drivers less special.
Initially discussed last year (!) with mpi@ at Miod's place.
Feedback and ok jcs@, deraadt@ agrees with the use of DVACT_WAKEUP here.
-rw-r--r-- | sys/dev/acpi/acpi.c | 15 | ||||
-rw-r--r-- | sys/dev/acpi/acpiac.c | 26 | ||||
-rw-r--r-- | sys/dev/acpi/acpibat.c | 37 | ||||
-rw-r--r-- | sys/dev/acpi/acpisbs.c | 20 |
4 files changed, 78 insertions, 20 deletions
diff --git a/sys/dev/acpi/acpi.c b/sys/dev/acpi/acpi.c index 7c103347980..99babcb5e4f 100644 --- a/sys/dev/acpi/acpi.c +++ b/sys/dev/acpi/acpi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpi.c,v 1.386 2020/05/29 04:42:24 deraadt Exp $ */ +/* $OpenBSD: acpi.c,v 1.387 2020/06/10 22:26:40 jca Exp $ */ /* * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com> * Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org> @@ -1941,20 +1941,11 @@ void acpi_sleep_task(void *arg0, int sleepmode) { struct acpi_softc *sc = arg0; - struct acpi_ac *ac; - struct acpi_bat *bat; - struct acpi_sbs *sbs; /* System goes to sleep here.. */ acpi_sleep_state(sc, sleepmode); - - /* AC and battery information needs refreshing */ - SLIST_FOREACH(ac, &sc->sc_ac, aac_link) - aml_notify(ac->aac_softc->sc_devnode, 0x80); - SLIST_FOREACH(bat, &sc->sc_bat, aba_link) - aml_notify(bat->aba_softc->sc_devnode, 0x80); - SLIST_FOREACH(sbs, &sc->sc_sbs, asbs_link) - aml_notify(sbs->asbs_softc->sc_devnode, 0x80); + /* Tell userland to recheck A/C and battery status */ + acpi_record_event(sc, APM_POWER_CHANGE); } #endif /* SMALL_KERNEL */ diff --git a/sys/dev/acpi/acpiac.c b/sys/dev/acpi/acpiac.c index 43d67dd64da..e2943ea4504 100644 --- a/sys/dev/acpi/acpiac.c +++ b/sys/dev/acpi/acpiac.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpiac.c,v 1.32 2020/05/09 00:40:48 jca Exp $ */ +/* $OpenBSD: acpiac.c,v 1.33 2020/06/10 22:26:40 jca Exp $ */ /* * Copyright (c) 2005 Marco Peereboom <marco@openbsd.org> * @@ -33,13 +33,18 @@ int acpiac_match(struct device *, void *, void *); void acpiac_attach(struct device *, struct device *, void *); +int acpiac_activate(struct device *, int); int acpiac_notify(struct aml_node *, int, void *); void acpiac_refresh(void *); int acpiac_getpsr(struct acpiac_softc *); struct cfattach acpiac_ca = { - sizeof(struct acpiac_softc), acpiac_match, acpiac_attach + sizeof(struct acpiac_softc), + acpiac_match, + acpiac_attach, + NULL, + acpiac_activate, }; struct cfdriver acpiac_cd = { @@ -92,6 +97,21 @@ acpiac_attach(struct device *parent, struct device *self, void *aux) acpiac_notify, sc, ACPIDEV_NOPOLL); } +int +acpiac_activate(struct device *self, int act) +{ + struct acpiac_softc *sc = (struct acpiac_softc *)self; + + switch (act) { + case DVACT_WAKEUP: + acpiac_refresh(sc); + dnprintf(10, "A/C status: %d\n", sc->sc_ac_stat); + break; + } + + return (0); +} + void acpiac_refresh(void *arg) { @@ -99,7 +119,6 @@ acpiac_refresh(void *arg) acpiac_getpsr(sc); sc->sc_sens[0].value = sc->sc_ac_stat; - acpi_record_event(sc->sc_acpi, APM_POWER_CHANGE); } int @@ -136,6 +155,7 @@ acpiac_notify(struct aml_node *node, int notify_type, void *arg) /* FALLTHROUGH */ case 0x80: acpiac_refresh(sc); + acpi_record_event(sc->sc_acpi, APM_POWER_CHANGE); dnprintf(10, "A/C status: %d\n", sc->sc_ac_stat); break; } diff --git a/sys/dev/acpi/acpibat.c b/sys/dev/acpi/acpibat.c index 6c669f05235..9075aa39722 100644 --- a/sys/dev/acpi/acpibat.c +++ b/sys/dev/acpi/acpibat.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpibat.c,v 1.67 2018/07/01 19:40:49 mlarkin Exp $ */ +/* $OpenBSD: acpibat.c,v 1.68 2020/06/10 22:26:40 jca Exp $ */ /* * Copyright (c) 2005 Marco Peereboom <marco@openbsd.org> * @@ -31,9 +31,14 @@ int acpibat_match(struct device *, void *, void *); void acpibat_attach(struct device *, struct device *, void *); +int acpibat_activate(struct device *, int); struct cfattach acpibat_ca = { - sizeof(struct acpibat_softc), acpibat_match, acpibat_attach + sizeof(struct acpibat_softc), + acpibat_match, + acpibat_attach, + NULL, + acpibat_activate, }; struct cfdriver acpibat_cd = { @@ -110,6 +115,31 @@ acpibat_attach(struct device *parent, struct device *self, void *aux) acpibat_notify, sc, ACPIDEV_POLL); } +int +acpibat_activate(struct device *self, int act) +{ + struct acpibat_softc *sc = (struct acpibat_softc *)self; + int64_t sta; + + switch (act) { + case DVACT_WAKEUP: + /* Check if installed state of battery has changed */ + if (aml_evalinteger(sc->sc_acpi, sc->sc_devnode, "_STA", 0, + NULL, &sta) == 0) { + if (sta & STA_BATTERY) + sc->sc_bat_present = 1; + else + sc->sc_bat_present = 0; + } + acpibat_getbix(sc); + acpibat_getbst(sc); + acpibat_refresh(sc); + break; + } + + return (0); +} + void acpibat_monitor(struct acpibat_softc *sc) { @@ -315,8 +345,6 @@ acpibat_refresh(void *arg) sc->sc_sens[9].flags = 0; } } - - acpi_record_event(sc->sc_acpi, APM_POWER_CHANGE); } int @@ -505,6 +533,7 @@ acpibat_notify(struct aml_node *node, int notify_type, void *arg) } acpibat_refresh(sc); + acpi_record_event(sc->sc_acpi, APM_POWER_CHANGE); return (0); } diff --git a/sys/dev/acpi/acpisbs.c b/sys/dev/acpi/acpisbs.c index bb2eb85a927..7fd85860f79 100644 --- a/sys/dev/acpi/acpisbs.c +++ b/sys/dev/acpi/acpisbs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpisbs.c,v 1.9 2020/01/27 11:04:18 jca Exp $ */ +/* $OpenBSD: acpisbs.c,v 1.10 2020/06/10 22:26:40 jca Exp $ */ /* * Smart Battery subsystem device driver * ACPI 5.0 spec section 10 @@ -128,6 +128,7 @@ extern void acpiec_write(struct acpiec_softc *, uint8_t, int, uint8_t *); int acpisbs_match(struct device *, void *, void *); void acpisbs_attach(struct device *, struct device *, void *); +int acpisbs_activate(struct device *, int); void acpisbs_setup_sensors(struct acpisbs_softc *); void acpisbs_refresh_sensors(struct acpisbs_softc *); void acpisbs_read(struct acpisbs_softc *); @@ -139,6 +140,8 @@ const struct cfattach acpisbs_ca = { sizeof(struct acpisbs_softc), acpisbs_match, acpisbs_attach, + NULL, + acpisbs_activate, }; struct cfdriver acpisbs_cd = { @@ -358,6 +361,21 @@ acpisbs_refresh_sensors(struct acpisbs_softc *sc) } int +acpisbs_activate(struct device *self, int act) +{ + struct acpisbs_softc *sc = (struct acpisbs_softc *)self; + + switch (act) { + case DVACT_WAKEUP: + acpisbs_read(sc); + acpisbs_refresh_sensors(sc); + break; + } + + return 0; +} + +int acpisbs_notify(struct aml_node *node, int notify_type, void *arg) { struct acpisbs_softc *sc = arg; |