From: Benjamin Herrenschmidt The ppc32 PowerMac cpufreq code, when using the PMU to switch the frequency, would eventually lose interrupts. The solution is to raise the CPU priority at the controller level. It's also unnecessary to call the full PIC suspend/resume code in this case as the IO chip isn't reset, unlike the sleep code. Signed-off-by: Benjamin Herrenschmidt Signed-off-by: Andrew Morton --- 25-akpm/arch/ppc/platforms/pmac_cpufreq.c | 10 ++++------ 25-akpm/arch/ppc/syslib/open_pic.c | 7 +++++-- 25-akpm/include/asm-ppc/open_pic.h | 1 + 3 files changed, 10 insertions(+), 8 deletions(-) diff -puN arch/ppc/platforms/pmac_cpufreq.c~ppc32-fix-an-irq-issue-with-cpufreq arch/ppc/platforms/pmac_cpufreq.c --- 25/arch/ppc/platforms/pmac_cpufreq.c~ppc32-fix-an-irq-issue-with-cpufreq 2004-11-21 15:59:46.605515864 -0800 +++ 25-akpm/arch/ppc/platforms/pmac_cpufreq.c 2004-11-21 15:59:46.614514496 -0800 @@ -33,6 +33,8 @@ #include #include #include +#include +#include /* WARNING !!! This will cause calibrate_delay() to be called, * but this is an __init function ! So you MUST go edit @@ -51,10 +53,6 @@ extern void low_choose_7447a_dfs(int dfs); extern void low_choose_750fx_pll(int pll); extern void low_sleep_handler(void); -extern void openpic_suspend(struct sys_device *sysdev, u32 state); -extern void openpic_resume(struct sys_device *sysdev); -extern void enable_kernel_altivec(void); -extern void enable_kernel_fp(void); /* * Currently, PowerMac cpufreq supports only high & low frequencies @@ -208,7 +206,7 @@ static int __pmac pmu_set_cpu_speed(int printk(KERN_DEBUG "HID1, before: %x\n", mfspr(SPRN_HID1)); #endif /* Disable all interrupt sources on openpic */ - openpic_suspend(NULL, 1); + openpic_set_priority(0xf); /* Make sure the decrementer won't interrupt us */ asm volatile("mtdec %0" : : "r" (0x7fffffff)); @@ -275,7 +273,7 @@ static int __pmac pmu_set_cpu_speed(int wakeup_decrementer(); /* Restore interrupts */ - openpic_resume(NULL); + openpic_set_priority(0); /* Let interrupts flow again ... */ local_irq_enable(); diff -puN arch/ppc/syslib/open_pic.c~ppc32-fix-an-irq-issue-with-cpufreq arch/ppc/syslib/open_pic.c --- 25/arch/ppc/syslib/open_pic.c~ppc32-fix-an-irq-issue-with-cpufreq 2004-11-21 15:59:46.606515712 -0800 +++ 25-akpm/arch/ppc/syslib/open_pic.c 2004-11-21 15:59:46.613514648 -0800 @@ -53,7 +53,6 @@ static int (*openpic_cascade_fn)(struct /* Global Operations */ static void openpic_disable_8259_pass_through(void); -static void openpic_set_priority(u_int pri); static void openpic_set_spurious(u_int vector); #ifdef CONFIG_SMP @@ -477,7 +476,7 @@ static u_int openpic_get_priority(void) } #endif /* notused */ -static void __init openpic_set_priority(u_int pri) +void openpic_set_priority(u_int pri) { DECL_THIS_CPU; @@ -955,6 +954,8 @@ int openpic_suspend(struct sys_device *s return 0; } + openpic_set_priority(0xf); + open_pic.enable = openpic_cached_enable_irq; open_pic.disable = openpic_cached_disable_irq; @@ -1028,6 +1029,8 @@ int openpic_resume(struct sys_device *sy open_pic.enable = openpic_enable_irq; open_pic.disable = openpic_disable_irq; + openpic_set_priority(0); + spin_unlock_irqrestore(&openpic_setup_lock, flags); return 0; diff -puN include/asm-ppc/open_pic.h~ppc32-fix-an-irq-issue-with-cpufreq include/asm-ppc/open_pic.h --- 25/include/asm-ppc/open_pic.h~ppc32-fix-an-irq-issue-with-cpufreq 2004-11-21 15:59:46.608515408 -0800 +++ 25-akpm/include/asm-ppc/open_pic.h 2004-11-21 15:59:46.612514800 -0800 @@ -55,6 +55,7 @@ extern void openpic_cause_IPI(u_int ipi, extern void smp_openpic_message_pass(int target, int msg, unsigned long data, int wait); extern void openpic_set_k2_cascade(int irq); +extern void openpic_set_priority(u_int pri); extern inline int openpic_to_irq(int irq) { _