Make sure we don't suspend if we have no way to wake up the machine.
authorkettenis <kettenis@openbsd.org>
Sat, 3 Sep 2022 18:05:10 +0000 (18:05 +0000)
committerkettenis <kettenis@openbsd.org>
Sat, 3 Sep 2022 18:05:10 +0000 (18:05 +0000)
The idea is that device drivers that can wake up the machine register
themselves by calling device_register_wakeup().  To prevent regressions
on amd64, we let acpi(4) register itself as a wakeup device if the AML
for the machine defines wakeup devices.  This may be refined in the
future.

This diff will prevent people from suspending their arm64 SBCs without
having a way to wake them up.  For now the only driver that registers
itself is axppmic(4), which means that at this moment only SBCs with
an allwinner A64 or H5 SoC will actually support suspend/resume.

ok mlarkin@, deraadt@

sys/dev/acpi/acpi.c
sys/dev/fdt/axppmic.c
sys/kern/subr_suspend.c
sys/sys/device.h

index 15373d4..7571828 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpi.c,v 1.414 2022/08/10 16:58:16 patrick Exp $ */
+/* $OpenBSD: acpi.c,v 1.415 2022/09/03 18:05:10 kettenis Exp $ */
 /*
  * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
  * Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
@@ -1158,6 +1158,11 @@ acpi_attach_common(struct acpi_softc *sc, paddr_t base)
        }
        printf("\n");
 
+#ifdef SUSPEND
+       if (wakeup_dev_ct > 0)
+               device_register_wakeup(&sc->sc_dev);
+#endif
+
        /*
         * ACPI is enabled now -- attach timer
         */
index 9363038..43afc6c 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: axppmic.c,v 1.15 2022/07/16 11:26:13 kettenis Exp $   */
+/*     $OpenBSD: axppmic.c,v 1.16 2022/09/03 18:05:10 kettenis Exp $   */
 /*
  * Copyright (c) 2017 Mark Kettenis <kettenis@openbsd.org>
  *
@@ -570,6 +570,12 @@ axppmic_attach_common(struct axppmic_softc *sc, const char *name, int node)
                powerdownfn = axp209_powerdown;
        }
 #endif
+
+#ifdef SUSPEND
+       /* AXP803 can wake us up. */
+       if (strcmp(name, "x-powers,axp803") == 0)
+               device_register_wakeup(&sc->sc_dev);
+#endif
 }
 
 void
index 8451276..59bc9dc 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: subr_suspend.c,v 1.11 2022/08/14 01:58:28 jsg Exp $ */
+/* $OpenBSD: subr_suspend.c,v 1.12 2022/09/03 18:05:10 kettenis Exp $ */
 /*
  * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
  * Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
 #include "softraid.h"
 #include "wsdisplay.h"
 
+/* Number of (active) wakeup devices in the system. */
+u_int wakeup_devices;
+
+void
+device_register_wakeup(struct device *dev)
+{
+       wakeup_devices++;
+}
+
 int
 sleep_state(void *v, int sleepmode)
 {
@@ -48,6 +57,9 @@ top:
        rndbuf = NULL;
        rndbuflen = 0;
 
+       if (sleepmode == SLEEP_SUSPEND && wakeup_devices == 0)
+               return EOPNOTSUPP;
+
        if (sleep_showstate(v, sleepmode))
                return EOPNOTSUPP;
 #if NWSDISPLAY > 0
index 1d1b5bc..564cc14 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: device.h,v 1.63 2022/04/07 09:37:32 tb Exp $  */
+/*     $OpenBSD: device.h,v 1.64 2022/09/03 18:05:10 kettenis Exp $    */
 /*     $NetBSD: device.h,v 1.15 1996/04/09 20:55:24 cgd Exp $  */
 
 /*
@@ -228,6 +228,7 @@ void        setroot(struct device *, int, int);
 struct device *getdisk(char *str, int len, int defpart, dev_t *devp);
 struct device *parsedisk(char *str, int len, int defpart, dev_t *devp);
 void   device_register(struct device *, void *);
+void   device_register_wakeup(struct device *);
 
 int loadfirmware(const char *name, u_char **bufp, size_t *buflen);
 #define FIRMWARE_MAX   5*1024*1024