Adds request_sleep(), a MI way of sending the machine to sleep in
authortobhe <tobhe@openbsd.org>
Sat, 8 Jul 2023 14:44:43 +0000 (14:44 +0000)
committertobhe <tobhe@openbsd.org>
Sat, 8 Jul 2023 14:44:43 +0000 (14:44 +0000)
a safe thread. Support is limited to amd64, i386 and arm64 at the
moment, macppc gets only an empty stub.

feedback from kettenis@
tested by bluhm@
ok phessler@

sys/arch/arm64/dev/aplsmc.c
sys/arch/arm64/dev/apm.c
sys/arch/macppc/dev/apm.c
sys/dev/acpi/acpi_apm.c
sys/sys/device.h

index 63d45d3..4b8d8cc 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: aplsmc.c,v 1.23 2023/05/29 04:24:39 deraadt Exp $     */
+/*     $OpenBSD: aplsmc.c,v 1.24 2023/07/08 14:44:43 tobhe Exp $       */
 /*
  * Copyright (c) 2021 Mark Kettenis <kettenis@openbsd.org>
  *
@@ -366,7 +366,6 @@ aplsmc_handle_notification(struct aplsmc_softc *sc, uint64_t data)
        extern int allowpowerdown;
 #ifdef SUSPEND
        extern int cpu_suspended;
-       extern void suspend(void);
 
        if (cpu_suspended) {
                switch (SMC_EV_TYPE(data)) {
@@ -433,7 +432,7 @@ aplsmc_handle_notification(struct aplsmc_softc *sc, uint64_t data)
                        }
                case 1:
 #ifdef SUSPEND
-                       suspend();
+                       request_sleep(SLEEP_SUSPEND);
 #endif
                        break;
                case 2:
index 2ccc822..903b355 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: apm.c,v 1.23 2023/07/05 08:26:56 tobhe Exp $  */
+/*     $OpenBSD: apm.c,v 1.24 2023/07/08 14:44:43 tobhe Exp $  */
 
 /*-
  * Copyright (c) 2001 Alexander Guy.  All rights reserved.
 #endif
 
 #ifdef SUSPEND
-struct taskq *suspend_taskq;
+struct taskq *sleep_taskq;
 struct task suspend_task;
 void   do_suspend(void *);
-void   suspend(void);
+#ifdef HIBERNATE
+struct task hibernate_task;
+void   do_hibernate(void *);
+#endif
 #endif
 
 struct apm_softc {
@@ -128,8 +131,11 @@ void
 apmattach(struct device *parent, struct device *self, void *aux)
 {
 #ifdef SUSPEND
-       suspend_taskq = taskq_create("suspend", 1, IPL_NONE, 0);
+       sleep_taskq = taskq_create("sleep", 1, IPL_NONE, 0);
        task_set(&suspend_task, do_suspend, NULL);
+#ifdef HIBERNATE
+       task_set(&hibernate_task, do_hibernate, NULL);
+#endif
 #endif
 
        acpiapm_open = apmopen;
@@ -224,7 +230,7 @@ apmioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
                        error = EBADF;
                        break;
                }
-               suspend();
+               error = request_sleep(SLEEP_SUSPEND);
                break;
 #ifdef HIBERNATE
        case APM_IOC_HIBERNATE:
@@ -234,11 +240,7 @@ apmioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
                        error = EBADF;
                        break;
                }
-               if (get_hibernate_io_function(swdevt[0].sw_dev) == NULL) {
-                       error = EOPNOTSUPP;
-                       break;
-               }
-               sleep_state(NULL, SLEEP_HIBERNATE);
+               error = request_sleep(SLEEP_HIBERNATE);
                break;
 #endif
 #endif
@@ -358,11 +360,34 @@ do_suspend(void *v)
        sleep_state(v, SLEEP_SUSPEND);
 }
 
+#ifdef HIBERNATE
 void
-suspend(void)
+do_hibernate(void *v)
+{
+       sleep_state(v, SLEEP_HIBERNATE);
+}
+#endif
+
+int
+request_sleep(int sleepmode)
 {
-       if (suspend_taskq)
-               task_add(suspend_taskq, &suspend_task);
+       if (sleep_taskq == NULL)
+               return EINVAL;
+
+       switch (sleepmode) {
+       case SLEEP_SUSPEND:
+               task_add(sleep_taskq, &suspend_task);
+               break;
+#ifdef HIBERNATE
+       case SLEEP_HIBERNATE:
+               if (get_hibernate_io_function(swdevt[0].sw_dev) == NULL)
+                       return EOPNOTSUPP;
+               task_add(sleep_taskq, &hibernate_task);
+               break;
+#endif
+       }
+
+       return 0;
 }
 
 #ifdef MULTIPROCESSOR
index 9082d86..d64203d 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: apm.c,v 1.34 2022/10/23 03:43:03 gkoehler Exp $       */
+/*     $OpenBSD: apm.c,v 1.35 2023/07/08 14:44:43 tobhe Exp $  */
 
 /*-
  * Copyright (c) 2001 Alexander Guy.  All rights reserved.
@@ -337,6 +337,12 @@ apmkqfilter(dev_t dev, struct knote *kn)
 
 #ifdef SUSPEND
 
+int
+request_sleep(int sleepmode)
+{
+       return EOPNOTSUPP;
+}
+
 #ifdef MULTIPROCESSOR
 
 void
index 37d5d3e..dc222ce 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpi_apm.c,v 1.1 2023/07/08 08:01:10 tobhe Exp $ */
+/* $OpenBSD: acpi_apm.c,v 1.2 2023/07/08 14:44:43 tobhe Exp $ */
 /*
  * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
  * Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
@@ -109,13 +109,16 @@ acpiioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
        s = splbio();
        /* fake APM */
        switch (cmd) {
+#ifdef SUSPEND
        case APM_IOC_SUSPEND:
        case APM_IOC_STANDBY:
                if ((flag & FWRITE) == 0) {
                        error = EBADF;
                        break;
                }
-               acpi_addtask(sc, acpi_sleep_task, sc, SLEEP_SUSPEND);
+               error = request_sleep(SLEEP_SUSPEND);
+               if (error)
+                       break;
                acpi_wakeup(sc);
                break;
 #ifdef HIBERNATE
@@ -130,9 +133,12 @@ acpiioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
                        error = EOPNOTSUPP;
                        break;
                }
