> Date: Sat, 8 Jul 2023 10:10:51 +0200
> From: Tobias Heider <tobias.hei...@stusta.de>
> 
> 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
> 
> 

Reply via email to