]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
powerpc/476: add machine check handler for 47x core
authorDave Kleikamp <shaggy@linux.vnet.ibm.com>
Fri, 5 Mar 2010 03:43:18 +0000 (03:43 +0000)
committerJosh Boyer <jwboyer@linux.vnet.ibm.com>
Wed, 5 May 2010 13:27:22 +0000 (09:27 -0400)
The 47x core's MCSR varies from 44x, so it needs it's own machine check
handler.

Signed-off-by: Dave Kleikamp <shaggy@linux.vnet.ibm.com>
Signed-off-by: Josh Boyer <jwboyer@linux.vnet.ibm.com>
arch/powerpc/include/asm/cputable.h
arch/powerpc/kernel/cputable.c
arch/powerpc/kernel/traps.c

index 97ab5089df6707d9146f2e3c0d0c0fd072e1c026..e3cba4e1eb347368307c83906c3845a017bc8aee 100644 (file)
@@ -72,6 +72,7 @@ extern int machine_check_4xx(struct pt_regs *regs);
 extern int machine_check_440A(struct pt_regs *regs);
 extern int machine_check_e500(struct pt_regs *regs);
 extern int machine_check_e200(struct pt_regs *regs);
+extern int machine_check_47x(struct pt_regs *regs);
 
 /* NOTE WELL: Update identify_cpu() if fields are added or removed! */
 struct cpu_spec {
index a1d8458397278b8319f790b870b2309a98cc8d3f..ad6baf834a76330601aeb2cb2b05ec796719fe8f 100644 (file)
@@ -1712,6 +1712,7 @@ static struct cpu_spec __initdata cpu_specs[] = {
                        MMU_FTR_USE_TLBIVAX_BCAST | MMU_FTR_LOCK_BCAST_INVAL,
                .icache_bsize           = 32,
                .dcache_bsize           = 128,
+               .machine_check          = machine_check_47x,
                .platform               = "ppc470",
        },
        {       /* default match */
index 29d128eb6c4353745e05e50534317b08c24ebe68..ca7ce85ebc2efc73476250e520d554abcf121ba0 100644 (file)
@@ -380,6 +380,46 @@ int machine_check_440A(struct pt_regs *regs)
        }
        return 0;
 }
+
+int machine_check_47x(struct pt_regs *regs)
+{
+       unsigned long reason = get_mc_reason(regs);
+       u32 mcsr;
+
+       printk(KERN_ERR "Machine check in kernel mode.\n");
+       if (reason & ESR_IMCP) {
+               printk(KERN_ERR
+                      "Instruction Synchronous Machine Check exception\n");
+               mtspr(SPRN_ESR, reason & ~ESR_IMCP);
+               return 0;
+       }
+       mcsr = mfspr(SPRN_MCSR);
+       if (mcsr & MCSR_IB)
+               printk(KERN_ERR "Instruction Read PLB Error\n");
+       if (mcsr & MCSR_DRB)
+               printk(KERN_ERR "Data Read PLB Error\n");
+       if (mcsr & MCSR_DWB)
+               printk(KERN_ERR "Data Write PLB Error\n");
+       if (mcsr & MCSR_TLBP)
+               printk(KERN_ERR "TLB Parity Error\n");
+       if (mcsr & MCSR_ICP) {
+               flush_instruction_cache();
+               printk(KERN_ERR "I-Cache Parity Error\n");
+       }
+       if (mcsr & MCSR_DCSP)
+               printk(KERN_ERR "D-Cache Search Parity Error\n");
+       if (mcsr & PPC47x_MCSR_GPR)
+               printk(KERN_ERR "GPR Parity Error\n");
+       if (mcsr & PPC47x_MCSR_FPR)
+               printk(KERN_ERR "FPR Parity Error\n");
+       if (mcsr & PPC47x_MCSR_IPR)
+               printk(KERN_ERR "Machine Check exception is imprecise\n");
+
+       /* Clear MCSR */
+       mtspr(SPRN_MCSR, mcsr);
+
+       return 0;
+}
 #elif defined(CONFIG_E500)
 int machine_check_e500(struct pt_regs *regs)
 {