diff options
author | Theo de Raadt <deraadt@cvs.openbsd.org> | 2012-10-08 21:47:52 +0000 |
---|---|---|
committer | Theo de Raadt <deraadt@cvs.openbsd.org> | 2012-10-08 21:47:52 +0000 |
commit | 4a7a1f17c7d6f8e79f29d4fde2ba5faf09b7f5a8 (patch) | |
tree | fdc5670bf4d0a8cd810fe846698cb565f1f51cb9 | |
parent | c7f240fd53223122e6fe8cee52bb76b460263763 (diff) |
Revamp the sequences for suspend/hibernate -> resume so that the code
paths are reflexive. It is now possible to fail part-way through a
suspend sequence, and recover along the resume code path.
Split DVACT_SUSPEND by adding a new DVACT_POWERDOWN method is used
after hibernate (and suspend too) to finish the job. Some drivers
must be converted at the same time to use this instead of shutdown hooks
(the others will follow at a later time)
ok kettenis mlarkin
52 files changed, 577 insertions, 535 deletions
diff --git a/sys/arch/alpha/alpha/machdep.c b/sys/arch/alpha/alpha/machdep.c index c562ff1843f..2538092cac1 100644 --- a/sys/arch/alpha/alpha/machdep.c +++ b/sys/arch/alpha/alpha/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.136 2012/08/22 13:33:32 okan Exp $ */ +/* $OpenBSD: machdep.c,v 1.137 2012/10/08 21:47:45 deraadt Exp $ */ /* $NetBSD: machdep.c,v 1.210 2000/06/01 17:12:38 thorpej Exp $ */ /*- @@ -1027,9 +1027,8 @@ boot(howto) dumpsys(); haltsys: - - /* run any shutdown hooks */ doshutdownhooks(); + config_suspend(TAILQ_FIRST(&alldevs), DVACT_POWERDOWN); #if defined(MULTIPROCESSOR) #if 0 /* XXX doesn't work when called from here?! */ diff --git a/sys/arch/amd64/amd64/acpi_machdep.c b/sys/arch/amd64/amd64/acpi_machdep.c index d9ad4c6790a..b255ee05580 100644 --- a/sys/arch/amd64/amd64/acpi_machdep.c +++ b/sys/arch/amd64/amd64/acpi_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpi_machdep.c,v 1.49 2012/07/13 16:02:24 mlarkin Exp $ */ +/* $OpenBSD: acpi_machdep.c,v 1.50 2012/10/08 21:47:47 deraadt Exp $ */ /* * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com> * @@ -23,6 +23,7 @@ #include <sys/memrange.h> #include <sys/proc.h> #include <sys/user.h> +#include <sys/reboot.h> #include <sys/hibernate.h> #include <uvm/uvm_extern.h> @@ -191,24 +192,48 @@ acpi_attach_machdep(struct acpi_softc *sc) } void -acpi_cpu_flush(struct acpi_softc *sc, int state) +acpi_sleep_clocks(struct acpi_softc *sc, int state) { - /* - * Flush write back caches since we'll lose them. - */ - if (state > ACPI_STATE_S1) - wbinvd(); + rtcstop(); } -int -acpi_sleep_machdep(struct acpi_softc *sc, int state) +/* + * We repair the interrupt hardware so that any events which occur + * will cause the least number of unexpected side effects. We re-start + * the clocks early because we will soon run AML whigh might do DELAY. + */ +void +acpi_resume_clocks(struct acpi_softc *sc) { - if (sc->sc_facs == NULL) { - printf("%s: acpi_sleep_machdep: no FACS\n", DEVNAME(sc)); - return (ENXIO); - } +#if NISA > 0 + i8259_default_setup(); +#endif + intr_calculatemasks(curcpu()); - rtcstop(); +#if NIOAPIC > 0 + ioapic_enable(); +#endif + +#if NLAPIC > 0 + lapic_enable(); + if (initclock_func == lapic_initclocks) + lapic_startclock(); + lapic_set_lvt(); +#endif + + i8254_startclock(); + if (initclock_func == i8254_initclocks) + rtcstart(); /* in i8254 mode, rtc is profclock */ +} + +/* + * This function may not have local variables due to a bug between + * acpi_savecpu() and the resume path. + */ +int +acpi_sleep_cpu(struct acpi_softc *sc, int state) +{ + /* amd64 does not do lazy pmap_activate */ /* * ACPI defines two wakeup vectors. One is used for ACPI 1.0 @@ -231,62 +256,88 @@ acpi_sleep_machdep(struct acpi_softc *sc, int state) if (acpi_savecpu()) { /* Suspend path */ fpusave_cpu(curcpu(), 1); -#ifdef MULTIPROCESSOR - x86_broadcast_ipi(X86_IPI_SYNCH_FPU); - x86_broadcast_ipi(X86_IPI_HALT); -#endif wbinvd(); + #ifdef HIBERNATE if (state == ACPI_STATE_S4) { uvm_pmr_zero_everything(); - if (hibernate_suspend()) - panic("%s: hibernate failed", DEVNAME(sc)); + if (hibernate_suspend()) { + printf("%s: hibernate_suspend failed", + DEVNAME(sc)); + hibernate_free(); + uvm_pmr_dirty_everything(); + return (ECANCELED); + } } #endif - acpi_enter_sleep_state(sc, state); - panic("%s: acpi_enter_sleep_state failed", DEVNAME(sc)); - } - /* Resume path continues here */ + boothowto |= RB_POWERDOWN; + config_suspend(TAILQ_FIRST(&alldevs), DVACT_POWERDOWN); + boothowto &= ~RB_POWERDOWN; - /* Reset the vector */ - sc->sc_facs->wakeup_vector = 0; + acpi_sleep_pm(sc, state); + printf("%s: acpi_sleep_pm failed", DEVNAME(sc)); + return (ECANCELED); + } + /* Resume path */ -#if NISA > 0 - i8259_default_setup(); +#ifdef HIBERNATE + if (state == ACPI_STATE_S4) { + hibernate_free(); + uvm_pmr_dirty_everything(); + } #endif - intr_calculatemasks(curcpu()); -#if NLAPIC > 0 - lapic_enable(); - if (initclock_func == lapic_initclocks) - lapic_startclock(); - lapic_set_lvt(); -#endif + /* Reset the vectors */ + sc->sc_facs->wakeup_vector = 0; + if (sc->sc_facs->length > 32 && sc->sc_facs->version >= 1) + sc->sc_facs->x_wakeup_vector = 0; - fpuinit(&cpu_info_primary); + return (0); +} - /* Re-initialise memory range handling */ +void +acpi_resume_cpu(struct acpi_softc *sc) +{ + /* Re-initialise memory range handling on BSP */ if (mem_range_softc.mr_op != NULL) mem_range_softc.mr_op->initAP(&mem_range_softc); + fpuinit(&cpu_info_primary); +} -#if NIOAPIC > 0 - ioapic_enable(); -#endif - i8254_startclock(); - if (initclock_func == i8254_initclocks) - rtcstart(); /* in i8254 mode, rtc is profclock */ - inittodr(time_second); +#ifdef MULTIPROCESSOR +void +acpi_sleep_mp(void) +{ + int i; - return (0); -} + sched_stop_secondary_cpus(); + KASSERT(CPU_IS_PRIMARY(curcpu())); -void cpu_start_secondary(struct cpu_info *ci); + /* Wait for cpus to save their floating point context */ + x86_broadcast_ipi(X86_IPI_SYNCH_FPU); + for (i = 0; i < ncpus; i++) { + struct cpu_info *ci = cpu_info[i]; + + while (!CPU_IS_PRIMARY(curcpu()) && ci->ci_fpcurproc) + ; + } + + /* Wait for cpus to halt so we know their caches are written back */ + x86_broadcast_ipi(X86_IPI_HALT); + for (i = 0; i < ncpus; i++) { + struct cpu_info *ci = cpu_info[i]; + + while (!CPU_IS_PRIMARY(curcpu()) && + (ci->ci_flags & CPUF_RUNNING)) + ; + } +} void -acpi_resume_machdep(void) +acpi_resume_mp(void) { -#ifdef MULTIPROCESSOR + void cpu_start_secondary(struct cpu_info *ci); struct cpu_info *ci; struct proc *p; struct pcb *pcb; @@ -324,6 +375,8 @@ acpi_resume_machdep(void) } cpu_boot_secondary_processors(); -#endif /* MULTIPROCESSOR */ + sched_start_secondary_cpus(); } +#endif /* MULTIPROCESSOR */ + #endif /* ! SMALL_KERNEL */ diff --git a/sys/arch/amd64/amd64/machdep.c b/sys/arch/amd64/amd64/machdep.c index 4406312d808..a6c09fcd299 100644 --- a/sys/arch/amd64/amd64/machdep.c +++ b/sys/arch/amd64/amd64/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.155 2012/06/04 15:19:47 jsing Exp $ */ +/* $OpenBSD: machdep.c,v 1.156 2012/10/08 21:47:47 deraadt Exp $ */ /* $NetBSD: machdep.c,v 1.3 2003/05/07 22:58:18 fvdl Exp $ */ /*- @@ -752,6 +752,7 @@ boot(int howto) haltsys: doshutdownhooks(); + config_suspend(TAILQ_FIRST(&alldevs), DVACT_POWERDOWN); #ifdef MULTIPROCESSOR x86_broadcast_ipi(X86_IPI_HALT); diff --git a/sys/arch/amd64/pci/pchb.c b/sys/arch/amd64/pci/pchb.c index e874db8e524..d51c6ddb9a5 100644 --- a/sys/arch/amd64/pci/pchb.c +++ b/sys/arch/amd64/pci/pchb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pchb.c,v 1.38 2012/09/19 23:23:50 kettenis Exp $ */ +/* $OpenBSD: pchb.c,v 1.39 2012/10/08 21:47:47 deraadt Exp $ */ /* $NetBSD: pchb.c,v 1.1 2003/04/26 18:39:50 fvdl Exp $ */ /* * Copyright (c) 2000 Michael Shalayeff @@ -286,6 +286,9 @@ pchbactivate(struct device *self, int act) case DVACT_SUSPEND: rv = config_activate_children(self, act); break; + case DVACT_POWERDOWN: + rv = config_activate_children(self, act); + break; case DVACT_RESUME: /* re-enable RNG, if we have it */ if (sc->sc_rng_active) diff --git a/sys/arch/arm/xscale/pxa2x0_apm.c b/sys/arch/arm/xscale/pxa2x0_apm.c index 664cc67a341..1807eb2bcde 100644 --- a/sys/arch/arm/xscale/pxa2x0_apm.c +++ b/sys/arch/arm/xscale/pxa2x0_apm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pxa2x0_apm.c,v 1.37 2011/07/02 22:20:07 nicm Exp $ */ +/* $OpenBSD: pxa2x0_apm.c,v 1.38 2012/10/08 21:47:47 deraadt Exp $ */ /*- * Copyright (c) 2001 Alexander Guy. All rights reserved. @@ -45,6 +45,7 @@ #include <sys/device.h> #include <sys/fcntl.h> #include <sys/ioctl.h> +#include <sys/reboot.h> #include <sys/event.h> #include <machine/conf.h> @@ -320,6 +321,11 @@ apm_suspend(struct pxa2x0_apm_softc *sc) s = splhigh(); config_suspend(TAILQ_FIRST(&alldevs), DVACT_SUSPEND); + + boothowto |= RB_POWERDOWN; + config_suspend(TAILQ_FIRST(&alldevs), DVACT_POWERDOWN); + boothowto &= ~RB_POWERDOWN; + splx(s); pxa2x0_apm_sleep(sc); diff --git a/sys/arch/aviion/aviion/machdep.c b/sys/arch/aviion/aviion/machdep.c index 69f5e83a660..e17a1f24e7e 100644 --- a/sys/arch/aviion/aviion/machdep.c +++ b/sys/arch/aviion/aviion/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.47 2011/10/09 17:09:27 miod Exp $ */ +/* $OpenBSD: machdep.c,v 1.48 2012/10/08 21:47:47 deraadt Exp $ */ /* * Copyright (c) 2007 Miodrag Vallat. * @@ -329,8 +329,8 @@ boot(howto) dumpsys(); haltsys: - /* Run any shutdown hooks. */ doshutdownhooks(); + config_suspend(TAILQ_FIRST(&alldevs), DVACT_POWERDOWN); if (howto & RB_HALT) { printf("System halted.\n\n"); diff --git a/sys/arch/hp300/hp300/machdep.c b/sys/arch/hp300/hp300/machdep.c index d23ea45a294..3a81cb385de 100644 --- a/sys/arch/hp300/hp300/machdep.c +++ b/sys/arch/hp300/hp300/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.135 2011/11/01 21:20:55 miod Exp $ */ +/* $OpenBSD: machdep.c,v 1.136 2012/10/08 21:47:47 deraadt Exp $ */ /* $NetBSD: machdep.c,v 1.121 1999/03/26 23:41:29 mycroft Exp $ */ /* @@ -615,8 +615,8 @@ boot(howto) dumpsys(); haltsys: - /* Run any shutdown hooks. */ doshutdownhooks(); + config_suspend(TAILQ_FIRST(&alldevs), DVACT_POWERDOWN); /* Finally, halt/reboot the system. */ if (howto & RB_HALT) { diff --git a/sys/arch/hppa/hppa/machdep.c b/sys/arch/hppa/hppa/machdep.c index 9deefc6a7e4..56e22b448b2 100644 --- a/sys/arch/hppa/hppa/machdep.c +++ b/sys/arch/hppa/hppa/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.207 2012/10/07 20:39:15 kettenis Exp $ */ +/* $OpenBSD: machdep.c,v 1.208 2012/10/08 21:47:47 deraadt Exp $ */ /* * Copyright (c) 1999-2003 Michael Shalayeff @@ -920,6 +920,7 @@ boot(int howto) dumpsys(); doshutdownhooks(); + config_suspend(TAILQ_FIRST(&alldevs), DVACT_POWERDOWN); #ifdef MULTIPROCESSOR hppa_ipi_broadcast(HPPA_IPI_HALT); diff --git a/sys/arch/hppa64/hppa64/machdep.c b/sys/arch/hppa64/hppa64/machdep.c index 8f18688ad7d..9262ad7ee40 100644 --- a/sys/arch/hppa64/hppa64/machdep.c +++ b/sys/arch/hppa64/hppa64/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.48 2012/07/13 15:10:51 jsing Exp $ */ +/* $OpenBSD: machdep.c,v 1.49 2012/10/08 21:47:48 deraadt Exp $ */ /* * Copyright (c) 2005 Michael Shalayeff @@ -570,6 +570,7 @@ boot(int howto) dumpsys(); doshutdownhooks(); + config_suspend(TAILQ_FIRST(&alldevs), DVACT_POWERDOWN); } /* in case we came on powerfail interrupt */ diff --git a/sys/arch/i386/i386/acpi_machdep.c b/sys/arch/i386/i386/acpi_machdep.c index ad27b83fbb0..aaea629c52d 100644 --- a/sys/arch/i386/i386/acpi_machdep.c +++ b/sys/arch/i386/i386/acpi_machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpi_machdep.c,v 1.43 2012/06/20 17:31:55 mlarkin Exp $ */ +/* $OpenBSD: acpi_machdep.c,v 1.44 2012/10/08 21:47:48 deraadt Exp $ */ /* * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com> * @@ -23,6 +23,7 @@ #include <sys/memrange.h> #include <sys/proc.h> #include <sys/user.h> +#include <sys/reboot.h> #include <sys/hibernate.h> #include <uvm/uvm_extern.h> @@ -207,38 +208,59 @@ acpi_attach_machdep(struct acpi_softc *sc) acpi_resume_end - acpi_real_mode_resume); } +#if NLAPIC > 0 +int save_lapic_tpr; +#endif + void -acpi_cpu_flush(struct acpi_softc *sc, int state) +acpi_sleep_clocks(struct acpi_softc *sc, int state) { - /* - * Flush write back caches since we'll lose them. - */ - if (state > ACPI_STATE_S1) - wbinvd(); + rtcstop(); +#if NLAPIC > 0 + save_lapic_tpr = lapic_tpr; +#endif } -int -acpi_sleep_machdep(struct acpi_softc *sc, int state) +/* + * Start the clocks early because AML will be executed next + * which might do DELAY. + */ +void +acpi_resume_clocks(struct acpi_softc *sc) { - int s; +#if NISA > 0 + isa_defaultirq(); +#endif + intr_calculatemasks(); - if (sc->sc_facs == NULL) { - printf("%s: acpi_sleep_machdep: no FACS\n", DEVNAME(sc)); - return (ENXIO); - } +#if NIOAPIC > 0 + ioapic_enable(); +#endif - rtcstop(); +#if NLAPIC > 0 + lapic_tpr = save_lapic_tpr; + lapic_enable(); + if (initclock_func == lapic_initclocks) + lapic_startclock(); + lapic_set_lvt(); +#endif - /* i386 does lazy pmap_activate */ + i8254_startclock(); + if (initclock_func == i8254_initclocks) + rtcstart(); /* in i8254 mode, rtc is profclock */ +} + +/* + * This function may not have local variables due to a bug between + * acpi_savecpu() and the resume path. + */ +int +acpi_sleep_cpu(struct acpi_softc *sc, int state) +{ + /* i386 does lazy pmap_activate: switch to kernel memory view */ pmap_activate(curproc); /* - * The local apic may lose its state, so save the Task - * Priority register where we keep the system priority level. - */ - s = lapic_tpr; - - /* * ACPI defines two wakeup vectors. One is used for ACPI 1.0 * implementations - it's in the FACS table as wakeup_vector and * indicates a 32-bit physical address containing real-mode wakeup @@ -259,71 +281,87 @@ acpi_sleep_machdep(struct acpi_softc *sc, int state) if (acpi_savecpu()) { /* Suspend path */ npxsave_cpu(curcpu(), 1); -#ifdef MULTIPROCESSOR - i386_broadcast_ipi(I386_IPI_SYNCH_FPU); - i386_broadcast_ipi(I386_IPI_HALT); -#endif wbinvd(); + #ifdef HIBERNATE if (state == ACPI_STATE_S4) { uvm_pmr_zero_everything(); - if (hibernate_suspend()) - panic("%s: hibernate failed", DEVNAME(sc)); + if (hibernate_suspend()) { + printf("%s: hibernate_suspend failed", + DEVNAME(sc)); + hibernate_free(); + uvm_pmr_dirty_everything(); + return (ECANCELED); + } } #endif - acpi_enter_sleep_state(sc, state); - panic("%s: acpi_enter_sleep_state failed", DEVNAME(sc)); - } - /* Resume path continues here */ + boothowto |= RB_POWERDOWN; + config_suspend(TAILQ_FIRST(&alldevs), DVACT_POWERDOWN); + boothowto &= ~RB_POWERDOWN; + + acpi_sleep_pm(sc, state); + printf("%s: acpi_sleep_pm failed", DEVNAME(sc)); + return (ECANCELED); + } + /* Resume path */ #ifdef HIBERNATE - /* Free piglet and other pages allocated during suspend */ if (state == ACPI_STATE_S4) { hibernate_free(); uvm_pmr_dirty_everything(); } #endif - /* Reset the vector */ + /* Reset the vectors */ sc->sc_facs->wakeup_vector = 0; + if (sc->sc_facs->length > 32 && sc->sc_facs->version >= 1) + sc->sc_facs->x_wakeup_vector = 0; - /* Restore the Task Priority register */ - lapic_tpr = s; + return (0); +} -#if NISA > 0 - isa_defaultirq(); -#endif - intr_calculatemasks(); +void +acpi_resume_cpu(struct acpi_softc *sc) +{ + /* Re-initialise memory range handling on BSP */ + if (mem_range_softc.mr_op != NULL) + mem_range_softc.mr_op->initAP(&mem_range_softc); + npxinit(&cpu_info_primary); +} -#if NLAPIC > 0 - lapic_enable(); - if (initclock_func == lapic_initclocks) - lapic_startclock(); - lapic_set_lvt(); -#endif +#ifdef MULTIPROCESSOR +void +acpi_sleep_mp() +{ + int i; - npxinit(&cpu_info_primary); + sched_stop_secondary_cpus(); + KASSERT(CPU_IS_PRIMARY(curcpu())); - /* Re-initialise memory range handling */ - if (mem_range_softc.mr_op != NULL) - mem_range_softc.mr_op->initAP(&mem_range_softc); + /* Wait for cpus to save their floating point context */ + i386_broadcast_ipi(I386_IPI_SYNCH_FPU); + for (i = 0; i < ncpus; i++) { + struct cpu_info *ci = cpu_info[i]; -#if NIOAPIC > 0 - ioapic_enable(); -#endif - i8254_startclock(); - if (initclock_func == i8254_initclocks) - rtcstart(); /* in i8254 mode, rtc is profclock */ - inittodr(time_second); + while (!CPU_IS_PRIMARY(curcpu()) && ci->ci_fpcurproc) + ; + } - return (0); + /* Wait for cpus to halt so we know their caches are written back */ + i386_broadcast_ipi(I386_IPI_HALT); + for (i = 0; i < ncpus; i++) { + struct cpu_info *ci = cpu_info[i]; + + while (!CPU_IS_PRIMARY(curcpu()) && + (ci->ci_flags & CPUF_RUNNING)) + ; + } } void -acpi_resume_machdep(void) +acpi_resume_mp(void) { -#ifdef MULTIPROCESSOR struct cpu_info *ci; struct proc *p; struct pcb *pcb; @@ -357,6 +395,8 @@ acpi_resume_machdep(void) } cpu_boot_secondary_processors(); -#endif /* MULTIPROCESSOR */ + sched_start_secondary_cpus(); } +#endif /* MULTIPROCESSOR */ + #endif /* ! SMALL_KERNEL */ diff --git a/sys/arch/i386/i386/apm.c b/sys/arch/i386/i386/apm.c index c6e1cc1a22a..57f61685a35 100644 --- a/sys/arch/i386/i386/apm.c +++ b/sys/arch/i386/i386/apm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: apm.c,v 1.98 2011/07/02 22:20:07 nicm Exp $ */ +/* $OpenBSD: apm.c,v 1.99 2012/10/08 21:47:48 deraadt Exp $ */ /*- * Copyright (c) 1998-2001 Michael Shalayeff. All rights reserved. @@ -49,6 +49,7 @@ #include <sys/fcntl.h> #include <sys/ioctl.h> #include <sys/buf.h> +#include <sys/reboot.h> #include <sys/event.h> #include <machine/conf.h> @@ -254,6 +255,10 @@ apm_suspend(int state) disable_intr(); config_suspend(TAILQ_FIRST(&alldevs), DVACT_SUSPEND); + boothowto |= RB_POWERDOWN; + config_suspend(TAILQ_FIRST(&alldevs), DVACT_POWERDOWN); + boothowto &= ~RB_POWERDOWN; + /* Send machine to sleep */ apm_set_powstate(APM_DEV_ALLDEVS, state); /* Wake up */ diff --git a/sys/arch/i386/i386/machdep.c b/sys/arch/i386/i386/machdep.c index 97591d87adb..36f521e3a97 100644 --- a/sys/arch/i386/i386/machdep.c +++ b/sys/arch/i386/i386/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.512 2012/09/19 20:19:31 jsg Exp $ */ +/* $OpenBSD: machdep.c,v 1.513 2012/10/08 21:47:48 deraadt Exp $ */ /* $NetBSD: machdep.c,v 1.214 1996/11/10 03:16:17 thorpej Exp $ */ /*- @@ -2530,6 +2530,7 @@ boot(int howto) haltsys: doshutdownhooks(); + config_suspend(TAILQ_FIRST(&alldevs), DVACT_POWERDOWN); #ifdef MULTIPROCESSOR i386_broadcast_ipi(I386_IPI_HALT); diff --git a/sys/arch/i386/pci/pchb.c b/sys/arch/i386/pci/pchb.c index c74622daf25..03ba73d9e5a 100644 --- a/sys/arch/i386/pci/pchb.c +++ b/sys/arch/i386/pci/pchb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pchb.c,v 1.86 2012/09/19 23:03:12 kettenis Exp $ */ +/* $OpenBSD: pchb.c,v 1.87 2012/10/08 21:47:48 deraadt Exp $ */ /* $NetBSD: pchb.c,v 1.65 2007/08/15 02:26:13 markd Exp $ */ /* @@ -429,6 +429,9 @@ pchbactivate(struct device *self, int act) case DVACT_SUSPEND: rv = config_activate_children(self, act); break; + case DVACT_POWERDOWN: + rv = config_activate_children(self, act); + break; case DVACT_RESUME: /* re-enable RNG, if we have it */ if (sc->sc_rng_active) diff --git a/sys/arch/landisk/landisk/machdep.c b/sys/arch/landisk/landisk/machdep.c index 0b12006638d..7e92e0ac1da 100644 --- a/sys/arch/landisk/landisk/machdep.c +++ b/sys/arch/landisk/landisk/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.26 2011/06/26 22:39:59 deraadt Exp $ */ +/* $OpenBSD: machdep.c,v 1.27 2012/10/08 21:47:48 deraadt Exp $ */ /* $NetBSD: machdep.c,v 1.1 2006/09/01 21:26:18 uwe Exp $ */ /*- @@ -222,6 +222,7 @@ boot(int howto) haltsys: doshutdownhooks(); + config_suspend(TAILQ_FIRST(&alldevs), DVACT_POWERDOWN); if ((howto & RB_POWERDOWN) == RB_POWERDOWN) { _reg_write_1(LANDISK_PWRMNG, PWRMNG_POWEROFF); diff --git a/sys/arch/loongson/dev/apm.c b/sys/arch/loongson/dev/apm.c index 37c2bcba289..bc321492ec9 100644 --- a/sys/arch/loongson/dev/apm.c +++ b/sys/arch/loongson/dev/apm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: apm.c,v 1.11 2011/09/20 14:06:26 deraadt Exp $ */ +/* $OpenBSD: apm.c,v 1.12 2012/10/08 21:47:48 deraadt Exp $ */ /*- * Copyright (c) 2001 Alexander Guy. All rights reserved. @@ -43,6 +43,7 @@ #include <sys/ioctl.h> #include <sys/buf.h> #include <sys/event.h> +#include <sys/reboot.h> #include <machine/autoconf.h> #include <machine/conf.h> @@ -369,6 +370,11 @@ apm_suspend() cold = 1; rv = config_suspend(TAILQ_FIRST(&alldevs), DVACT_SUSPEND); + + boothowto |= RB_POWERDOWN; + (void) config_suspend(TAILQ_FIRST(&alldevs), DVACT_POWERDOWN); + boothowto &= ~RB_POWERDOWN; + if (rv == 0) { rv = sys_platform->suspend(); if (rv == 0) diff --git a/sys/arch/loongson/loongson/machdep.c b/sys/arch/loongson/loongson/machdep.c index 4f72f20b3be..5c2afe19934 100644 --- a/sys/arch/loongson/loongson/machdep.c +++ b/sys/arch/loongson/loongson/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.38 2012/10/03 21:44:51 miod Exp $ */ +/* $OpenBSD: machdep.c,v 1.39 2012/10/08 21:47:48 deraadt Exp $ */ /* * Copyright (c) 2009, 2010 Miodrag Vallat. @@ -853,6 +853,7 @@ boot(int howto) haltsys: doshutdownhooks(); + config_suspend(TAILQ_FIRST(&alldevs), DVACT_POWERDOWN); if (howto & RB_HALT) { if (howto & RB_POWERDOWN) { diff --git a/sys/arch/luna88k/luna88k/machdep.c b/sys/arch/luna88k/luna88k/machdep.c index 8c0cbeccf4b..d0d507b1051 100644 --- a/sys/arch/luna88k/luna88k/machdep.c +++ b/sys/arch/luna88k/luna88k/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.81 2012/02/28 13:40:53 aoyama Exp $ */ +/* $OpenBSD: machdep.c,v 1.82 2012/10/08 21:47:48 deraadt Exp $ */ /* * Copyright (c) 1998, 1999, 2000, 2001 Steve Murphree, Jr. * Copyright (c) 1996 Nivas Madhur @@ -507,8 +507,8 @@ boot(howto) dumpsys(); haltsys: - /* Run any shutdown hooks. */ doshutdownhooks(); + config_suspend(TAILQ_FIRST(&alldevs), DVACT_POWERDOWN); /* Luna88k supports automatic powerdown */ if ((howto & RB_POWERDOWN) == RB_POWERDOWN) { diff --git a/sys/arch/macppc/macppc/machdep.c b/sys/arch/macppc/macppc/machdep.c index 80c0d732f3c..b040a25ff50 100644 --- a/sys/arch/macppc/macppc/machdep.c +++ b/sys/arch/macppc/macppc/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.132 2012/08/21 09:24:52 kettenis Exp $ */ +/* $OpenBSD: machdep.c,v 1.133 2012/10/08 21:47:48 deraadt Exp $ */ /* $NetBSD: machdep.c,v 1.4 1996/10/16 19:33:11 ws Exp $ */ /* @@ -859,6 +859,7 @@ boot(int howto) splhigh(); if (howto & RB_HALT) { doshutdownhooks(); + config_suspend(TAILQ_FIRST(&alldevs), DVACT_POWERDOWN); if ((howto & RB_POWERDOWN) == RB_POWERDOWN) { #if NADB > 0 delay(1000000); @@ -874,6 +875,7 @@ boot(int howto) if (!cold && (howto & RB_DUMP)) dumpsys(); doshutdownhooks(); + config_suspend(TAILQ_FIRST(&alldevs), DVACT_POWERDOWN); printf("rebooting\n\n"); #if NADB > 0 diff --git a/sys/arch/mvme68k/mvme68k/machdep.c b/sys/arch/mvme68k/mvme68k/machdep.c index 1a581e127e8..8637f4d21ca 100644 --- a/sys/arch/mvme68k/mvme68k/machdep.c +++ b/sys/arch/mvme68k/mvme68k/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.126 2011/06/26 22:40:00 deraadt Exp $ */ +/* $OpenBSD: machdep.c,v 1.127 2012/10/08 21:47:48 deraadt Exp $ */ /* * Copyright (c) 1995 Theo de Raadt @@ -491,8 +491,8 @@ boot(howto) dumpsys(); haltsys: - /* Run any shutdown hooks. */ doshutdownhooks(); + config_suspend(TAILQ_FIRST(&alldevs), DVACT_POWERDOWN); if (howto & RB_HALT) { printf("System halted. Press any key to reboot...\n\n"); diff --git a/sys/arch/mvme88k/mvme88k/machdep.c b/sys/arch/mvme88k/mvme88k/machdep.c index b9f8a00027e..0299d413d85 100644 --- a/sys/arch/mvme88k/mvme88k/machdep.c +++ b/sys/arch/mvme88k/mvme88k/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.245 2011/10/09 17:01:34 miod Exp $ */ +/* $OpenBSD: machdep.c,v 1.246 2012/10/08 21:47:49 deraadt Exp $ */ /* * Copyright (c) 1998, 1999, 2000, 2001 Steve Murphree, Jr. * Copyright (c) 1996 Nivas Madhur @@ -435,8 +435,8 @@ boot(howto) dumpsys(); haltsys: - /* Run any shutdown hooks. */ doshutdownhooks(); + config_suspend(TAILQ_FIRST(&alldevs), DVACT_POWERDOWN); if (howto & RB_HALT) { printf("System halted. Press any key to reboot...\n\n"); diff --git a/sys/arch/octeon/octeon/machdep.c b/sys/arch/octeon/octeon/machdep.c index 3bd4a1532ba..a10c1c8e299 100644 --- a/sys/arch/octeon/octeon/machdep.c +++ b/sys/arch/octeon/octeon/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.22 2012/10/03 19:42:54 miod Exp $ */ +/* $OpenBSD: machdep.c,v 1.23 2012/10/08 21:47:50 deraadt Exp $ */ /* * Copyright (c) 2009, 2010 Miodrag Vallat. @@ -673,6 +673,7 @@ boot(int howto) haltsys: doshutdownhooks(); + config_suspend(TAILQ_FIRST(&alldevs), DVACT_POWERDOWN); if (howto & RB_HALT) { if (howto & RB_POWERDOWN) diff --git a/sys/arch/sgi/sgi/machdep.c b/sys/arch/sgi/sgi/machdep.c index bb0d256c724..fa106c14917 100644 --- a/sys/arch/sgi/sgi/machdep.c +++ b/sys/arch/sgi/sgi/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.131 2012/10/03 11:18:23 miod Exp $ */ +/* $OpenBSD: machdep.c,v 1.132 2012/10/08 21:47:50 deraadt Exp $ */ /* * Copyright (c) 2003-2004 Opsycon AB (www.opsycon.se / www.opsycon.com) @@ -867,6 +867,7 @@ boot(int howto) haltsys: doshutdownhooks(); + config_suspend(TAILQ_FIRST(&alldevs), DVACT_POWERDOWN); if (howto & RB_HALT) { if (howto & RB_POWERDOWN) diff --git a/sys/arch/socppc/socppc/machdep.c b/sys/arch/socppc/socppc/machdep.c index 168075f8fac..ca1a710dae5 100644 --- a/sys/arch/socppc/socppc/machdep.c +++ b/sys/arch/socppc/socppc/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.34 2012/03/14 21:56:46 kettenis Exp $ */ +/* $OpenBSD: machdep.c,v 1.35 2012/10/08 21:47:50 deraadt Exp $ */ /* $NetBSD: machdep.c,v 1.4 1996/10/16 19:33:11 ws Exp $ */ /* @@ -1067,6 +1067,7 @@ boot(int howto) splhigh(); if (howto & RB_HALT) { doshutdownhooks(); + config_suspend(TAILQ_FIRST(&alldevs), DVACT_POWERDOWN); if ((howto & RB_POWERDOWN) == RB_POWERDOWN) { ; } @@ -1077,6 +1078,7 @@ boot(int howto) if (!cold && (howto & RB_DUMP)) dumpsys(); doshutdownhooks(); + config_suspend(TAILQ_FIRST(&alldevs), DVACT_POWERDOWN); printf("rebooting\n\n"); { diff --git a/sys/arch/solbourne/solbourne/machdep.c b/sys/arch/solbourne/solbourne/machdep.c index 8a9b17f0fb1..642df6c28df 100644 --- a/sys/arch/solbourne/solbourne/machdep.c +++ b/sys/arch/solbourne/solbourne/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.23 2012/08/22 13:33:32 okan Exp $ */ +/* $OpenBSD: machdep.c,v 1.24 2012/10/08 21:47:50 deraadt Exp $ */ /* OpenBSD: machdep.c,v 1.105 2005/04/11 15:13:01 deraadt Exp */ /* @@ -564,8 +564,8 @@ boot(howto) dumpsys(); haltsys: - /* Run any shutdown hooks */ doshutdownhooks(); + config_suspend(TAILQ_FIRST(&alldevs), DVACT_POWERDOWN); if ((howto & RB_HALT) || (howto & RB_POWERDOWN)) { printf("halted\n\n"); diff --git a/sys/arch/sparc/sparc/machdep.c b/sys/arch/sparc/sparc/machdep.c index e74b9ecc34f..ae8e84a9bcc 100644 --- a/sys/arch/sparc/sparc/machdep.c +++ b/sys/arch/sparc/sparc/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.140 2012/08/22 13:33:32 okan Exp $ */ +/* $OpenBSD: machdep.c,v 1.141 2012/10/08 21:47:50 deraadt Exp $ */ /* $NetBSD: machdep.c,v 1.85 1997/09/12 08:55:02 pk Exp $ */ /* @@ -577,8 +577,8 @@ boot(howto) dumpsys(); haltsys: - /* Run any shutdown hooks */ doshutdownhooks(); + config_suspend(TAILQ_FIRST(&alldevs), DVACT_POWERDOWN); if ((howto & RB_HALT) || (howto & RB_POWERDOWN)) { #if defined(SUN4M) diff --git a/sys/arch/sparc64/sparc64/machdep.c b/sys/arch/sparc64/sparc64/machdep.c index 042cbef9c24..e3c4c9095ff 100644 --- a/sys/arch/sparc64/sparc64/machdep.c +++ b/sys/arch/sparc64/sparc64/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.140 2012/08/24 10:00:55 jsg Exp $ */ +/* $OpenBSD: machdep.c,v 1.141 2012/10/08 21:47:50 deraadt Exp $ */ /* $NetBSD: machdep.c,v 1.108 2001/07/24 19:30:14 eeh Exp $ */ /*- @@ -670,8 +670,8 @@ boot(howto) dumpsys(); haltsys: - /* Run any shutdown hooks. */ doshutdownhooks(); + config_suspend(TAILQ_FIRST(&alldevs), DVACT_POWERDOWN); /* If powerdown was requested, do it. */ if ((howto & RB_POWERDOWN) == RB_POWERDOWN) { diff --git a/sys/arch/vax/vax/machdep.c b/sys/arch/vax/vax/machdep.c index 2dd062a5428..fd8ea7d88ee 100644 --- a/sys/arch/vax/vax/machdep.c +++ b/sys/arch/vax/vax/machdep.c @@ -1,4 +1,4 @@ -/* $OpenBSD: machdep.c,v 1.121 2012/03/24 19:09:20 guenther Exp $ */ +/* $OpenBSD: machdep.c,v 1.122 2012/10/08 21:47:50 deraadt Exp $ */ /* $NetBSD: machdep.c,v 1.108 2000/09/13 15:00:23 thorpej Exp $ */ /* @@ -546,10 +546,11 @@ boot(howto) if (howto & RB_DUMP) dumpsys(); - /* Run any shutdown hooks. */ - doshutdownhooks(); haltsys: + doshutdownhooks(); + config_suspend(TAILQ_FIRST(&alldevs), DVACT_POWERDOWN); + if (howto & RB_HALT) { if (dep_call->cpu_halt) (*dep_call->cpu_halt) (); diff --git a/sys/arch/zaurus/dev/zaurus_apm.c b/sys/arch/zaurus/dev/zaurus_apm.c index fdcd91475f0..7c026d7c513 100644 --- a/sys/arch/zaurus/dev/zaurus_apm.c +++ b/sys/arch/zaurus/dev/zaurus_apm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: zaurus_apm.c,v 1.20 2010/09/07 16:21:41 deraadt Exp $ */ +/* $OpenBSD: zaurus_apm.c,v 1.21 2012/10/08 21:47:50 deraadt Exp $ */ /* * Copyright (c) 2005 Uwe Stuehler <uwe@bsdx.de> @@ -24,6 +24,7 @@ #include <sys/proc.h> #include <sys/buf.h> #include <sys/sysctl.h> +#include <sys/reboot.h> #include <arm/xscale/pxa2x0reg.h> #include <arm/xscale/pxa2x0var.h> @@ -654,6 +655,10 @@ zapm_poweroff(void) s = splhigh(); config_suspend(TAILQ_FIRST(&alldevs), DVACT_SUSPEND); + boothowto |= RB_POWERDOWN; + config_suspend(TAILQ_FIRST(&alldevs), DVACT_POWERDOWN); + boothowto &= ~RB_POWERDOWN; + /* XXX enable charging during suspend */ /* XXX keep power LED state during suspend */ diff --git a/sys/dev/acpi/acpi.c b/sys/dev/acpi/acpi.c index b3468d22cb6..5bd1162cf6a 100644 --- a/sys/dev/acpi/acpi.c +++ b/sys/dev/acpi/acpi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: acpi.c,v 1.240 2012/10/04 08:32:20 ehrhardt Exp $ */ +/* $OpenBSD: acpi.c,v 1.241 2012/10/08 21:47:50 deraadt Exp $ */ /* * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com> * Copyright (c) 2005 Jordan Hargrave <jordan@openbsd.org> @@ -102,7 +102,6 @@ void acpi_pbtn_task(void *, int); int acpi_thinkpad_enabled; int acpi_toshiba_enabled; int acpi_asus_enabled; -int acpi_saved_spl; int acpi_saved_boothowto; int acpi_enabled; @@ -112,9 +111,8 @@ int acpi_matchhids(struct acpi_attach_args *aa, const char *hids[], void acpi_thread(void *); void acpi_create_thread(void *); void acpi_init_pm(struct acpi_softc *); - -void acpi_handle_suspend_failure(struct acpi_softc *); void acpi_init_gpes(struct acpi_softc *); +void acpi_indicator(struct acpi_softc *, int); int acpi_founddock(struct aml_node *, void *); int acpi_foundpss(struct aml_node *, void *); @@ -140,7 +138,6 @@ struct idechnl { int64_t sta; }; -void acpi_resume(struct acpi_softc *, int); int acpi_add_device(struct aml_node *node, void *arg); struct gpe_block *acpi_find_gpe(struct acpi_softc *, int); @@ -579,20 +576,21 @@ acpi_pci_min_powerstate(pci_chipset_tag_t pc, pcitag_t tag) { struct acpi_pci *pdev; int bus, dev, fun; - int state; + int state = -1, defaultstate = pci_get_powerstate(pc, tag); pci_decompose_tag(pc, tag, &bus, &dev, &fun); TAILQ_FOREACH(pdev, &acpi_pcidevs, next) { if (pdev->bus == bus && pdev->dev == dev && pdev->fun == fun) { - switch (acpi_softc->sc_nextstate) { + switch (acpi_softc->sc_state) { case ACPI_STATE_S3: + defaultstate = PCI_PMCSR_STATE_D3; state = MAX(pdev->_s3d, pdev->_s3w); break; case ACPI_STATE_S4: state = MAX(pdev->_s4d, pdev->_s4w); break; + case ACPI_STATE_S5: default: - state = -1; break; } @@ -602,7 +600,7 @@ acpi_pci_min_powerstate(pci_chipset_tag_t pc, pcitag_t tag) } } - return PCI_PMCSR_STATE_D3; + return defaultstate; } void @@ -637,6 +635,7 @@ acpi_attach(struct device *parent, struct device *self, void *aux) struct device *dev; struct acpi_ac *ac; struct acpi_bat *bat; + int s; #endif /* SMALL_KERNEL */ paddr_t facspa; @@ -761,7 +760,9 @@ acpi_attach(struct device *parent, struct device *self, void *aux) #ifndef SMALL_KERNEL /* Initialize GPE handlers */ + s = spltty(); acpi_init_gpes(sc); + splx(s); /* some devices require periodic polling */ timeout_set(&sc->sc_dev_timeout, acpi_poll, sc); @@ -1456,6 +1457,9 @@ acpi_reset(void) struct acpi_softc *sc = acpi_softc; struct acpi_fadt *fadt = sc->sc_fadt; + if (acpi_enabled == 0) + return; + /* * RESET_REG_SUP is not properly set in some implementations, * but not testing against it breaks more machines than it fixes @@ -1695,43 +1699,36 @@ void acpi_enable_onegpe(struct acpi_softc *sc, int gpe) { uint8_t mask, en; - int s; /* Read enabled register */ - s = spltty(); mask = (1L << (gpe & 7)); en = acpi_read_pmreg(sc, ACPIREG_GPE_EN, gpe>>3); dnprintf(50, "enabling GPE %.2x (current: %sabled) %.2x\n", gpe, (en & mask) ? "en" : "dis", en); acpi_write_pmreg(sc, ACPIREG_GPE_EN, gpe>>3, en | mask); - splx(s); } /* Clear all GPEs */ void acpi_disable_allgpes(struct acpi_softc *sc) { - int idx, s; + int idx; - s = spltty(); for (idx = 0; idx < sc->sc_lastgpe; idx += 8) { acpi_write_pmreg(sc, ACPIREG_GPE_EN, idx >> 3, 0); acpi_write_pmreg(sc, ACPIREG_GPE_STS, idx >> 3, -1); } - splx(s); } /* Enable runtime GPEs */ void acpi_enable_rungpes(struct acpi_softc *sc) { - int s, idx; + int idx; - s = spltty(); for (idx = 0; idx < sc->sc_lastgpe; idx++) if (sc->gpe_table[idx].handler) acpi_enable_onegpe(sc, idx); - splx(s); } /* Enable wakeup GPEs */ @@ -1739,9 +1736,7 @@ void acpi_enable_wakegpes(struct acpi_softc *sc, int state) { struct acpi_wakeq *wentry; - int s; - s = spltty(); SIMPLEQ_FOREACH(wentry, &sc->sc_wakedevs, q_next) { dnprintf(10, "%.4s(S%d) gpe %.2x\n", wentry->q_node->name, wentry->q_state, @@ -1749,7 +1744,6 @@ acpi_enable_wakegpes(struct acpi_softc *sc, int state) if (state <= wentry->q_state) acpi_enable_onegpe(sc, wentry->q_gpe); } - splx(s); } int @@ -1778,19 +1772,15 @@ acpi_gpe(struct acpi_softc *sc, int gpe, void *arg) { struct aml_node *node = arg; uint8_t mask, en; - int s; dnprintf(10, "handling GPE %.2x\n", gpe); aml_evalnode(sc, node, 0, NULL, NULL); - s = spltty(); mask = (1L << (gpe & 7)); if (!sc->gpe_table[gpe].edge) acpi_write_pmreg(sc, ACPIREG_GPE_STS, gpe>>3, mask); en = acpi_read_pmreg(sc, ACPIREG_GPE_EN, gpe>>3); acpi_write_pmreg(sc, ACPIREG_GPE_EN, gpe>>3, en | mask); - splx(s); - return (0); } @@ -1894,45 +1884,21 @@ acpi_init_pm(struct acpi_softc *sc) sc->sc_sst = aml_searchname(&aml_root, "_SI_._SST"); } -int -acpi_sleep_state(struct acpi_softc *sc, int state) +void +acpi_sleep_pm(struct acpi_softc *sc, int state) { - int ret; - - switch (state) { - case ACPI_STATE_S0: - case ACPI_STATE_S1: - case ACPI_STATE_S2: - case ACPI_STATE_S5: - return (0); - } + uint16_t rega, regb, regra, regrb; + int retry = 0; - if (sc->sc_sleeptype[state].slp_typa == -1 || - sc->sc_sleeptype[state].slp_typb == -1) - return (EOPNOTSUPP); - - if ((ret = acpi_prepare_sleep_state(sc, state)) != 0) - return (ret); - - ret = acpi_sleep_machdep(sc, state); - -#ifndef SMALL_KERNEL - acpi_resume(sc, state); -#endif /* !SMALL_KERNEL */ - return (ret); -} - -int -acpi_enter_sleep_state(struct acpi_softc *sc, int state) -{ - uint16_t rega, regb; - int retries; + disable_intr(); /* Clear WAK_STS bit */ acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, ACPI_PM1_WAK_STS); - /* Disable BM arbitration */ - acpi_write_pmreg(sc, ACPIREG_PM2_CNT, 0, ACPI_PM2_ARB_DIS); + /* Disable BM arbitration at deep sleep and beyond */ + if (state >= ACPI_STATE_S3 && + sc->sc_fadt->pm2_cnt_blk && sc->sc_fadt->pm2_cnt_len) + acpi_write_pmreg(sc, ACPIREG_PM2_CNT, 0, ACPI_PM2_ARB_DIS); /* Write SLP_TYPx values */ rega = acpi_read_pmreg(sc, ACPIREG_PM1A_CNT, 0); @@ -1944,259 +1910,194 @@ acpi_enter_sleep_state(struct acpi_softc *sc, int state) acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, 0, rega); acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, 0, regb); - /* Set SLP_EN bit */ + /* Loop on WAK_STS, setting the SLP_EN bits once in a while */ rega |= ACPI_PM1_SLP_EN; regb |= ACPI_PM1_SLP_EN; + while (1) { + if (retry == 0) { + acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, 0, rega); + acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, 0, regb); + } + retry = (retry + 1) % 100000; - /* - * Let the machdep code flush caches and do any other necessary - * tasks before going away. - */ - acpi_cpu_flush(sc, state); - - /* - * XXX The following sequence is probably not right. - */ - acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, 0, rega); - acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, 0, regb); - - /* Loop on WAK_STS */ - for (retries = 1000; retries > 0; retries--) { - rega = acpi_read_pmreg(sc, ACPIREG_PM1A_STS, 0); - regb = acpi_read_pmreg(sc, ACPIREG_PM1B_STS, 0); - if ((rega & ACPI_PM1_WAK_STS) || - (regb & ACPI_PM1_WAK_STS)) + regra = acpi_read_pmreg(sc, ACPIREG_PM1A_STS, 0); + regrb = acpi_read_pmreg(sc, ACPIREG_PM1B_STS, 0); + if ((regra & ACPI_PM1_WAK_STS) || + (regrb & ACPI_PM1_WAK_STS)) break; - DELAY(1000); } - - return (-1); } void -acpi_resume(struct acpi_softc *sc, int state) +acpi_resume_pm(struct acpi_softc *sc, int fromstate) { - struct aml_value env; + uint16_t rega, regb, en; - memset(&env, 0, sizeof(env)); - env.type = AML_OBJTYPE_INTEGER; - env.v_integer = sc->sc_state; + /* Write SLP_TYPx values */ + rega = acpi_read_pmreg(sc, ACPIREG_PM1A_CNT, 0); + regb = acpi_read_pmreg(sc, ACPIREG_PM1B_CNT, 0); + rega &= ~(ACPI_PM1_SLP_TYPX_MASK | ACPI_PM1_SLP_EN); + regb &= ~(ACPI_PM1_SLP_TYPX_MASK | ACPI_PM1_SLP_EN); + rega |= ACPI_PM1_SLP_TYPX(sc->sc_sleeptype[ACPI_STATE_S0].slp_typa); + regb |= ACPI_PM1_SLP_TYPX(sc->sc_sleeptype[ACPI_STATE_S0].slp_typb); + acpi_write_pmreg(sc, ACPIREG_PM1A_CNT, 0, rega); + acpi_write_pmreg(sc, ACPIREG_PM1B_CNT, 0, regb); /* Force SCI_EN on resume to fix horribly broken machines */ acpi_write_pmreg(sc, ACPIREG_PM1_CNT, 0, ACPI_PM1_SCI_EN); /* Clear fixed event status */ - acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, - ACPI_PM1_ALL_STS); + acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, ACPI_PM1_ALL_STS); - if (sc->sc_bfs) - if (aml_evalnode(sc, sc->sc_bfs, 1, &env, NULL) != 0) { - dnprintf(10, "%s evaluating method _BFS failed.\n", - DEVNAME(sc)); - } - - if (sc->sc_wak) - if (aml_evalnode(sc, sc->sc_wak, 1, &env, NULL) != 0) { - dnprintf(10, "%s evaluating method _WAK failed.\n", - DEVNAME(sc)); - } - - /* Reset the indicator lights to "waking" */ - if (sc->sc_sst) { - env.v_integer = ACPI_SST_WAKING; - aml_evalnode(sc, sc->sc_sst, 1, &env, NULL); - } + /* acpica-reference.pdf page 148 says do not call _BFS */ + /* 1st resume AML step: _BFS(fromstate) */ + aml_node_setval(sc, sc->sc_bfs, fromstate); /* Enable runtime GPEs */ acpi_disable_allgpes(sc); acpi_enable_rungpes(sc); - if (state == ACPI_STATE_S4) - boothowto = acpi_saved_boothowto; - - config_suspend(TAILQ_FIRST(&alldevs), DVACT_RESUME); - - cold = 0; - enable_intr(); - splx(acpi_saved_spl); + acpi_indicator(sc, ACPI_SST_WAKING); - acpi_resume_machdep(); + /* 2nd resume AML step: _WAK(fromstate) */ + aml_node_setval(sc, sc->sc_wak, fromstate); - sc->sc_state = ACPI_STATE_S0; - if (sc->sc_tts) { - env.v_integer = sc->sc_state; - if (aml_evalnode(sc, sc->sc_tts, 1, &env, NULL) != 0) { - dnprintf(10, "%s evaluating method _TTS failed.\n", - DEVNAME(sc)); - } - } + /* Clear WAK_STS bit */ + acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, ACPI_PM1_WAK_STS); - /* disable _LID for wakeup */ - acpibtn_disable_psw(); + en = acpi_read_pmreg(sc, ACPIREG_PM1_EN, 0); + if (!(sc->sc_fadt->flags & FADT_PWR_BUTTON)) + en |= ACPI_PM1_PWRBTN_EN; + if (!(sc->sc_fadt->flags & FADT_SLP_BUTTON)) + en |= ACPI_PM1_SLPBTN_EN; + acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en); - /* Reset the indicator lights to "working" */ - if (sc->sc_sst) { - env.v_integer = ACPI_SST_WORKING; - aml_evalnode(sc, sc->sc_sst, 1, &env, NULL); + /* + * If PM2 exists, re-enable BM arbitration (reportedly some + * BIOS forget to) + */ + if (sc->sc_fadt->pm2_cnt_blk && sc->sc_fadt->pm2_cnt_len) { + rega = acpi_read_pmreg(sc, ACPIREG_PM2_CNT, 0); + rega &= ~ACPI_PM2_ARB_DIS; + acpi_write_pmreg(sc, ACPIREG_PM2_CNT, 0, rega); } - -#ifdef MULTIPROCESSOR - sched_start_secondary_cpus(); -#endif - - acpi_record_event(sc, APM_NORMAL_RESUME); - - bufq_restart(); - -#if NWSDISPLAY > 0 - wsdisplay_resume(); -#endif /* NWSDISPLAY > 0 */ } +/* Set the indicator light to some state */ void -acpi_handle_suspend_failure(struct acpi_softc *sc) +acpi_indicator(struct acpi_softc *sc, int led_state) { - struct aml_value env; + static int save_led_state = -1; - /* Undo a partial suspend. Devices will have already been resumed */ - cold = 0; - enable_intr(); - splx(acpi_saved_spl); - - /* Tell ACPI to go back to S0 */ - memset(&env, 0, sizeof(env)); - env.type = AML_OBJTYPE_INTEGER; - sc->sc_state = ACPI_STATE_S0; - if (sc->sc_tts) { - env.v_integer = sc->sc_state; - if (aml_evalnode(sc, sc->sc_tts, 1, &env, NULL) != 0) { - dnprintf(10, "%s evaluating method _TTS failed.\n", - DEVNAME(sc)); - } + if (save_led_state != led_state) { + aml_node_setval(sc, sc->sc_sst, led_state); + save_led_state = led_state; } - - /* disable _LID for wakeup */ - acpibtn_disable_psw(); - - /* Reset the indicator lights to "working" */ - if (sc->sc_sst) { - env.v_integer = ACPI_SST_WORKING; - aml_evalnode(sc, sc->sc_sst, 1, &env, NULL); - } - -#ifdef MULTIPROCESSOR - sched_start_secondary_cpus(); -#endif } int -acpi_prepare_sleep_state(struct acpi_softc *sc, int state) +acpi_sleep_state(struct acpi_softc *sc, int state) { - struct aml_value env; - int error = 0; + int error = ENXIO; + int s; - if (sc == NULL || state == ACPI_STATE_S0) - return(0); + switch (state) { + case ACPI_STATE_S0: + return (0); + case ACPI_STATE_S1: + return (EOPNOTSUPP); + case ACPI_STATE_S5: /* only sleep states handled here */ + 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 (ENXIO); + return (EOPNOTSUPP); } -#ifdef MULTIPROCESSOR - sched_stop_secondary_cpus(); - KASSERT(CPU_IS_PRIMARY(curcpu())); -#endif - - sc->sc_nextstate = state; - - memset(&env, 0, sizeof(env)); - env.type = AML_OBJTYPE_INTEGER; - env.v_integer = state; - /* _TTS(state) */ - if (sc->sc_tts) - if (aml_evalnode(sc, sc->sc_tts, 1, &env, NULL) != 0) { - dnprintf(10, "%s evaluating method _TTS failed.\n", - DEVNAME(sc)); - return (ENXIO); - } - - if (state == ACPI_STATE_S4) - printf("%s: hibernating to disk ...\n", DEVNAME(sc)); + /* 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 - if (state == ACPI_STATE_S3 || state == ACPI_STATE_S4) - wsdisplay_suspend(); + wsdisplay_suspend(); #endif /* NWSDISPLAY > 0 */ + bufq_quiesce(); - if (state == ACPI_STATE_S3) - resettodr(); + if (config_suspend(TAILQ_FIRST(&alldevs), DVACT_QUIESCE)) + goto fail_quiesce; - bufq_quiesce(); - config_suspend(TAILQ_FIRST(&alldevs), DVACT_QUIESCE); +#ifdef MULTIPROCESSOR + acpi_sleep_mp(); +#endif - acpi_saved_spl = splhigh(); - disable_intr(); - cold = 1; - if (state == ACPI_STATE_S4) { - acpi_saved_boothowto = boothowto; - boothowto = RB_RDONLY; - } - if (state == ACPI_STATE_S3 || state == ACPI_STATE_S4) - if (config_suspend(TAILQ_FIRST(&alldevs), DVACT_SUSPEND) != 0) { - acpi_handle_suspend_failure(sc); - error = ENXIO; - goto fail; - } + resettodr(); - /* _PTS(state) */ - if (sc->sc_pts) - if (aml_evalnode(sc, sc->sc_pts, 1, &env, NULL) != 0) { - dnprintf(10, "%s evaluating method _PTS failed.\n", - DEVNAME(sc)); - error = ENXIO; - goto fail; - } + s = splhigh(); + disable_intr(); /* PSL_I for resume; PIC/APIC broken until repair */ + cold = 1; /* Force other code to delay() instead of tsleep() */ - /* enable _LID for wakeup */ - acpibtn_enable_psw(); + if (config_suspend(TAILQ_FIRST(&alldevs), DVACT_SUSPEND) != 0) + goto fail_suspend; + acpi_sleep_clocks(sc, state); - /* Reset the indicator lights to "sleeping" */ - if (sc->sc_sst) { - env.v_integer = ACPI_SST_SLEEPING; - aml_evalnode(sc, sc->sc_sst, 1, &env, NULL); - } - env.v_integer = state; + /* 2nd suspend AML step: _PTS(tostate) */ + if (aml_node_setval(sc, sc->sc_pts, state) != 0) + goto fail_pts; - sc->sc_state = state; - /* _GTS(state) */ - if (sc->sc_gts) - if (aml_evalnode(sc, sc->sc_gts, 1, &env, NULL) != 0) { - dnprintf(10, "%s evaluating method _GTS failed.\n", - DEVNAME(sc)); - error = ENXIO; - goto fail; - } + 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); + acpi_write_pmreg(sc, ACPIREG_PM1_STS, 0, ACPI_PM1_ALL_STS); /* Enable wake GPEs */ acpi_disable_allgpes(sc); acpi_enable_wakegpes(sc, state); -fail: - if (error) { - bufq_restart(); + /* Sleep */ + sc->sc_state = state; + error = acpi_sleep_cpu(sc, state); + sc->sc_state = ACPI_STATE_S0; + /* Resume */ + + acpi_resume_clocks(sc); /* AML may need clocks */ + acpi_resume_pm(sc, state); + acpi_resume_cpu(sc); + acpibtn_disable_psw(); /* disable _LID for wakeup */ + +fail_pts: + config_suspend(TAILQ_FIRST(&alldevs), DVACT_RESUME); + +fail_suspend: + cold = 0; + enable_intr(); + splx(s); + + inittodr(time_second); + /* 3rd resume AML step: _TTS(runstate) */ + aml_node_setval(sc, sc->sc_tts, sc->sc_state); + +#ifdef MULTIPROCESSOR + acpi_resume_mp(); +#endif + +fail_quiesce: + bufq_restart(); #if NWSDISPLAY > 0 - wsdisplay_resume(); + wsdisplay_resume(); #endif /* NWSDISPLAY > 0 */ - } + acpi_record_event(sc, APM_NORMAL_RESUME); + acpi_indicator(sc, ACPI_SST_WORKING); +fail_tts: return (error); } @@ -2209,17 +2110,37 @@ acpi_wakeup(void *arg) wakeup(sc); } +/* 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 + * intermediate context. Wish us luck. + */ void acpi_powerdown(void) { - /* - * In case acpi_prepare_sleep fails, we shouldn't try to enter - * the sleep state. It might cost us the battery. - */ - acpi_disable_allgpes(acpi_softc); - acpi_enable_wakegpes(acpi_softc, ACPI_STATE_S5); - if (acpi_prepare_sleep_state(acpi_softc, ACPI_STATE_S5) == 0) - acpi_enter_sleep_state(acpi_softc, ACPI_STATE_S5); + int state = ACPI_STATE_S5, s; + struct acpi_softc *sc = acpi_softc; + + if (acpi_enabled == 0) + return; + + s = splhigh(); + disable_intr(); + cold = 1; + + /* 1st powerdown AML step: _PTS(tostate) */ + aml_node_setval(sc, sc->sc_pts, state); + + acpi_disable_allgpes(sc); + acpi_enable_wakegpes(sc, state); + + /* 2nd powerdown AML step: _GTS(tostate) */ + aml_node_setval(sc, sc->sc_gts, state); + + acpi_sleep_pm(sc, state); + panic("acpi S5 transition did not happen"); + while (1) + ; } void @@ -2254,10 +2175,10 @@ acpi_thread(void *arg) if (!(sc->sc_fadt->flags & FADT_SLP_BUTTON)) en |= ACPI_PM1_SLPBTN_EN; acpi_write_pmreg(sc, ACPIREG_PM1_EN, 0, en); - splx(s); /* Enable handled GPEs here */ acpi_enable_rungpes(sc); + splx(s); } while (thread->running) { diff --git a/sys/dev/acpi/acpivar.h b/sys/dev/acpi/acpivar.h index b791df6092a..2f9b0e1afcd 100644 --- a/sys/dev/acpi/acpivar.h +++ b/sys/dev/acpi/acpivar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: acpivar.h,v 1.73 2012/10/04 08:32:20 ehrhardt Exp $ */ +/* $OpenBSD: acpivar.h,v 1.74 2012/10/08 21:47:50 deraadt Exp $ */ /* * Copyright (c) 2005 Thorsten Lockert <tholo@sigmasoft.com> * @@ -228,7 +228,6 @@ struct acpi_softc { struct aml_node *sc_sst; struct aml_node *sc_wak; int sc_state; - int sc_nextstate; struct acpiec_softc *sc_ec; /* XXX assume single EC */ struct acpi_ac_head sc_ac; @@ -282,12 +281,15 @@ void acpi_attach_machdep(struct acpi_softc *); int acpi_interrupt(void *); void acpi_powerdown(void); void acpi_reset(void); -void acpi_cpu_flush(struct acpi_softc *, int); int acpi_sleep_state(struct acpi_softc *, int); -int acpi_prepare_sleep_state(struct acpi_softc *, int); -int acpi_enter_sleep_state(struct acpi_softc *, int); -int acpi_sleep_machdep(struct acpi_softc *, int); -void acpi_resume_machdep(void); +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_clocks(struct acpi_softc *); +void acpi_resume_cpu(struct acpi_softc *); +void acpi_resume_mp(void); void acpi_sleep_walk(struct acpi_softc *, int); diff --git a/sys/dev/ata/wd.c b/sys/dev/ata/wd.c index 2e1c23b920b..7edd174a772 100644 --- a/sys/dev/ata/wd.c +++ b/sys/dev/ata/wd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: wd.c,v 1.108 2011/07/06 04:49:36 matthew Exp $ */ +/* $OpenBSD: wd.c,v 1.109 2012/10/08 21:47:50 deraadt Exp $ */ /* $NetBSD: wd.c,v 1.193 1999/02/28 17:15:27 explorer Exp $ */ /* @@ -142,7 +142,6 @@ void wdrestart(void *); int wd_get_params(struct wd_softc *, u_int8_t, struct ataparams *); void wd_flushcache(struct wd_softc *, int); void wd_standby(struct wd_softc *, int); -void wd_shutdown(void *); /* XXX: these should go elsewhere */ cdev_decl(wd); @@ -327,10 +326,6 @@ wdattach(struct device *parent, struct device *self, void *aux) */ wd->sc_dk.dk_name = wd->sc_dev.dv_xname; bufq_init(&wd->sc_bufq, BUFQ_DEFAULT); - wd->sc_sdhook = shutdownhook_establish(wd_shutdown, wd); - if (wd->sc_sdhook == NULL) - printf("%s: WARNING: unable to establish shutdown hook\n", - wd->sc_dev.dv_xname); timeout_set(&wd->sc_restart_timeout, wdrestart, wd); /* Attach disk. */ @@ -346,8 +341,11 @@ wdactivate(struct device *self, int act) switch (act) { case DVACT_SUSPEND: + break; + case DVACT_POWERDOWN: wd_flushcache(wd, AT_POLL); - wd_standby(wd, AT_POLL); + if (boothowto & RB_POWERDOWN) + wd_standby(wd, AT_POLL); break; case DVACT_RESUME: /* @@ -377,10 +375,6 @@ wddetach(struct device *self, int flags) disk_gone(wdopen, self->dv_unit); - /* Get rid of the shutdown hook. */ - if (sc->sc_sdhook != NULL) - shutdownhook_disestablish(sc->sc_sdhook); - /* Detach disk. */ bufq_destroy(&sc->sc_bufq); disk_detach(&sc->sc_dk); @@ -1142,13 +1136,3 @@ wd_standby(struct wd_softc *wd, int flags) * standby */ } - -void -wd_shutdown(void *arg) -{ - struct wd_softc *wd = arg; - - wd_flushcache(wd, AT_POLL); - if (boothowto & RB_POWERDOWN) - wd_standby(wd, AT_POLL); -} diff --git a/sys/dev/cardbus/ehci_cardbus.c b/sys/dev/cardbus/ehci_cardbus.c index bd4d2b913c8..af54433b740 100644 --- a/sys/dev/cardbus/ehci_cardbus.c +++ b/sys/dev/cardbus/ehci_cardbus.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ehci_cardbus.c,v 1.15 2010/03/27 21:40:13 jsg Exp $ */ +/* $OpenBSD: ehci_cardbus.c,v 1.16 2012/10/08 21:47:50 deraadt Exp $ */ /* $NetBSD: ehci_cardbus.c,v 1.6.6.3 2004/09/21 13:27:25 skrll Exp $ */ /* @@ -73,7 +73,7 @@ struct ehci_cardbus_softc { struct cfattach ehci_cardbus_ca = { sizeof(struct ehci_cardbus_softc), ehci_cardbus_match, - ehci_cardbus_attach, ehci_cardbus_detach, ehci_activate + ehci_cardbus_attach, ehci_cardbus_detach, ehci_activate }; #define CARDBUS_CBMEM PCI_CBMEM @@ -161,8 +161,6 @@ ehci_cardbus_attach(struct device *parent, struct device *self, void *aux) return; } - sc->sc.sc_shutdownhook = shutdownhook_establish(ehci_shutdown, &sc->sc); - /* Attach usb device. */ sc->sc.sc_child = config_found((void *)sc, &sc->sc.sc_bus, usbctlprint); @@ -189,4 +187,3 @@ ehci_cardbus_detach(struct device *self, int flags) } return (0); } - diff --git a/sys/dev/pci/ahci.c b/sys/dev/pci/ahci.c index 7bda90956ce..edd071050df 100644 --- a/sys/dev/pci/ahci.c +++ b/sys/dev/pci/ahci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ahci.c,v 1.193 2012/08/11 13:52:27 jmatthew Exp $ */ +/* $OpenBSD: ahci.c,v 1.194 2012/10/08 21:47:50 deraadt Exp $ */ /* * Copyright (c) 2006 David Gwynne <dlg@openbsd.org> @@ -985,6 +985,9 @@ ahci_pci_activate(struct device *self, int act) break; case DVACT_SUSPEND: rv = config_activate_children(self, act); + break; + case DVACT_POWERDOWN: + rv = config_activate_children(self, act); for (i = 0; i < AHCI_MAX_PORTS; i++) { if (sc->sc_ports[i] != NULL) ahci_port_stop(sc->sc_ports[i], 1); diff --git a/sys/dev/pci/ehci_pci.c b/sys/dev/pci/ehci_pci.c index 6f46a987f55..11565cf2531 100644 --- a/sys/dev/pci/ehci_pci.c +++ b/sys/dev/pci/ehci_pci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ehci_pci.c,v 1.23 2011/04/26 00:37:34 deraadt Exp $ */ +/* $OpenBSD: ehci_pci.c,v 1.24 2012/10/08 21:47:50 deraadt Exp $ */ /* $NetBSD: ehci_pci.c,v 1.15 2004/04/23 21:13:06 itojun Exp $ */ /* @@ -75,9 +75,10 @@ int ehci_pci_match(struct device *, void *, void *); void ehci_pci_attach(struct device *, struct device *, void *); int ehci_pci_detach(struct device *, int); int ehci_pci_activate(struct device *, int); +#if 0 void ehci_pci_givecontroller(struct ehci_pci_softc *); +#endif void ehci_pci_takecontroller(struct ehci_pci_softc *, int); -void ehci_pci_shutdown(void *); struct cfattach ehci_pci_ca = { sizeof(struct ehci_pci_softc), ehci_pci_match, ehci_pci_attach, @@ -215,7 +216,6 @@ ehci_pci_attach(struct device *parent, struct device *self, void *aux) goto disestablish_ret; } - sc->sc.sc_shutdownhook = shutdownhook_establish(ehci_pci_shutdown, sc); splx(s); /* Attach usb device. */ @@ -235,15 +235,24 @@ int ehci_pci_activate(struct device *self, int act) { struct ehci_pci_softc *sc = (struct ehci_pci_softc *)self; + int rv; - /* On resume, take ownership from the BIOS */ switch (act) { case DVACT_RESUME: ehci_pci_takecontroller(sc, 1); break; } - return ehci_activate(self, act); + rv = ehci_activate(self, act); + +#if 0 + switch (act) { + case DVACT_POWERDOWN: + ehci_pci_givecontroller(sc); + break; + } +#endif + return (rv); } int @@ -266,7 +275,7 @@ ehci_pci_detach(struct device *self, int flags) return (0); } -#if 0 /* not used */ +#if 0 void ehci_pci_givecontroller(struct ehci_pci_softc *sc) { @@ -319,18 +328,6 @@ ehci_pci_takecontroller(struct ehci_pci_softc *sc, int silent) } } -void -ehci_pci_shutdown(void *v) -{ - struct ehci_pci_softc *sc = (struct ehci_pci_softc *)v; - - ehci_shutdown(&sc->sc); -#if 0 - /* best not to do this anymore; BIOS SMM spins? */ - ehci_pci_givecontroller(sc); -#endif -} - int ehci_sb700_match(struct pci_attach_args *pa) { diff --git a/sys/dev/pci/glxpcib.c b/sys/dev/pci/glxpcib.c index fa1ccaeb16e..30a4dcde277 100644 --- a/sys/dev/pci/glxpcib.c +++ b/sys/dev/pci/glxpcib.c @@ -1,4 +1,4 @@ -/* $OpenBSD: glxpcib.c,v 1.5 2012/03/06 12:57:36 mikeb Exp $ */ +/* $OpenBSD: glxpcib.c,v 1.6 2012/10/08 21:47:50 deraadt Exp $ */ /* * Copyright (c) 2007 Marc Balmer <mbalmer@openbsd.org> @@ -426,6 +426,9 @@ glxpcib_activate(struct device *self, int act) #endif break; + case DVACT_POWERDOWN: + rv = config_activate_children(self, act); + break; case DVACT_RESUME: #ifndef SMALL_KERNEL if (sc->sc_wdog) diff --git a/sys/dev/pci/pccbb.c b/sys/dev/pci/pccbb.c index fd37b407280..e2d233d766e 100644 --- a/sys/dev/pci/pccbb.c +++ b/sys/dev/pci/pccbb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pccbb.c,v 1.87 2010/12/08 20:22:49 miod Exp $ */ +/* $OpenBSD: pccbb.c,v 1.88 2012/10/08 21:47:50 deraadt Exp $ */ /* $NetBSD: pccbb.c,v 1.96 2004/03/28 09:49:31 nakayama Exp $ */ /* @@ -457,8 +457,6 @@ pccbbattach(struct device *parent, struct device *self, void *aux) printf("\n"); - shutdownhook_establish(pccbb_shutdown, sc); - /* Disable legacy register mapping. */ pccbb_legacy_disable(sc); @@ -2841,6 +2839,10 @@ pccbbactivate(struct device *self, int act) sc->sc_iobase[1] = pci_conf_read(pc, tag, PCI_CB_IOBASE1); sc->sc_iolimit[1] = pci_conf_read(pc, tag, PCI_CB_IOLIMIT1); break; + case DVACT_POWERDOWN: + rv = config_activate_children(self, act); + pccbb_shutdown(self); + break; case DVACT_RESUME: /* Restore the registers saved above. */ pci_conf_write(pc, tag, PCI_BHLC_REG, sc->sc_bhlcr); diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index a19420b7d18..6bd03cb39dd 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pci.c,v 1.96 2012/09/19 23:01:21 kettenis Exp $ */ +/* $OpenBSD: pci.c,v 1.97 2012/10/08 21:47:50 deraadt Exp $ */ /* $NetBSD: pci.c,v 1.31 1997/06/06 23:48:04 thorpej Exp $ */ /* @@ -51,6 +51,7 @@ void pciattach(struct device *, struct device *, void *); int pcidetach(struct device *, int); int pciactivate(struct device *, int); void pci_suspend(struct pci_softc *); +void pci_powerdown(struct pci_softc *); void pci_resume(struct pci_softc *); #define NMAPREG ((PCI_MAPREG_END - PCI_MAPREG_START) / \ @@ -215,6 +216,10 @@ pciactivate(struct device *self, int act) rv = config_activate_children(self, act); pci_suspend((struct pci_softc *)self); break; + case DVACT_POWERDOWN: + rv = config_activate_children(self, act); + pci_powerdown((struct pci_softc *)self); + break; case DVACT_RESUME: pci_resume((struct pci_softc *)self); rv = config_activate_children(self, act); @@ -266,6 +271,24 @@ pci_suspend(struct pci_softc *sc) } pd->pd_msi_mc = reg; } + } +} + +void +pci_powerdown(struct pci_softc *sc) +{ + struct pci_dev *pd; + pcireg_t bhlc; + + LIST_FOREACH(pd, &sc->sc_devs, pd_next) { + /* + * Only handle header type 0 here; PCI-PCI bridges and + * CardBus bridges need special handling, which will + * be done in their specific drivers. + */ + bhlc = pci_conf_read(sc->sc_pc, pd->pd_tag, PCI_BHLC_REG); + if (PCI_HDRTYPE_TYPE(bhlc) != 0) + continue; if (pci_dopm) { /* @@ -297,11 +320,10 @@ pci_resume(struct pci_softc *sc) if (PCI_HDRTYPE_TYPE(bhlc) != 0) continue; - if (pci_dopm) { - /* Restore power. */ + /* Restore power. */ + if (pci_dopm) pci_set_powerstate(sc->sc_pc, pd->pd_tag, pd->pd_pmcsr_state); - } /* Restore the registers saved above. */ for (i = 0; i < NMAPREG; i++) diff --git a/sys/dev/pci/pciide.c b/sys/dev/pci/pciide.c index 34976ae11a6..45f112c53ea 100644 --- a/sys/dev/pci/pciide.c +++ b/sys/dev/pci/pciide.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pciide.c,v 1.339 2012/04/22 14:22:28 miod Exp $ */ +/* $OpenBSD: pciide.c,v 1.340 2012/10/08 21:47:50 deraadt Exp $ */ /* $NetBSD: pciide.c,v 1.127 2001/08/03 01:31:08 tsutsui Exp $ */ /* @@ -1489,6 +1489,9 @@ pciide_activate(struct device *self, int act) sc->sc_tag, NFORCE_UDMATIM); } break; + case DVACT_POWERDOWN: + rv = config_activate_children(self, act); + break; case DVACT_RESUME: for (i = 0; i < nitems(sc->sc_save); i++) pci_conf_write(sc->sc_pc, sc->sc_tag, diff --git a/sys/dev/pci/ppb.c b/sys/dev/pci/ppb.c index 32dfce9523e..c9a7f9cca53 100644 --- a/sys/dev/pci/ppb.c +++ b/sys/dev/pci/ppb.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ppb.c,v 1.54 2012/09/07 19:26:48 kettenis Exp $ */ +/* $OpenBSD: ppb.c,v 1.55 2012/10/08 21:47:50 deraadt Exp $ */ /* $NetBSD: ppb.c,v 1.16 1997/06/06 23:48:05 thorpej Exp $ */ /* @@ -389,7 +389,10 @@ ppbactivate(struct device *self, int act) } sc->sc_msi_mc = reg; } - + break; + case DVACT_POWERDOWN: + rv = config_activate_children(self, act); + if (pci_dopm) { /* * Place the bridge into the lowest possible diff --git a/sys/dev/pci/sdhc_pci.c b/sys/dev/pci/sdhc_pci.c index eac6107992a..5abe511d84e 100644 --- a/sys/dev/pci/sdhc_pci.c +++ b/sys/dev/pci/sdhc_pci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sdhc_pci.c,v 1.12 2011/12/23 21:58:47 kettenis Exp $ */ +/* $OpenBSD: sdhc_pci.c,v 1.13 2012/10/08 21:47:50 deraadt Exp $ */ /* * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org> @@ -172,11 +172,6 @@ sdhc_pci_attach(struct device *parent, struct device *self, void *aux) printf("%s at 0x%x: can't initialize host\n", sc->sc.sc_dev.dv_xname, reg); } - - /* - * Establish shutdown hooks. - */ - (void)shutdownhook_establish(sdhc_shutdown, &sc->sc); } void diff --git a/sys/dev/pci/sili_pci.c b/sys/dev/pci/sili_pci.c index 2be1405924d..d4f0b6510df 100644 --- a/sys/dev/pci/sili_pci.c +++ b/sys/dev/pci/sili_pci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sili_pci.c,v 1.12 2010/08/31 17:13:44 deraadt Exp $ */ +/* $OpenBSD: sili_pci.c,v 1.13 2012/10/08 21:47:50 deraadt Exp $ */ /* * Copyright (c) 2007 David Gwynne <dlg@openbsd.org> @@ -212,6 +212,9 @@ sili_pci_activate(struct device *self, int act) case DVACT_SUSPEND: rv = config_activate_children(self, act); break; + case DVACT_POWERDOWN: + rv = config_activate_children(self, act); + break; case DVACT_RESUME: sili_resume(sc); rv = config_activate_children(self, act); diff --git a/sys/dev/pci/vga_pci.c b/sys/dev/pci/vga_pci.c index 595483c23c9..56f977a1b93 100644 --- a/sys/dev/pci/vga_pci.c +++ b/sys/dev/pci/vga_pci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vga_pci.c,v 1.68 2012/08/22 20:58:30 mpi Exp $ */ +/* $OpenBSD: vga_pci.c,v 1.69 2012/10/08 21:47:50 deraadt Exp $ */ /* $NetBSD: vga_pci.c,v 1.3 1998/06/08 06:55:58 thorpej Exp $ */ /* @@ -336,6 +336,9 @@ vga_pci_activate(struct device *self, int act) #endif rv = config_activate_children(self, act); break; + case DVACT_POWERDOWN: + rv = config_activate_children(self, act); + break; } return (rv); diff --git a/sys/dev/pcmcia/pcmcia.c b/sys/dev/pcmcia/pcmcia.c index ef59a7e837f..2637c5e0a20 100644 --- a/sys/dev/pcmcia/pcmcia.c +++ b/sys/dev/pcmcia/pcmcia.c @@ -1,4 +1,4 @@ -/* $OpenBSD: pcmcia.c,v 1.45 2011/09/17 15:38:43 miod Exp $ */ +/* $OpenBSD: pcmcia.c,v 1.46 2012/10/08 21:47:50 deraadt Exp $ */ /* $NetBSD: pcmcia.c,v 1.9 1998/08/13 02:10:55 eeh Exp $ */ /* @@ -140,6 +140,7 @@ pcmcia_activate(struct device *self, int act) switch (act) { case DVACT_QUIESCE: case DVACT_SUSPEND: + case DVACT_POWERDOWN: case DVACT_RESUME: for (pf = SIMPLEQ_FIRST(&sc->card.pf_head); pf != NULL; pf = SIMPLEQ_NEXT(pf, pf_list)) { diff --git a/sys/dev/pcmcia/wdc_pcmcia.c b/sys/dev/pcmcia/wdc_pcmcia.c index 803419cc976..ac42b8a3a3e 100644 --- a/sys/dev/pcmcia/wdc_pcmcia.c +++ b/sys/dev/pcmcia/wdc_pcmcia.c @@ -1,4 +1,4 @@ -/* $OpenBSD: wdc_pcmcia.c,v 1.27 2011/07/03 15:47:17 matthew Exp $ */ +/* $OpenBSD: wdc_pcmcia.c,v 1.28 2012/10/08 21:47:50 deraadt Exp $ */ /* $NetBSD: wdc_pcmcia.c,v 1.19 1999/02/19 21:49:43 abs Exp $ */ /*- @@ -436,6 +436,9 @@ wdc_pcmcia_activate(self, act) break; case DVACT_SUSPEND: rv = config_activate_children(self, act); + break; + case DVACT_POWERDOWN: + rv = config_activate_children(self, act); if (sc->sc_ih) pcmcia_intr_disestablish(sc->sc_pf, sc->sc_ih); sc->sc_ih = NULL; diff --git a/sys/dev/sdmmc/sdhc.c b/sys/dev/sdmmc/sdhc.c index 828e54284fb..9f8824661d5 100644 --- a/sys/dev/sdmmc/sdhc.c +++ b/sys/dev/sdmmc/sdhc.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sdhc.c,v 1.34 2011/07/31 16:55:01 kettenis Exp $ */ +/* $OpenBSD: sdhc.c,v 1.35 2012/10/08 21:47:50 deraadt Exp $ */ /* * Copyright (c) 2006 Uwe Stuehler <uwe@openbsd.org> @@ -271,6 +271,10 @@ sdhc_activate(struct device *self, int act) } rv = config_activate_children(self, act); break; + case DVACT_POWERDOWN: + rv = config_activate_children(self, act); + sdhc_shutdown(self); + break; case DVACT_RESUME: /* Restore the host controller state. */ for (n = 0; n < sc->sc_nhosts; n++) { diff --git a/sys/dev/usb/ehci.c b/sys/dev/usb/ehci.c index c00470f9991..8dd140ad489 100644 --- a/sys/dev/usb/ehci.c +++ b/sys/dev/usb/ehci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: ehci.c,v 1.126 2012/08/17 17:29:00 krw Exp $ */ +/* $OpenBSD: ehci.c,v 1.127 2012/10/08 21:47:50 deraadt Exp $ */ /* $NetBSD: ehci.c,v 1.66 2004/06/30 03:11:56 mycroft Exp $ */ /* @@ -1040,9 +1040,6 @@ ehci_detach(struct ehci_softc *sc, int flags) timeout_del(&sc->sc_tmo_intrlist); - if (sc->sc_shutdownhook != NULL) - shutdownhook_disestablish(sc->sc_shutdownhook); - usb_delay_ms(&sc->sc_bus, 300); /* XXX let stray task complete */ /* XXX free other data structures XXX */ @@ -1104,6 +1101,9 @@ ehci_activate(struct device *self, int act) sc->sc_bus.use_polling--; break; + case DVACT_POWERDOWN: + ehci_shutdown(sc); + break; case DVACT_RESUME: sc->sc_bus.use_polling++; diff --git a/sys/dev/usb/ehcivar.h b/sys/dev/usb/ehcivar.h index 0bea547ae82..51a71d1c9a6 100644 --- a/sys/dev/usb/ehcivar.h +++ b/sys/dev/usb/ehcivar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: ehcivar.h,v 1.22 2012/05/12 17:39:51 mpi Exp $ */ +/* $OpenBSD: ehcivar.h,v 1.23 2012/10/08 21:47:50 deraadt Exp $ */ /* $NetBSD: ehcivar.h,v 1.19 2005/04/29 15:04:29 augustss Exp $ */ /* @@ -126,7 +126,6 @@ typedef struct ehci_softc { int sc_id_vendor; /* vendor ID for root hub */ u_int32_t sc_cmd; /* shadow of cmd reg during suspend */ - void *sc_shutdownhook; /* cookie from shutdown hook */ usb_dma_t sc_fldma; ehci_link_t *sc_flist; diff --git a/sys/kern/subr_autoconf.c b/sys/kern/subr_autoconf.c index d43827e8db4..ff5c4313db9 100644 --- a/sys/kern/subr_autoconf.c +++ b/sys/kern/subr_autoconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: subr_autoconf.c,v 1.66 2011/07/03 15:47:16 matthew Exp $ */ +/* $OpenBSD: subr_autoconf.c,v 1.67 2012/10/08 21:47:50 deraadt Exp $ */ /* $NetBSD: subr_autoconf.c,v 1.21 1996/04/04 06:06:18 cgd Exp $ */ /* @@ -802,6 +802,7 @@ config_activate_children(struct device *parent, int act) case DVACT_SUSPEND: case DVACT_RESUME: case DVACT_QUIESCE: + case DVACT_POWERDOWN: rv = config_suspend(d, act); break; case DVACT_DEACTIVATE: @@ -822,6 +823,8 @@ config_activate_children(struct device *parent, int act) #endif if (act == DVACT_RESUME) printf("failing resume cannot be handled\n"); + if (act == DVACT_POWERDOWN) + return (rv); if (act != DVACT_SUSPEND) return (rv); diff --git a/sys/scsi/scsiconf.c b/sys/scsi/scsiconf.c index 7ab9a02d207..c503a5a10ef 100644 --- a/sys/scsi/scsiconf.c +++ b/sys/scsi/scsiconf.c @@ -1,4 +1,4 @@ -/* $OpenBSD: scsiconf.c,v 1.182 2011/09/22 21:36:00 jsing Exp $ */ +/* $OpenBSD: scsiconf.c,v 1.183 2012/10/08 21:47:51 deraadt Exp $ */ /* $NetBSD: scsiconf.c,v 1.57 1996/05/02 01:09:01 neil Exp $ */ /* @@ -251,6 +251,7 @@ scsi_activate_lun(struct scsibus_softc *sc, int target, int lun, int act) case DVACT_QUIESCE: case DVACT_SUSPEND: case DVACT_RESUME: + case DVACT_POWERDOWN: config_suspend(dev, act); break; case DVACT_DEACTIVATE: diff --git a/sys/scsi/sd.c b/sys/scsi/sd.c index 0cb8b51a30a..3b3aeeab7aa 100644 --- a/sys/scsi/sd.c +++ b/sys/scsi/sd.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sd.c,v 1.242 2012/07/09 12:58:01 krw Exp $ */ +/* $OpenBSD: sd.c,v 1.243 2012/10/08 21:47:51 deraadt Exp $ */ /* $NetBSD: sd.c,v 1.111 1997/04/02 02:29:41 mycroft Exp $ */ /*- @@ -87,7 +87,6 @@ int sddetach(struct device *, int); void sdminphys(struct buf *); int sdgetdisklabel(dev_t, struct sd_softc *, struct disklabel *, int); void sdstart(struct scsi_xfer *); -void sd_shutdown(void *); int sd_interpret_sense(struct scsi_xfer *); int sd_read_cap_10(struct sd_softc *, int); int sd_read_cap_16(struct sd_softc *, int); @@ -260,19 +259,6 @@ sdattach(struct device *parent, struct device *self, void *aux) sd_ioctl_cache(sc, DIOCSCACHE, &dkc); } - /* - * Establish a shutdown hook so that we can ensure that - * our data has actually made it onto the platter at - * shutdown time. Note that this relies on the fact - * that the shutdown hook code puts us at the head of - * the list (thus guaranteeing that our hook runs before - * our ancestors'). - */ - if ((sc->sc_sdhook = - shutdownhook_establish(sd_shutdown, sc)) == NULL) - printf("%s: WARNING: unable to establish shutdown hook\n", - sc->sc_dev.dv_xname); - /* Attach disk. */ disk_attach(&sc->sc_dev, &sc->sc_dk); } @@ -285,6 +271,8 @@ sdactivate(struct device *self, int act) switch (act) { case DVACT_SUSPEND: + break; + case DVACT_POWERDOWN: /* * Stop the disk. Stopping the disk should flush the * cache, but we are paranoid so we flush the cache @@ -292,8 +280,9 @@ sdactivate(struct device *self, int act) */ if ((sc->flags & SDF_DIRTY) != 0) sd_flush(sc, SCSI_AUTOCONF); - scsi_start(sc->sc_link, SSS_STOP, - SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_AUTOCONF); + if (boothowto & RB_POWERDOWN) + scsi_start(sc->sc_link, SSS_STOP, + SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_AUTOCONF); break; case DVACT_RESUME: scsi_start(sc->sc_link, SSS_START, @@ -316,10 +305,6 @@ sddetach(struct device *self, int flags) disk_gone(sdopen, self->dv_unit); - /* Get rid of the shutdown hook. */ - if (sc->sc_sdhook != NULL) - shutdownhook_disestablish(sc->sc_sdhook); - /* Detach disk. */ bufq_destroy(&sc->sc_bufq); disk_detach(&sc->sc_dk); @@ -1118,31 +1103,6 @@ sdgetdisklabel(dev_t dev, struct sd_softc *sc, struct disklabel *lp, return readdisklabel(DISKLABELDEV(dev), sdstrategy, lp, spoofonly); } - -void -sd_shutdown(void *arg) -{ - struct sd_softc *sc = (struct sd_softc *)arg; - - /* - * If the disk cache needs to be flushed, and the disk supports - * it, flush it. We're cold at this point, so we poll for - * completion. - */ - if ((sc->flags & SDF_DIRTY) != 0) - sd_flush(sc, SCSI_AUTOCONF); - if (boothowto & RB_POWERDOWN) - scsi_start(sc->sc_link, SSS_STOP, - SCSI_IGNORE_ILLEGAL_REQUEST | SCSI_AUTOCONF); - - /* - * There should be no outstanding IO at this point, but lets stop - * it just in case. - */ - timeout_del(&sc->sc_timeout); - scsi_xsh_del(&sc->sc_xsh); -} - /* * Check Errors */ diff --git a/sys/scsi/sdvar.h b/sys/scsi/sdvar.h index f723a7e9729..4e2accdfde1 100644 --- a/sys/scsi/sdvar.h +++ b/sys/scsi/sdvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: sdvar.h,v 1.38 2011/07/11 06:26:09 dlg Exp $ */ +/* $OpenBSD: sdvar.h,v 1.39 2012/10/08 21:47:51 deraadt Exp $ */ /* $NetBSD: sdvar.h,v 1.7 1998/08/17 00:49:03 mycroft Exp $ */ /*- @@ -69,7 +69,6 @@ struct sd_softc { u_int32_t unmap_sectors; /* maximum sectors/unmap */ u_int32_t unmap_descs; /* maximum descriptors/unmap */ } params; - void *sc_sdhook; /* our shutdown hook */ struct timeout sc_timeout; struct scsi_xshandler sc_xsh; diff --git a/sys/sys/device.h b/sys/sys/device.h index ac75c800081..8ef70a0191f 100644 --- a/sys/sys/device.h +++ b/sys/sys/device.h @@ -1,4 +1,4 @@ -/* $OpenBSD: device.h,v 1.44 2011/07/03 15:47:16 matthew Exp $ */ +/* $OpenBSD: device.h,v 1.45 2012/10/08 21:47:51 deraadt Exp $ */ /* $NetBSD: device.h,v 1.15 1996/04/09 20:55:24 cgd Exp $ */ /* @@ -66,6 +66,7 @@ enum devclass { #define DVACT_SUSPEND 2 /* suspend the device */ #define DVACT_RESUME 3 /* resume the device */ #define DVACT_QUIESCE 4 /* warn the device about suspend */ +#define DVACT_POWERDOWN 5 /* power device down */ struct device { enum devclass dv_class; /* this device's classification */ |