-               acpi_addtask(sc, acpi_sleep_task, sc, SLEEP_HIBERNATE);
+               error = request_sleep(SLEEP_HIBERNATE);
+               if (error)
+                       break;
                acpi_wakeup(sc);
                break;
+#endif
 #endif
        case APM_IOC_GETPOWER:
                error = acpi_apminfo(pi);
@@ -199,6 +205,23 @@ acpi_filtread(struct knote *kn, long hint)
        return (1);
 }
 
+#ifdef SUSPEND
+int
+request_sleep(int sleepmode)
+{
+       struct acpi_softc *sc = acpi_softc;
+
+#ifdef HIBERNATE
+       if (sleepmode == SLEEP_HIBERNATE) {
+               if (get_hibernate_io_function(swdevt[0].sw_dev) == NULL)
+                       return EOPNOTSUPP;
+       }
+#endif
+       acpi_addtask(sc, acpi_sleep_task, sc, sleepmode);
+       return 0;
+}
+#endif /* SUSPEND */
+
 #else /* SMALL_KERNEL */
 
 int
index e99f2d7..77fc2b1 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: device.h,v 1.65 2023/05/17 20:23:14 patrick Exp $     */
+/*     $OpenBSD: device.h,v 1.66 2023/07/08 14:44:43 tobhe Exp $       */
 /*     $NetBSD: device.h,v 1.15 1996/04/09 20:55:24 cgd Exp $  */
 
 /*
@@ -199,6 +199,7 @@ void config_pending_decr(void);
 void config_mountroot(struct device *, void (*)(struct device *));
 void config_process_deferred_mountroot(void);
 
+int    request_sleep(int);
 int    sleep_state(void *, int);
 #define SLEEP_SUSPEND  0x01
 #define SLEEP_HIBERNATE        0x02