Subject: [PATCH 3/5] MIPS: Octeon: Use board_cache_error_setup for cache error handler setup.

From: David Daney <[email-masked]>
Date: Mon, 19 Dec 2011 15:16:40 -0800

From: David Daney <[email-masked]>

Signed-off-by: David Daney <[email-masked]>
---
 arch/mips/mm/c-octeon.c |   14 ++++++++------
 1 files changed, 8 insertions(+), 6 deletions(-)

diff --git a/arch/mips/mm/c-octeon.c b/arch/mips/mm/c-octeon.c
index cf7895d..2d99a1d 100644
--- a/arch/mips/mm/c-octeon.c
+++ b/arch/mips/mm/c-octeon.c
@@ -22,6 +22,7 @@
 #include <asm/pgtable.h>
 #include <asm/r4kcache.h>
 #include <asm/system.h>
+#include <asm/traps.h>
 #include <asm/mmu_context.h>
 #include <asm/war.h>
 
@@ -249,6 +250,11 @@ static void __cpuinit probe_octeon(void)
 	}
 }
 
+static void  __cpuinit octeon_cache_error_setup(void)
+{
+	extern char except_vec2_octeon;
+	set_handler(0x100, &except_vec2_octeon, 0x80);
+}
 
 /**
  * Setup the Octeon cache flush routines
@@ -256,12 +262,6 @@ static void __cpuinit probe_octeon(void)
  */
 void __cpuinit octeon_cache_init(void)
 {
-	extern unsigned long ebase;
-	extern char except_vec2_octeon;
-
-	memcpy((void *)(ebase + 0x100), &except_vec2_octeon, 0x80);
-	octeon_flush_cache_sigtramp(ebase + 0x100);
-
 	probe_octeon();
 
 	shm_align_mask = PAGE_SIZE - 1;
@@ -281,6 +281,8 @@ void __cpuinit octeon_cache_init(void)
 
 	build_clear_page();
 	build_copy_page();
+
+	board_cache_error_setup = octeon_cache_error_setup;
 }
 
 /**
-- 
1.7.2.3

---

From: David Daney <[email-masked]>
Date: Mon, 19 Dec 2011 15:16:38 -0800

This is used in subsequent patches.

Signed-off-by: David Daney <[email-masked]>
---
 arch/mips/include/asm/traps.h |    1 +
 arch/mips/kernel/traps.c      |    5 ++++-
 2 files changed, 5 insertions(+), 1 deletions(-)

diff --git a/arch/mips/include/asm/traps.h b/arch/mips/include/asm/traps.h
index 90ff2f4..d4d0e76 100644
--- a/arch/mips/include/asm/traps.h
+++ b/arch/mips/include/asm/traps.h
@@ -24,5 +24,6 @@ extern int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
 extern void (*board_nmi_handler_setup)(void);
 extern void (*board_ejtag_handler_setup)(void);
 extern void (*board_bind_eic_interrupt)(int irq, int regset);
+extern void (*board_cache_error_setup)(void);
 
 #endif /* _ASM_TRAPS_H */
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 363c476..f305c04 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -91,7 +91,7 @@ int (*board_be_handler)(struct pt_regs *regs, int is_fixup);
 void (*board_nmi_handler_setup)(void);
 void (*board_ejtag_handler_setup)(void);
 void (*board_bind_eic_interrupt)(int irq, int regset);
