diff options
author | Pete Popov <ppopov@embeddedalley.com> | 2005-03-13 08:19:05 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2005-10-29 19:30:56 +0100 |
commit | a3701ca48763bbc681ee8db3d203827975849185 (patch) | |
tree | 9677ce80fb2dd3db49394665ddd1ca4f3bf8f2d5 /arch/mips/au1000 | |
parent | 90a67b5909ed39425fd2402b2b4c46ef1372b300 (diff) | |
download | op-kernel-dev-a3701ca48763bbc681ee8db3d203827975849185.zip op-kernel-dev-a3701ca48763bbc681ee8db3d203827975849185.tar.gz |
When CONFIG_PM is enabled, it uses the TOY_MATCH2 interrupt as the system
timer tick. Prior to this patch, if IDE IRQ probing occured, then the
TOY_MATCH2 interrupt would be permanently disabled, and no system timer
tick occurs. This patch corrects this situation by correctly registering
the TOY_MATCH2 interrupt so that IDE IRQ probing doesn't have adverse
side effects.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips/au1000')
-rw-r--r-- | arch/mips/au1000/common/irq.c | 36 | ||||
-rw-r--r-- | arch/mips/au1000/common/time.c | 5 |
2 files changed, 26 insertions, 15 deletions
diff --git a/arch/mips/au1000/common/irq.c b/arch/mips/au1000/common/irq.c index ebf93bd..6a25677 100644 --- a/arch/mips/au1000/common/irq.c +++ b/arch/mips/au1000/common/irq.c @@ -293,8 +293,30 @@ static struct hw_interrupt_type level_irq_type = { }; #ifdef CONFIG_PM -void startup_match20_interrupt(void) +void startup_match20_interrupt(void (*handler)(int, void *, struct pt_regs *)) { + static struct irqaction action; + /* This is a big problem.... since we didn't use request_irq + when kernel/irq.c calls probe_irq_xxx this interrupt will + be probed for usage. This will end up disabling the device :( + + Give it a bogus "action" pointer -- this will keep it from + getting auto-probed! + + By setting the status to match that of request_irq() we + can avoid it. --cgray + */ + action.dev_id = handler; + action.flags = 0; + action.mask = 0; + action.name = "Au1xxx TOY"; + action.handler = handler; + action.next = NULL; + + irq_desc[AU1000_TOY_MATCH2_INT].action = &action; + irq_desc[AU1000_TOY_MATCH2_INT].status + &= ~(IRQ_DISABLED | IRQ_AUTODETECT | IRQ_WAITING | IRQ_INPROGRESS); + local_enable_irq(AU1000_TOY_MATCH2_INT); } #endif @@ -517,17 +539,7 @@ void intc0_req1_irqdispatch(struct pt_regs *regs) irq = au_ffs(intc0_req1) - 1; intc0_req1 &= ~(1<<irq); -#ifdef CONFIG_PM - if (irq == AU1000_TOY_MATCH2_INT) { - mask_and_ack_rise_edge_irq(irq); - counter0_irq(irq, NULL, regs); - local_enable_irq(irq); - } - else -#endif - { - do_IRQ(irq, regs); - } + do_IRQ(irq, regs); } diff --git a/arch/mips/au1000/common/time.c b/arch/mips/au1000/common/time.c index 57675b4..90a0755 100644 --- a/arch/mips/au1000/common/time.c +++ b/arch/mips/au1000/common/time.c @@ -50,7 +50,6 @@ #include <linux/mc146818rtc.h> #include <linux/timex.h> -extern void startup_match20_interrupt(void); extern void do_softirq(void); extern volatile unsigned long wall_jiffies; unsigned long missed_heart_beats = 0; @@ -65,7 +64,7 @@ static unsigned int timerhi = 0, timerlo = 0; #ifdef CONFIG_PM #define MATCH20_INC 328 -extern void startup_match20_interrupt(void); +extern void startup_match20_interrupt(void (*handler)(int, void *, struct pt_regs *)); static unsigned long last_pc0, last_match20; #endif @@ -446,7 +445,7 @@ void au1xxx_timer_setup(struct irqaction *irq) au_writel(last_match20 + MATCH20_INC, SYS_TOYMATCH2); au_sync(); while (au_readl(SYS_COUNTER_CNTRL) & SYS_CNTRL_M20); - startup_match20_interrupt(); + startup_match20_interrupt(counter0_irq); do_gettimeoffset = do_fast_pm_gettimeoffset; |