diff options
-rw-r--r-- | arch/powerpc/kernel/time.c | 39 | ||||
-rw-r--r-- | drivers/macintosh/via-pmu.c | 48 | ||||
-rw-r--r-- | include/asm-powerpc/machdep.h | 13 |
3 files changed, 58 insertions, 42 deletions
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c index 85cf317c906..5cd3db5cae4 100644 --- a/arch/powerpc/kernel/time.c +++ b/arch/powerpc/kernel/time.c @@ -629,6 +629,45 @@ void wakeup_decrementer(void) set_dec(ticks); } +#ifdef CONFIG_SUSPEND +void generic_suspend_disable_irqs(void) +{ + preempt_disable(); + + /* Disable the decrementer, so that it doesn't interfere + * with suspending. + */ + + set_dec(0x7fffffff); + local_irq_disable(); + set_dec(0x7fffffff); +} + +void generic_suspend_enable_irqs(void) +{ + wakeup_decrementer(); + + local_irq_enable(); + preempt_enable(); +} + +/* Overrides the weak version in kernel/power/main.c */ +void arch_suspend_disable_irqs(void) +{ + if (ppc_md.suspend_disable_irqs) + ppc_md.suspend_disable_irqs(); + generic_suspend_disable_irqs(); +} + +/* Overrides the weak version in kernel/power/main.c */ +void arch_suspend_enable_irqs(void) +{ + generic_suspend_enable_irqs(); + if (ppc_md.suspend_enable_irqs) + ppc_md.suspend_enable_irqs(); +} +#endif + #ifdef CONFIG_SMP void __init smp_space_timers(unsigned int max_cpus) { diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c index 8f98257e6a1..7e77ac7e370 100644 --- a/drivers/macintosh/via-pmu.c +++ b/drivers/macintosh/via-pmu.c @@ -197,12 +197,6 @@ static int proc_read_options(char *page, char **start, off_t off, static int proc_write_options(struct file *file, const char __user *buffer, unsigned long count, void *data); -#if defined(CONFIG_PM_SLEEP) && defined(CONFIG_PPC32) -static void powerbook_sleep_init_3400(void); -#else -#define powerbook_sleep_init_3400() do { } while (0) -#endif - #ifdef CONFIG_ADB struct adb_driver via_pmu_driver = { "PMU", @@ -450,10 +444,6 @@ static int __init via_pmu_start(void) pmu_poll(); } while (pmu_state != idle); - /* Do allocations and ioremaps that will be needed for sleep */ - if (pmu_kind == PMU_OHARE_BASED) - powerbook_sleep_init_3400(); - return 0; } @@ -2168,13 +2158,7 @@ pmu_release(struct inode *inode, struct file *file) } #if defined(CONFIG_SUSPEND) && defined(CONFIG_PPC32) -/* - * overrides the weak arch_suspend_disable_irqs in kernel/power/main.c - * - * XXX: Once Scott Wood's patch is merged, this needs to use the ppc_md - * hooks that patch adds! - */ -void arch_suspend_disable_irqs(void) +static void pmac_suspend_disable_irqs(void) { #ifdef CONFIG_PMAC_BACKLIGHT /* Tell backlight code not to muck around with the chip anymore */ @@ -2184,18 +2168,6 @@ void arch_suspend_disable_irqs(void) /* Call platform functions marked "on sleep" */ pmac_pfunc_i2c_suspend(); pmac_pfunc_base_suspend(); - - /* Stop preemption */ - preempt_disable(); - - /* Make sure the decrementer won't interrupt us */ - asm volatile("mtdec %0" : : "r" (0x7fffffff)); - /* Make sure any pending DEC interrupt occurring while we did - * the above didn't re-enable the DEC */ - mb(); - asm volatile("mtdec %0" : : "r" (0x7fffffff)); - - local_irq_disable(); } static int powerbook_sleep(suspend_state_t state) @@ -2244,25 +2216,13 @@ static int powerbook_sleep(suspend_state_t state) return 0; } -/* - * overrides the weak arch_suspend_enable_irqs in kernel/power/main.c - * - * XXX: Once Scott Wood's patch is merged, this needs to use the ppc_md - * hooks that patch adds! - */ -void arch_suspend_enable_irqs(void) +static void pmac_suspend_enable_irqs(void) { /* Force a poll of ADB interrupts */ adb_int_pending = 1; via_pmu_interrupt(0, NULL); - /* Restart jiffies & scheduling */ - wakeup_decrementer(); - - /* Re-enable local CPU interrupts */ - local_irq_enable(); mdelay(10); - preempt_enable(); /* Call platform functions marked "on wake" */ pmac_pfunc_base_resume(); @@ -2282,6 +2242,10 @@ static struct platform_suspend_ops pmu_pm_ops = { static int register_pmu_pm_ops(void) { + if (pmu_kind == PMU_OHARE_BASED) + powerbook_sleep_init_3400(); + ppc_md.suspend_disable_irqs = pmac_suspend_disable_irqs; + ppc_md.suspend_enable_irqs = pmac_suspend_enable_irqs; suspend_set_ops(&pmu_pm_ops); return 0; diff --git a/include/asm-powerpc/machdep.h b/include/asm-powerpc/machdep.h index 79c704ed538..0872ec228c1 100644 --- a/include/asm-powerpc/machdep.h +++ b/include/asm-powerpc/machdep.h @@ -251,6 +251,16 @@ struct machdep_calls { */ void (*machine_kexec)(struct kimage *image); #endif /* CONFIG_KEXEC */ + +#ifdef CONFIG_SUSPEND + /* These are called to disable and enable, respectively, IRQs when + * entering a suspend state. If NULL, then the generic versions + * will be called. The generic versions disable/enable the + * decrementer along with interrupts. + */ + void (*suspend_disable_irqs)(void); + void (*suspend_enable_irqs)(void); +#endif }; extern void power4_idle(void); @@ -347,5 +357,8 @@ static inline void log_error(char *buf, unsigned int err_type, int fatal) #define machine_late_initcall(mach,fn) __define_machine_initcall(mach,"7",fn,7) #define machine_late_initcall_sync(mach,fn) __define_machine_initcall(mach,"7s",fn,7s) +void generic_suspend_disable_irqs(void); +void generic_suspend_enable_irqs(void); + #endif /* __KERNEL__ */ #endif /* _ASM_POWERPC_MACHDEP_H */ |