The suspend/resume code is a sticky mess of MI, MD, and ACPI sequencing.
authorderaadt <deraadt@openbsd.org>
Tue, 8 Feb 2022 17:25:10 +0000 (17:25 +0000)
committerderaadt <deraadt@openbsd.org>
Tue, 8 Feb 2022 17:25:10 +0000 (17:25 +0000)
This splits out the MI sequencing, backing it with per-architecture helper
functions.  Further steps will be neccesary because ACPI and MD are too
tightly coupled, but soon we'll be able to use this code for more architectures
(which depends on figuring out the lowest-level cpu sleeping method)
ok kettenis

14 files changed:
sys/arch/amd64/amd64/acpi_machdep.c
sys/arch/amd64/conf/GENERIC
sys/arch/arm64/arm64/acpi_machdep.c
sys/arch/i386/conf/GENERIC
sys/arch/i386/i386/acpi_machdep.c
sys/conf/files
sys/dev/acpi/acpi.c
sys/dev/acpi/acpibtn.c
sys/dev/acpi/acpisony.c
sys/dev/acpi/acpithinkpad.c
sys/dev/acpi/acpitoshiba.c
sys/dev/acpi/acpivar.h
sys/kern/subr_suspend.c [new file with mode: 0644]
sys/sys/device.h

index 0502a18..7767877 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: acpi_machdep.c,v 1.94 2021/03/15 22:44:57 patrick Exp $       */
+/*     $OpenBSD: acpi_machdep.c,v 1.95 2022/02/08 17:25:10 deraadt Exp $       */
 /*
  * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
  *
 #include <dev/isa/isareg.h>
 #include <dev/pci/pcivar.h>
 
+#include <machine/apmvar.h>
+
 #include "isa.h"
+#include "wsdisplay.h"
 #include "ioapic.h"
 #include "lapic.h"
 
@@ -53,6 +56,8 @@
 #include <machine/i82489var.h>
 #endif
 
+#include <dev/wscons/wsdisplayvar.h>
+
 extern u_char acpi_real_mode_resume[], acpi_resume_end[];
 extern u_char acpi_tramp_data_start[], acpi_tramp_data_end[];
 extern u_int32_t acpi_pdirpa;
@@ -372,7 +377,7 @@ acpi_attach_machdep(struct acpi_softc *sc)
 #ifndef SMALL_KERNEL
 
 void
-acpi_sleep_clocks(struct acpi_softc *sc, int state)
+sleep_clocks(void *v)
 {
        rtcstop();
 
@@ -499,7 +504,7 @@ acpi_resume_cpu(struct acpi_softc *sc, int state)
 
 #ifdef MULTIPROCESSOR
 void
-acpi_sleep_mp(void)
+sleep_mp(void)
 {
        int i;
 
@@ -522,7 +527,7 @@ acpi_sleep_mp(void)
 }
 
 void
-acpi_resume_mp(void)
+resume_mp(void)
 {
        void    cpu_start_secondary(struct cpu_info *ci);
        struct cpu_info *ci;
@@ -567,6 +572,54 @@ acpi_resume_mp(void)
 }
 #endif /* MULTIPROCESSOR */
 
+void
+display_suspend(void *v)
+{
+#if NWSDISPLAY > 0
+       struct acpi_softc *sc = v;
+
+       /*
+        * Temporarily release the lock to prevent the X server from
+        * blocking on setting the display brightness.
+        */
+       rw_exit_write(&sc->sc_lck);
+       wsdisplay_suspend();
+       rw_enter_write(&sc->sc_lck);
+#endif /* NWSDISPLAY > 0 */
+}
+
+void
+display_resume(void *v)
+{
+#if NWSDISPLAY > 0
+       struct acpi_softc *sc = v;
+
+       rw_exit_write(&sc->sc_lck);
+       wsdisplay_resume();
+       rw_enter_write(&sc->sc_lck);
+#endif /* NWSDISPLAY > 0 */
+}
+
+void
+suspend_finish(void *v)
+{
+       struct acpi_softc *sc = v;
+       extern int lid_action;
+
+       acpi_record_event(sc, APM_NORMAL_RESUME);
+       acpi_indicator(sc, ACPI_SST_WORKING);
+
+       /* If we woke up but all the lids are closed, go back to sleep */
+       if (acpibtn_numopenlids() == 0 && lid_action != 0)
+               acpi_addtask(sc, acpi_sleep_task, sc, sc->sc_state);
+}
+
+void
+disable_lid_wakeups(void *v)
+{
+       acpibtn_disable_psw();          /* disable _LID for wakeup */
+}
+
 #endif /* ! SMALL_KERNEL */
 
 bus_dma_tag_t
