diff options
Diffstat (limited to 'sys')
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 */ |