diff mbox

powerpc/85xx: Add machine check handler to fix PCIe erratum on mpc85xx

Message ID 1328861387-31390-1-git-send-email-shuo.liu@freesacle.com (mailing list archive)
State Changes Requested
Delegated to: Kumar Gala
Headers show

Commit Message

shuo.liu@freesacle.com Feb. 10, 2012, 8:09 a.m. UTC
From: Liu Shuo <shuo.liu@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@freescale.com>
Signed-off-by: Li Yang <leoli@freescale.com>
Signed-off-by: Liu Shuo <b35362@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(-)

Comments

Kumar Gala March 16, 2012, 8:35 p.m. UTC | #1
On Feb 10, 2012, at 2:09 AM, <shuo.liu@freesacle.com> <shuo.liu@freesacle.com> wrote:

> From: Liu Shuo <shuo.liu@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@freescale.com>
> Signed-off-by: Li Yang <leoli@freescale.com>
> Signed-off-by: Liu Shuo <b35362@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@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@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
Scott Wood March 16, 2012, 8:42 p.m. UTC | #2
On 03/16/2012 03:35 PM, Kumar Gala wrote:
> On Feb 10, 2012, at 2:09 AM, <shuo.liu@freesacle.com> <shuo.liu@freesacle.com> wrote:
>> +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.

A separate function increases readability.

-Scott
Kumar Gala March 16, 2012, 9:03 p.m. UTC | #3
On Mar 16, 2012, at 3:42 PM, Scott Wood wrote:

> On 03/16/2012 03:35 PM, Kumar Gala wrote:
>> On Feb 10, 2012, at 2:09 AM, <shuo.liu@freesacle.com> <shuo.liu@freesacle.com> wrote:
>>> +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.
> 
> A separate function increases readability.
> 
> -Scott

I'll accept that.

- k
Kumar Gala March 16, 2012, 9:03 p.m. UTC | #4
On Feb 10, 2012, at 2:09 AM, <shuo.liu@freesacle.com> <shuo.liu@freesacle.com> wrote:

> From: Liu Shuo <shuo.liu@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@freescale.com>
> Signed-off-by: Li Yang <leoli@freescale.com>
> Signed-off-by: Liu Shuo <b35362@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(-)

Should we have a check to make sure the hose is for PCIe and not PCI?

- k
Hongtao Jia March 26, 2012, 6:14 a.m. UTC | #5
> -----Original Message-----
> From: linuxppc-dev-bounces+b38951=freescale.com@lists.ozlabs.org
> [mailto:linuxppc-dev-bounces+b38951=freescale.com@lists.ozlabs.org] On
> Behalf Of Kumar Gala
> Sent: Saturday, March 17, 2012 5:04 AM
> To: <shuo.liu@freesacle.com>
> Cc: Zhao Chenhui-B35336; Liu Shuo-B35362; Zang Roy-R61911; Liu Shuo-
> B35362; Wood Scott-B07421; linuxppc-dev@lists.ozlabs.org
> Subject: Re: [PATCH] powerpc/85xx: Add machine check handler to fix PCIe
> erratum on mpc85xx
> 
> 
> On Feb 10, 2012, at 2:09 AM, <shuo.liu@freesacle.com>
> <shuo.liu@freesacle.com> wrote:
> 
> > From: Liu Shuo <shuo.liu@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@freescale.com>
> > Signed-off-by: Li Yang <leoli@freescale.com>
> > Signed-off-by: Liu Shuo <b35362@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(-)
> 
> Should we have a check to make sure the hose is for PCIe and not PCI?
> 
> - k

Due to errata spec pcie check is necessary.
I will send a new version of this patch to solve this problem soon.

Thanks.

Btw, from now on I will follow this patch instead of Liu Shuo.
- Jia Hongtao.
diff mbox

Patch

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@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;
+}
+
+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; }
+#endif
+
 #endif /* __POWERPC_FSL_PCI_H */
 #endif /* __KERNEL__ */