diff options
author | Scott Wood <scottwood@freescale.com> | 2007-12-12 12:35:19 -0500 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2007-12-21 06:13:35 -0500 |
commit | 7ac5dde99eb9fefdb526973c600075b7c5703a86 (patch) | |
tree | 3ea3277339990880697d2ce89197293b7a0a2277 /arch/powerpc/kernel/time.c | |
parent | cbea92383d0d55fb4b4eb5833488bfee325254d6 (diff) |
[POWERPC] Implement arch disable/enable irq hooks.
These hooks ensure that a decrementer interrupt is not pending when
suspending; otherwise, problems may occur on 6xx/7xx/7xxx-based
systems (except for powermacs, which use a separate suspend path).
For example, with deep sleep on the 831x, a pending decrementer will
cause a system freeze because the SoC thinks the decrementer interrupt
would have woken the system, but the core must have interrupts
disabled due to the setup required for deep sleep.
Changed via-pmu.c to use the new ppc_md hooks, and made the arch_*
functions call the generic_* functions unconditionally. -- paulus
Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/time.c')
-rw-r--r-- | arch/powerpc/kernel/time.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 85cf317c9069..5cd3db5cae41 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c | |||
@@ -629,6 +629,45 @@ void wakeup_decrementer(void) | |||
629 | set_dec(ticks); | 629 | set_dec(ticks); |
630 | } | 630 | } |
631 | 631 | ||
632 | #ifdef CONFIG_SUSPEND | ||
633 | void generic_suspend_disable_irqs(void) | ||
634 | { | ||
635 | preempt_disable(); | ||
636 | |||
637 | /* Disable the decrementer, so that it doesn't interfere | ||
638 | * with suspending. | ||
639 | */ | ||
640 | |||
641 | set_dec(0x7fffffff); | ||
642 | local_irq_disable(); | ||
643 | set_dec(0x7fffffff); | ||
644 | } | ||
645 | |||
646 | void generic_suspend_enable_irqs(void) | ||
647 | { | ||
648 | wakeup_decrementer(); | ||
649 | |||
650 | local_irq_enable(); | ||
651 | preempt_enable(); | ||
652 | } | ||
653 | |||
654 | /* Overrides the weak version in kernel/power/main.c */ | ||
655 | void arch_suspend_disable_irqs(void) | ||
656 | { | ||
657 | if (ppc_md.suspend_disable_irqs) | ||
658 | ppc_md.suspend_disable_irqs(); | ||
659 | generic_suspend_disable_irqs(); | ||
660 | } | ||
661 | |||
662 | /* Overrides the weak version in kernel/power/main.c */ | ||
663 | void arch_suspend_enable_irqs(void) | ||
664 | { | ||
665 | generic_suspend_enable_irqs(); | ||
666 | if (ppc_md.suspend_enable_irqs) | ||
667 | ppc_md.suspend_enable_irqs(); | ||
668 | } | ||
669 | #endif | ||
670 | |||
632 | #ifdef CONFIG_SMP | 671 | #ifdef CONFIG_SMP |
633 | void __init smp_space_timers(unsigned int max_cpus) | 672 | void __init smp_space_timers(unsigned int max_cpus) |
634 | { | 673 | { |