index af15c7f..e3e424c 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: GENERIC,v 1.510 2022/01/04 05:50:43 gnezdo Exp $
+#      $OpenBSD: GENERIC,v 1.511 2022/02/08 17:25:11 deraadt Exp $
 #
 # For further information on compiling OpenBSD kernels, see the config(8)
 # man page.
@@ -19,7 +19,8 @@ option                APERTURE        # in-kernel aperture driver for XFree86
 option         MTRR            # CPU memory range attributes control
 
 option         NTFS            # NTFS support
-option         HIBERNATE       # Hibernate support
+option         SUSPEND
+option         HIBERNATE
 
 config         bsd     swap generic
 
index 9fb20a2..cc92da1 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: acpi_machdep.c,v 1.16 2021/10/24 17:52:28 mpi Exp $   */
+/*     $OpenBSD: acpi_machdep.c,v 1.17 2022/02/08 17:25:11 deraadt Exp $       */
 /*
  * Copyright (c) 2018 Mark Kettenis
  *
@@ -191,7 +191,7 @@ acpi_intr_disestablish(void *cookie)
 }
 
 void
-acpi_sleep_clocks(struct acpi_softc *sc, int state)
+sleep_clocks(void *)
 {
 }
 
index 80f1807..0ae9592 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: GENERIC,v 1.860 2022/01/02 23:14:27 jsg Exp $
+#      $OpenBSD: GENERIC,v 1.861 2022/02/08 17:25:11 deraadt Exp $
 #
 # For further information on compiling OpenBSD kernels, see the config(8)
 # man page.
@@ -19,7 +19,8 @@ option                APERTURE        # in-kernel aperture driver for XFree86
 option         MTRR            # CPU memory range attributes control
 
 option         NTFS            # NTFS support
-option         HIBERNATE       # Hibernate support
+option         SUSPEND
+option         HIBERNATE
 
 config         bsd     swap generic
 
index 4f011d4..3416683 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: acpi_machdep.c,v 1.76 2021/03/15 22:44:57 patrick Exp $       */
+/*     $OpenBSD: acpi_machdep.c,v 1.77 2022/02/08 17:25:11 deraadt Exp $       */
 /*
  * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
  *
 #include <dev/acpi/acpireg.h>
 #include <dev/acpi/acpivar.h>
 #include <dev/acpi/acpidev.h>
+#include <dev/acpi/dsdt.h>
 #include <dev/isa/isareg.h>
 #include <dev/pci/pcivar.h>
 
+#include <machine/apmvar.h>
+
 #include "apm.h"
+#include "wsdisplay.h"
 #include "isa.h"
 #include "ioapic.h"
 #include "lapic.h"
@@ -60,6 +64,8 @@
 #include <machine/i82489var.h>
 #endif
 
+#include <dev/wscons/wsdisplayvar.h>
+
 #if NAPM > 0
 int haveacpibutusingapm;
 #endif
@@ -329,7 +335,7 @@ int save_lapic_tpr;
 #endif
 
 void
-acpi_sleep_clocks(struct acpi_softc *sc, int state)
+sleep_clocks(void *v)
 {
        rtcstop();
 
@@ -457,7 +463,7 @@ acpi_resume_cpu(struct acpi_softc *sc, int state)
 
 #ifdef MULTIPROCESSOR
 void
-acpi_sleep_mp(void)
+sleep_mp(void)
 {
        int i;
 
@@ -480,7 +486,7 @@ acpi_sleep_mp(void)
 }
 
 void
-acpi_resume_mp(void)
+resume_mp(void)
 {
        struct cpu_info *ci;
        struct proc *p;
@@ -519,6 +525,54 @@ acpi_resume_mp(void)
 }
 #endif /* MULTIPROCESSOR */
 
