aboutsummaryrefslogtreecommitdiff
path: root/arch/sh/kernel/irq.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@woody.osdl.org>2006-12-06 08:10:55 -0800
committerLinus Torvalds <torvalds@woody.osdl.org>2006-12-06 08:10:55 -0800
commitdd6a7c19e4630f635467246a81b8e0cc818c05e6 (patch)
tree8fc93cdef4070183cbd3fa06019c84728380b389 /arch/sh/kernel/irq.c
parentdd8856bda5f1308beb113281b248683992998a9e (diff)
parentea0f8feaa041f3ccec3d6b8ee51325b177daef06 (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6
* master.kernel.org:/pub/scm/linux/kernel/git/lethal/sh-2.6: (43 commits) sh: sh775x/titan fixes for irq header changes. sh: update r7780rp defconfig. sh: compile fixes for header cleanup. sh: Fixup pte_mkhuge() build failure. sh: set KBUILD_IMAGE to something sensible. sh: show held locks in stack trace with lockdep. sh: platform_pata support for R7780RP sh: stacktrace/lockdep/irqflags tracing support. sh: Fixup movli.l/movco.l atomic ops for gcc4. sh: dyntick infrastructure. sh: Clock framework tidying. sh: Turn off IRQs around get_timer_offset() calls. sh: Get the PGD right in oops case with 64-bit PTEs. sh: Fix store queue bitmap end. sh: More flexible + SH7780 earlyprintk SCIF support. sh: Fixup various PAGE_SIZE == 4096 assumptions. sh: Fixup 4K irq stacks. sh: dma-api channel capability extensions. sh: Drop name overload in dma-sh. sh: Make dma-isa depend on ISA_DMA_API. ...
Diffstat (limited to 'arch/sh/kernel/irq.c')
-rw-r--r--arch/sh/kernel/irq.c55
1 files changed, 44 insertions, 11 deletions
diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index 944128ce970..67be2b6e8cd 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -12,7 +12,7 @@
#include <linux/kernel_stat.h>
#include <linux/seq_file.h>
#include <linux/io.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
#include <asm/processor.h>
#include <asm/uaccess.h>
#include <asm/thread_info.h>
@@ -78,15 +78,16 @@ union irq_ctx {
u32 stack[THREAD_SIZE/sizeof(u32)];
};
-static union irq_ctx *hardirq_ctx[NR_CPUS];
-static union irq_ctx *softirq_ctx[NR_CPUS];
+static union irq_ctx *hardirq_ctx[NR_CPUS] __read_mostly;
+static union irq_ctx *softirq_ctx[NR_CPUS] __read_mostly;
#endif
asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
unsigned long r6, unsigned long r7,
- struct pt_regs regs)
+ struct pt_regs __regs)
{
- struct pt_regs *old_regs = set_irq_regs(&regs);
+ struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
+ struct pt_regs *old_regs = set_irq_regs(regs);
int irq;
#ifdef CONFIG_4KSTACKS
union irq_ctx *curctx, *irqctx;
@@ -111,7 +112,7 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
#endif
#ifdef CONFIG_CPU_HAS_INTEVT
- irq = (ctrl_inl(INTEVT) >> 5) - 16;
+ irq = evt2irq(ctrl_inl(INTEVT));
#else
irq = r4;
#endif
@@ -135,17 +136,24 @@ asmlinkage int do_IRQ(unsigned long r4, unsigned long r5,
irqctx->tinfo.task = curctx->tinfo.task;
irqctx->tinfo.previous_sp = current_stack_pointer;
+ /*
+ * Copy the softirq bits in preempt_count so that the
+ * softirq checks work in the hardirq context.
+ */
+ irqctx->tinfo.preempt_count =
+ (irqctx->tinfo.preempt_count & ~SOFTIRQ_MASK) |
+ (curctx->tinfo.preempt_count & SOFTIRQ_MASK);
+
__asm__ __volatile__ (
"mov %0, r4 \n"
- "mov r15, r9 \n"
+ "mov r15, r8 \n"
"jsr @%1 \n"
/* swith to the irq stack */
" mov %2, r15 \n"
/* restore the stack (ring zero) */
- "mov r9, r15 \n"
+ "mov r8, r15 \n"
: /* no outputs */
: "r" (irq), "r" (generic_handle_irq), "r" (isp)
- /* XXX: A somewhat excessive clobber list? -PFM */
: "memory", "r0", "r1", "r2", "r3", "r4",
"r5", "r6", "r7", "r8", "t", "pr"
);
@@ -193,7 +201,7 @@ void irq_ctx_init(int cpu)
irqctx->tinfo.task = NULL;
irqctx->tinfo.exec_domain = NULL;
irqctx->tinfo.cpu = cpu;
- irqctx->tinfo.preempt_count = SOFTIRQ_OFFSET;
+ irqctx->tinfo.preempt_count = 0;
irqctx->tinfo.addr_limit = MAKE_MM_SEG(0);
softirq_ctx[cpu] = irqctx;
@@ -239,13 +247,38 @@ asmlinkage void do_softirq(void)
"mov r9, r15 \n"
: /* no outputs */
: "r" (__do_softirq), "r" (isp)
- /* XXX: A somewhat excessive clobber list? -PFM */
: "memory", "r0", "r1", "r2", "r3", "r4",
"r5", "r6", "r7", "r8", "r9", "r15", "t", "pr"
);
+
+ /*
+ * Shouldnt happen, we returned above if in_interrupt():
+ */
+ WARN_ON_ONCE(softirq_count());
}
local_irq_restore(flags);
}
EXPORT_SYMBOL(do_softirq);
#endif
+
+void __init init_IRQ(void)
+{
+#ifdef CONFIG_CPU_HAS_PINT_IRQ
+ init_IRQ_pint();
+#endif
+
+#ifdef CONFIG_CPU_HAS_INTC2_IRQ
+ init_IRQ_intc2();
+#endif
+
+#ifdef CONFIG_CPU_HAS_IPR_IRQ
+ init_IRQ_ipr();
+#endif
+
+ /* Perform the machine specific initialisation */
+ if (sh_mv.mv_init_irq)
+ sh_mv.mv_init_irq();
+
+ irq_ctx_init(smp_processor_id());
+}