summaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel/irq.c
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2010-04-15 06:13:52 +0200
committerPaul Mundt <lethal@linux-sh.org>2010-04-15 06:13:52 +0200
commitdc825b17904a06bbd2f79d720b23156e4c01a22f (patch)
tree8f1e13b850a06264530f1f1bb680a541e73cef34 /arch/sh/kernel/irq.c
parentsh: Disable IRQ balancing for timer and IPI IRQs. (diff)
downloadlinux-dc825b17904a06bbd2f79d720b23156e4c01a22f.tar.xz
linux-dc825b17904a06bbd2f79d720b23156e4c01a22f.zip
sh: intc: IRQ auto-distribution support.
This implements support for hardware-managed IRQ balancing as implemented by SH-X3 cores (presently only hooked up for SH7786, but can probably be carried over to other SH-X3 cores, too). CPUs need to specify their distribution register along with the mask definitions, as these follow the same format. Peripheral IRQs that don't opt out of balancing will be automatically distributed at the whim of the hardware block, while each CPU needs to verify whether it is handling the IRQ or not, especially before clearing the mask. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/kernel/irq.c')
-rw-r--r--arch/sh/kernel/irq.c49
1 files changed, 29 insertions, 20 deletions
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index d2d41d046657..f6a9319c28e2 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -113,19 +113,14 @@ union irq_ctx {
static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly;
static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly;
-#endif
-asmlinkage __irq_entry int do_IRQ(unsigned int irq, struct pt_regs *regs)
+static char softirq_stack[NR_CPUS * THREAD_SIZE] __page_aligned_bss;
+static char hardirq_stack[NR_CPUS * THREAD_SIZE] __page_aligned_bss;
+
+static inline void handle_one_irq(unsigned int irq)
{
- struct pt_regs *old_regs = set_irq_regs(regs);
-#ifdef CONFIG_IRQSTACKS
union irq_ctx *curctx, *irqctx;
-#endif
-
- irq_enter();
- irq = irq_demux(irq);
-#ifdef CONFIG_IRQSTACKS
curctx = (union irq_ctx *)current_thread_info();
irqctx = hardirq_ctx[smp_processor_id()];
@@ -164,20 +159,9 @@ asmlinkage __irq_entry int do_IRQ(unsigned int irq, struct pt_regs *regs)
"r5", "r6", "r7", "r8", "t", "pr"
);
} else
-#endif
generic_handle_irq(irq);
-
- irq_exit();
-
- set_irq_regs(old_regs);
- return 1;
}
-#ifdef CONFIG_IRQSTACKS
-static char softirq_stack[NR_CPUS * THREAD_SIZE] __page_aligned_bss;
-
-static char hardirq_stack[NR_CPUS * THREAD_SIZE] __page_aligned_bss;
-
/*
* allocate per-cpu stacks for hardirq and for softirq processing
*/
@@ -257,8 +241,33 @@ asmlinkage void do_softirq(void)
local_irq_restore(flags);
}
+#else
+static inline void handle_one_irq(unsigned int irq)
+{
+ generic_handle_irq(irq);
+}
#endif
+asmlinkage __irq_entry int do_IRQ(unsigned int irq, struct pt_regs *regs)
+{
+ struct pt_regs *old_regs = set_irq_regs(regs);
+
+ irq_enter();
+
+ irq = irq_demux(irq_lookup(irq));
+
+ if (irq != NO_IRQ_IGNORE) {
+ handle_one_irq(irq);
+ irq_finish(irq);
+ }
+
+ irq_exit();
+
+ set_irq_regs(old_regs);
+
+ return IRQ_HANDLED;
+}
+
void __init init_IRQ(void)
{
plat_irq_setup();