+void
+display_suspend(void *v)
+{
+#if NWSDISPLAY > 0
+       struct acpi_softc *sc = v;
+
+       /*
+        * Temporarily release the lock to prevent the X server from
+        * blocking on setting the display brightness.
+        */
+       rw_exit_write(&sc->sc_lck);
+       wsdisplay_suspend();
+       rw_enter_write(&sc->sc_lck);
+#endif /* NWSDISPLAY > 0 */
+}
+
+void
+display_resume(void *v)
+{
+#if NWSDISPLAY > 0
+       struct acpi_softc *sc = v;
+
+       rw_exit_write(&sc->sc_lck);
+       wsdisplay_resume();
+       rw_enter_write(&sc->sc_lck);
+#endif /* NWSDISPLAY > 0 */
+}
+
+void
+suspend_finish(void *v)
+{
+       struct acpi_softc *sc = v;
+       extern int lid_action;
+
+       acpi_record_event(sc, APM_NORMAL_RESUME);
+       acpi_indicator(sc, ACPI_SST_WORKING);
+
+       /* If we woke up but all the lids are closed, go back to sleep */
+       if (acpibtn_numopenlids() == 0 && lid_action != 0)
+               acpi_addtask(sc, acpi_sleep_task, sc, sc->sc_state);
+}
+
+void
+disable_lid_wakeups(void *v)
+{
+       acpibtn_disable_psw();          /* disable _LID for wakeup */
+}
+
 #endif /* ! SMALL_KERNEL */
 
 bus_dma_tag_t
index 8996d9b..86d464c 100644 (file)
@@ -1,4 +1,4 @@
-#      $OpenBSD: files,v 1.708 2022/01/09 13:26:08 visa Exp $
+#      $OpenBSD: files,v 1.709 2022/02/08 17:25:11 deraadt Exp $
 #      $NetBSD: files,v 1.87 1996/05/19 17:17:50 jonathan Exp $
 
 #      @(#)files.newconf       7.5 (Berkeley) 5/10/93
@@ -724,6 +724,7 @@ file kern/subr_autoconf.c
 file kern/subr_disk.c
 file kern/subr_evcount.c
 file kern/subr_extent.c
+file kern/subr_suspend.c               suspend
 file kern/subr_hibernate.c             hibernate
 file kern/subr_kubsan.c                        kubsan
 file kern/subr_log.c
index 5788520..ebcd047 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpi.c,v 1.409 2022/02/04 08:06:48 robert Exp $ */
+/* $OpenBSD: acpi.c,v 1.410 2022/02/08 17:25:12 deraadt Exp $ */
 /*
  * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
  * Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
@@ -113,8 +113,6 @@ void        acpi_enable_onegpe(struct acpi_softc *, int);
 int    acpi_gpe(struct acpi_softc *, int, void *);
 
 void   acpi_enable_rungpes(struct acpi_softc *);
-void   acpi_enable_wakegpes(struct acpi_softc *, int);
-
 
 int    acpi_foundec(struct aml_node *, void *);
 int    acpi_foundsony(struct aml_node *node, void *arg);
@@ -126,8 +124,6 @@ void        acpi_create_thread(void *);
 
 #ifndef SMALL_KERNEL
 
-void   acpi_indicator(struct acpi_softc *, int);
-
 void   acpi_init_pm(struct acpi_softc *);
 
 int    acpi_founddock(struct aml_node *, void *);
@@ -1961,8 +1957,9 @@ acpi_sleep_task(void *arg0, int sleepmode)
 {
        struct acpi_softc *sc = arg0;
 
-       /* System goes to sleep here.. */
-       acpi_sleep_state(sc, sleepmode);
+#ifdef SUSPEND
+       sleep_state(sc, sleepmode);
+#endif
        /* Tell userland to recheck A/C and battery status */
        acpi_record_event(sc, APM_POWER_CHANGE);
 }
@@ -2043,7 +2040,7 @@ acpi_pbtn_task(void *arg0, int dummy)
                break;
 #ifndef SMALL_KERNEL
        case 2:
-               acpi_addtask(sc, acpi_sleep_task, sc, ACPI_SLEEP_SUSPEND);
+               acpi_addtask(sc, acpi_sleep_task, sc, SLEEP_SUSPEND);
                break;
 #endif
        }
@@ -2549,203 +2546,6 @@ acpi_indicator(struct acpi_softc *sc, int led_state)
        }
 }
 
