aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/ipic.c
diff options
context:
space:
mode:
authordayu@datangmobile.cn <dayu@datangmobile.cn>2009-02-18 00:47:42 -0500
committerKumar Gala <galak@kernel.crashing.org>2009-03-09 10:25:35 -0400
commit30c404699dd650f213d480d263c775915a0e1297 (patch)
tree915be54e8939a83259ab272f47d74b152ce35b0b /arch/powerpc/sysdev/ipic.c
parent1ab082d7cbd0f34e39a5396cc6340c00bc5d66ef (diff)
powerpc/83xx: Fix the interrupt loss problem on ipic
The interrupt pending register is write 1 clear. If there are more than one external interrupts pending at the same time, acking the first interrupt by reading pending register then OR the corresponding bit and write back to pending register will also clear other interrupt pending bits. That will cause loss of interrupt. Signed-off-by: Da Yu <dayu@datangmobile.cn> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
Diffstat (limited to 'arch/powerpc/sysdev/ipic.c')
-rw-r--r--arch/powerpc/sysdev/ipic.c6
1 files changed, 2 insertions, 4 deletions
diff --git a/arch/powerpc/sysdev/ipic.c b/arch/powerpc/sysdev/ipic.c
index 9a89cd3e80a2..a86d3ce01ead 100644
--- a/arch/powerpc/sysdev/ipic.c
+++ b/arch/powerpc/sysdev/ipic.c
@@ -568,8 +568,7 @@ static void ipic_ack_irq(unsigned int virq)
568 568
569 spin_lock_irqsave(&ipic_lock, flags); 569 spin_lock_irqsave(&ipic_lock, flags);
570 570
571 temp = ipic_read(ipic->regs, ipic_info[src].ack); 571 temp = 1 << (31 - ipic_info[src].bit);
572 temp |= (1 << (31 - ipic_info[src].bit));
573 ipic_write(ipic->regs, ipic_info[src].ack, temp); 572 ipic_write(ipic->regs, ipic_info[src].ack, temp);
574 573
575 /* mb() can't guarantee that ack is finished. But it does finish 574 /* mb() can't guarantee that ack is finished. But it does finish
@@ -592,8 +591,7 @@ static void ipic_mask_irq_and_ack(unsigned int virq)
592 temp &= ~(1 << (31 - ipic_info[src].bit)); 591 temp &= ~(1 << (31 - ipic_info[src].bit));
593 ipic_write(ipic->regs, ipic_info[src].mask, temp); 592 ipic_write(ipic->regs, ipic_info[src].mask, temp);
594 593
595 temp = ipic_read(ipic->regs, ipic_info[src].ack); 594 temp = 1 << (31 - ipic_info[src].bit);
596 temp |= (1 << (31 - ipic_info[src].bit));
597 ipic_write(ipic->regs, ipic_info[src].ack, temp); 595 ipic_write(ipic->regs, ipic_info[src].ack, temp);
598 596
599 /* mb() can't guarantee that ack is finished. But it does finish 597 /* mb() can't guarantee that ack is finished. But it does finish