From d0e05bb3d611c7c3d37cadd8c1016ee2e22beefa Mon Sep 17 00:00:00 2001
From: Paul Mundt <lethal@linux-sh.org>
Date: Fri, 18 May 2012 10:20:33 +0900
Subject: sh: mach-se: Migrate 7724SE off of deprecated dynamic IRQ API.

The generic hardirq layer provides all of the routines that we need these
days, so we don't require any of the dynamic IRQ API wrapping, and can
call in to irq_alloc_descs() directly.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
---
 arch/sh/boards/mach-se/7724/irq.c | 36 +++++++++++++-----------------------
 1 file changed, 13 insertions(+), 23 deletions(-)

(limited to 'arch/sh')

diff --git a/arch/sh/boards/mach-se/7724/irq.c b/arch/sh/boards/mach-se/7724/irq.c
index c6342ce7768..5d1d3ec9a6c 100644
--- a/arch/sh/boards/mach-se/7724/irq.c
+++ b/arch/sh/boards/mach-se/7724/irq.c
@@ -17,8 +17,10 @@
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
-#include <asm/irq.h>
-#include <asm/io.h>
+#include <linux/export.h>
+#include <linux/topology.h>
+#include <linux/io.h>
+#include <linux/err.h>
 #include <mach-se/mach/se7724.h>
 
 struct fpga_irq {
@@ -111,7 +113,7 @@ static void se7724_irq_demux(unsigned int irq, struct irq_desc *desc)
  */
 void __init init_se7724_IRQ(void)
 {
-	int i, nid = cpu_to_node(boot_cpu_data);
+	int irq_base, i;
 
 	__raw_writew(0xffff, IRQ0_MR);  /* mask all */
 	__raw_writew(0xffff, IRQ1_MR);  /* mask all */
@@ -121,28 +123,16 @@ void __init init_se7724_IRQ(void)
 	__raw_writew(0x0000, IRQ2_SR);  /* clear irq */
 	__raw_writew(0x002a, IRQ_MODE); /* set irq type */
 
-	for (i = 0; i < SE7724_FPGA_IRQ_NR; i++) {
-		int irq, wanted;
-
-		wanted = SE7724_FPGA_IRQ_BASE + i;
-
-		irq = create_irq_nr(wanted, nid);
-		if (unlikely(irq == 0)) {
-			pr_err("%s: failed hooking irq %d for FPGA\n",
-			       __func__, wanted);
-			return;
-		}
-
-		if (unlikely(irq != wanted)) {
-			pr_err("%s: got irq %d but wanted %d, bailing.\n",
-			       __func__, irq, wanted);
-			destroy_irq(irq);
-			return;
-		}
+	irq_base = irq_alloc_descs(SE7724_FPGA_IRQ_BASE, SE7724_FPGA_IRQ_BASE,
+				   SE7724_FPGA_IRQ_NR, numa_node_id());
+	if (IS_ERR_VALUE(irq_base)) {
+		pr_err("%s: failed hooking irqs for FPGA\n", __func__);
+		return;
+	}
 
-		irq_set_chip_and_handler_name(irq, &se7724_irq_chip,
+	for (i = 0; i < SE7724_FPGA_IRQ_NR; i++)
+		irq_set_chip_and_handler_name(irq_base + i, &se7724_irq_chip,
 					      handle_level_irq, "level");
-	}
 
 	irq_set_chained_handler(IRQ0_IRQ, se7724_irq_demux);
 	irq_set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW);
-- 
cgit v1.2.3-18-g5258


From 051f923d922d105f4d32e64cba1ed6f5a749d530 Mon Sep 17 00:00:00 2001
From: Paul Mundt <lethal@linux-sh.org>
Date: Fri, 18 May 2012 23:20:09 +0900
Subject: sh: hd64461: Migrate off of deprecated dynamic IRQ API.

Switches from create_irq_nr() to irq_alloc_descs().

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
---
 arch/sh/cchips/hd6446x/hd64461.c | 33 +++++++++------------------------
 1 file changed, 9 insertions(+), 24 deletions(-)

(limited to 'arch/sh')

diff --git a/arch/sh/cchips/hd6446x/hd64461.c b/arch/sh/cchips/hd6446x/hd64461.c
index eb4ea4d44d5..e9735616bdc 100644
--- a/arch/sh/cchips/hd6446x/hd64461.c
+++ b/arch/sh/cchips/hd6446x/hd64461.c
@@ -73,10 +73,7 @@ static void hd64461_irq_demux(unsigned int irq, struct irq_desc *desc)
 
 int __init setup_hd64461(void)
 {
-	int i, nid = cpu_to_node(boot_cpu_data);
-
-	if (!MACH_HD64461)
-		return 0;
+	int irq_base, i;
 
 	printk(KERN_INFO
 	       "HD64461 configured at 0x%x on irq %d(mapped into %d to %d)\n",
@@ -89,28 +86,16 @@ int __init setup_hd64461(void)
 #endif
 	__raw_writew(0xffff, HD64461_NIMR);
 
-	/*  IRQ 80 -> 95 belongs to HD64461  */
-	for (i = HD64461_IRQBASE; i < HD64461_IRQBASE + 16; i++) {
-		unsigned int irq;
-
-		irq = create_irq_nr(i, nid);
-		if (unlikely(irq == 0)) {
-			pr_err("%s: failed hooking irq %d for HD64461\n",
-			       __func__, i);
-			return -EBUSY;
-		}
-
-		if (unlikely(irq != i)) {
-			pr_err("%s: got irq %d but wanted %d, bailing.\n",
-			       __func__, irq, i);
-			destroy_irq(irq);
-			return -EINVAL;
-		}
-
-		irq_set_chip_and_handler(i, &hd64461_irq_chip,
-					 handle_level_irq);
+	irq_base = irq_alloc_descs(HD64461_IRQBASE, HD64461_IRQBASE, 16, -1);
+	if (IS_ERR_VALUE(irq_base)) {
+		pr_err("%s: failed hooking irqs for HD64461\n", __func__);
+		return irq_base;
 	}
 
+	for (i = 0; i < 16; i++)
+		irq_set_chip_and_handler(irq_base + i, &hd64461_irq_chip,
+					 handle_level_irq);
+
 	irq_set_chained_handler(CONFIG_HD64461_IRQ, hd64461_irq_demux);
 	irq_set_irq_type(CONFIG_HD64461_IRQ, IRQ_TYPE_LEVEL_LOW);
 
-- 
cgit v1.2.3-18-g5258


From 3b1267b90f6b7c080024101696c0454f455761f4 Mon Sep 17 00:00:00 2001
From: Paul Mundt <lethal@linux-sh.org>
Date: Fri, 18 May 2012 23:36:44 +0900
Subject: sh: dreamcast: Migrate off of deprecated dynamic IRQ API.

Switches from create_irq_nr() to irq_alloc_descs().

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
---
 arch/sh/boards/mach-dreamcast/irq.c | 32 +++++++++++---------------------
 1 file changed, 11 insertions(+), 21 deletions(-)

(limited to 'arch/sh')

diff --git a/arch/sh/boards/mach-dreamcast/irq.c b/arch/sh/boards/mach-dreamcast/irq.c
index f63d323f411..2789647abeb 100644
--- a/arch/sh/boards/mach-dreamcast/irq.c
+++ b/arch/sh/boards/mach-dreamcast/irq.c
@@ -8,10 +8,11 @@
  * This file is part of the LinuxDC project (www.linuxdc.org)
  * Released under the terms of the GNU GPL v2.0
  */
-
 #include <linux/irq.h>
 #include <linux/io.h>
-#include <asm/irq.h>
+#include <linux/irq.h>
+#include <linux/export.h>
+#include <linux/err.h>
 #include <mach/sysasic.h>
 
 /*
@@ -141,26 +142,15 @@ int systemasic_irq_demux(int irq)
 
 void systemasic_irq_init(void)
 {
-	int i, nid = cpu_to_node(boot_cpu_data);
-
-	/* Assign all virtual IRQs to the System ASIC int. handler */
-	for (i = HW_EVENT_IRQ_BASE; i < HW_EVENT_IRQ_MAX; i++) {
-		unsigned int irq;
-
-		irq = create_irq_nr(i, nid);
-		if (unlikely(irq == 0)) {
-			pr_err("%s: failed hooking irq %d for systemasic\n",
-			       __func__, i);
-			return;
-		}
+	int irq_base, i;
 
-		if (unlikely(irq != i)) {
-			pr_err("%s: got irq %d but wanted %d, bailing.\n",
-			       __func__, irq, i);
-			destroy_irq(irq);
-			return;
-		}
+	irq_base = irq_alloc_descs(HW_EVENT_IRQ_BASE, HW_EVENT_IRQ_BASE,
+				   HW_EVENT_IRQ_MAX - HW_EVENT_IRQ_BASE, -1);
+	if (IS_ERR_VALUE(irq_base)) {
+		pr_err("%s: failed hooking irqs\n", __func__);
+		return;
+	}
 
+	for (i = HW_EVENT_IRQ_BASE; i < HW_EVENT_IRQ_MAX; i++)
 		irq_set_chip_and_handler(i, &systemasic_int, handle_level_irq);
-	}
 }
-- 
cgit v1.2.3-18-g5258


From 76b386624576eb00a7c7cad0e713952121708598 Mon Sep 17 00:00:00 2001
From: Paul Mundt <lethal@linux-sh.org>
Date: Thu, 24 May 2012 13:59:35 +0900
Subject: sh: Kill off now unused arch_probe_nr_irqs().

Now that legacy pre-allocation is done away with, we can just use the
generic stub in kernel/softirq.c.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
---
 arch/sh/kernel/irq.c | 10 ----------
 1 file changed, 10 deletions(-)

(limited to 'arch/sh')

diff --git a/arch/sh/kernel/irq.c b/arch/sh/kernel/irq.c
index dadce735f74..063af10ff3c 100644
--- a/arch/sh/kernel/irq.c
+++ b/arch/sh/kernel/irq.c
@@ -231,16 +231,6 @@ void __init init_IRQ(void)
 	irq_ctx_init(smp_processor_id());
 }
 
-#ifdef CONFIG_SPARSE_IRQ
-int __init arch_probe_nr_irqs(void)
-{
-	/*
-	 * No pre-allocated IRQs.
-	 */
-	return 0;
-}
-#endif
-
 #ifdef CONFIG_HOTPLUG_CPU
 static void route_irq(struct irq_data *data, unsigned int irq, unsigned int cpu)
 {
-- 
cgit v1.2.3-18-g5258


From 49453264997f232008efae457553d82381f9614f Mon Sep 17 00:00:00 2001
From: Paul Mundt <lethal@linux-sh.org>
Date: Thu, 24 May 2012 15:03:46 +0900
Subject: sh64: Convert to unwinder API.

This switches over to use the sh unwinder API which brings it all in line
with the general sh routines (which we shuffle around at the same time),
and lets us kill off more sh64-specific cruft.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
---
 arch/sh/include/asm/kdebug.h    |  2 ++
 arch/sh/kernel/cpu/sh5/unwind.c | 63 +++++++++++++++++++++++++++--------------
 arch/sh/kernel/dumpstack.c      | 58 +++++++++++++++++++++++++++++++++++++
 arch/sh/kernel/traps_32.c       | 50 --------------------------------
 arch/sh/kernel/traps_64.c       | 26 -----------------
 5 files changed, 101 insertions(+), 98 deletions(-)

(limited to 'arch/sh')

diff --git a/arch/sh/include/asm/kdebug.h b/arch/sh/include/asm/kdebug.h
index a6201f10c27..8d6a831e7ba 100644
--- a/arch/sh/include/asm/kdebug.h
+++ b/arch/sh/include/asm/kdebug.h
@@ -10,6 +10,8 @@ enum die_val {
 	DIE_SSTEP,
 };
 
+/* arch/sh/kernel/dumpstack.c */
 extern void printk_address(unsigned long address, int reliable);
+extern void dump_mem(const char *str, unsigned long bottom, unsigned long top);
 
 #endif /* __ASM_SH_KDEBUG_H */
diff --git a/arch/sh/kernel/cpu/sh5/unwind.c b/arch/sh/kernel/cpu/sh5/unwind.c
index b205b25eaf4..10aed41757f 100644
--- a/arch/sh/kernel/cpu/sh5/unwind.c
+++ b/arch/sh/kernel/cpu/sh5/unwind.c
@@ -16,6 +16,8 @@
 #include <asm/ptrace.h>
 #include <asm/processor.h>
 #include <asm/io.h>
+#include <asm/unwinder.h>
+#include <asm/stacktrace.h>
 
 static u8 regcache[63];
 
@@ -199,8 +201,11 @@ static int lookup_prev_stack_frame(unsigned long fp, unsigned long pc,
 	return 0;
 }
 
-/* Don't put this on the stack since we'll want to call sh64_unwind
- * when we're close to underflowing the stack anyway. */
+/*
+ * Don't put this on the stack since we'll want to call in to
+ * sh64_unwinder_dump() when we're close to underflowing the stack
+ * anyway.
+ */
 static struct pt_regs here_regs;
 
 extern const char syscall_ret;
@@ -208,17 +213,19 @@ extern const char ret_from_syscall;
 extern const char ret_from_exception;
 extern const char ret_from_irq;
 
-static void sh64_unwind_inner(struct pt_regs *regs);
+static void sh64_unwind_inner(const struct stacktrace_ops *ops,
+			      void *data, struct pt_regs *regs);
 
-static void unwind_nested (unsigned long pc, unsigned long fp)
+static inline void unwind_nested(const struct stacktrace_ops *ops, void *data,
+				 unsigned long pc, unsigned long fp)
 {
 	if ((fp >= __MEMORY_START) &&
-	    ((fp & 7) == 0)) {
-		sh64_unwind_inner((struct pt_regs *) fp);
-	}
+	    ((fp & 7) == 0))
+		sh64_unwind_inner(ops, data, (struct pt_regs *)fp);
 }
 
-static void sh64_unwind_inner(struct pt_regs *regs)
+static void sh64_unwind_inner(const struct stacktrace_ops *ops,
+			      void *data, struct pt_regs *regs)
 {
 	unsigned long pc, fp;
 	int ofs = 0;
@@ -232,29 +239,29 @@ static void sh64_unwind_inner(struct pt_regs *regs)
 		int cond;
 		unsigned long next_fp, next_pc;
 
-		if (pc == ((unsigned long) &syscall_ret & ~1)) {
+		if (pc == ((unsigned long)&syscall_ret & ~1)) {
 			printk("SYSCALL\n");
-			unwind_nested(pc,fp);
+			unwind_nested(ops, data, pc, fp);
 			return;
 		}
 
-		if (pc == ((unsigned long) &ret_from_syscall & ~1)) {
+		if (pc == ((unsigned long)&ret_from_syscall & ~1)) {
 			printk("SYSCALL (PREEMPTED)\n");
-			unwind_nested(pc,fp);
+			unwind_nested(ops, data, pc, fp);
 			return;
 		}
 
 		/* In this case, the PC is discovered by lookup_prev_stack_frame but
 		   it has 4 taken off it to look like the 'caller' */
-		if (pc == ((unsigned long) &ret_from_exception & ~1)) {
+		if (pc == ((unsigned long)&ret_from_exception & ~1)) {
 			printk("EXCEPTION\n");
-			unwind_nested(pc,fp);
+			unwind_nested(ops, data, pc, fp);
 			return;
 		}
 
-		if (pc == ((unsigned long) &ret_from_irq & ~1)) {
+		if (pc == ((unsigned long)&ret_from_irq & ~1)) {
 			printk("IRQ\n");
-			unwind_nested(pc,fp);
+			unwind_nested(ops, data, pc, fp);
 			return;
 		}
 
@@ -263,8 +270,7 @@ static void sh64_unwind_inner(struct pt_regs *regs)
 
 		pc -= ofs;
 
-		printk("[<%08lx>] ", pc);
-		print_symbol("%s\n", pc);
+		ops->address(data, pc, 1);
 
 		if (first_pass) {
 			/* If the innermost frame is a leaf function, it's
@@ -287,10 +293,13 @@ static void sh64_unwind_inner(struct pt_regs *regs)
 	}
 
 	printk("\n");
-
 }
 
-void sh64_unwind(struct pt_regs *regs)
+static void sh64_unwinder_dump(struct task_struct *task,
+			       struct pt_regs *regs,
+			       unsigned long *sp,
+			       const struct stacktrace_ops *ops,
+			       void *data)
 {
 	if (!regs) {
 		/*
@@ -320,7 +329,17 @@ void sh64_unwind(struct pt_regs *regs)
 		);
 	}
 
-	printk("\nCall Trace:\n");
-	sh64_unwind_inner(regs);
+	sh64_unwind_inner(ops, data, regs);
 }
 
+static struct unwinder sh64_unwinder = {
+	.name	= "sh64-unwinder",
+	.dump	= sh64_unwinder_dump,
+	.rating	= 150,
+};
+
+static int __init sh64_unwinder_init(void)
+{
+	return unwinder_register(&sh64_unwinder);
+}
+early_initcall(sh64_unwinder_init);
diff --git a/arch/sh/kernel/dumpstack.c b/arch/sh/kernel/dumpstack.c
index 694158b9a50..7617dc4129a 100644
--- a/arch/sh/kernel/dumpstack.c
+++ b/arch/sh/kernel/dumpstack.c
@@ -2,13 +2,48 @@
  *  Copyright (C) 1991, 1992  Linus Torvalds
  *  Copyright (C) 2000, 2001, 2002 Andi Kleen, SuSE Labs
  *  Copyright (C) 2009  Matt Fleming
+ *  Copyright (C) 2002 - 2012  Paul Mundt
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
  */
 #include <linux/kallsyms.h>
 #include <linux/ftrace.h>
 #include <linux/debug_locks.h>
+#include <linux/kdebug.h>
+#include <linux/export.h>
+#include <linux/uaccess.h>
 #include <asm/unwinder.h>
 #include <asm/stacktrace.h>
 
+void dump_mem(const char *str, unsigned long bottom, unsigned long top)
+{
+	unsigned long p;
+	int i;
+
+	printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top);
+
+	for (p = bottom & ~31; p < top; ) {
+		printk("%04lx: ", p & 0xffff);
+
+		for (i = 0; i < 8; i++, p += 4) {
+			unsigned int val;
+
+			if (p < bottom || p >= top)
+				printk("         ");
+			else {
+				if (__get_user(val, (unsigned int __user *)p)) {
+					printk("\n");
+					return;
+				}
+				printk("%08x ", val);
+			}
+		}
+		printk("\n");
+	}
+}
+
 void printk_address(unsigned long address, int reliable)
 {
 	printk(" [<%p>] %s%pS\n", (void *) address,
@@ -106,3 +141,26 @@ void show_trace(struct task_struct *tsk, unsigned long *sp,
 
 	debug_show_held_locks(tsk);
 }
+
+void show_stack(struct task_struct *tsk, unsigned long *sp)
+{
+	unsigned long stack;
+
+	if (!tsk)
+		tsk = current;
+	if (tsk == current)
+		sp = (unsigned long *)current_stack_pointer;
+	else
+		sp = (unsigned long *)tsk->thread.sp;
+
+	stack = (unsigned long)sp;
+	dump_mem("Stack: ", stack, THREAD_SIZE +
+		 (unsigned long)task_stack_page(tsk));
+	show_trace(tsk, sp, NULL);
+}
+
+void dump_stack(void)
+{
+	show_stack(NULL, NULL);
+}
+EXPORT_SYMBOL(dump_stack);
diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c
index a37175deb73..b8f5a51841e 100644
--- a/arch/sh/kernel/traps_32.c
+++ b/arch/sh/kernel/traps_32.c
@@ -48,33 +48,6 @@
 #define TRAP_ILLEGAL_SLOT_INST	13
 #endif
 
-static void dump_mem(const char *str, unsigned long bottom, unsigned long top)
-{
-	unsigned long p;
-	int i;
-
-	printk("%s(0x%08lx to 0x%08lx)\n", str, bottom, top);
-
-	for (p = bottom & ~31; p < top; ) {
-		printk("%04lx: ", p & 0xffff);
-
-		for (i = 0; i < 8; i++, p += 4) {
-			unsigned int val;
-
-			if (p < bottom || p >= top)
-				printk("         ");
-			else {
-				if (__get_user(val, (unsigned int __user *)p)) {
-					printk("\n");
-					return;
-				}
-				printk("%08x ", val);
-			}
-		}
-		printk("\n");
-	}
-}
-
 static DEFINE_SPINLOCK(die_lock);
 
 void die(const char * str, struct pt_regs * regs, long err)
@@ -900,26 +873,3 @@ void __init trap_init(void)
 	set_exception_table_vec(TRAP_UBC, breakpoint_trap_handler);
 #endif
 }
-
-void show_stack(struct task_struct *tsk, unsigned long *sp)
-{
-	unsigned long stack;
-
-	if (!tsk)
-		tsk = current;
-	if (tsk == current)
-		sp = (unsigned long *)current_stack_pointer;
-	else
-		sp = (unsigned long *)tsk->thread.sp;
-
-	stack = (unsigned long)sp;
-	dump_mem("Stack: ", stack, THREAD_SIZE +
-		 (unsigned long)task_stack_page(tsk));
-	show_trace(tsk, sp, NULL);
-}
-
-void dump_stack(void)
-{
-	show_stack(NULL, NULL);
-}
-EXPORT_SYMBOL(dump_stack);
diff --git a/arch/sh/kernel/traps_64.c b/arch/sh/kernel/traps_64.c
index 8dae93ed8af..ba95d63e623 100644
--- a/arch/sh/kernel/traps_64.c
+++ b/arch/sh/kernel/traps_64.c
@@ -253,32 +253,6 @@ int do_unknown_trapa(unsigned long scId, struct pt_regs *regs)
 	return -ENOSYS;
 }
 
-void show_stack(struct task_struct *tsk, unsigned long *sp)
-{
-#ifdef CONFIG_KALLSYMS
-	extern void sh64_unwind(struct pt_regs *regs);
-	struct pt_regs *regs;
-
-	regs = tsk ? tsk->thread.kregs : NULL;
-
-	sh64_unwind(regs);
-#else
-	printk(KERN_ERR "Can't backtrace on sh64 without CONFIG_KALLSYMS\n");
-#endif
-}
-
-void show_task(unsigned long *sp)
-{
-	show_stack(NULL, sp);
-}
-
-void dump_stack(void)
-{
-	show_task(NULL);
-}
-/* Needed by any user of WARN_ON in view of the defn in include/asm-sh/bug.h */
-EXPORT_SYMBOL(dump_stack);
-
 static void do_unhandled_exception(int trapnr, int signr, char *str, char *fn_name,
 		unsigned long error_code, struct pt_regs *regs, struct task_struct *tsk)
 {
-- 
cgit v1.2.3-18-g5258


From 3a898c0f36f9fe312cb6e98865a6833110e67cb2 Mon Sep 17 00:00:00 2001
From: Paul Mundt <lethal@linux-sh.org>
Date: Thu, 24 May 2012 15:05:29 +0900
Subject: sh64: Ensure KALLSYMS is enabled for unwinder use.

Since sh64 depends on kallsyms unconditionally for its stack unwinding to
be of any use, make sure it's selected. In practice we don't have any
case where it's disabled anyways, so moving to this to a select is fine.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
---
 arch/sh/Kconfig | 1 +
 1 file changed, 1 insertion(+)

(limited to 'arch/sh')

diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index 3e723aaa5e1..931310b49bc 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -55,6 +55,7 @@ config SUPERH32
 
 config SUPERH64
 	def_bool ARCH = "sh64"
+	select KALLSYMS
 
 config ARCH_DEFCONFIG
 	string
-- 
cgit v1.2.3-18-g5258


From b98b35815f40f01337e25e3f0d10d57b7cec5126 Mon Sep 17 00:00:00 2001
From: Paul Mundt <lethal@linux-sh.org>
Date: Thu, 24 May 2012 15:24:39 +0900
Subject: sh: mach-x3proto: Migrate to linear irq domain.

In the interest of getting off of the create_irq() API we can get all of
the functionality we're interested in through a linear IRQ domain. Fairly
straightforward conversion utilizing a single linear domain.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
---
 arch/sh/boards/Kconfig             |  1 +
 arch/sh/boards/mach-x3proto/gpio.c | 57 +++++++++++++++++++++-----------------
 2 files changed, 32 insertions(+), 26 deletions(-)

(limited to 'arch/sh')

diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig
index d893411022d..f2024a91319 100644
--- a/arch/sh/boards/Kconfig
+++ b/arch/sh/boards/Kconfig
@@ -292,6 +292,7 @@ config SH_X3PROTO
 	bool "SH-X3 Prototype board"
 	depends on CPU_SUBTYPE_SHX3
 	select NO_IOPORT if !PCI
+	select IRQ_DOMAIN
 
 config SH_MAGIC_PANEL_R2
 	bool "Magic Panel R2"
diff --git a/arch/sh/boards/mach-x3proto/gpio.c b/arch/sh/boards/mach-x3proto/gpio.c
index f33b2b57019..3ea65e9b56e 100644
--- a/arch/sh/boards/mach-x3proto/gpio.c
+++ b/arch/sh/boards/mach-x3proto/gpio.c
@@ -3,7 +3,7 @@
  *
  * Renesas SH-X3 Prototype Baseboard GPIO Support.
  *
- * Copyright (C) 2010  Paul Mundt
+ * Copyright (C) 2010 - 2012  Paul Mundt
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
@@ -17,6 +17,7 @@
 #include <linux/irq.h>
 #include <linux/kernel.h>
 #include <linux/spinlock.h>
+#include <linux/irqdomain.h>
 #include <linux/io.h>
 #include <mach/ilsel.h>
 #include <mach/hardware.h>
@@ -26,7 +27,7 @@
 #define KEYDETR 0xb81c0004
 
 static DEFINE_SPINLOCK(x3proto_gpio_lock);
-static unsigned int x3proto_gpio_irq_map[NR_BASEBOARD_GPIOS] = { 0, };
+static struct irq_domain *x3proto_irq_domain;
 
 static int x3proto_gpio_direction_input(struct gpio_chip *chip, unsigned gpio)
 {
@@ -49,7 +50,14 @@ static int x3proto_gpio_get(struct gpio_chip *chip, unsigned gpio)
 
 static int x3proto_gpio_to_irq(struct gpio_chip *chip, unsigned gpio)
 {
-	return x3proto_gpio_irq_map[gpio];
+	int virq;
+
+	if (gpio < chip->ngpio)
+		virq = irq_create_mapping(x3proto_irq_domain, gpio);
+	else
+		virq = -ENXIO;
+
+	return virq;
 }
 
 static void x3proto_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
@@ -62,9 +70,8 @@ static void x3proto_gpio_irq_handler(unsigned int irq, struct irq_desc *desc)
 	chip->irq_mask_ack(data);
 
 	mask = __raw_readw(KEYDETR);
-
 	for_each_set_bit(pin, &mask, NR_BASEBOARD_GPIOS)
-		generic_handle_irq(x3proto_gpio_to_irq(NULL, pin));
+		generic_handle_irq(irq_linear_revmap(x3proto_irq_domain, pin));
 
 	chip->irq_unmask(data);
 }
@@ -78,10 +85,23 @@ struct gpio_chip x3proto_gpio_chip = {
 	.ngpio			= NR_BASEBOARD_GPIOS,
 };
 
+static int x3proto_gpio_irq_map(struct irq_domain *domain, unsigned int virq,
+				irq_hw_number_t hwirq)
+{
+	irq_set_chip_and_handler_name(virq, &dummy_irq_chip, handle_simple_irq,
+				      "gpio");
+
+	return 0;
+}
+
+static struct irq_domain_ops x3proto_gpio_irq_ops = {
+	.map	= x3proto_gpio_irq_map,
+	.xlate	= irq_domain_xlate_twocell,
+};
+
 int __init x3proto_gpio_setup(void)
 {
-	int ilsel;
-	int ret, i;
+	int ilsel, ret;
 
 	ilsel = ilsel_enable(ILSEL_KEY);
 	if (unlikely(ilsel < 0))
@@ -91,21 +111,10 @@ int __init x3proto_gpio_setup(void)
 	if (unlikely(ret))
 		goto err_gpio;
 
-	for (i = 0; i < NR_BASEBOARD_GPIOS; i++) {
-		unsigned long flags;
-		int irq = create_irq();
-
-		if (unlikely(irq < 0)) {
-			ret = -EINVAL;
-			goto err_irq;
-		}
-
-		spin_lock_irqsave(&x3proto_gpio_lock, flags);
-		x3proto_gpio_irq_map[i] = irq;
-		irq_set_chip_and_handler_name(irq, &dummy_irq_chip,
-					      handle_simple_irq, "gpio");
-		spin_unlock_irqrestore(&x3proto_gpio_lock, flags);
-	}
+	x3proto_irq_domain = irq_domain_add_linear(NULL, NR_BASEBOARD_GPIOS,
+						   &x3proto_gpio_irq_ops, NULL);
+	if (unlikely(!x3proto_irq_domain))
+		goto err_irq;
 
 	pr_info("registering '%s' support, handling GPIOs %u -> %u, "
 		"bound to IRQ %u\n",
@@ -119,10 +128,6 @@ int __init x3proto_gpio_setup(void)
 	return 0;
 
 err_irq:
-	for (; i >= 0; --i)
-		if (x3proto_gpio_irq_map[i])
-			destroy_irq(x3proto_gpio_irq_map[i]);
-
 	ret = gpiochip_remove(&x3proto_gpio_chip);
 	if (unlikely(ret))
 		pr_err("Failed deregistering GPIO\n");
-- 
cgit v1.2.3-18-g5258


From 5df38b9b7676e4e46c5c13e75f023ffb82542980 Mon Sep 17 00:00:00 2001
From: Paul Mundt <lethal@linux-sh.org>
Date: Thu, 24 May 2012 18:24:32 +0900
Subject: sh: se722: Move FPGA IRQs to irqdomain and generic irq chip.

This implements a total rewrite of the rather buggy SE7722 FPGA IRQ code,
utilizing a linear irq domain as well as the generic irq chip type.

While the interaction between the two APIs is a bit clunky (ie, revmap
lookup for gc irq_base), they work well enough together that it's easy
enough to work with going forward.

While we're at it, deal with irq_mask_ack/unmask of the chained IRQ in
the demux handler to prevent smc91x screaming about spurious interrupts.

There's also some more improvement that can be made to the irqdomain code
to create backing irqdescs for the entire linear range in one bang
instead of iterating over the number of hwirqs and doing it
irq-at-a-time. This is easily dealt with at a later point, though.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
---
 arch/sh/boards/Kconfig                |   2 +
 arch/sh/boards/mach-se/7722/irq.c     | 131 ++++++++++++++++++++++------------
 arch/sh/boards/mach-se/7722/setup.c   |   6 +-
 arch/sh/include/mach-se/mach/se7722.h |  10 +--
 4 files changed, 94 insertions(+), 55 deletions(-)

(limited to 'arch/sh')

diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig
index f2024a91319..525b9e32cd1 100644
--- a/arch/sh/boards/Kconfig
+++ b/arch/sh/boards/Kconfig
@@ -44,6 +44,8 @@ config SH_7721_SOLUTION_ENGINE
 config SH_7722_SOLUTION_ENGINE
 	bool "SolutionEngine7722"
 	select SOLUTION_ENGINE
+	select GENERIC_IRQ_CHIP
+	select IRQ_DOMAIN
 	depends on CPU_SUBTYPE_SH7722
 	help
 	  Select 7722 SolutionEngine if configuring for a Hitachi SH772
diff --git a/arch/sh/boards/mach-se/7722/irq.c b/arch/sh/boards/mach-se/7722/irq.c
index aac92f21ebd..f5e2af1bf04 100644
--- a/arch/sh/boards/mach-se/7722/irq.c
+++ b/arch/sh/boards/mach-se/7722/irq.c
@@ -1,79 +1,96 @@
 /*
- * linux/arch/sh/boards/se/7722/irq.c
+ * Hitachi UL SolutionEngine 7722 FPGA IRQ Support.
  *
  * Copyright (C) 2007  Nobuhiro Iwamatsu
- *
- * Hitachi UL SolutionEngine 7722 Support.
+ * Copyright (C) 2012  Paul Mundt
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  */
+#define DRV_NAME "SE7722-FPGA"
+#define pr_fmt(fmt) DRV_NAME ": " fmt
+
+#define irq_reg_readl	ioread16
+#define irq_reg_writel	iowrite16
+
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
-#include <asm/irq.h>
-#include <asm/io.h>
+#include <linux/irqdomain.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <asm/sizes.h>
 #include <mach-se/mach/se7722.h>
 
-unsigned int se7722_fpga_irq[SE7722_FPGA_IRQ_NR] = { 0, };
+#define IRQ01_BASE_ADDR	0x11800000
+#define IRQ01_MODE_REG	0
+#define IRQ01_STS_REG	4
+#define IRQ01_MASK_REG	8
 
-static void disable_se7722_irq(struct irq_data *data)
-{
-	unsigned int bit = (unsigned int)irq_data_get_irq_chip_data(data);
-	__raw_writew(__raw_readw(IRQ01_MASK) | 1 << bit, IRQ01_MASK);
-}
+static void __iomem *se7722_irq_regs;
+struct irq_domain *se7722_irq_domain;
 
-static void enable_se7722_irq(struct irq_data *data)
+static void se7722_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
-	unsigned int bit = (unsigned int)irq_data_get_irq_chip_data(data);
-	__raw_writew(__raw_readw(IRQ01_MASK) & ~(1 << bit), IRQ01_MASK);
-}
+	struct irq_data *data = irq_get_irq_data(irq);
+	struct irq_chip *chip = irq_data_get_irq_chip(data);
+	unsigned long mask;
+	int bit;
 
-static struct irq_chip se7722_irq_chip __read_mostly = {
-	.name		= "SE7722-FPGA",
-	.irq_mask	= disable_se7722_irq,
-	.irq_unmask	= enable_se7722_irq,
-};
+	chip->irq_mask_ack(data);
 
-static void se7722_irq_demux(unsigned int irq, struct irq_desc *desc)
+	mask = ioread16(se7722_irq_regs + IRQ01_STS_REG);
+
+	for_each_set_bit(bit, &mask, SE7722_FPGA_IRQ_NR)
+		generic_handle_irq(irq_linear_revmap(se7722_irq_domain, bit));
+
+	chip->irq_unmask(data);
+}
+
+static void __init se7722_domain_init(void)
 {
-	unsigned short intv = __raw_readw(IRQ01_STS);
-	unsigned int ext_irq = 0;
+	int i;
 
-	intv &= (1 << SE7722_FPGA_IRQ_NR) - 1;
+	se7722_irq_domain = irq_domain_add_linear(NULL, SE7722_FPGA_IRQ_NR,
+						  &irq_domain_simple_ops, NULL);
+	if (unlikely(!se7722_irq_domain)) {
+		printk("Failed to get IRQ domain\n");
+		return;
+	}
 
-	for (; intv; intv >>= 1, ext_irq++) {
-		if (!(intv & 1))
-			continue;
+	for (i = 0; i < SE7722_FPGA_IRQ_NR; i++) {
+		int irq = irq_create_mapping(se7722_irq_domain, i);
 
-		generic_handle_irq(se7722_fpga_irq[ext_irq]);
+		if (unlikely(irq == 0)) {
+			printk("Failed to allocate IRQ %d\n", i);
+			return;
+		}
 	}
 }
 
-/*
- * Initialize IRQ setting
- */
-void __init init_se7722_IRQ(void)
+static void __init se7722_gc_init(void)
 {
-	int i, irq;
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
+	unsigned int irq_base;
 
-	__raw_writew(0, IRQ01_MASK);       /* disable all irqs */
-	__raw_writew(0x2000, 0xb03fffec);  /* mrshpc irq enable */
+	irq_base = irq_linear_revmap(se7722_irq_domain, 0);
 
-	for (i = 0; i < SE7722_FPGA_IRQ_NR; i++) {
-		irq = create_irq();
-		if (irq < 0)
-			return;
-		se7722_fpga_irq[i] = irq;
+	gc = irq_alloc_generic_chip(DRV_NAME, 1, irq_base, se7722_irq_regs,
+				    handle_level_irq);
+	if (unlikely(!gc))
+		return;
 
-		irq_set_chip_and_handler_name(se7722_fpga_irq[i],
-					      &se7722_irq_chip,
-					      handle_level_irq,
-					      "level");
+	ct = gc->chip_types;
+	ct->chip.irq_mask = irq_gc_mask_set_bit;
+	ct->chip.irq_unmask = irq_gc_mask_clr_bit;
 
-		irq_set_chip_data(se7722_fpga_irq[i], (void *)i);
-	}
+	ct->regs.mask = IRQ01_MASK_REG;
+
+	irq_setup_generic_chip(gc, IRQ_MSK(SE7722_FPGA_IRQ_NR),
+			       IRQ_GC_INIT_MASK_CACHE,
+			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);
 
 	irq_set_chained_handler(IRQ0_IRQ, se7722_irq_demux);
 	irq_set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW);
@@ -81,3 +98,25 @@ void __init init_se7722_IRQ(void)
 	irq_set_chained_handler(IRQ1_IRQ, se7722_irq_demux);
 	irq_set_irq_type(IRQ1_IRQ, IRQ_TYPE_LEVEL_LOW);
 }
+
+/*
+ * Initialize FPGA IRQs
+ */
+void __init init_se7722_IRQ(void)
+{
+	se7722_irq_regs = ioremap(IRQ01_BASE_ADDR, SZ_16);
+	if (unlikely(!se7722_irq_regs)) {
+		printk("Failed to remap IRQ01 regs\n");
+		return;
+	}
+
+	/*
+	 * All FPGA IRQs disabled by default
+	 */
+	iowrite16(0, se7722_irq_regs + IRQ01_MASK_REG);
+
+	__raw_writew(0x2000, 0xb03fffec);  /* mrshpc irq enable */
+
+	se7722_domain_init();
+	se7722_gc_init();
+}
diff --git a/arch/sh/boards/mach-se/7722/setup.c b/arch/sh/boards/mach-se/7722/setup.c
index e1963fecd76..2ec0111fdf9 100644
--- a/arch/sh/boards/mach-se/7722/setup.c
+++ b/arch/sh/boards/mach-se/7722/setup.c
@@ -2,6 +2,7 @@
  * linux/arch/sh/boards/se/7722/setup.c
  *
  * Copyright (C) 2007 Nobuhiro Iwamatsu
+ * Copyright (C) 2012 Paul Mundt
  *
  * Hitachi UL SolutionEngine 7722 Support.
  *
@@ -15,6 +16,7 @@
 #include <linux/ata_platform.h>
 #include <linux/input.h>
 #include <linux/input/sh_keysc.h>
+#include <linux/irqdomain.h>
 #include <linux/smc91x.h>
 #include <mach-se/mach/se7722.h>
 #include <mach-se/mach/mrshpc.h>
@@ -142,10 +144,10 @@ static int __init se7722_devices_setup(void)
 
 	/* Wire-up dynamic vectors */
 	cf_ide_resources[2].start = cf_ide_resources[2].end =
-		se7722_fpga_irq[SE7722_FPGA_IRQ_MRSHPC0];
+		irq_find_mapping(se7722_irq_domain, SE7722_FPGA_IRQ_MRSHPC0);
 
 	smc91x_eth_resources[1].start = smc91x_eth_resources[1].end =
-		se7722_fpga_irq[SE7722_FPGA_IRQ_SMC];
+		irq_find_mapping(se7722_irq_domain, SE7722_FPGA_IRQ_SMC);
 
 	return platform_add_devices(se7722_devices, ARRAY_SIZE(se7722_devices));
 }
diff --git a/arch/sh/include/mach-se/mach/se7722.h b/arch/sh/include/mach-se/mach/se7722.h
index 16505bfb8a9..5508dc42e4d 100644
--- a/arch/sh/include/mach-se/mach/se7722.h
+++ b/arch/sh/include/mach-se/mach/se7722.h
@@ -80,12 +80,6 @@
 #define IRQ0_IRQ        32
 #define IRQ1_IRQ        33
 
-#define IRQ01_MODE      0xb1800000
-#define IRQ01_STS       0xb1800004
-#define IRQ01_MASK      0xb1800008
-
-/* Bits in IRQ01_* registers */
-
 #define SE7722_FPGA_IRQ_USB	0 /* IRQ0 */
 #define SE7722_FPGA_IRQ_SMC	1 /* IRQ0 */
 #define SE7722_FPGA_IRQ_MRSHPC0	2 /* IRQ1 */
@@ -94,8 +88,10 @@
 #define SE7722_FPGA_IRQ_MRSHPC3	5 /* IRQ1 */
 #define SE7722_FPGA_IRQ_NR	6
 
+struct irq_domain;
+
 /* arch/sh/boards/se/7722/irq.c */
-extern unsigned int se7722_fpga_irq[];
+extern struct irq_domain *se7722_irq_domain;
 
 void init_se7722_IRQ(void);
 
-- 
cgit v1.2.3-18-g5258


From 197b58e6651426bec8b2582013258b52cd15a444 Mon Sep 17 00:00:00 2001
From: Paul Mundt <lethal@linux-sh.org>
Date: Thu, 24 May 2012 19:07:18 +0900
Subject: sh: se7343: Move CPLD IRQs to irqdomain and generic irq chip.

Follows the se7722 change, see there for more information.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
---
 arch/sh/boards/Kconfig                |   2 +
 arch/sh/boards/mach-se/7343/irq.c     | 129 ++++++++++++++++++++++------------
 arch/sh/boards/mach-se/7343/setup.c   |  10 +--
 arch/sh/include/mach-se/mach/se7343.h |   7 +-
 4 files changed, 97 insertions(+), 51 deletions(-)

(limited to 'arch/sh')

diff --git a/arch/sh/boards/Kconfig b/arch/sh/boards/Kconfig
index 525b9e32cd1..1a280048e2c 100644
--- a/arch/sh/boards/Kconfig
+++ b/arch/sh/boards/Kconfig
@@ -81,6 +81,8 @@ config SH_7780_SOLUTION_ENGINE
 config SH_7343_SOLUTION_ENGINE
 	bool "SolutionEngine7343"
 	select SOLUTION_ENGINE
+	select GENERIC_IRQ_CHIP
+	select IRQ_DOMAIN
 	depends on CPU_SUBTYPE_SH7343
 	help
 	  Select 7343 SolutionEngine if configuring for a Hitachi
diff --git a/arch/sh/boards/mach-se/7343/irq.c b/arch/sh/boards/mach-se/7343/irq.c
index fd45ffc4834..7646bf0486c 100644
--- a/arch/sh/boards/mach-se/7343/irq.c
+++ b/arch/sh/boards/mach-se/7343/irq.c
@@ -1,86 +1,129 @@
 /*
- * linux/arch/sh/boards/se/7343/irq.c
+ * Hitachi UL SolutionEngine 7343 FPGA IRQ Support.
  *
  * Copyright (C) 2008  Yoshihiro Shimoda
+ * Copyright (C) 2012  Paul Mundt
  *
- * Based on linux/arch/sh/boards/se/7722/irq.c
+ * Based on linux/arch/sh/boards/se/7343/irq.c
  * Copyright (C) 2007  Nobuhiro Iwamatsu
  *
  * This file is subject to the terms and conditions of the GNU General Public
  * License.  See the file "COPYING" in the main directory of this archive
  * for more details.
  */
+#define DRV_NAME "SE7343-FPGA"
+#define pr_fmt(fmt) DRV_NAME ": " fmt
+
+#define irq_reg_readl	ioread16
+#define irq_reg_writel	iowrite16
+
 #include <linux/init.h>
 #include <linux/irq.h>
 #include <linux/interrupt.h>
+#include <linux/irqdomain.h>
 #include <linux/io.h>
+#include <asm/sizes.h>
 #include <mach-se/mach/se7343.h>
 
-unsigned int se7343_fpga_irq[SE7343_FPGA_IRQ_NR] = { 0, };
+#define PA_CPLD_BASE_ADDR	0x11400000
+#define PA_CPLD_ST_REG		0x08	/* CPLD Interrupt status register */
+#define PA_CPLD_IMSK_REG	0x0a	/* CPLD Interrupt mask register */
 
-static void disable_se7343_irq(struct irq_data *data)
-{
-	unsigned int bit = (unsigned int)irq_data_get_irq_chip_data(data);
-	__raw_writew(__raw_readw(PA_CPLD_IMSK) | 1 << bit, PA_CPLD_IMSK);
-}
+static void __iomem *se7343_irq_regs;
+struct irq_domain *se7343_irq_domain;
 
-static void enable_se7343_irq(struct irq_data *data)
+static void se7343_irq_demux(unsigned int irq, struct irq_desc *desc)
 {
-	unsigned int bit = (unsigned int)irq_data_get_irq_chip_data(data);
-	__raw_writew(__raw_readw(PA_CPLD_IMSK) & ~(1 << bit), PA_CPLD_IMSK);
-}
+	struct irq_data *data = irq_get_irq_data(irq);
+	struct irq_chip *chip = irq_data_get_irq_chip(data);
+	unsigned long mask;
+	int bit;
 
-static struct irq_chip se7343_irq_chip __read_mostly = {
-	.name		= "SE7343-FPGA",
-	.irq_mask	= disable_se7343_irq,
-	.irq_unmask	= enable_se7343_irq,
-};
+	chip->irq_mask_ack(data);
 
-static void se7343_irq_demux(unsigned int irq, struct irq_desc *desc)
+	mask = ioread16(se7343_irq_regs + PA_CPLD_ST_REG);
+
+	for_each_set_bit(bit, &mask, SE7343_FPGA_IRQ_NR)
+		generic_handle_irq(irq_linear_revmap(se7343_irq_domain, bit));
+
+	chip->irq_unmask(data);
+}
+
+static void __init se7343_domain_init(void)
 {
-	unsigned short intv = __raw_readw(PA_CPLD_ST);
-	unsigned int ext_irq = 0;
+	int i;
 
-	intv &= (1 << SE7343_FPGA_IRQ_NR) - 1;
+	se7343_irq_domain = irq_domain_add_linear(NULL, SE7343_FPGA_IRQ_NR,
+						  &irq_domain_simple_ops, NULL);
+	if (unlikely(!se7343_irq_domain)) {
+		printk("Failed to get IRQ domain\n");
+		return;
+	}
 
-	for (; intv; intv >>= 1, ext_irq++) {
-		if (!(intv & 1))
-			continue;
+	for (i = 0; i < SE7343_FPGA_IRQ_NR; i++) {
+		int irq = irq_create_mapping(se7343_irq_domain, i);
 
-		generic_handle_irq(se7343_fpga_irq[ext_irq]);
+		if (unlikely(irq == 0)) {
+			printk("Failed to allocate IRQ %d\n", i);
+			return;
+		}
 	}
 }
 
-/*
- * Initialize IRQ setting
- */
-void __init init_7343se_IRQ(void)
+static void __init se7343_gc_init(void)
 {
-	int i, irq;
+	struct irq_chip_generic *gc;
+	struct irq_chip_type *ct;
+	unsigned int irq_base;
 
-	__raw_writew(0, PA_CPLD_IMSK);	/* disable all irqs */
-	__raw_writew(0x2000, 0xb03fffec);	/* mrshpc irq enable */
+	irq_base = irq_linear_revmap(se7343_irq_domain, 0);
 
-	for (i = 0; i < SE7343_FPGA_IRQ_NR; i++) {
-		irq = create_irq();
-		if (irq < 0)
-			return;
-		se7343_fpga_irq[i] = irq;
+	gc = irq_alloc_generic_chip(DRV_NAME, 1, irq_base, se7343_irq_regs,
+				    handle_level_irq);
+	if (unlikely(!gc))
+		return;
 
-		irq_set_chip_and_handler_name(se7343_fpga_irq[i],
-					      &se7343_irq_chip,
-					      handle_level_irq,
-					      "level");
+	ct = gc->chip_types;
+	ct->chip.irq_mask = irq_gc_mask_set_bit;
+	ct->chip.irq_unmask = irq_gc_mask_clr_bit;
 
-		irq_set_chip_data(se7343_fpga_irq[i], (void *)i);
-	}
+	ct->regs.mask = PA_CPLD_IMSK_REG;
+
+	irq_setup_generic_chip(gc, IRQ_MSK(SE7343_FPGA_IRQ_NR),
+			       IRQ_GC_INIT_MASK_CACHE,
+			       IRQ_NOREQUEST | IRQ_NOPROBE, 0);
 
 	irq_set_chained_handler(IRQ0_IRQ, se7343_irq_demux);
 	irq_set_irq_type(IRQ0_IRQ, IRQ_TYPE_LEVEL_LOW);
+
 	irq_set_chained_handler(IRQ1_IRQ, se7343_irq_demux);
 	irq_set_irq_type(IRQ1_IRQ, IRQ_TYPE_LEVEL_LOW);
+
 	irq_set_chained_handler(IRQ4_IRQ, se7343_irq_demux);
 	irq_set_irq_type(IRQ4_IRQ, IRQ_TYPE_LEVEL_LOW);
+
 	irq_set_chained_handler(IRQ5_IRQ, se7343_irq_demux);
 	irq_set_irq_type(IRQ5_IRQ, IRQ_TYPE_LEVEL_LOW);
 }
+
+/*
+ * Initialize IRQ setting
+ */
+void __init init_7343se_IRQ(void)
+{
+	se7343_irq_regs = ioremap(PA_CPLD_BASE_ADDR, SZ_16);
+	if (unlikely(!se7343_irq_regs)) {
+		pr_err("Failed to remap CPLD\n");
+		return;
+	}
+
+	/*
+	 * All FPGA IRQs disabled by default
+	 */
+	iowrite16(0, se7343_irq_regs + PA_CPLD_IMSK_REG);
+
+	__raw_writew(0x2000, 0xb03fffec);	/* mrshpc irq enable */
+
+	se7343_domain_init();
+	se7343_gc_init();
+}
diff --git a/arch/sh/boards/mach-se/7343/setup.c b/arch/sh/boards/mach-se/7343/setup.c
index d2370af56d7..8ce4f2a202a 100644
--- a/arch/sh/boards/mach-se/7343/setup.c
+++ b/arch/sh/boards/mach-se/7343/setup.c
@@ -5,6 +5,7 @@
 #include <linux/serial_reg.h>
 #include <linux/usb/isp116x.h>
 #include <linux/delay.h>
+#include <linux/irqdomain.h>
 #include <asm/machvec.h>
 #include <mach-se/mach/se7343.h>
 #include <asm/heartbeat.h>
@@ -145,11 +146,12 @@ static struct platform_device *sh7343se_platform_devices[] __initdata = {
 static int __init sh7343se_devices_setup(void)
 {
 	/* Wire-up dynamic vectors */
-	serial_platform_data[0].irq = se7343_fpga_irq[SE7343_FPGA_IRQ_UARTA];
-	serial_platform_data[1].irq = se7343_fpga_irq[SE7343_FPGA_IRQ_UARTB];
-
+	serial_platform_data[0].irq = irq_find_mapping(se7343_irq_domain,
+						       SE7343_FPGA_IRQ_UARTA);
+	serial_platform_data[1].irq = irq_find_mapping(se7343_irq_domain,
+						       SE7343_FPGA_IRQ_UARTB);
 	usb_resources[2].start = usb_resources[2].end =
-		se7343_fpga_irq[SE7343_FPGA_IRQ_USB];
+		irq_find_mapping(se7343_irq_domain, SE7343_FPGA_IRQ_USB);
 
 	return platform_add_devices(sh7343se_platform_devices,
 				    ARRAY_SIZE(sh7343se_platform_devices));
diff --git a/arch/sh/include/mach-se/mach/se7343.h b/arch/sh/include/mach-se/mach/se7343.h
index 8d8170d6cc4..2ec6f75a44d 100644
--- a/arch/sh/include/mach-se/mach/se7343.h
+++ b/arch/sh/include/mach-se/mach/se7343.h
@@ -49,9 +49,6 @@
 #define PA_LED		0xb0C00000	/* LED */
 #define LED_SHIFT       0
 #define PA_DIPSW	0xb0900000	/* Dip switch 31 */
-#define PA_CPLD_MODESET	0xb1400004	/* CPLD Mode set register */
-#define PA_CPLD_ST	0xb1400008	/* CPLD Interrupt status register */
-#define PA_CPLD_IMSK	0xb140000a	/* CPLD Interrupt mask register */
 /* Area 5 */
 #define PA_EXT5		0x14000000
 #define PA_EXT5_SIZE	0x04000000
@@ -134,8 +131,10 @@
 
 #define SE7343_FPGA_IRQ_NR	12
 
+struct irq_domain;
+
 /* arch/sh/boards/se/7343/irq.c */
-extern unsigned int se7343_fpga_irq[];
+extern struct irq_domain *se7343_irq_domain;
 
 void init_7343se_IRQ(void);
 
-- 
cgit v1.2.3-18-g5258


From db218b3d55627ef515d3b32888b269ed319c4c8d Mon Sep 17 00:00:00 2001
From: Paul Mundt <lethal@linux-sh.org>
Date: Thu, 14 Jun 2012 14:05:24 +0900
Subject: sh64: Use generic unaligned access control/counters.

This switches over from the special-casing that sh64 had and to the model
that's being employed for sh32.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
---
 arch/sh/kernel/traps_64.c | 150 ++++++++++++----------------------------------
 1 file changed, 37 insertions(+), 113 deletions(-)

(limited to 'arch/sh')

diff --git a/arch/sh/kernel/traps_64.c b/arch/sh/kernel/traps_64.c
index ba95d63e623..488c1cd557f 100644
--- a/arch/sh/kernel/traps_64.c
+++ b/arch/sh/kernel/traps_64.c
@@ -27,7 +27,7 @@
 #include <linux/perf_event.h>
 #include <asm/uaccess.h>
 #include <asm/io.h>
-#include <linux/atomic.h>
+#include <asm/alignment.h>
 #include <asm/processor.h>
 #include <asm/pgtable.h>
 #include <asm/fpu.h>
@@ -264,20 +264,20 @@ static void do_unhandled_exception(int trapnr, int signr, char *str, char *fn_na
 	die_if_no_fixup(str, regs, error_code);
 }
 
-static int read_opcode(unsigned long long pc, unsigned long *result_opcode, int from_user_mode)
+static int read_opcode(reg_size_t pc, insn_size_t *result_opcode, int from_user_mode)
 {
 	int get_user_error;
 	unsigned long aligned_pc;
-	unsigned long opcode;
+	insn_size_t opcode;
 
 	if ((pc & 3) == 1) {
 		/* SHmedia */
 		aligned_pc = pc & ~3;
 		if (from_user_mode) {
-			if (!access_ok(VERIFY_READ, aligned_pc, sizeof(unsigned long))) {
+			if (!access_ok(VERIFY_READ, aligned_pc, sizeof(insn_size_t))) {
 				get_user_error = -EFAULT;
 			} else {
-				get_user_error = __get_user(opcode, (unsigned long *)aligned_pc);
+				get_user_error = __get_user(opcode, (insn_size_t *)aligned_pc);
 				*result_opcode = opcode;
 			}
 			return get_user_error;
@@ -285,7 +285,7 @@ static int read_opcode(unsigned long long pc, unsigned long *result_opcode, int
 			/* If the fault was in the kernel, we can either read
 			 * this directly, or if not, we fault.
 			*/
-			*result_opcode = *(unsigned long *) aligned_pc;
+			*result_opcode = *(insn_size_t *)aligned_pc;
 			return 0;
 		}
 	} else if ((pc & 1) == 0) {
@@ -311,17 +311,23 @@ static int address_is_sign_extended(__u64 a)
 #endif
 }
 
+/* return -1 for fault, 0 for OK */
 static int generate_and_check_address(struct pt_regs *regs,
-				      __u32 opcode,
+				      insn_size_t opcode,
 				      int displacement_not_indexed,
 				      int width_shift,
 				      __u64 *address)
 {
-	/* return -1 for fault, 0 for OK */
-
 	__u64 base_address, addr;
 	int basereg;
 
+	switch (1 << width_shift) {
+	case 1: inc_unaligned_byte_access(); break;
+	case 2: inc_unaligned_word_access(); break;
+	case 4: inc_unaligned_dword_access(); break;
+	case 8: inc_unaligned_multi_access(); break;
+	}
+
 	basereg = (opcode >> 20) & 0x3f;
 	base_address = regs->regs[basereg];
 	if (displacement_not_indexed) {
@@ -338,28 +344,28 @@ static int generate_and_check_address(struct pt_regs *regs,
 	}
 
 	/* Check sign extended */
-	if (!address_is_sign_extended(addr)) {
+	if (!address_is_sign_extended(addr))
 		return -1;
-	}
 
 	/* Check accessible.  For misaligned access in the kernel, assume the
 	   address is always accessible (and if not, just fault when the
 	   load/store gets done.) */
 	if (user_mode(regs)) {
-		if (addr >= TASK_SIZE) {
+		inc_unaligned_user_access();
+
+		if (addr >= TASK_SIZE)
 			return -1;
-		}
-		/* Do access_ok check later - it depends on whether it's a load or a store. */
-	}
+	} else
+		inc_unaligned_kernel_access();
 
 	*address = addr;
+
+	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, addr);
+	unaligned_fixups_notify(current, opcode, regs);
+
 	return 0;
 }
 
-static int user_mode_unaligned_fixup_count = 10;
-static int user_mode_unaligned_fixup_enable = 1;
-static int kernel_mode_unaligned_fixup_count = 32;
-
 static void misaligned_kernel_word_load(__u64 address, int do_sign_extend, __u64 *result)
 {
 	unsigned short x;
@@ -389,7 +395,7 @@ static void misaligned_kernel_word_store(__u64 address, __u64 value)
 }
 
 static int misaligned_load(struct pt_regs *regs,
-			   __u32 opcode,
+			   insn_size_t opcode,
 			   int displacement_not_indexed,
 			   int width_shift,
 			   int do_sign_extend)
@@ -401,11 +407,8 @@ static int misaligned_load(struct pt_regs *regs,
 
 	error = generate_and_check_address(regs, opcode,
 			displacement_not_indexed, width_shift, &address);
-	if (error < 0) {
+	if (error < 0)
 		return error;
-	}
-
-	perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, address);
 
 	destreg = (opcode >> 4) & 0x3f;
 	if (user_mode(regs)) {
@@ -464,11 +467,10 @@ static int misaligned_load(struct pt_regs *regs,
 	}
 
 	return 0;
-
 }
 
 static int misaligned_store(struct pt_regs *regs,
-			    __u32 opcode,
+			    insn_size_t opcode,
 			    int displacement_not_indexed,
 			    int width_shift)
 {
@@ -479,11 +481,8 @@ static int misaligned_store(struct pt_regs *regs,
 
 	error = generate_and_check_address(regs, opcode,
 			displacement_not_indexed, width_shift, &address);
-	if (error < 0) {
+	if (error < 0)
 		return error;
-	}
-
-	perf_sw_event(PERF_COUNT_SW_ALIGNMENT_FAULTS, 1, regs, address);
 
 	srcreg = (opcode >> 4) & 0x3f;
 	if (user_mode(regs)) {
@@ -537,13 +536,12 @@ static int misaligned_store(struct pt_regs *regs,
 	}
 
 	return 0;
-
 }
 
 /* Never need to fix up misaligned FPU accesses within the kernel since that's a real
    error. */
 static int misaligned_fpu_load(struct pt_regs *regs,
-			   __u32 opcode,
+			   insn_size_t opcode,
 			   int displacement_not_indexed,
 			   int width_shift,
 			   int do_paired_load)
@@ -555,11 +553,8 @@ static int misaligned_fpu_load(struct pt_regs *regs,
 
 	error = generate_and_check_address(regs, opcode,
 			displacement_not_indexed, width_shift, &address);
-	if (error < 0) {
+	if (error < 0)
 		return error;
-	}
-
-	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, address);
 
 	destreg = (opcode >> 4) & 0x3f;
 	if (user_mode(regs)) {
@@ -615,12 +610,10 @@ static int misaligned_fpu_load(struct pt_regs *regs,
 		die ("Misaligned FPU load inside kernel", regs, 0);
 		return -1;
 	}
-
-
 }
 
 static int misaligned_fpu_store(struct pt_regs *regs,
-			   __u32 opcode,
+			   insn_size_t opcode,
 			   int displacement_not_indexed,
 			   int width_shift,
 			   int do_paired_load)
@@ -632,11 +625,8 @@ static int misaligned_fpu_store(struct pt_regs *regs,
 
 	error = generate_and_check_address(regs, opcode,
 			displacement_not_indexed, width_shift, &address);
-	if (error < 0) {
+	if (error < 0)
 		return error;
-	}
-
-	perf_sw_event(PERF_COUNT_SW_EMULATION_FAULTS, 1, regs, address);
 
 	srcreg = (opcode >> 4) & 0x3f;
 	if (user_mode(regs)) {
@@ -697,11 +687,13 @@ static int misaligned_fpu_store(struct pt_regs *regs,
 
 static int misaligned_fixup(struct pt_regs *regs)
 {
-	unsigned long opcode;
+	insn_size_t opcode;
 	int error;
 	int major, minor;
+	unsigned int user_action;
 
-	if (!user_mode_unaligned_fixup_enable)
+	user_action = unaligned_user_action();
+	if (!(user_action & UM_FIXUP))
 		return -1;
 
 	error = read_opcode(regs->pc, &opcode, user_mode(regs));
@@ -711,23 +703,6 @@ static int misaligned_fixup(struct pt_regs *regs)
 	major = (opcode >> 26) & 0x3f;
 	minor = (opcode >> 16) & 0xf;
 
-	if (user_mode(regs) && (user_mode_unaligned_fixup_count > 0)) {
-		--user_mode_unaligned_fixup_count;
-		/* Only do 'count' worth of these reports, to remove a potential DoS against syslog */
-		printk("Fixing up unaligned userspace access in \"%s\" pid=%d pc=0x%08x ins=0x%08lx\n",
-		       current->comm, task_pid_nr(current), (__u32)regs->pc, opcode);
-	} else if (!user_mode(regs) && (kernel_mode_unaligned_fixup_count > 0)) {
-		--kernel_mode_unaligned_fixup_count;
-		if (in_interrupt()) {
-			printk("Fixing up unaligned kernelspace access in interrupt pc=0x%08x ins=0x%08lx\n",
-			       (__u32)regs->pc, opcode);
-		} else {
-			printk("Fixing up unaligned kernelspace access in \"%s\" pid=%d pc=0x%08x ins=0x%08lx\n",
-			       current->comm, task_pid_nr(current), (__u32)regs->pc, opcode);
-		}
-	}
-
-
 	switch (major) {
 		case (0x84>>2): /* LD.W */
 			error = misaligned_load(regs, opcode, 1, 1, 1);
@@ -855,57 +830,6 @@ static int misaligned_fixup(struct pt_regs *regs)
 
 }
 
-static ctl_table unaligned_table[] = {
-	{
-		.procname	= "kernel_reports",
-		.data		= &kernel_mode_unaligned_fixup_count,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= proc_dointvec
-	},
-	{
-		.procname	= "user_reports",
-		.data		= &user_mode_unaligned_fixup_count,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= proc_dointvec
-	},
-	{
-		.procname	= "user_enable",
-		.data		= &user_mode_unaligned_fixup_enable,
-		.maxlen		= sizeof(int),
-		.mode		= 0644,
-		.proc_handler	= proc_dointvec},
-	{}
-};
-
-static ctl_table unaligned_root[] = {
-	{
-		.procname	= "unaligned_fixup",
-		.mode		= 0555,
-		.child		= unaligned_table
-	},
-	{}
-};
-
-static ctl_table sh64_root[] = {
-	{
-		.procname	= "sh64",
-		.mode		= 0555,
-		.child		= unaligned_root
-	},
-	{}
-};
-static struct ctl_table_header *sysctl_header;
-static int __init init_sysctl(void)
-{
-	sysctl_header = register_sysctl_table(sh64_root);
-	return 0;
-}
-
-__initcall(init_sysctl);
-
-
 asmlinkage void do_debug_interrupt(unsigned long code, struct pt_regs *regs)
 {
 	u64 peek_real_address_q(u64 addr);
-- 
cgit v1.2.3-18-g5258


From 37c9ee0161332291c8d13bc40084d24c744ed842 Mon Sep 17 00:00:00 2001
From: Paul Mundt <lethal@linux-sh.org>
Date: Thu, 14 Jun 2012 14:12:18 +0900
Subject: sh64: Kill off old exception debugging helpers.

There's not much here that we can't get at through alternate means (aside
from the TLB contents, but that doesn't belong here anyways). Most of
this information is already provided by the sh32 routines, which we'll
consolidate on next.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
---
 arch/sh/kernel/traps_64.c |  12 ---
 arch/sh/lib64/Makefile    |   2 +-
 arch/sh/lib64/dbg.c       | 248 ----------------------------------------------
 3 files changed, 1 insertion(+), 261 deletions(-)
 delete mode 100644 arch/sh/lib64/dbg.c

(limited to 'arch/sh')

diff --git a/arch/sh/kernel/traps_64.c b/arch/sh/kernel/traps_64.c
index 488c1cd557f..c902c29400a 100644
--- a/arch/sh/kernel/traps_64.c
+++ b/arch/sh/kernel/traps_64.c
@@ -32,15 +32,6 @@
 #include <asm/pgtable.h>
 #include <asm/fpu.h>
 
-#undef DEBUG_EXCEPTION
-#ifdef DEBUG_EXCEPTION
-/* implemented in ../lib/dbg.c */
-extern void show_excp_regs(char *fname, int trapnr, int signr,
-			   struct pt_regs *regs);
-#else
-#define show_excp_regs(a, b, c, d)
-#endif
-
 static void do_unhandled_exception(int trapnr, int signr, char *str, char *fn_name,
 		unsigned long error_code, struct pt_regs *regs, struct task_struct *tsk);
 
@@ -239,7 +230,6 @@ DO_ERROR(12, SIGILL,  "reserved instruction", reserved_inst, current)
 /* Called with interrupts disabled */
 asmlinkage void do_exception_error(unsigned long ex, struct pt_regs *regs)
 {
-	show_excp_regs(__func__, -1, -1, regs);
 	die_if_kernel("exception", regs, ex);
 }
 
@@ -256,8 +246,6 @@ int do_unknown_trapa(unsigned long scId, struct pt_regs *regs)
 static void do_unhandled_exception(int trapnr, int signr, char *str, char *fn_name,
 		unsigned long error_code, struct pt_regs *regs, struct task_struct *tsk)
 {
-	show_excp_regs(fn_name, trapnr, signr, regs);
-
 	if (user_mode(regs))
 		force_sig(signr, tsk);
 
diff --git a/arch/sh/lib64/Makefile b/arch/sh/lib64/Makefile
index 1fee75aa1f9..69779ff741d 100644
--- a/arch/sh/lib64/Makefile
+++ b/arch/sh/lib64/Makefile
@@ -10,7 +10,7 @@
 #
 
 # Panic should really be compiled as PIC
-lib-y  := udelay.o dbg.o panic.o memcpy.o memset.o \
+lib-y  := udelay.o panic.o memcpy.o memset.o \
 	  copy_user_memcpy.o copy_page.o strcpy.o strlen.o
 
 # Extracted from libgcc
diff --git a/arch/sh/lib64/dbg.c b/arch/sh/lib64/dbg.c
deleted file mode 100644
index 6152a6a6d9c..00000000000
--- a/arch/sh/lib64/dbg.c
+++ /dev/null
@@ -1,248 +0,0 @@
-/*--------------------------------------------------------------------------
---
--- Identity : Linux50 Debug Funcions
---
--- File     : arch/sh/lib64/dbg.c
---
--- Copyright 2000, 2001 STMicroelectronics Limited.
--- Copyright 2004 Richard Curnow (evt_debug etc)
---
---------------------------------------------------------------------------*/
-#include <linux/types.h>
-#include <linux/kernel.h>
-#include <linux/sched.h>
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <asm/mmu_context.h>
-
-typedef u64 regType_t;
-
-static regType_t getConfigReg(u64 id)
-{
-	register u64 reg __asm__("r2");
-	asm volatile ("getcfg   %1, 0, %0":"=r" (reg):"r"(id));
-	return (reg);
-}
-
-/* ======================================================================= */
-
-static char *szTab[] = { "4k", "64k", "1M", "512M" };
-static char *protTab[] = { "----",
-	"---R",
-	"--X-",
-	"--XR",
-	"-W--",
-	"-W-R",
-	"-WX-",
-	"-WXR",
-	"U---",
-	"U--R",
-	"U-X-",
-	"U-XR",
-	"UW--",
-	"UW-R",
-	"UWX-",
-	"UWXR"
-};
-#define  ITLB_BASE	0x00000000
-#define  DTLB_BASE	0x00800000
-#define  MAX_TLBs		64
-/* PTE High */
-#define  GET_VALID(pte)        ((pte) & 0x1)
-#define  GET_SHARED(pte)       ((pte) & 0x2)
-#define  GET_ASID(pte)         ((pte >> 2) & 0x0ff)
-#define  GET_EPN(pte)          ((pte) & 0xfffff000)
-
-/* PTE Low */
-#define  GET_CBEHAVIOR(pte)    ((pte) & 0x3)
-#define  GET_PAGE_SIZE(pte)    szTab[((pte >> 3) & 0x3)]
-#define  GET_PROTECTION(pte)   protTab[((pte >> 6) & 0xf)]
-#define  GET_PPN(pte)          ((pte) & 0xfffff000)
-
-#define PAGE_1K_MASK           0x00000000
-#define PAGE_4K_MASK           0x00000010
-#define PAGE_64K_MASK          0x00000080
-#define MMU_PAGESIZE_MASK      (PAGE_64K_MASK | PAGE_4K_MASK)
-#define PAGE_1MB_MASK          MMU_PAGESIZE_MASK
-#define PAGE_1K                (1024)
-#define PAGE_4K                (1024 * 4)
-#define PAGE_64K               (1024 * 64)
-#define PAGE_1MB               (1024 * 1024)
-
-#define HOW_TO_READ_TLB_CONTENT  \
-       "[ ID]  PPN         EPN        ASID  Share  CB  P.Size   PROT.\n"
-
-void print_single_tlb(unsigned long tlb, int single_print)
-{
-	regType_t pteH;
-	regType_t pteL;
-	unsigned int valid, shared, asid, epn, cb, ppn;
-	char *pSize;
-	char *pProt;
-
-	/*
-	   ** in case of single print <single_print> is true, this implies:
-	   **   1) print the TLB in any case also if NOT VALID
-	   **   2) print out the header
-	 */
-
-	pteH = getConfigReg(tlb);
-	valid = GET_VALID(pteH);
-	if (single_print)
-		printk(HOW_TO_READ_TLB_CONTENT);
-	else if (!valid)
-		return;
-
-	pteL = getConfigReg(tlb + 1);
-
-	shared = GET_SHARED(pteH);
-	asid = GET_ASID(pteH);
-	epn = GET_EPN(pteH);
-	cb = GET_CBEHAVIOR(pteL);
-	pSize = GET_PAGE_SIZE(pteL);
-	pProt = GET_PROTECTION(pteL);
-	ppn = GET_PPN(pteL);
-	printk("[%c%2ld]  0x%08x  0x%08x  %03d   %02x    %02x   %4s    %s\n",
-	       ((valid) ? ' ' : 'u'), ((tlb & 0x0ffff) / TLB_STEP),
-	       ppn, epn, asid, shared, cb, pSize, pProt);
-}
-
-void print_dtlb(void)
-{
-	int count;
-	unsigned long tlb;
-
-	printk(" ================= SH-5 D-TLBs Status ===================\n");
-	printk(HOW_TO_READ_TLB_CONTENT);
-	tlb = DTLB_BASE;
-	for (count = 0; count < MAX_TLBs; count++, tlb += TLB_STEP)
-		print_single_tlb(tlb, 0);
-	printk
-	    (" =============================================================\n");
-}
-
-void print_itlb(void)
-{
-	int count;
-	unsigned long tlb;
-
-	printk(" ================= SH-5 I-TLBs Status ===================\n");
-	printk(HOW_TO_READ_TLB_CONTENT);
-	tlb = ITLB_BASE;
-	for (count = 0; count < MAX_TLBs; count++, tlb += TLB_STEP)
-		print_single_tlb(tlb, 0);
-	printk
-	    (" =============================================================\n");
-}
-
-void show_excp_regs(char *from, int trapnr, int signr, struct pt_regs *regs)
-{
-
-	unsigned long long ah, al, bh, bl, ch, cl;
-
-	printk("\n");
-	printk("EXCEPTION - %s: task %d; Linux trap # %d; signal = %d\n",
-	       ((from) ? from : "???"), current->pid, trapnr, signr);
-
-	asm volatile ("getcon   " __EXPEVT ", %0":"=r"(ah));
-	asm volatile ("getcon   " __EXPEVT ", %0":"=r"(al));
-	ah = (ah) >> 32;
-	al = (al) & 0xffffffff;
-	asm volatile ("getcon   " __KCR1 ", %0":"=r"(bh));
-	asm volatile ("getcon   " __KCR1 ", %0":"=r"(bl));
-	bh = (bh) >> 32;
-	bl = (bl) & 0xffffffff;
-	asm volatile ("getcon   " __INTEVT ", %0":"=r"(ch));
-	asm volatile ("getcon   " __INTEVT ", %0":"=r"(cl));
-	ch = (ch) >> 32;
-	cl = (cl) & 0xffffffff;
-	printk("EXPE: %08Lx%08Lx KCR1: %08Lx%08Lx INTE: %08Lx%08Lx\n",
-	       ah, al, bh, bl, ch, cl);
-
-	asm volatile ("getcon   " __PEXPEVT ", %0":"=r"(ah));
-	asm volatile ("getcon   " __PEXPEVT ", %0":"=r"(al));
-	ah = (ah) >> 32;
-	al = (al) & 0xffffffff;
-	asm volatile ("getcon   " __PSPC ", %0":"=r"(bh));
-	asm volatile ("getcon   " __PSPC ", %0":"=r"(bl));
-	bh = (bh) >> 32;
-	bl = (bl) & 0xffffffff;
-	asm volatile ("getcon   " __PSSR ", %0":"=r"(ch));
-	asm volatile ("getcon   " __PSSR ", %0":"=r"(cl));
-	ch = (ch) >> 32;
-	cl = (cl) & 0xffffffff;
-	printk("PEXP: %08Lx%08Lx PSPC: %08Lx%08Lx PSSR: %08Lx%08Lx\n",
-	       ah, al, bh, bl, ch, cl);
-
-	ah = (regs->pc) >> 32;
-	al = (regs->pc) & 0xffffffff;
-	bh = (regs->regs[18]) >> 32;
-	bl = (regs->regs[18]) & 0xffffffff;
-	ch = (regs->regs[15]) >> 32;
-	cl = (regs->regs[15]) & 0xffffffff;
-	printk("PC  : %08Lx%08Lx LINK: %08Lx%08Lx SP  : %08Lx%08Lx\n",
-	       ah, al, bh, bl, ch, cl);
-
-	ah = (regs->sr) >> 32;
-	al = (regs->sr) & 0xffffffff;
-	asm volatile ("getcon   " __TEA ", %0":"=r"(bh));
-	asm volatile ("getcon   " __TEA ", %0":"=r"(bl));
-	bh = (bh) >> 32;
-	bl = (bl) & 0xffffffff;
-	asm volatile ("getcon   " __KCR0 ", %0":"=r"(ch));
-	asm volatile ("getcon   " __KCR0 ", %0":"=r"(cl));
-	ch = (ch) >> 32;
-	cl = (cl) & 0xffffffff;
-	printk("SR  : %08Lx%08Lx TEA : %08Lx%08Lx KCR0: %08Lx%08Lx\n",
-	       ah, al, bh, bl, ch, cl);
-
-	ah = (regs->regs[0]) >> 32;
-	al = (regs->regs[0]) & 0xffffffff;
-	bh = (regs->regs[1]) >> 32;
-	bl = (regs->regs[1]) & 0xffffffff;
-	ch = (regs->regs[2]) >> 32;
-	cl = (regs->regs[2]) & 0xffffffff;
-	printk("R0  : %08Lx%08Lx R1  : %08Lx%08Lx R2  : %08Lx%08Lx\n",
-	       ah, al, bh, bl, ch, cl);
-
-	ah = (regs->regs[3]) >> 32;
-	al = (regs->regs[3]) & 0xffffffff;
-	bh = (regs->regs[4]) >> 32;
-	bl = (regs->regs[4]) & 0xffffffff;
-	ch = (regs->regs[5]) >> 32;
-	cl = (regs->regs[5]) & 0xffffffff;
-	printk("R3  : %08Lx%08Lx R4  : %08Lx%08Lx R5  : %08Lx%08Lx\n",
-	       ah, al, bh, bl, ch, cl);
-
-	ah = (regs->regs[6]) >> 32;
-	al = (regs->regs[6]) & 0xffffffff;
-	bh = (regs->regs[7]) >> 32;
-	bl = (regs->regs[7]) & 0xffffffff;
-	ch = (regs->regs[8]) >> 32;
-	cl = (regs->regs[8]) & 0xffffffff;
-	printk("R6  : %08Lx%08Lx R7  : %08Lx%08Lx R8  : %08Lx%08Lx\n",
-	       ah, al, bh, bl, ch, cl);
-
-	ah = (regs->regs[9]) >> 32;
-	al = (regs->regs[9]) & 0xffffffff;
-	bh = (regs->regs[10]) >> 32;
-	bl = (regs->regs[10]) & 0xffffffff;
-	ch = (regs->regs[11]) >> 32;
-	cl = (regs->regs[11]) & 0xffffffff;
-	printk("R9  : %08Lx%08Lx R10 : %08Lx%08Lx R11 : %08Lx%08Lx\n",
-	       ah, al, bh, bl, ch, cl);
-	printk("....\n");
-
-	ah = (regs->tregs[0]) >> 32;
-	al = (regs->tregs[0]) & 0xffffffff;
-	bh = (regs->tregs[1]) >> 32;
-	bl = (regs->tregs[1]) & 0xffffffff;
-	ch = (regs->tregs[2]) >> 32;
-	cl = (regs->tregs[2]) & 0xffffffff;
-	printk("T0  : %08Lx%08Lx T1  : %08Lx%08Lx T2  : %08Lx%08Lx\n",
-	       ah, al, bh, bl, ch, cl);
-	printk("....\n");
-
-	print_dtlb();
-	print_itlb();
-}
-- 
cgit v1.2.3-18-g5258


From 5f857bce21cfd0531dc7d4daac74d976caf6166b Mon Sep 17 00:00:00 2001
From: Paul Mundt <lethal@linux-sh.org>
Date: Thu, 14 Jun 2012 14:18:51 +0900
Subject: sh: Consolidate die definitions for trap handlers.

This kills off the _64 versions and consolidates on the more robust _32
versions instead.

Signed-off-by: Paul Mundt <lethal@linux-sh.org>
---
 arch/sh/include/asm/bug.h |  4 +++
 arch/sh/kernel/traps.c    | 71 +++++++++++++++++++++++++++++++++++++++++++++++
 arch/sh/kernel/traps_32.c | 71 -----------------------------------------------
 arch/sh/kernel/traps_64.c | 31 ---------------------
 4 files changed, 75 insertions(+), 102 deletions(-)

(limited to 'arch/sh')

diff --git a/arch/sh/include/asm/bug.h b/arch/sh/include/asm/bug.h
index 2b87d86bfc4..dcf27807542 100644
--- a/arch/sh/include/asm/bug.h
+++ b/arch/sh/include/asm/bug.h
@@ -110,6 +110,10 @@ do {							\
 #include <asm-generic/bug.h>
 
 struct pt_regs;
+
+/* arch/sh/kernel/traps.c */
 extern void die(const char *str, struct pt_regs *regs, long err) __attribute__ ((noreturn));
+extern void die_if_kernel(const char *str, struct pt_regs *regs, long err);
+extern void die_if_no_fixup(const char *str, struct pt_regs *regs, long err);
 
 #endif /* __ASM_SH_BUG_H */
diff --git a/arch/sh/kernel/traps.c b/arch/sh/kernel/traps.c
index a87e58a9e38..72246bc0688 100644
--- a/arch/sh/kernel/traps.c
+++ b/arch/sh/kernel/traps.c
@@ -6,9 +6,80 @@
 #include <linux/sched.h>
 #include <linux/uaccess.h>
 #include <linux/hardirq.h>
+#include <linux/kernel.h>
+#include <linux/kexec.h>
+#include <linux/module.h>
 #include <asm/unwinder.h>
 #include <asm/traps.h>
 
+static DEFINE_SPINLOCK(die_lock);
+
+void die(const char *str, struct pt_regs *regs, long err)
+{
+	static int die_counter;
+
+	oops_enter();
+
+	spin_lock_irq(&die_lock);
+	console_verbose();
+	bust_spinlocks(1);
+
+	printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
+	print_modules();
+	show_regs(regs);
+
+	printk("Process: %s (pid: %d, stack limit = %p)\n", current->comm,
+			task_pid_nr(current), task_stack_page(current) + 1);
+
+	if (!user_mode(regs) || in_interrupt())
+		dump_mem("Stack: ", regs->regs[15], THREAD_SIZE +
+			 (unsigned long)task_stack_page(current));
+
+	notify_die(DIE_OOPS, str, regs, err, 255, SIGSEGV);
+
+	bust_spinlocks(0);
+	add_taint(TAINT_DIE);
+	spin_unlock_irq(&die_lock);
+	oops_exit();
+
+	if (kexec_should_crash(current))
+		crash_kexec(regs);
+
+	if (in_interrupt())
+		panic("Fatal exception in interrupt");
+
+	if (panic_on_oops)
+		panic("Fatal exception");
+
+	do_exit(SIGSEGV);
+}
+
+void die_if_kernel(const char *str, struct pt_regs *regs, long err)
+{
+	if (!user_mode(regs))
+		die(str, regs, err);
+}
+
+/*
+ * try and fix up kernelspace address errors
+ * - userspace errors just cause EFAULT to be returned, resulting in SEGV
+ * - kernel/userspace interfaces cause a jump to an appropriate handler
+ * - other kernel errors are bad
+ */
+void die_if_no_fixup(const char *str, struct pt_regs *regs, long err)
+{
+	if (!user_mode(regs)) {
+		const struct exception_table_entry *fixup;
+		fixup = search_exception_tables(regs->pc);
+		if (fixup) {
+			regs->pc = fixup->fixup;
+			return;
+		}
+
+		die(str, regs, err);
+	}
+}
+
 #ifdef CONFIG_GENERIC_BUG
 static void handle_BUG(struct pt_regs *regs)
 {
diff --git a/arch/sh/kernel/traps_32.c b/arch/sh/kernel/traps_32.c
index b8f5a51841e..5f513a64ded 100644
--- a/arch/sh/kernel/traps_32.c
+++ b/arch/sh/kernel/traps_32.c
@@ -16,13 +16,11 @@
 #include <linux/hardirq.h>
 #include <linux/init.h>
 #include <linux/spinlock.h>
-#include <linux/module.h>
 #include <linux/kallsyms.h>
 #include <linux/io.h>
 #include <linux/bug.h>
 #include <linux/debug_locks.h>
 #include <linux/kdebug.h>
-#include <linux/kexec.h>
 #include <linux/limits.h>
 #include <linux/sysfs.h>
 #include <linux/uaccess.h>
@@ -48,75 +46,6 @@
 #define TRAP_ILLEGAL_SLOT_INST	13
 #endif
 
-static DEFINE_SPINLOCK(die_lock);
-
-void die(const char * str, struct pt_regs * regs, long err)
-{
-	static int die_counter;
-
-	oops_enter();
-
-	spin_lock_irq(&die_lock);
-	console_verbose();
-	bust_spinlocks(1);
-
-	printk("%s: %04lx [#%d]\n", str, err & 0xffff, ++die_counter);
-	print_modules();
-	show_regs(regs);
-
-	printk("Process: %s (pid: %d, stack limit = %p)\n", current->comm,
-			task_pid_nr(current), task_stack_page(current) + 1);
-
-	if (!user_mode(regs) || in_interrupt())
-		dump_mem("Stack: ", regs->regs[15], THREAD_SIZE +
-			 (unsigned long)task_stack_page(current));
-
-	notify_die(DIE_OOPS, str, regs, err, 255, SIGSEGV);
-
-	bust_spinlocks(0);
-	add_taint(TAINT_DIE);
-	spin_unlock_irq(&die_lock);
-	oops_exit();
-
-	if (kexec_should_crash(current))
-		crash_kexec(regs);
-
-	if (in_interrupt())
-		panic("Fatal exception in interrupt");
-
-	if (panic_on_oops)
-		panic("Fatal exception");
-
-	do_exit(SIGSEGV);
-}
-
-static inline void die_if_kernel(const char *str, struct pt_regs *regs,
-				 long err)
-{
-	if (!user_mode(regs))
-		die(str, regs, err);
-}
-
-/*
- * try and fix up kernelspace address errors
- * - userspace errors just cause EFAULT to be returned, resulting in SEGV
- * - kernel/userspace interfaces cause a jump to an appropriate handler
- * - other kernel errors are bad
- */
-static void die_if_no_fixup(const char * str, struct pt_regs * regs, long err)
-{
-	if (!user_mode(regs)) {
-		const struct exception_table_entry *fixup;
-		fixup = search_exception_tables(regs->pc);
-		if (fixup) {
-			regs->pc = fixup->fixup;
-			return;
-		}
-
-		die(str, regs, err);
-	}
-}
-
 static inline void sign_extend(unsigned int count, unsigned char *dst)
 {
 #ifdef __LITTLE_ENDIAN__
diff --git a/arch/sh/kernel/traps_64.c b/arch/sh/kernel/traps_64.c
index c902c29400a..75bef61892d 100644
--- a/arch/sh/kernel/traps_64.c
+++ b/arch/sh/kernel/traps_64.c
@@ -41,37 +41,6 @@ asmlinkage void do_##name(unsigned long error_code, struct pt_regs *regs) \
 	do_unhandled_exception(trapnr, signr, str, __stringify(name), error_code, regs, current); \
 }
 
-static DEFINE_SPINLOCK(die_lock);
-
-void die(const char * str, struct pt_regs * re