[PATCH] powerpc/85xx: Add machine check handler to fix PCIe erratum on mpc85xx
Kumar Gala
galak at kernel.crashing.org
Sat Mar 17 07:35:15 EST 2012
On Feb 10, 2012, at 2:09 AM, <shuo.liu at freesacle.com> <shuo.liu at freesacle.com> wrote:
> From: Liu Shuo <shuo.liu at freescale.com>
>
> A PCIe erratum of mpc85xx may causes a core hang when a link of PCIe
> goes down. when the link goes down, Non-posted transactions issued
> via the ATMU requiring completion result in an instruction stall.
> At the same time a machine-check exception is generated to the core
> to allow further processing by the handler. We implements the handler
> which skips the instruction caused the stall.
>
> Signed-off-by: Zhao Chenhui <b35336 at freescale.com>
> Signed-off-by: Li Yang <leoli at freescale.com>
> Signed-off-by: Liu Shuo <b35362 at freescale.com>
> ---
> arch/powerpc/kernel/cpu_setup_fsl_booke.S | 2 +-
> arch/powerpc/kernel/traps.c | 3 ++
> arch/powerpc/sysdev/fsl_pci.c | 36 +++++++++++++++++++++++++++++
> arch/powerpc/sysdev/fsl_pci.h | 6 +++++
> 4 files changed, 46 insertions(+), 1 deletions(-)
>
> diff --git a/arch/powerpc/kernel/cpu_setup_fsl_booke.S b/arch/powerpc/kernel/cpu_setup_fsl_booke.S
> index 2c03ac2..beef028 100644
> --- a/arch/powerpc/kernel/cpu_setup_fsl_booke.S
> +++ b/arch/powerpc/kernel/cpu_setup_fsl_booke.S
> @@ -64,7 +64,7 @@ _GLOBAL(__setup_cpu_e500v2)
> bl __e500_icache_setup
> bl __e500_dcache_setup
> bl __setup_e500_ivors
> -#ifdef CONFIG_FSL_RIO
> +#if defined(CONFIG_FSL_RIO) || defined(CONFIG_FSL_PCI)
> /* Ensure that RFXE is set */
> mfspr r3,SPRN_HID1
> oris r3,r3,HID1_RFXE at h
> diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
> index 343c46b..1d6bcc0 100644
> --- a/arch/powerpc/kernel/traps.c
> +++ b/arch/powerpc/kernel/traps.c
> @@ -57,6 +57,7 @@
> #include <asm/kexec.h>
> #include <asm/ppc-opcode.h>
> #include <asm/rio.h>
> +#include <sysdev/fsl_pci.h>
>
> #if defined(CONFIG_DEBUGGER) || defined(CONFIG_KEXEC)
> int (*__debugger)(struct pt_regs *regs) __read_mostly;
> @@ -525,6 +526,8 @@ int machine_check_e500(struct pt_regs *regs)
> if (reason & MCSR_BUS_RBERR) {
> if (fsl_rio_mcheck_exception(regs))
> return 1;
> + if (fsl_pci_mcheck_exception(regs))
> + return 1;
> }
>
> printk("Machine check in kernel mode.\n");
> diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
> index 6bc3bfd..8ea23f0 100644
> --- a/arch/powerpc/sysdev/fsl_pci.c
> +++ b/arch/powerpc/sysdev/fsl_pci.c
> @@ -30,6 +30,7 @@
> #include <asm/io.h>
> #include <asm/prom.h>
> #include <asm/pci-bridge.h>
> +#include <asm/ppc-pci.h>
> #include <asm/machdep.h>
> #include <sysdev/fsl_soc.h>
> #include <sysdev/fsl_pci.h>
> @@ -727,3 +728,38 @@ u64 fsl_pci_immrbar_base(struct pci_controller *hose)
>
> return 0;
> }
> +
> +static int is_in_pci_mem_space(phys_addr_t addr)
> +{
> + struct pci_controller *hose;
> + struct resource *res;
> + int i;
> +
> + list_for_each_entry(hose, &hose_list, list_node) {
> + for (i = 0; i < 3; i++) {
> + res = &hose->mem_resources[i];
> + if ((res->flags & IORESOURCE_MEM) &&
> + addr >= res->start && addr <= res->end)
> + return 1;
> + }
> + }
> + return 0;
just move this into fsl_pci_mcheck_exception() no need for a separate function.
> +}
> +
> +int fsl_pci_mcheck_exception(struct pt_regs *regs)
> +{
> + phys_addr_t addr = 0;
> +
> +#ifdef CONFIG_PHYS_64BIT
> + addr = mfspr(SPRN_MCARU);
> + addr <<= 32;
> +#endif
> + addr += mfspr(SPRN_MCAR);
> +
> + if (is_in_pci_mem_space(addr)) {
> + regs->nip += 4;
> + return 1;
> + }
> +
> + return 0;
> +}
> diff --git a/arch/powerpc/sysdev/fsl_pci.h b/arch/powerpc/sysdev/fsl_pci.h
> index a39ed5c..96b07ce 100644
> --- a/arch/powerpc/sysdev/fsl_pci.h
> +++ b/arch/powerpc/sysdev/fsl_pci.h
> @@ -93,5 +93,11 @@ extern void fsl_pcibios_fixup_bus(struct pci_bus *bus);
> extern int mpc83xx_add_bridge(struct device_node *dev);
> u64 fsl_pci_immrbar_base(struct pci_controller *hose);
>
> +#ifdef CONFIG_FSL_PCI
> +extern int fsl_pci_mcheck_exception(struct pt_regs *);
> +#else
> +static inline int fsl_pci_mcheck_exception(struct pt_regs *regs) {return 0; }
Add space after {
> +#endif
> +
> #endif /* __POWERPC_FSL_PCI_H */
> #endif /* __KERNEL__ */
> --
> 1.7.1
>
>
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev at lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
More information about the Linuxppc-dev
mailing list