-
-int
-acpi_sleep_state(struct acpi_softc *sc, int sleepmode)
-{
-       extern int perflevel;
-       extern int lid_action;
-       int error = ENXIO;
-       size_t rndbuflen = 0;
-       char *rndbuf = NULL;
-       int state, s;
-#if NSOFTRAID > 0
-       extern void sr_quiesce(void);
-#endif
-
-       switch (sleepmode) {
-       case ACPI_SLEEP_SUSPEND:
-               state = ACPI_STATE_S3;
-               break;
-       case ACPI_SLEEP_HIBERNATE:
-               state = ACPI_STATE_S4;
-               break;
-       default:
-               return (EOPNOTSUPP);
-       }
-
-       if (sc->sc_sleeptype[state].slp_typa == -1 ||
-           sc->sc_sleeptype[state].slp_typb == -1) {
-               printf("%s: state S%d unavailable\n",
-                   sc->sc_dev.dv_xname, state);
-               return (EOPNOTSUPP);
-       }
-
-       /* 1st suspend AML step: _TTS(tostate) */
-       if (aml_node_setval(sc, sc->sc_tts, state) != 0)
-               goto fail_tts;
-       acpi_indicator(sc, ACPI_SST_WAKING);    /* blink */
-
-#if NWSDISPLAY > 0
-       /*
-        * Temporarily release the lock to prevent the X server from
-        * blocking on setting the display brightness.
-        */
-       rw_exit_write(&sc->sc_lck);
-       wsdisplay_suspend();
-       rw_enter_write(&sc->sc_lck);
-#endif /* NWSDISPLAY > 0 */
-
-       stop_periodic_resettodr();
-
-#ifdef HIBERNATE
-       if (sleepmode == ACPI_SLEEP_HIBERNATE) {
-               /*
-                * Discard useless memory to reduce fragmentation,
-                * and attempt to create a hibernate work area
-                */
-               hibernate_suspend_bufcache();
-               uvmpd_hibernate();
-               if (hibernate_alloc()) {
-                       printf("%s: failed to allocate hibernate memory\n",
-                           sc->sc_dev.dv_xname);
-                       goto fail_alloc;
-               }
-       }
-#endif /* HIBERNATE */
-
-       sensor_quiesce();
-       if (config_suspend_all(DVACT_QUIESCE))
-               goto fail_quiesce;
-
-       vfs_stall(curproc, 1);
-#if NSOFTRAID > 0
-       sr_quiesce();
-#endif
-       bufq_quiesce();
-
-#ifdef MULTIPROCESSOR
-       acpi_sleep_mp();
-#endif
-
-#ifdef HIBERNATE
-       if (sleepmode == ACPI_SLEEP_HIBERNATE) {
-               /*
-                * We've just done various forms of syncing to disk
-                * churned lots of memory dirty.  We don't need to
-                * save that dirty memory to hibernate, so release it.
-                */
-               hibernate_suspend_bufcache();
-               uvmpd_hibernate();
-       }
-#endif /* HIBERNATE */
-
-       resettodr();
-
-       s = splhigh();
-       intr_disable(); /* PSL_I for resume; PIC/APIC broken until repair */
-       cold = 2;       /* Force other code to delay() instead of tsleep() */
-
-       if (config_suspend_all(DVACT_SUSPEND) != 0)
-               goto fail_suspend;
-       acpi_sleep_clocks(sc, state);
-
-       suspend_randomness();
-
-       /* 2nd suspend AML step: _PTS(tostate) */
-       if (aml_node_setval(sc, sc->sc_pts, state) != 0)
-               goto fail_pts;
-
-       acpibtn_enable_psw();   /* enable _LID for wakeup */
-       acpi_indicator(sc, ACPI_SST_SLEEPING);
-
-       /* 3rd suspend AML step: _GTS(tostate) */
-       aml_node_setval(sc, sc->sc_gts, state);
-
-       /* Clear fixed event status */
-       acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, ACPI_PM1_ALL_STS);
-
-       /* Enable wake GPEs */
-       acpi_disable_allgpes(sc);
-       acpi_enable_wakegpes(sc, state);
-
-       /* Sleep */
-       sc->sc_state = state;
-       error = acpi_sleep_cpu(sc, state);
-       sc->sc_state = ACPI_STATE_S0;
-       /* Resume */
-
-#ifdef HIBERNATE
-       if (sleepmode == ACPI_SLEEP_HIBERNATE) {
-               uvm_pmr_dirty_everything();
-               hib_getentropy(&rndbuf, &rndbuflen);
-       }
-#endif /* HIBERNATE */
-
-       acpi_resume_cpu(sc, state);
-
-fail_pts:
-       config_suspend_all(DVACT_RESUME);
-
-fail_suspend:
-       cold = 0;
-       intr_enable();
-       splx(s);
-
-       acpibtn_disable_psw();          /* disable _LID for wakeup */
-
-       inittodr(gettime());
-
-       /* 3rd resume AML step: _TTS(runstate) */
-       aml_node_setval(sc, sc->sc_tts, sc->sc_state);
-
-       /* force RNG upper level reseed */
-       resume_randomness(rndbuf, rndbuflen);
-
-#ifdef MULTIPROCESSOR
-       acpi_resume_mp();
-#endif
-
-       vfs_stall(curproc, 0);
-       bufq_restart();
-
-fail_quiesce:
-       config_suspend_all(DVACT_WAKEUP);
-       sensor_restart();
-
-#ifdef HIBERNATE
-       if (sleepmode == ACPI_SLEEP_HIBERNATE) {
-               hibernate_free();
-fail_alloc:
-               hibernate_resume_bufcache();
-       }
-#endif /* HIBERNATE */
-
-       start_periodic_resettodr();
-
-#if NWSDISPLAY > 0
-       rw_exit_write(&sc->sc_lck);
-       wsdisplay_resume();
-       rw_enter_write(&sc->sc_lck);
-#endif /* NWSDISPLAY > 0 */
-
-       sys_sync(curproc, NULL, NULL);
-
-       /* Restore hw.setperf */
-       if (cpu_setperf != NULL)
-               cpu_setperf(perflevel);
-
-       acpi_record_event(sc, APM_NORMAL_RESUME);
-       acpi_indicator(sc, ACPI_SST_WORKING);
-
-       /* If we woke up but all the lids are closed, go back to sleep */
-       if (acpibtn_numopenlids() == 0 && lid_action != 0)
-               acpi_addtask(sc, acpi_sleep_task, sc, sleepmode);
-
-fail_tts:
-       return (error);
-}
-
 /* XXX
  * We are going to do AML execution but are not in the acpi thread.
  * We do not know if the acpi thread is sleeping on acpiec in some
@@ -3528,7 +3328,7 @@ acpiioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p)
                        error = EBADF;
                        break;
                }
-               acpi_addtask(sc, acpi_sleep_task, sc, ACPI_SLEEP_SUSPEND);
+               acpi_addtask(sc, acpi_sleep_task, sc, SLEEP_SUSPEND);
                acpi_wakeup(sc);
                break;
 #ifdef HIBERNATE
@@ -3543,7 +3343,7 @@ 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, ACPI_SLEEP_HIBERNATE);
+               acpi_addtask(sc, acpi_sleep_task, sc, SLEEP_HIBERNATE);
                acpi_wakeup(sc);
                break;
 #endif
@@ -3718,6 +3518,86 @@ acpikqfilter(dev_t dev, struct knote *kn)
        return (0);
 }
 
+int
+sleep_showstate(void *v, int sleepmode)
+{
+       struct acpi_softc *sc = v;
+
+       switch (sleepmode) {
+       case SLEEP_SUSPEND:
+               sc->sc_state = ACPI_STATE_S3;
+               break;
+       case SLEEP_HIBERNATE:
+               sc->sc_state = ACPI_STATE_S4;
+               break;
+       default:
+               return (EOPNOTSUPP);
+       }
+
+       if (sc->sc_sleeptype[sc->sc_state].slp_typa == -1 ||
+           sc->sc_sleeptype[sc->sc_state].slp_typb == -1) {
+               printf("%s: state S%d unavailable\n",
+                   sc->sc_dev.dv_xname, sc->sc_state);
+               return (EOPNOTSUPP);
+       }
+
+       /* 1st suspend AML step: _TTS(tostate) */
+       if (aml_node_setval(sc, sc->sc_tts, sc->sc_state) != 0)
+               return (EINVAL);
+       acpi_indicator(sc, ACPI_SST_WAKING);    /* blink */
+       return 0;
+}
+
+int
+sleep_setstate(void *v)
+{
+       struct acpi_softc *sc = v;
+
+       /* 2nd suspend AML step: _PTS(tostate) */
+       if (aml_node_setval(sc, sc->sc_pts, sc->sc_state) != 0)
+               return (EINVAL);
+       acpi_indicator(sc, ACPI_SST_WAKING);    /* blink */
+       return 0;
+}
+
+void
+gosleep(void *v)
+{
+       struct acpi_softc *sc = v;
+
+       acpibtn_enable_psw();   /* enable _LID for wakeup */
+       acpi_indicator(v, ACPI_SST_SLEEPING);
+
+       /* 3rd suspend AML step: _GTS(tostate) */
+       aml_node_setval(sc, sc->sc_gts, sc->sc_state);
+
+       /* Clear fixed event status */
+       acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, ACPI_PM1_ALL_STS);
+
+       /* Enable wake GPEs */
+       acpi_disable_allgpes(sc);
+       acpi_enable_wakegpes(sc, sc->sc_state);
+
+       /* Sleep */
+       acpi_sleep_cpu(sc, sc->sc_state);
+       sc->sc_state = ACPI_STATE_S0;
+       /* Resume */
+
+       acpi_resume_cpu(sc, sc->sc_state);
+}
+
+int
+sleep_resume(void *v)
+{
+       struct acpi_softc *sc = v;
+
+       /* 3rd resume AML step: _TTS(runstate) */
+       if (aml_node_setval(sc, sc->sc_tts, sc->sc_state) != 0)
+               return (EINVAL);
+       acpi_indicator(sc, ACPI_SST_WAKING);    /* blink */
+       return 0;
+}
+
 #else /* SMALL_KERNEL */
 
 int
