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