-
+void __cpuinitdata(*board_cache_error_setup)(void);
 
 static void show_raw_backtrace(unsigned long reg29)
 {
@@ -1786,6 +1786,9 @@ void __init trap_init(void)
 
 	set_except_vector(26, handle_dsp);
 
+	if (board_cache_error_setup)
+		board_cache_error_setup();
+
 	if (cpu_has_vce)
 		/* Special exception: R4[04]00 uses also the divec space. */
 		memcpy((void *)(ebase + 0x180), &except_vec3_r4000, 0x100);
-- 
1.7.2.3

---

From: David Daney <[email-masked]>
Date: Mon, 19 Dec 2011 15:16:37 -0800

Found on 3.2-rc4, if jump label things are enabled, the kernel will
not boot on MIPS.

As noted in patch 5/5, this was caused by: commit
97ce2c88f9ad42e3c60a9beb9fca87abf3639faa (jump-label: initialize
jump-label subsystem much earlier).

The fix is to make flush_icache_range() usable earlier.  I do this by
calling cpu_cache_init() from setup_arch().  For the boot CPU we can
no longer call this from per_cpu_trap_init(), so I add a flag to that
function so we can skip the call if on the boot CPU.

Some of the code in the various cpu_cache_init() functions however
could not be called this early, so I moved it into functions called by
the new board_cache_error_setup() hook.

Tested on Octeon and ip32-R5000

David Daney (5):
  MIPS: Introduce board_cache_error_setup() hook.
  MIPS: Make set_handler() __cpuinit.
  MIPS: Octeon: Use board_cache_error_setup for cache error handler
    setup.
  MIPS: Use board_cache_error_setup for r4k cache error handler setup.
  MIPS: Move cache setup to setup_arch().

 arch/mips/include/asm/system.h |    2 +-
 arch/mips/include/asm/traps.h  |    1 +
 arch/mips/kernel/setup.c       |    3 +++
 arch/mips/kernel/smp.c         |    2 +-
 arch/mips/kernel/traps.c       |   15 ++++++++++-----
 arch/mips/mm/c-octeon.c        |   14 ++++++++------
 arch/mips/mm/c-r4k.c           |   14 ++++++++++----
 7 files changed, 34 insertions(+), 17 deletions(-)

-- 
1.7.2.3

---

From: David Daney <[email-masked]>
Date: Mon, 19 Dec 2011 15:16:41 -0800

Signed-off-by: David Daney <[email-masked]>
---
 arch/mips/mm/c-r4k.c |   14 ++++++++++----
 1 files changed, 10 insertions(+), 4 deletions(-)

diff --git a/arch/mips/mm/c-r4k.c b/arch/mips/mm/c-r4k.c
index a79fe9a..036c004 100644
--- a/arch/mips/mm/c-r4k.c
+++ b/arch/mips/mm/c-r4k.c
@@ -33,7 +33,7 @@
 #include <asm/mmu_context.h>
 #include <asm/war.h>
 #include <asm/cacheflush.h> /* for run_uncached() */
-
+#include <asm/traps.h>
 
 /*
  * Special Variant of smp_call_function for use by cache functions:
@@ -1383,10 +1383,8 @@ static int __init setcoherentio(char *str)
 __setup("coherentio", setcoherentio);
 #endif
 
-void __cpuinit r4k_cache_init(void)
+static void __cpuinit r4k_cache_error_setup(void)
 {
-	extern void build_clear_page(void);
-	extern void build_copy_page(void);
 	extern char __weak except_vec2_generic;
 	extern char __weak except_vec2_sb1;
 	struct cpuinfo_mips *c = &current_cpu_data;
@@ -1401,6 +1399,13 @@ void __cpuinit r4k_cache_init(void)
 		set_uncached_handler(0x100, &except_vec2_generic, 0x80);
 		break;
 	}
+}
+
+void __cpuinit r4k_cache_init(void)
+{
+	extern void build_clear_page(void);
+	extern void build_copy_page(void);
+	struct cpuinfo_mips *c = &current_cpu_data;
 
 	probe_pcache();
 	setup_scache();
@@ -1463,4 +1468,5 @@ void __cpuinit r4k_cache_init(void)
 	local_r4k___flush_cache_all(NULL);
 #endif
 	coherency_setup();
+	board_cache_error_setup = r4k_cache_error_setup;
 }
-- 
1.7.2.3

---

From: David Daney <[email-masked]>
Date: Mon, 19 Dec 2011 15:16:39 -0800

Follow-on patched require this.

Signed-off-by: David Daney <[email-masked]>
---
 arch/mips/kernel/traps.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index f305c04..0430700 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1623,7 +1623,7 @@ void __cpuinit per_cpu_trap_init(void)
 }
 
 /* Install CPU exception handler */
-void __init set_handler(unsigned long offset, void *addr, unsigned long size)
+void __cpuinit set_handler(unsigned long offset, void *addr, unsigned long size)
 {
 	memcpy((void *)(ebase + offset), addr, size);
 	local_flush_icache_range(ebase + offset, ebase + offset + size);
-- 
1.7.2.3

---

From: David Daney <[email-masked]>
Date: Mon, 19 Dec 2011 15:16:42 -0800

commit 97ce2c88f9ad42e3c60a9beb9fca87abf3639faa (jump-label: initialize
jump-label subsystem much earlier) breaks MIPS.  The jump_label_init()
call was moved before trap_init() which is where we initialize
flush_icache_range().

In order to be good citizens, we move cache initialization earlier so
that we don't jump through a null flush_icache_range function pointer
when doing the jump label initialization.

Signed-off-by: David Daney <[email-masked]>
---
 arch/mips/include/asm/system.h |    2 +-
 arch/mips/kernel/setup.c       |    3 +++
 arch/mips/kernel/smp.c         |    2 +-
 arch/mips/kernel/traps.c       |    8 +++++---
 4 files changed, 10 insertions(+), 5 deletions(-)

diff --git a/arch/mips/include/asm/system.h b/arch/mips/include/asm/system.h
index 6018c80..28f16a2 100644
--- a/arch/mips/include/asm/system.h
+++ b/arch/mips/include/asm/system.h
@@ -222,7 +222,7 @@ extern void *set_vi_handler(int n, vi_handler_t addr);
 
 extern void *set_except_vector(int n, void *addr);
 extern unsigned long ebase;
-extern void per_cpu_trap_init(void);
+extern void per_cpu_trap_init(bool);
 
 /*
  * See include/asm-ia64/system.h; prevents deadlock on SMP
diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c
index 84af26a..2e0bb49 100644
--- a/arch/mips/kernel/setup.c
+++ b/arch/mips/kernel/setup.c
@@ -547,6 +547,7 @@ static void __init resource_init(void)
 	}
 }
 
+extern void cpu_cache_init(void);
 void __init setup_arch(char **cmdline_p)
 {
 	cpu_probe();
@@ -570,6 +571,8 @@ void __init setup_arch(char **cmdline_p)
 
 	resource_init();
 	plat_smp_setup();
+
+	cpu_cache_init();
 }
 
 unsigned long kernelsp[NR_CPUS];
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c
index 32c1e95..43cd1ed 100644
--- a/arch/mips/kernel/smp.c
+++ b/arch/mips/kernel/smp.c
@@ -106,7 +106,7 @@ asmlinkage __cpuinit void start_secondary(void)
 #endif /* CONFIG_MIPS_MT_SMTC */
 	cpu_probe();
 	cpu_report();
-	per_cpu_trap_init();
+	per_cpu_trap_init(false);
 	mips_clockevent_init();
 	mp_ops->init_secondary();
 
diff --git a/arch/mips/kernel/traps.c b/arch/mips/kernel/traps.c
index 0430700..0d55eb8 100644
--- a/arch/mips/kernel/traps.c
+++ b/arch/mips/kernel/traps.c
@@ -1508,7 +1508,7 @@ static int __init ulri_disable(char *s)
 }
 __setup("noulri", ulri_disable);
 
-void __cpuinit per_cpu_trap_init(void)
+void __cpuinit per_cpu_trap_init(bool is_boot_cpu)
 {
 	unsigned int cpu = smp_processor_id();
 	unsigned int status_set = ST0_CU0;
@@ -1607,7 +1607,9 @@ void __cpuinit per_cpu_trap_init(void)
 #ifdef CONFIG_MIPS_MT_SMTC
 	if (bootTC) {
 #endif /* CONFIG_MIPS_MT_SMTC */
-		cpu_cache_init();
+		/* Boot CPU's cache setup in setup_arch(). */
+		if (!is_boot_cpu)
+			cpu_cache_init();
 		tlb_init();
 #ifdef CONFIG_MIPS_MT_SMTC
 	} else if (!secondaryTC) {
@@ -1682,7 +1684,7 @@ void __init trap_init(void)
 			ebase += (read_c0_ebase() & 0x3ffff000);
 	}
 
-	per_cpu_trap_init();
+	per_cpu_trap_init(true);
 
 	/*
 	 * Copy the generic exception handlers to their final destination.
-- 
1.7.2.3