mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-26 19:00:25 +00:00
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>
This commit is contained in:
parent
90a67b5909
commit
a3701ca487
2 changed files with 26 additions and 15 deletions
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue