From 8cae9a59ce3f27648a688ac6762276e6eddfdcf1 Mon Sep 17 00:00:00 2001 From: tobhe Date: Sat, 8 Jul 2023 14:44:43 +0000 Subject: [PATCH] Adds request_sleep(), a MI way of sending the machine to sleep in 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 | 5 ++-- sys/arch/arm64/dev/apm.c | 51 +++++++++++++++++++++++++++---------- sys/arch/macppc/dev/apm.c | 8 +++++- sys/dev/acpi/acpi_apm.c | 29 ++++++++++++++++++--- sys/sys/device.h | 3 ++- 5 files changed, 75 insertions(+), 21 deletions(-) diff --git a/sys/arch/arm64/dev/aplsmc.c b/sys/arch/arm64/dev/aplsmc.c index 63d45d3697e..4b8d8cc2a03 100644 --- a/sys/arch/arm64/dev/aplsmc.c +++ b/sys/arch/arm64/dev/aplsmc.c @@ -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 * @@ -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: diff --git a/sys/arch/arm64/dev/apm.c b/sys/arch/arm64/dev/apm.c index 2ccc8229914..903b35535be 100644 --- a/sys/arch/arm64/dev/apm.c +++ b/sys/arch/arm64/dev/apm.c @@ -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. @@ -57,10 +57,13 @@ #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 diff --git a/sys/arch/macppc/dev/apm.c b/sys/arch/macppc/dev/apm.c index 9082d868f96..d64203d8fad 100644 --- a/sys/arch/macppc/dev/apm.c +++ b/sys/arch/macppc/dev/apm.c @@ -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 diff --git a/sys/dev/acpi/acpi_apm.c b/sys/dev/acpi/acpi_apm.c index 37d5d3e2feb..dc222cec166 100644 --- a/sys/dev/acpi/acpi_apm.c +++ b/sys/dev/acpi/acpi_apm.c @@ -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 * Copyright (c) 2005 Jordan Hargrave @@ -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 diff --git a/sys/sys/device.h b/sys/sys/device.h index e99f2d75e16..77fc2b1b2bd 100644 --- a/sys/sys/device.h +++ b/sys/sys/device.h @@ -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 -- 2.20.1