aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel/irq.c
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2006-10-11 23:03:04 -0400
committerPaul Mundt <lethal@linux-sh.org>2006-10-11 23:03:04 -0400
commitbaf4326e49801526e4516e4de7f37b5e51468c49 (patch)
tree44fc3dd7c68827613cf0bcfcf2f4edacc63b1ea1 /arch/sh/kernel/irq.c
parent8884c4cb8b621963b5eb4a9ae45070bd0cb7085f (diff)
sh: interrupt exception handling rework
Kill off interrupt_table for all of the CPU subtypes, we now default in to stepping in to do_IRQ() for _all_ IRQ exceptions and counting the spurious ones, rather than simply flipping on the ones we cared about. This and enabling the IRQ by default automatically has already uncovered a couple of bugs and IRQs that weren't being caught, as well as some that are being generated far too often (SCI Tx Data Empty, for example). The general rationale is to use a marker for interrupt exceptions, test for it in the handle_exception() path, and skip out to do_IRQ() if it's found. Everything else follows the same behaviour of finding the cached EXPEVT value in r2/r2_bank, we just rip out the INTEVT read from entry.S entirely (except for in the kGDB NMI case, which is another matter). Note that while this changes the do_IRQ() semantics regarding r4 handling, they were fundamentally broken anyways (relying entirely on r2_bank for the cached code). With this, we do the INTEVT read from do_IRQ() itself (in the CONFIG_CPU_HAS_INTEVT case), or fall back on r4 for the muxed IRQ number, which should also be closer to what SH-2 and SH-2A want anyways. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/kernel/irq.c')
-rw-r--r--arch/sh/kernel/irq.c23
1 files changed, 7 insertions, 16 deletions
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index 3b93682bf18..acf2602569c 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -11,6 +11,7 @@
11#include <linux/module.h> 11#include <linux/module.h>
12#include <linux/kernel_stat.h> 12#include <linux/kernel_stat.h>
13#include <linux/seq_file.h> 13#include <linux/seq_file.h>
14#include <linux/io.h>
14#include <asm/irq.h> 15#include <asm/irq.h>
15#include <asm/processor.h> 16#include <asm/processor.h>
16#include <asm/uaccess.h> 17#include <asm/uaccess.h>
@@ -26,6 +27,7 @@ atomic_t irq_err_count;
26 */ 27 */
27void ack_bad_irq(unsigned int irq) 28void ack_bad_irq(unsigned int irq)
28{ 29{
30 atomic_inc(&irq_err_count);
29 printk("unexpected IRQ trap at vector %02x\n", irq); 31 printk("unexpected IRQ trap at vector %02x\n", irq);
30} 32}
31 33
@@ -85,7 +87,7 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
85 struct pt_regs regs) 87 struct pt_regs regs)
86{ 88{
87 struct pt_regs *old_regs = set_irq_regs(&regs); 89 struct pt_regs *old_regs = set_irq_regs(&regs);
88 int irq = r4; 90 int irq;
89#ifdef CONFIG_4KSTACKS 91#ifdef CONFIG_4KSTACKS
90 union irq_ctx *curctx, *irqctx; 92 union irq_ctx *curctx, *irqctx;
91#endif 93#endif
@@ -109,20 +111,9 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
109#endif 111#endif
110 112
111#ifdef CONFIG_CPU_HAS_INTEVT 113#ifdef CONFIG_CPU_HAS_INTEVT
112 __asm__ __volatile__ ( 114 irq = (ctrl_inl(INTEVT) >> 5) - 16;
113#ifdef CONFIG_CPU_HAS_SR_RB
114 "stc r2_bank, %0\n\t"
115#else 115#else
116 "mov.l @%1, %0\n\t" 116 irq = r4;
117#endif
118 "shlr2 %0\n\t"
119 "shlr2 %0\n\t"
120 "shlr %0\n\t"
121 "add #-16, %0\n\t"
122 : "=z" (irq), "=r" (r4)
123 : "1" (INTEVT)
124 : "memory"
125 );
126#endif 117#endif
127 118
128 irq = irq_demux(irq); 119 irq = irq_demux(irq);
@@ -147,9 +138,9 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
147 __asm__ __volatile__ ( 138 __asm__ __volatile__ (
148 "mov %0, r4 \n" 139 "mov %0, r4 \n"
149 "mov r15, r9 \n" 140 "mov r15, r9 \n"
150 "jsr @%2 \n" 141 "jsr @%1 \n"
151 /* swith to the irq stack */ 142 /* swith to the irq stack */
152 " mov %3, r15 \n" 143 " mov %2, r15 \n"
153 /* restore the stack (ring zero) */ 144 /* restore the stack (ring zero) */
154 "mov r9, r15 \n" 145 "mov r9, r15 \n"
155 : /* no outputs */ 146 : /* no outputs */