> Date: Sat, 8 Jul 2023 10:10:51 +0200
> From: Tobias Heider <[email protected]>
>
> 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?
Should the macppc version return EOPNOTSUPP?
> 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
>
>