This diff 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 is currently an empty stub since it doesn't implement a sleep task (yet).
Once this works, my next plan is adding a Ks_Cmd_Sleep keybinding that is handled in wskbd to get the suspend button working on my m2. I also tested this on a bunch of different archs and kernel configs. ok? diff 6c06be8c9470ada9d77f3ea989b6ed3d857ec4e6 a896f4652f8b00e4f2bbd64d751c85560c264222 commit - 6c06be8c9470ada9d77f3ea989b6ed3d857ec4e6 commit + a896f4652f8b00e4f2bbd64d751c85560c264222 blob - 63d45d3697e4093cf5751308851d470bf5dc62bb blob + 721d18a4ae212c80f44313a3cd27f4191146c3d6 --- sys/arch/arm64/dev/aplsmc.c +++ sys/arch/arm64/dev/aplsmc.c @@ -366,7 +366,6 @@ aplsmc_handle_notification(struct aplsmc_softc *sc, ui 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, ui } case 1: #ifdef SUSPEND - suspend(); + request_sleep(SLEEP_SUSPEND); #endif break; case 2: blob - 2ccc822991480c6b4f4dd44f263ac945a141a6bf blob + 4491ca380d08182244a8157874fc51bcc9665f26 --- sys/arch/arm64/dev/apm.c +++ sys/arch/arm64/dev/apm.c @@ -57,11 +57,14 @@ struct taskq *suspend_taskq; #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 { struct device sc_dev; @@ -128,9 +131,12 @@ apmattach(struct device *parent, struct device *self, 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; acpiapm_close = apmclose; @@ -224,7 +230,7 @@ apmioctl(dev_t dev, u_long cmd, caddr_t data, int flag 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 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,13 +360,36 @@ void sleep_state(v, SLEEP_SUSPEND); } +#ifdef HIBERNATE void -suspend(void) +do_hibernate(void *v) { - if (suspend_taskq) - task_add(suspend_taskq, &suspend_task); + sleep_state(v, SLEEP_HIBERNATE); } +#endif +int +request_sleep(int sleepmode) +{ + 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 void blob - 9082d868f963b80cf0f64453914146a980020883 blob + 52166ca3bfcb826f8c47835024804e5d59061f96 --- sys/arch/macppc/dev/apm.c +++ sys/arch/macppc/dev/apm.c @@ -337,6 +337,12 @@ apmkqfilter(dev_t dev, struct knote *kn) #ifdef SUSPEND +int +request_sleep(int sleepmode) +{ + return 0; +} + #ifdef MULTIPROCESSOR void blob - f7d59513aad484983a8932671c1d06fb4474f550 blob + 59adebc66708d6a1d1c2168e6d01675ae776dca3 --- sys/dev/acpi/acpi_apm.c +++ sys/dev/acpi/acpi_apm.c @@ -109,13 +109,16 @@ acpiioctl(dev_t dev, u_long cmd, caddr_t data, int fla 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,10 +133,13 @@ acpiioctl(dev_t dev, u_long cmd, caddr_t data, int fla 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); break; @@ -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 blob - e99f2d75e16f5c5299e5819fbc20c48fca7c4524 blob + f545bdf5043d51c519765055d5bde6d73b429f3d --- sys/sys/device.h +++ sys/sys/device.h @@ -199,6 +199,7 @@ int sleep_state(void *, int); 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