powerpc/e500: fix breakage with fsl_rio_mcheck_exception
Scott Wood [Thu, 16 Jun 2011 19:09:17 +0000 (14:09 -0500)]
The wrong MCSR bit was being used on e500mc.  MCSR_BUS_RBERR only exists
on e500v1/v2.  Use MCSR_LD on e500mc, and remove all MCSR checking
in fsl_rio_mcheck_exception as we now no longer call that function
if the appropriate bit in MCSR is not set.

If RIO support was enabled at compile-time, but was never probed, just
return from fsl_rio_mcheck_exception rather than dereference a NULL
pointer.

TODO: There is still a remaining, though comparitively minor, issue in
that this recovery mechanism will falsely engage if there's an unrelated
MCSR_LD event at the same time as a RIO error.

Signed-off-by: Scott Wood <scottwood@freescale.com>
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>

arch/powerpc/kernel/traps.c
arch/powerpc/sysdev/fsl_rio.c

index 0ff4ab9..6414a0d 100644 (file)
@@ -425,7 +425,7 @@ int machine_check_e500mc(struct pt_regs *regs)
        unsigned long reason = mcsr;
        int recoverable = 1;
 
-       if (reason & MCSR_BUS_RBERR) {
+       if (reason & MCSR_LD) {
                recoverable = fsl_rio_mcheck_exception(regs);
                if (recoverable == 1)
                        goto silent_out;
index 5b206a2..b3fd081 100644 (file)
@@ -283,23 +283,24 @@ static void __iomem *rio_regs_win;
 #ifdef CONFIG_E500
 int fsl_rio_mcheck_exception(struct pt_regs *regs)
 {
-       const struct exception_table_entry *entry = NULL;
-       unsigned long reason = mfspr(SPRN_MCSR);
-
-       if (reason & MCSR_BUS_RBERR) {
-               reason = in_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR));
-               if (reason & (RIO_LTLEDCSR_IER | RIO_LTLEDCSR_PRT)) {
-                       /* Check if we are prepared to handle this fault */
-                       entry = search_exception_tables(regs->nip);
-                       if (entry) {
-                               pr_debug("RIO: %s - MC Exception handled\n",
-                                        __func__);
-                               out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR),
-                                        0);
-                               regs->msr |= MSR_RI;
-                               regs->nip = entry->fixup;
-                               return 1;
-                       }
+       const struct exception_table_entry *entry;
+       unsigned long reason;
+
+       if (!rio_regs_win)
+               return 0;
+
+       reason = in_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR));
+       if (reason & (RIO_LTLEDCSR_IER | RIO_LTLEDCSR_PRT)) {
+               /* Check if we are prepared to handle this fault */
+               entry = search_exception_tables(regs->nip);
+               if (entry) {
+                       pr_debug("RIO: %s - MC Exception handled\n",
+                                __func__);
+                       out_be32((u32 *)(rio_regs_win + RIO_LTLEDCSR),
+                                0);
+                       regs->msr |= MSR_RI;
+                       regs->nip = entry->fixup;
+                       return 1;
                }
        }