index da3b59e..1728f1c 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpibtn.c,v 1.47 2019/01/20 02:45:44 tedu Exp $ */
+/* $OpenBSD: acpibtn.c,v 1.48 2022/02/08 17:25:12 deraadt Exp $ */
 /*
  * Copyright (c) 2005 Marco Peereboom <marco@openbsd.org>
  *
@@ -245,7 +245,7 @@ acpibtn_notify(struct aml_node *node, int notify_type, void *arg)
                        /* Request to go to sleep */
                        if (acpi_record_event(sc->sc_acpi, APM_USER_HIBERNATE_REQ))
                                acpi_addtask(sc->sc_acpi, acpi_sleep_task,
-                                   sc->sc_acpi, ACPI_SLEEP_HIBERNATE);
+                                   sc->sc_acpi, SLEEP_HIBERNATE);
                        break;
 #endif
                default:
@@ -264,7 +264,7 @@ sleep:
                        /* Request to go to sleep */
                        if (acpi_record_event(sc->sc_acpi, APM_USER_SUSPEND_REQ))
                                acpi_addtask(sc->sc_acpi, acpi_sleep_task,
-                                   sc->sc_acpi, ACPI_SLEEP_SUSPEND);
+                                   sc->sc_acpi, SLEEP_SUSPEND);
                        break;
                }
 #endif /* SMALL_KERNEL */
