aboutsummaryrefslogtreecommitdiff
path: root/drivers/macintosh
diff options
context:
space:
mode:
authorScott Wood2007-12-13 04:35:19 +1100
committerPaul Mackerras2007-12-21 22:13:35 +1100
commit7ac5dde99eb9fefdb526973c600075b7c5703a86 (patch)
tree3ea3277339990880697d2ce89197293b7a0a2277 /drivers/macintosh
parentcbea92383d0d55fb4b4eb5833488bfee325254d6 (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 'drivers/macintosh')
-rw-r--r--drivers/macintosh/via-pmu.c48
1 files changed, 6 insertions, 42 deletions
diff --git a/drivers/macintosh/via-pmu.c b/drivers/macintosh/via-pmu.c
index 8f98257e6a15..7e77ac7e3705 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;