summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremie Courreges-Anglas <jca@cvs.openbsd.org>2020-06-10 22:26:41 +0000
committerJeremie Courreges-Anglas <jca@cvs.openbsd.org>2020-06-10 22:26:41 +0000
commit436fa7e69f0eb41c4f58b0c798bc619f4dcd6a38 (patch)
tree67a1ef862504a3da7bf9b4519f2c8b16c33ebf15
parent966e090892aa0bea26580f682af56b01950adbf7 (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.c15
-rw-r--r--sys/dev/acpi/acpiac.c26
-rw-r--r--sys/dev/acpi/acpibat.c37
-rw-r--r--sys/dev/acpi/acpisbs.c20
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;