index 4faf3ae..5ddda1d 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpisony.c,v 1.8 2020/04/06 00:01:08 pirofti Exp $ */
+/* $OpenBSD: acpisony.c,v 1.9 2022/02/08 17:25:12 deraadt Exp $ */
 /*
  * Copyright (c) 2010 Paul Irofti <paul@irofti.net>
  *
@@ -198,7 +198,7 @@ acpisony_notify(struct aml_node *node, int notify, void *arg)
 #ifndef SMALL_KERNEL
                if (acpi_record_event(sc->sc_acpi, APM_USER_SUSPEND_REQ))
                        acpi_addtask(sc->sc_acpi, acpi_sleep_task,
-                           sc->sc_acpi, ACPI_SLEEP_SUSPEND);
+                           sc->sc_acpi, SLEEP_SUSPEND);
 #endif
                break;
        case SONY_NOTIFY_SUSPEND_RELEASED:
index 9c311da..8d43792 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: acpithinkpad.c,v 1.68 2019/12/31 01:38:33 jsg Exp $   */
+/*     $OpenBSD: acpithinkpad.c,v 1.69 2022/02/08 17:25:12 deraadt Exp $       */
 /*
  * Copyright (c) 2008 joshua stein <jcs@openbsd.org>
  *
@@ -421,7 +421,7 @@ thinkpad_hotkey(struct aml_node *node, int notify_type, void *arg)
 #ifndef SMALL_KERNEL
                        if (acpi_record_event(sc->sc_acpi, APM_USER_SUSPEND_REQ))
                                acpi_addtask(sc->sc_acpi, acpi_sleep_task, 
-                                   sc->sc_acpi, ACPI_SLEEP_SUSPEND);
+                                   sc->sc_acpi, SLEEP_SUSPEND);
 #endif
                        break;
                case THINKPAD_BUTTON_VOLUME_MUTE:
@@ -442,7 +442,7 @@ thinkpad_hotkey(struct aml_node *node, int notify_type, void *arg)
 #if defined(HIBERNATE) && !defined(SMALL_KERNEL)
                        if (acpi_record_event(sc->sc_acpi, APM_USER_HIBERNATE_REQ))
                                acpi_addtask(sc->sc_acpi, acpi_sleep_task, 
-                                   sc->sc_acpi, ACPI_SLEEP_HIBERNATE);
+                                   sc->sc_acpi, SLEEP_HIBERNATE);
 #endif
                        break;
                case THINKPAD_BUTTON_THINKLIGHT:
index 4ee4b08..bdf643b 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: acpitoshiba.c,v 1.13 2020/03/16 08:51:48 jasper Exp $ */
+/* $OpenBSD: acpitoshiba.c,v 1.14 2022/02/08 17:25:12 deraadt Exp $ */
 /*-
  * Copyright (c) 2003 Hiroyuki Aizu <aizu@navi.org>
  * All rights reserved.
@@ -397,7 +397,7 @@ toshiba_hotkey(struct aml_node *node, int notify, void *arg)
 #ifndef SMALL_KERNEL
                if (acpi_record_event(sc->sc_acpi, APM_USER_SUSPEND_REQ)) {
                        acpi_addtask(sc->sc_acpi, acpi_sleep_task,
-                           sc->sc_acpi, ACPI_SLEEP_SUSPEND);
+                           sc->sc_acpi, SLEEP_SUSPEND);
                        ret = HCI_SUCCESS;
                }
 #endif
@@ -406,7 +406,7 @@ toshiba_hotkey(struct aml_node *node, int notify, void *arg)
 #if defined(HIBERNATE) && !defined(SMALL_KERNEL)
                if (acpi_record_event(sc->sc_acpi, APM_USER_HIBERNATE_REQ)) {
                        acpi_addtask(sc->sc_acpi, acpi_sleep_task,
-                           sc->sc_acpi, ACPI_SLEEP_HIBERNATE);
+                           sc->sc_acpi, SLEEP_HIBERNATE);
                        ret = HCI_SUCCESS;
                }
 #endif
index 9058193..52b7526 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: acpivar.h,v 1.117 2022/02/01 18:09:00 deraadt Exp $   */
+/*     $OpenBSD: acpivar.h,v 1.118 2022/02/08 17:25:12 deraadt Exp $   */
 /*
  * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
  *
@@ -334,21 +334,12 @@ int        acpi_interrupt(void *);
 void    acpi_powerdown(void);
 void    acpi_reset(void);
 
-
-#define ACPI_SLEEP_SUSPEND     0x01
-#define ACPI_SLEEP_HIBERNATE   0x02
-
-int     acpi_sleep_state(struct acpi_softc *, int);
-void    acpi_sleep_clocks(struct acpi_softc *, int);
 int     acpi_sleep_cpu(struct acpi_softc *, int);
-void    acpi_sleep_mp(void);
 void    acpi_sleep_pm(struct acpi_softc *, int);
 void    acpi_resume_pm(struct acpi_softc *, int);
 void    acpi_resume_cpu(struct acpi_softc *, int);
-void    acpi_resume_mp(void);
 void    acpi_sleep_walk(struct acpi_softc *, int);
 
-
 #define ACPI_IOREAD 0
 #define ACPI_IOWRITE 1
 
@@ -387,6 +378,10 @@ int64_t    acpi_getsta(struct acpi_softc *sc, struct aml_node *);
 int    acpi_getprop(struct aml_node *, const char *, void *, int);
 uint64_t acpi_getpropint(struct aml_node *, const char *, uint64_t);
 
+void   acpi_indicator(struct acpi_softc *, int);
+void   acpi_disable_allgpes(struct acpi_softc *);
+void   acpi_enable_wakegpes(struct acpi_softc *, int);
+
 int    acpi_record_event(struct acpi_softc *, u_int);
 
 void   acpi_addtask(struct acpi_softc *, void (*)(void *, int), void *, int);
diff --git a/sys/kern/subr_suspend.c b/sys/kern/subr_suspend.c
new file mode 100644 (file)
index 0000000..f92ee7d
--- /dev/null
@@ -0,0 +1,170 @@
+/* $OpenBSD: subr_suspend.c,v 1.1 2022/02/08 17:25:12 deraadt Exp $ */
+/*
+ * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com>
+ * Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/buf.h>
+#include <sys/malloc.h>
+#include <sys/pool.h>
+#include <sys/proc.h>
+#include <sys/sensors.h>
+#include <sys/sysctl.h>
+#include <sys/mount.h>
+#include <sys/syscallargs.h>
+#include <dev/wscons/wsdisplayvar.h>
+#ifdef HIBERNATE
+#include <sys/hibernate.h>
+#endif
+
+#include "softraid.h"
+
+int
+sleep_state(void *v, int sleepmode)
+{
+       int error = ENXIO;
+       extern int perflevel;
+       size_t rndbuflen = 0;
+       char *rndbuf = NULL;
+       int s;
+#if NSOFTRAID > 0
+       extern void sr_quiesce(void);
+#endif
+
+       if (sleep_showstate(v, sleepmode))
+               return EOPNOTSUPP;
+
+       display_suspend(v);
+
+       stop_periodic_resettodr();
+
+#ifdef HIBERNATE
+       if (sleepmode == SLEEP_HIBERNATE) {
+               /*
+                * Discard useless memory to reduce fragmentation,
+                * and attempt to create a hibernate work area
+                */
+               hibernate_suspend_bufcache();
+               uvmpd_hibernate();
+               if (hibernate_alloc()) {
+                       printf("failed to allocate hibernate memory\n");
+                       goto fail_alloc;
+               }
+       }
+#endif /* HIBERNATE */
+
+       sensor_quiesce();
+       if (config_suspend_all(DVACT_QUIESCE))
+               goto fail_quiesce;
+
+       vfs_stall(curproc, 1);
+#if NSOFTRAID > 0
+       sr_quiesce();
+#endif
+       bufq_quiesce();
+
+       
+#ifdef MULTIPROCESSOR
+       sleep_mp();
+#endif
+
+#ifdef HIBERNATE
+       if (sleepmode == SLEEP_HIBERNATE) {
+               /*
+                * We've just done various forms of syncing to disk
+                * churned lots of memory dirty.  We don't need to
+                * save that dirty memory to hibernate, so release it.
+                */
+               hibernate_suspend_bufcache();
+               uvmpd_hibernate();
+       }
+#endif /* HIBERNATE */
+
+       resettodr();
+
+       s = splhigh();
+       intr_disable(); /* PSL_I for resume; PIC/APIC broken until repair */
+       cold = 2;       /* Force other code to delay() instead of tsleep() */
+
+       if (config_suspend_all(DVACT_SUSPEND) != 0)
+               goto fail_suspend;
+       sleep_clocks(v);
+
+       suspend_randomness();
+
+       if (sleep_setstate(v))
+               goto fail_pts;
+
+       gosleep(v);
+
+#ifdef HIBERNATE
+       if (sleepmode == SLEEP_HIBERNATE) {
+               uvm_pmr_dirty_everything();
+               hib_getentropy(&rndbuf, &rndbuflen);
+       }
+#endif /* HIBERNATE */
+
+fail_pts:
+       config_suspend_all(DVACT_RESUME);
+
+fail_suspend:
+       cold = 0;
+       intr_enable();
+       splx(s);
+
+       disable_lid_wakeups(v);
+
+       inittodr(gettime());
+
+       sleep_resume(v);
+
+       /* force RNG upper level reseed */
+       resume_randomness(rndbuf, rndbuflen);
+
+#ifdef MULTIPROCESSOR
+       resume_mp();
+#endif
+
+       vfs_stall(curproc, 0);
+       bufq_restart();
+
+fail_quiesce:
+       config_suspend_all(DVACT_WAKEUP);
+       sensor_restart();
+
+#ifdef HIBERNATE
+       if (sleepmode == SLEEP_HIBERNATE) {
+               hibernate_free();
+fail_alloc:
+               hibernate_resume_bufcache();
+       }
+#endif /* HIBERNATE */
+
+       start_periodic_resettodr();
+
+       display_resume(v);
+
+       sys_sync(curproc, NULL, NULL);
+
+       /* Restore hw.setperf */
+       if (cpu_setperf != NULL)
+               cpu_setperf(perflevel);
+
+       suspend_finish(v);
+
+       return (error);
+}
index ec6c264..ec5e2b9 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: device.h,v 1.56 2021/10/26 16:29:49 deraadt Exp $     */
+/*     $OpenBSD: device.h,v 1.57 2022/02/08 17:25:12 deraadt Exp $     */
 /*     $NetBSD: device.h,v 1.15 1996/04/09 20:55:24 cgd Exp $  */
 
 /*
@@ -199,6 +199,21 @@ void config_pending_decr(void);
 void config_mountroot(struct device *, void (*)(struct device *));
 void config_process_deferred_mountroot(void);
 
+int    sleep_state(void *, int);
+#define SLEEP_SUSPEND  0x01
+#define SLEEP_HIBERNATE        0x02
+void   sleep_clocks(void *);
+void   sleep_mp(void);
+void   resume_mp(void);
+int    sleep_showstate(void *v, int sleepmode);
+int    sleep_setstate(void *v);
+int    sleep_resume(void *v);
+void   gosleep(void *v);
+void   display_suspend(void *v);
+void   display_resume(void *v);
+void   suspend_finish(void *v);
+void   disable_lid_wakeups(void *v);
+
 struct device *device_mainbus(void);
 struct device *device_mpath(void);
 struct device *device_lookup(struct cfdriver *, int unit);