LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 06/10] powerpc/eeh: Support blocked IO access
From: Gavin Shan @ 2013-06-25  5:55 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Gavin Shan
In-Reply-To: <1372139717-14885-1-git-send-email-shangw@linux.vnet.ibm.com>

The patch intends to support blocking IO access. Basically, if
the EEH core detects that the IO access has been blocked on one
specific PHB, we will simply return 0xFF's for reading and drop
writing.

Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/eeh.h               |  231 +++++++++++++++++++++-----
 arch/powerpc/include/asm/io.h                |   67 +++++---
 arch/powerpc/kernel/eeh.c                    |   50 ++++--
 arch/powerpc/platforms/powernv/eeh-powernv.c |    4 +-
 4 files changed, 269 insertions(+), 83 deletions(-)

diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
index de821c1..a8dd983 100644
--- a/arch/powerpc/include/asm/eeh.h
+++ b/arch/powerpc/include/asm/eeh.h
@@ -211,7 +211,9 @@ void eeh_dev_phb_init_dynamic(struct pci_controller *phb);
 int __init eeh_init(void);
 int __init eeh_ops_register(struct eeh_ops *ops);
 int __exit eeh_ops_unregister(const char *name);
-unsigned long eeh_check_failure(const volatile void __iomem *token,
+int eeh_check_blocked_io(const volatile void __iomem *token,
+			 void **pedev);
+unsigned long eeh_check_failure(struct eeh_dev *edev,
 				unsigned long val);
 int eeh_dev_check_failure(struct eeh_dev *edev);
 void __init eeh_addr_cache_build(void);
@@ -249,7 +251,13 @@ static inline void *eeh_dev_init(struct device_node *dn, void *data)
 
 static inline void eeh_dev_phb_init_dynamic(struct pci_controller *phb) { }
 
-static inline unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned long val)
+int eeh_check_blocked_io(const volatile void __iomem *token,
+			 void **pedev)
+{
+	return 0;
+}
+
+static inline unsigned long eeh_check_failure(void *data, unsigned long val)
 {
 	return val;
 }
@@ -276,57 +284,99 @@ static inline void eeh_remove_bus_device(struct pci_dev *dev, int purge_pe) { }
  */
 static inline u8 eeh_readb(const volatile void __iomem *addr)
 {
-	u8 val = in_8(addr);
-	if (EEH_POSSIBLE_ERROR(val, u8))
-		return eeh_check_failure(addr, val);
+	u8 val = 0xFF;
+	void *edev;
+
+	if (!eeh_check_blocked_io(addr, &edev)) {
+		val = in_8(addr);
+		if (EEH_POSSIBLE_ERROR(val, u8))
+			return eeh_check_failure(edev, val);
+	}
+
 	return val;
 }
 
 static inline u16 eeh_readw(const volatile void __iomem *addr)
 {
-	u16 val = in_le16(addr);
-	if (EEH_POSSIBLE_ERROR(val, u16))
-		return eeh_check_failure(addr, val);
+	u16 val = 0xFFFF;
+	void *edev;
+
+	if (!eeh_check_blocked_io(addr, &edev)) {
+		val = in_le16(addr);
+		if (EEH_POSSIBLE_ERROR(val, u16))
+			return eeh_check_failure(edev, val);
+	}
+
 	return val;
 }
 
 static inline u32 eeh_readl(const volatile void __iomem *addr)
 {
-	u32 val = in_le32(addr);
-	if (EEH_POSSIBLE_ERROR(val, u32))
-		return eeh_check_failure(addr, val);
+	u32 val = 0xFFFFFFFF;
+	void *edev;
+
+	if (!eeh_check_blocked_io(addr, &edev)) {
+		val = in_le32(addr);
+		if (EEH_POSSIBLE_ERROR(val, u32))
+			return eeh_check_failure(edev, val);
+	}
+
 	return val;
 }
 
 static inline u64 eeh_readq(const volatile void __iomem *addr)
 {
-	u64 val = in_le64(addr);
-	if (EEH_POSSIBLE_ERROR(val, u64))
-		return eeh_check_failure(addr, val);
+	u64 val = 0xFFFFFFFFFFFFFFFF;
+	void *edev;
+
+	if (!eeh_check_blocked_io(addr, &edev)) {
+		val = in_le64(addr);
+		if (EEH_POSSIBLE_ERROR(val, u64))
+			return eeh_check_failure(edev, val);
+	}
+
 	return val;
 }
 
 static inline u16 eeh_readw_be(const volatile void __iomem *addr)
 {
-	u16 val = in_be16(addr);
-	if (EEH_POSSIBLE_ERROR(val, u16))
-		return eeh_check_failure(addr, val);
+	u16 val = 0xFFFF;
+	void *edev;
+
+	if (!eeh_check_blocked_io(addr, &edev)) {
+		val = in_be16(addr);
+		if (EEH_POSSIBLE_ERROR(val, u16))
+			return eeh_check_failure(edev, val);
+	}
+
 	return val;
 }
 
 static inline u32 eeh_readl_be(const volatile void __iomem *addr)
 {
-	u32 val = in_be32(addr);
-	if (EEH_POSSIBLE_ERROR(val, u32))
-		return eeh_check_failure(addr, val);
+	u32 val = 0xFFFFFFFF;
+	void *edev;
+
+	if (!eeh_check_blocked_io(addr, &edev)) {
+		val = in_be32(addr);
+		if (EEH_POSSIBLE_ERROR(val, u32))
+			return eeh_check_failure(edev, val);
+	}
+
 	return val;
 }
 
 static inline u64 eeh_readq_be(const volatile void __iomem *addr)
 {
-	u64 val = in_be64(addr);
-	if (EEH_POSSIBLE_ERROR(val, u64))
-		return eeh_check_failure(addr, val);
+	u64 val = 0xFFFFFFFFFFFFFFFF;
+	void *edev;
+
+	if (!eeh_check_blocked_io(addr, &edev)) {
+		val = in_be64(addr);
+		if (EEH_POSSIBLE_ERROR(val, u64))
+			return eeh_check_failure(edev, val);
+	}
+
 	return val;
 }
 
@@ -334,40 +384,145 @@ static inline void eeh_memcpy_fromio(void *dest, const
 				     volatile void __iomem *src,
 				     unsigned long n)
 {
-	_memcpy_fromio(dest, src, n);
+	void *edev;
+
+	memset(dest, 0xFF, n);
+
+	if (!eeh_check_blocked_io(src, &edev)) {
+		_memcpy_fromio(dest, src, n);
 
-	/* Look for ffff's here at dest[n].  Assume that at least 4 bytes
-	 * were copied. Check all four bytes.
-	 */
-	if (n >= 4 && EEH_POSSIBLE_ERROR(*((u32 *)(dest + n - 4)), u32))
-		eeh_check_failure(src, *((u32 *)(dest + n - 4)));
+		/*
+		 * Look for ffff's here at dest[n]. Assume that at
+		 * least 4 bytes were copied. Check all four bytes.
+		 */
+		if (n >= 4 && EEH_POSSIBLE_ERROR(*((u32 *)(dest + n - 4)), u32))
+			eeh_check_failure(edev, *((u32 *)(dest + n - 4)));
+	}
 }
 
 /* in-string eeh macros */
 static inline void eeh_readsb(const volatile void __iomem *addr, void * buf,
 			      int ns)
 {
-	_insb(addr, buf, ns);
-	if (EEH_POSSIBLE_ERROR((*(((u8*)buf)+ns-1)), u8))
-		eeh_check_failure(addr, *(u8*)buf);
+	void *edev;
+
+	memset(buf, 0xFF, ns);
+
+	if (!eeh_check_blocked_io(addr, &edev)) {
+		_insb(addr, buf, ns);
+		if (EEH_POSSIBLE_ERROR((*(((u8*)buf)+ns-1)), u8))
+			eeh_check_failure(edev, *(u8*)buf);
+	}
 }
 
 static inline void eeh_readsw(const volatile void __iomem *addr, void * buf,
 			      int ns)
 {
-	_insw(addr, buf, ns);
-	if (EEH_POSSIBLE_ERROR((*(((u16*)buf)+ns-1)), u16))
-		eeh_check_failure(addr, *(u16*)buf);
+	void *edev;
+
+	memset(buf, 0xFF, ns * sizeof(u16));
+
+	if (!eeh_check_blocked_io(addr, &edev)) {
+		_insw(addr, buf, ns);
+		if (EEH_POSSIBLE_ERROR((*(((u16*)buf)+ns-1)), u16))
+			eeh_check_failure(edev, *(u16*)buf);
+	}
 }
 
 static inline void eeh_readsl(const volatile void __iomem *addr, void * buf,
 			      int nl)
 {
-	_insl(addr, buf, nl);
-	if (EEH_POSSIBLE_ERROR((*(((u32*)buf)+nl-1)), u32))
-		eeh_check_failure(addr, *(u32*)buf);
+	void *edev;
+
+	memset(buf, 0xFF, nl * sizeof(u32));
+
+	if (!eeh_check_blocked_io(addr, &edev)) {
+		_insl(addr, buf, nl);
+		if (EEH_POSSIBLE_ERROR((*(((u32*)buf)+nl-1)), u32))
+			eeh_check_failure(edev, *(u32*)buf);
+	}
+}
+
+/* MMIO write */
+static inline void eeh_writeb(volatile u8 __iomem *addr, u8 val)
+{
+	if (!eeh_check_blocked_io(addr, NULL))
+		out_8(addr, val);
+}
+
+static inline void eeh_writew(volatile u16 __iomem *addr, u16 val)
+{
+	if (!eeh_check_blocked_io(addr, NULL))
+		out_le16(addr, val);
 }
 
+static inline void eeh_writel(volatile u32 __iomem *addr, u32 val)
+{
+	if (!eeh_check_blocked_io(addr, NULL))
+		out_le32(addr, val);
+}
+
+static inline void eeh_writeq(volatile u64 __iomem *addr, u64 val)
+{
+	if (!eeh_check_blocked_io(addr, NULL))
+		out_le64(addr, val);
+}
+
+static inline void eeh_writew_be(volatile u16 __iomem *addr, u16 val)
+{
+	if (!eeh_check_blocked_io(addr, NULL))
+		out_be16(addr, val);
+}
+
+static inline void eeh_writel_be(volatile u32 __iomem *addr, u32 val)
+{
+	if (!eeh_check_blocked_io(addr, NULL))
+		out_be32(addr, val);
+}
+
+static inline void eeh_writeq_be(volatile u64 __iomem *addr, u64 val)
+{
+	if (!eeh_check_blocked_io(addr, NULL))
+		out_be64(addr, val);
+}
+
+static inline void eeh_writesb(volatile u8 __iomem *addr,
+			       const void *buf, long count)
+{
+	if (!eeh_check_blocked_io(addr, NULL))
+		_outsb(addr, buf, count);
+}
+
+static inline void eeh_writesw(volatile u16 __iomem *addr,
+			       const void *buf, long count)
+{
+	if (!eeh_check_blocked_io(addr, NULL))
+		_outsw(addr, buf, count);
+}
+
+static inline void eeh_writesl(volatile u32 __iomem *addr,
+			       const void *buf, long count)
+{
+	if (!eeh_check_blocked_io(addr, NULL))
+		_outsl(addr, buf, count);
+}
+
+static inline void eeh_memset_io(volatile void __iomem *addr,
+				 int c, unsigned long n)
+{
+	if (!eeh_check_blocked_io(addr, NULL))
+		_memset_io(addr, c, n);
+}
+
+static inline void eeh_memcpy_toio(volatile void __iomem *dest,
+				   const void *src, unsigned long n)
+{
+	if (!eeh_check_blocked_io(dest, NULL))
+		_memcpy_toio(dest, src, n);
+}
+
+
+
 #endif /* CONFIG_PPC64 */
 #endif /* __KERNEL__ */
 #endif /* _POWERPC_EEH_H */
diff --git a/arch/powerpc/include/asm/io.h b/arch/powerpc/include/asm/io.h
index dd15e5e..fa58c45 100644
--- a/arch/powerpc/include/asm/io.h
+++ b/arch/powerpc/include/asm/io.h
@@ -412,30 +412,37 @@ __do_out_asm(_rec_outl, "stwbrx")
  * possible to hook directly at the toplevel PIO operation if they have to
  * be handled differently
  */
-#define __do_writeb(val, addr)	out_8(PCI_FIX_ADDR(addr), val)
-#define __do_writew(val, addr)	out_le16(PCI_FIX_ADDR(addr), val)
-#define __do_writel(val, addr)	out_le32(PCI_FIX_ADDR(addr), val)
-#define __do_writeq(val, addr)	out_le64(PCI_FIX_ADDR(addr), val)
-#define __do_writew_be(val, addr) out_be16(PCI_FIX_ADDR(addr), val)
-#define __do_writel_be(val, addr) out_be32(PCI_FIX_ADDR(addr), val)
-#define __do_writeq_be(val, addr) out_be64(PCI_FIX_ADDR(addr), val)
 
 #ifdef CONFIG_EEH
-#define __do_readb(addr)	eeh_readb(PCI_FIX_ADDR(addr))
-#define __do_readw(addr)	eeh_readw(PCI_FIX_ADDR(addr))
-#define __do_readl(addr)	eeh_readl(PCI_FIX_ADDR(addr))
-#define __do_readq(addr)	eeh_readq(PCI_FIX_ADDR(addr))
-#define __do_readw_be(addr)	eeh_readw_be(PCI_FIX_ADDR(addr))
-#define __do_readl_be(addr)	eeh_readl_be(PCI_FIX_ADDR(addr))
-#define __do_readq_be(addr)	eeh_readq_be(PCI_FIX_ADDR(addr))
+#define __do_readb(addr)		eeh_readb(PCI_FIX_ADDR(addr))
+#define __do_readw(addr)		eeh_readw(PCI_FIX_ADDR(addr))
+#define __do_readl(addr)		eeh_readl(PCI_FIX_ADDR(addr))
+#define __do_readq(addr)		eeh_readq(PCI_FIX_ADDR(addr))
+#define __do_readw_be(addr)		eeh_readw_be(PCI_FIX_ADDR(addr))
+#define __do_readl_be(addr)		eeh_readl_be(PCI_FIX_ADDR(addr))
+#define __do_readq_be(addr)		eeh_readq_be(PCI_FIX_ADDR(addr))
+#define __do_writeb(val, addr)		eeh_writeb(PCI_FIX_ADDR(addr), val)
+#define __do_writew(val, addr)          eeh_writew(PCI_FIX_ADDR(addr), val)
+#define __do_writel(val, addr)          eeh_writel(PCI_FIX_ADDR(addr), val)
+#define __do_writeq(val, addr)          eeh_writeq(PCI_FIX_ADDR(addr), val)
+#define __do_writew_be(val, addr)       eeh_writew_be(PCI_FIX_ADDR(addr), val)
+#define __do_writel_be(val, addr)       eeh_writel_be(PCI_FIX_ADDR(addr), val)
+#define __do_writeq_be(val, addr)       eeh_writeq_be(PCI_FIX_ADDR(addr), val)
 #else /* CONFIG_EEH */
-#define __do_readb(addr)	in_8(PCI_FIX_ADDR(addr))
-#define __do_readw(addr)	in_le16(PCI_FIX_ADDR(addr))
-#define __do_readl(addr)	in_le32(PCI_FIX_ADDR(addr))
-#define __do_readq(addr)	in_le64(PCI_FIX_ADDR(addr))
-#define __do_readw_be(addr)	in_be16(PCI_FIX_ADDR(addr))
-#define __do_readl_be(addr)	in_be32(PCI_FIX_ADDR(addr))
-#define __do_readq_be(addr)	in_be64(PCI_FIX_ADDR(addr))
+#define __do_readb(addr)		in_8(PCI_FIX_ADDR(addr))
+#define __do_readw(addr)		in_le16(PCI_FIX_ADDR(addr))
+#define __do_readl(addr)		in_le32(PCI_FIX_ADDR(addr))
+#define __do_readq(addr)		in_le64(PCI_FIX_ADDR(addr))
+#define __do_readw_be(addr)		in_be16(PCI_FIX_ADDR(addr))
+#define __do_readl_be(addr)		in_be32(PCI_FIX_ADDR(addr))
+#define __do_readq_be(addr)		in_be64(PCI_FIX_ADDR(addr))
+#define __do_writeb(val, addr)		out_8(PCI_FIX_ADDR(addr), val)
+#define __do_writew(val, addr)		out_le16(PCI_FIX_ADDR(addr), val)
+#define __do_writel(val, addr)		out_le32(PCI_FIX_ADDR(addr), val)
+#define __do_writeq(val, addr)		out_le64(PCI_FIX_ADDR(addr), val)
+#define __do_writew_be(val, addr)	out_be16(PCI_FIX_ADDR(addr), val)
+#define __do_writel_be(val, addr)	out_be32(PCI_FIX_ADDR(addr), val)
+#define __do_writeq_be(val, addr)	out_be64(PCI_FIX_ADDR(addr), val)
 #endif /* !defined(CONFIG_EEH) */
 
 #ifdef CONFIG_PPC32
@@ -458,14 +465,17 @@ __do_out_asm(_rec_outl, "stwbrx")
 #define __do_readsb(a, b, n)	eeh_readsb(PCI_FIX_ADDR(a), (b), (n))
 #define __do_readsw(a, b, n)	eeh_readsw(PCI_FIX_ADDR(a), (b), (n))
 #define __do_readsl(a, b, n)	eeh_readsl(PCI_FIX_ADDR(a), (b), (n))
+#define __do_writesb(a, b, n)   eeh_writesb(PCI_FIX_ADDR(a),(b),(n))
+#define __do_writesw(a, b, n)   eeh_writesw(PCI_FIX_ADDR(a),(b),(n))
+#define __do_writesl(a, b, n)   eeh_writesl(PCI_FIX_ADDR(a),(b),(n))
 #else /* CONFIG_EEH */
 #define __do_readsb(a, b, n)	_insb(PCI_FIX_ADDR(a), (b), (n))
 #define __do_readsw(a, b, n)	_insw(PCI_FIX_ADDR(a), (b), (n))
 #define __do_readsl(a, b, n)	_insl(PCI_FIX_ADDR(a), (b), (n))
-#endif /* !CONFIG_EEH */
 #define __do_writesb(a, b, n)	_outsb(PCI_FIX_ADDR(a),(b),(n))
 #define __do_writesw(a, b, n)	_outsw(PCI_FIX_ADDR(a),(b),(n))
 #define __do_writesl(a, b, n)	_outsl(PCI_FIX_ADDR(a),(b),(n))
+#endif /* !CONFIG_EEH */
 
 #define __do_insb(p, b, n)	readsb((PCI_IO_ADDR)_IO_BASE+(p), (b), (n))
 #define __do_insw(p, b, n)	readsw((PCI_IO_ADDR)_IO_BASE+(p), (b), (n))
@@ -474,17 +484,20 @@ __do_out_asm(_rec_outl, "stwbrx")
 #define __do_outsw(p, b, n)	writesw((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
 #define __do_outsl(p, b, n)	writesl((PCI_IO_ADDR)_IO_BASE+(p),(b),(n))
 
-#define __do_memset_io(addr, c, n)	\
-				_memset_io(PCI_FIX_ADDR(addr), c, n)
-#define __do_memcpy_toio(dst, src, n)	\
-				_memcpy_toio(PCI_FIX_ADDR(dst), src, n)
-
 #ifdef CONFIG_EEH
 #define __do_memcpy_fromio(dst, src, n)	\
 				eeh_memcpy_fromio(dst, PCI_FIX_ADDR(src), n)
+#define __do_memset_io(addr, c, n)	\
+				eeh_memset_io(PCI_FIX_ADDR(addr), c, n)
+#define __do_memcpy_toio(dst, src, n)	\
+				eeh_memcpy_toio(PCI_FIX_ADDR(dst), src, n)
 #else /* CONFIG_EEH */
 #define __do_memcpy_fromio(dst, src, n)	\
 				_memcpy_fromio(dst,PCI_FIX_ADDR(src),n)
+#define __do_memset_io(addr, c, n)	\
+				_memset_io(PCI_FIX_ADDR(addr), c, n)
+#define __do_memcpy_toio(dst, src, n)	\
+				_memcpy_toio(PCI_FIX_ADDR(dst), src, n)
 #endif /* !CONFIG_EEH */
 
 #ifdef CONFIG_PPC_INDIRECT_PIO
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index 65320fd..b46f1ca 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -464,39 +464,57 @@ dn_unlock:
 EXPORT_SYMBOL_GPL(eeh_dev_check_failure);
 
 /**
- * eeh_check_failure - Check if all 1's data is due to EEH slot freeze
- * @token: I/O token, should be address in the form 0xA....
- * @val: value, should be all 1's (XXX why do we need this arg??)
- *
- * Check for an EEH failure at the given token address.  Call this
- * routine if the result of a read was all 0xff's and you want to
- * find out if this is due to an EEH slot freeze event.  This routine
- * will query firmware for the EEH status.
+ * eeh_check_blocked_io - Check if the I/O access has been blocked
+ * @token: I/O token
+ * @pedev: EEH device
  *
- * Note this routine is safe to call in an interrupt context.
+ * Check if the I/O access has been blocked. If that's the case, we
+ * should return 0xFF's on read, or sliently drop the write.
  */
-unsigned long eeh_check_failure(const volatile void __iomem *token, unsigned long val)
+int eeh_check_blocked_io(const volatile void __iomem *token,
+			 void **pedev)
 {
-	unsigned long addr;
 	struct eeh_dev *edev;
+	unsigned long addr;
+	int rc;
 
-	/* Finding the phys addr + pci device; this is pretty quick. */
+	/* Don't block I/O ranges which aren't traced by cache */
 	addr = eeh_token_to_phys((unsigned long __force) token);
 	edev = eeh_addr_cache_get_dev(addr);
 	if (!edev) {
+		if (pedev) *pedev = NULL;
 		eeh_stats.no_device++;
-		return val;
+		return 0;
 	}
 
-	eeh_dev_check_failure(edev);
+	if (pedev) *pedev = edev;
+	eeh_ops->get_setting(EEH_SETTING_BLOCK_IO, &rc, edev->phb);
+	return rc;
+}
+
+EXPORT_SYMBOL(eeh_check_blocked_io);
+
+/**
+ * eeh_check_failure - Check if all 1's data is due to EEH slot freeze
+ * @edev: EEH device
+ * @val: value
+ *
+ * Check if the EEH device has been frozen.
+ *
+ * Note this routine is safe to call in an interrupt context.
+ */
+unsigned long eeh_check_failure(struct eeh_dev *edev, unsigned long val)
+{
+	if (edev) {
+		eeh_dev_check_failure(edev);
+		pci_dev_put(eeh_dev_to_pci_dev(edev));
+	}
 
-	pci_dev_put(eeh_dev_to_pci_dev(edev));
 	return val;
 }
 
 EXPORT_SYMBOL(eeh_check_failure);
 
-
 /**
  * eeh_pci_enable - Enable MMIO or DMA transfers for this slot
  * @pe: EEH PE
diff --git a/arch/powerpc/platforms/powernv/eeh-powernv.c b/arch/powerpc/platforms/powernv/eeh-powernv.c
index cac5e18..20a7865 100644
--- a/arch/powerpc/platforms/powernv/eeh-powernv.c
+++ b/arch/powerpc/platforms/powernv/eeh-powernv.c
@@ -367,7 +367,7 @@ static int powernv_eeh_set_setting(int option, int value, void *data)
 	struct pci_controller *hose = data;
 	struct pnv_phb *phb = hose->private_data;
 
-	return phb->set_setting(option, value, data);
+	return phb->eeh_ops->set_setting(option, value, data);
 }
 
 /**
@@ -383,7 +383,7 @@ static int powernv_eeh_get_setting(int option, int *value, void *data)
 	struct pci_controller *hose = data;
 	struct pnv_phb *phb = hose->private_data;
 
-	return phb->get_setting(option, value, data);
+	return phb->eeh_ops->get_setting(option, value, data);
 }
 
 /**
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH 08/10] powerpc/powernv: Hold PCI-CFG and I/O access
From: Gavin Shan @ 2013-06-25  5:55 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Gavin Shan
In-Reply-To: <1372139717-14885-1-git-send-email-shangw@linux.vnet.ibm.com>

While doing recovery from fenced PHB, we need hold the PCI-CFG and
I/O access until the complete PHB reset and BARs restore are done.
The patch addresses that.

Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
---
 arch/powerpc/kernel/eeh_driver.c          |   11 +++++++++++
 arch/powerpc/platforms/powernv/eeh-ioda.c |   10 ++++++++--
 2 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/arch/powerpc/kernel/eeh_driver.c b/arch/powerpc/kernel/eeh_driver.c
index 0974e13..944e225 100644
--- a/arch/powerpc/kernel/eeh_driver.c
+++ b/arch/powerpc/kernel/eeh_driver.c
@@ -349,12 +349,14 @@ static void *eeh_report_failure(void *data, void *userdata)
  */
 static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
 {
+	struct pci_controller *hose;
 	struct timeval tstamp;
 	int cnt, rc;
 
 	/* pcibios will clear the counter; save the value */
 	cnt = pe->freeze_count;
 	tstamp = pe->tstamp;
+	hose = (pe->type & EEH_PE_PHB) ? pe->phb : NULL;
 
 	/*
 	 * We don't remove the corresponding PE instances because
@@ -377,6 +379,15 @@ static int eeh_reset_device(struct eeh_pe *pe, struct pci_bus *bus)
 	eeh_ops->configure_bridge(pe);
 	eeh_pe_restore_bars(pe);
 
+	/*
+	 * If we're recovering fenced PHB, the PCI-CFG and I/O should
+	 * have been blocked. We need reenable that.
+	 */
+	if (hose) {
+		eeh_ops->set_setting(EEH_SETTING_BLOCK_CFG, 0, hose);
+		eeh_ops->set_setting(EEH_SETTING_BLOCK_IO,  0, hose);
+	}
+
 	/* Give the system 5 seconds to finish running the user-space
 	 * hotplug shutdown scripts, e.g. ifdown for ethernet.  Yes,
 	 * this is a hack, but if we don't do this, and try to bring
diff --git a/arch/powerpc/platforms/powernv/eeh-ioda.c b/arch/powerpc/platforms/powernv/eeh-ioda.c
index 64c3d1e..23c2442 100644
--- a/arch/powerpc/platforms/powernv/eeh-ioda.c
+++ b/arch/powerpc/platforms/powernv/eeh-ioda.c
@@ -922,7 +922,9 @@ static int ioda_eeh_next_error(struct eeh_pe **pe)
 				list_for_each_entry_safe(hose, tmp,
 						&hose_list, list_node) {
 					phb = hose->private_data;
-					phb->eeh_state |= PNV_EEH_STATE_REMOVED;
+					phb->eeh_state |= (PNV_EEH_STATE_REMOVED |
+							   PNV_EEH_STATE_IO_BLOCKED |
+							   PNV_EEH_STATE_IO_BLOCKED);
 				}
 
 				WARN(1, "EEH: dead IOC detected\n");
@@ -939,7 +941,9 @@ static int ioda_eeh_next_error(struct eeh_pe **pe)
 
 				WARN(1, "EEH: dead PHB#%x detected\n",
 				     hose->global_number);
-				phb->eeh_state |= PNV_EEH_STATE_REMOVED;
+				phb->eeh_state |= (PNV_EEH_STATE_REMOVED |
+						   PNV_EEH_STATE_CFG_BLOCKED |
+						   PNV_EEH_STATE_IO_BLOCKED);
 				ret = 3;
 				goto out;
 			} else if (severity == OPAL_EEH_SEV_PHB_FENCED) {
@@ -948,6 +952,8 @@ static int ioda_eeh_next_error(struct eeh_pe **pe)
 
 				WARN(1, "EEH: fenced PHB#%x detected\n",
 				     hose->global_number);
+				phb->eeh_state |= (PNV_EEH_STATE_CFG_BLOCKED |
+						   PNV_EEH_STATE_IO_BLOCKED);
 				ret = 2;
 				goto out;
 			} else if (severity == OPAL_EEH_SEV_INF)
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH 09/10] powerpc/eeh: Fix address catch for PowerNV
From: Gavin Shan @ 2013-06-25  5:55 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Gavin Shan
In-Reply-To: <1372139717-14885-1-git-send-email-shangw@linux.vnet.ibm.com>

On the PowerNV platform, the EEH address cache isn't built correctly
because we skipped the EEH devices without binding PE. The patch
fixes that.

Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
---
 arch/powerpc/kernel/eeh_cache.c           |    2 +-
 arch/powerpc/platforms/powernv/pci-ioda.c |    1 +
 2 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/kernel/eeh_cache.c b/arch/powerpc/kernel/eeh_cache.c
index 1d5d9a6..858ebea 100644
--- a/arch/powerpc/kernel/eeh_cache.c
+++ b/arch/powerpc/kernel/eeh_cache.c
@@ -194,7 +194,7 @@ static void __eeh_addr_cache_insert_dev(struct pci_dev *dev)
 	}
 
 	/* Skip any devices for which EEH is not enabled. */
-	if (!edev->pe) {
+	if (!eeh_probe_mode_dev() && !edev->pe) {
 #ifdef DEBUG
 		pr_info("PCI: skip building address cache for=%s - %s\n",
 			pci_name(dev), dn->full_name);
diff --git a/arch/powerpc/platforms/powernv/pci-ioda.c b/arch/powerpc/platforms/powernv/pci-ioda.c
index 3e5c3d5..0ff9a3a 100644
--- a/arch/powerpc/platforms/powernv/pci-ioda.c
+++ b/arch/powerpc/platforms/powernv/pci-ioda.c
@@ -998,6 +998,7 @@ static void pnv_pci_ioda_fixup(void)
 	pnv_pci_ioda_create_dbgfs();
 
 #ifdef CONFIG_EEH
+	eeh_probe_mode_set(EEH_PROBE_MODE_DEV);
 	eeh_addr_cache_build();
 	eeh_init();
 #endif
-- 
1.7.5.4

^ permalink raw reply related

* Re: [RFC] [PATCH] powerpc: Add MSR_DE to MSR_KERNEL
From: Joakim Tjernlund @ 2013-06-25  6:00 UTC (permalink / raw)
  To: Scott Wood
  Cc: Wood Scott-B07421, Zang Roy-R61911, Bob Cochran,
	linuxppc-dev@ozlabs.org, Dan Malek, Support
In-Reply-To: <20130625005100.GA22976@home.buserror.net>

Scott Wood <scottwood@freescale.com> wrote on 2013/06/25 02:51:00:
> 
> On Fri, Jul 20, 2012 at 10:37:17AM +0200, Joakim Tjernlund wrote:
> > Zang Roy-R61911 <r61911@freescale.com> wrote on 2012/07/20 10:27:52:
> > >
> > >
> > >
> > > > -----Original Message-----
> > > > From: 
linuxppc-dev-bounces+tie-fei.zang=freescale.com@lists.ozlabs.org
> > > > [
mailto:linuxppc-dev-bounces+tie-fei.zang=freescale.com@lists.ozlabs.org]
> > > > On Behalf Of Joakim Tjernlund
> > > > Sent: Friday, June 01, 2012 6:36 AM
> > > > To: Wood Scott-B07421
> > > > Cc: linuxppc-dev@ozlabs.org; Dan Malek; Bob Cochran; Support
> > > > Subject: Re: [RFC] [PATCH] powerpc: Add MSR_DE to MSR_KERNEL
> > > >
> > > > It just occurred to me that you guys have this already in your 
Linux SDK so
> > > > it can't be that bad.
> > > No. MSR_DE is ONLY added when using CW debug in SDK.
> > > Roy
> > >
> > 
> > Yes, and I later found that user space debugging is busted if you turn 
on MSR_DE in
> > kernel.
> 
> So, how should we handle the CONFIG_BDI_SWITCH patch?  It seems like it
> should at least have a warning in the kconfig help text that it breaks
> userspace debugging (to the point of causing a kernel oops if it's
> tried).  Or maybe it can deselect CONFIG_PPC_ADV_DEBUG_REGS?
> 
> It'd also be nice to keep things like this, that are a consequence of 
how
> external debug works on e500, separate from the Abatron-specific stuff.
> 

I was hoping the kernel would grow per context handling of MSR_DE. Then 
one could have
MSR_DE on in MSR_KERNEL but off in user space(unless gdb request it on a 
per process basis). 

 Jocke

^ permalink raw reply

* Re: [PATCH 03/10] powerpc/eeh: Check PCIe link after reset
From: Benjamin Herrenschmidt @ 2013-06-25  6:06 UTC (permalink / raw)
  To: Gavin Shan; +Cc: linuxppc-dev
In-Reply-To: <1372139717-14885-4-git-send-email-shangw@linux.vnet.ibm.com>

On Tue, 2013-06-25 at 13:55 +0800, Gavin Shan wrote:
>         * don't touch the other command bits
>          */
> -       eeh_ops->read_config(dn, PCI_COMMAND, 4, &cmd);
> -       if (edev->config_space[1] & PCI_COMMAND_PARITY)
> -               cmd |= PCI_COMMAND_PARITY;
> -       else
> -               cmd &= ~PCI_COMMAND_PARITY;
> -       if (edev->config_space[1] & PCI_COMMAND_SERR)
> -               cmd |= PCI_COMMAND_SERR;
> -       else
> -               cmd &= ~PCI_COMMAND_SERR;
> -       eeh_ops->write_config(dn, PCI_COMMAND, 4, cmd);
> +       if (pdev) {
> +               eeh_ops->write_config(dn, PCI_COMMAND, 4,
> +                                     edev->config_space[1]);
> +       } else {

That needs a much better comment. Why are you doing that instead
of what's below ? In fact there is more to restore in a bridge
right ? (windows etc...). Do you do that ? Should we just have a
different function to restore a device vs. a bridge ?

I also don't see a need to do thing differently between phyp and
powernv. Bridges inside partitions would suffer the same fate in
both cases.

Ben.

> +               eeh_ops->read_config(dn, PCI_COMMAND, 4, &cmd);
> +               if (edev->config_space[1] & PCI_COMMAND_PARITY)
> +                       cmd |= PCI_COMMAND_PARITY;
> +               else
> +                       cmd &= ~PCI_COMMAND_PARITY;
> +               if (edev->config_space[1] & PCI_COMMAND_SERR)
> +                       cmd |= PCI_COMMAND_SERR;
> +               else
> +                       cmd &= ~PCI_COMMAND_SERR;
> +               eeh_ops->write_config(dn, PCI_COMMAND, 4, cmd);
> +       }
> +

^ permalink raw reply

* Re: [PATCH 04/10] powerpc/eeh: Backends to get/set settings
From: Benjamin Herrenschmidt @ 2013-06-25  6:07 UTC (permalink / raw)
  To: Gavin Shan; +Cc: linuxppc-dev
In-Reply-To: <1372139717-14885-5-git-send-email-shangw@linux.vnet.ibm.com>

On Tue, 2013-06-25 at 13:55 +0800, Gavin Shan wrote:
> When the PHB gets fenced, 0xFF's returns from PCI config space and
> MMIO space in the hardware. The operations writting to them should
> be dropped. The patch introduce backends allow to set/get flags that
> indicate the access to PCI-CFG and MMIO should be blocked.

We can't block MMIO without massive overhead. Config space can be
blocked inside the firmware, can't it ?

Cheers,
Ben.

> Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
> ---
>  arch/powerpc/include/asm/eeh.h               |    6 +++
>  arch/powerpc/platforms/pseries/eeh_pseries.c |   44 ++++++++++++++++++++++++++
>  2 files changed, 50 insertions(+), 0 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
> index dd65e31..de821c1 100644
> --- a/arch/powerpc/include/asm/eeh.h
> +++ b/arch/powerpc/include/asm/eeh.h
> @@ -131,6 +131,10 @@ static inline struct pci_dev *eeh_dev_to_pci_dev(struct eeh_dev *edev)
>  #define EEH_LOG_TEMP		1	/* EEH temporary error log	*/
>  #define EEH_LOG_PERM		2	/* EEH permanent error log	*/
>  
> +/* Settings for platforms */
> +#define EEH_SETTING_BLOCK_CFG	1	/* Blocked PCI config access	*/
> +#define EEH_SETTING_BLOCK_IO	2	/* Blocked MMIO access		*/
> +
>  struct eeh_ops {
>  	char *name;
>  	int (*init)(void);
> @@ -146,6 +150,8 @@ struct eeh_ops {
>  	int (*configure_bridge)(struct eeh_pe *pe);
>  	int (*read_config)(struct device_node *dn, int where, int size, u32 *val);
>  	int (*write_config)(struct device_node *dn, int where, int size, u32 val);
> +	int (*get_setting)(int option, int *value, void *data);
> +	int (*set_setting)(int option, int value, void *data);
>  	int (*next_error)(struct eeh_pe **pe);
>  };
>  
> diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c
> index 62415f2..8c9509b 100644
> --- a/arch/powerpc/platforms/pseries/eeh_pseries.c
> +++ b/arch/powerpc/platforms/pseries/eeh_pseries.c
> @@ -612,6 +612,48 @@ static int pseries_eeh_write_config(struct device_node *dn, int where, int size,
>  	return rtas_write_config(pdn, where, size, val);
>  }
>  
> +/**
> + * pseries_eeh_get_setting - Retrieve settings that affect EEH core
> + * @option: option
> + * @value: value
> + * @data: dependent data
> + *
> + * Retrieve the settings from the platform in order to affect the
> + * behaviour of EEH core. We don't block PCI config or MMIO access
> + * on pSeries platform.
> + */
> +static int pseries_eeh_get_setting(int option, int *value, void *data)
> +{
> +	int ret = 0;
> +
> +	switch (option) {
> +	case EEH_SETTING_BLOCK_CFG:
> +	case EEH_SETTING_BLOCK_IO:
> +		*value = 0;
> +		break;
> +	default:
> +		pr_warning("%s: Unrecognized option (%d)\n",
> +			   __func__, option);
> +		ret = -EINVAL;
> +	}
> +
> +	return ret;
> +}
> +
> +/**
> + * pseries_eeh_set_setting - Configure settings to affect EEH core
> + * @option: option
> + * @value: value
> + * @data: dependent data
> + *
> + * Configure the settings for the platform in order to affect the
> + * behaviour of EEH core.
> + */
> +static int pseries_eeh_set_setting(int option, int value, void *data)
> +{
> +	return 0;
> +}
> +
>  static struct eeh_ops pseries_eeh_ops = {
>  	.name			= "pseries",
>  	.init			= pseries_eeh_init,
> @@ -626,6 +668,8 @@ static struct eeh_ops pseries_eeh_ops = {
>  	.configure_bridge       = pseries_eeh_configure_bridge,
>  	.read_config		= pseries_eeh_read_config,
>  	.write_config		= pseries_eeh_write_config,
> +	.get_setting		= pseries_eeh_get_setting,
> +	.set_setting		= pseries_eeh_set_setting,
>  	.next_error		= NULL
>  };
>  

^ permalink raw reply

* Re: [PATCH 10/10] net/tg3: Avoid delay during MMIO access
From: Benjamin Herrenschmidt @ 2013-06-25  6:15 UTC (permalink / raw)
  To: Gavin Shan; +Cc: linuxppc-dev
In-Reply-To: <1372139717-14885-11-git-send-email-shangw@linux.vnet.ibm.com>

On Tue, 2013-06-25 at 13:55 +0800, Gavin Shan wrote:
> When the driver is encountering EEH errors, which might be caused
> by frozen PCI host controller, the driver needn't keep reading on
> MMIO until timeout. For the case, 0xFF's should be returned from
> hardware. Otherwise, it possibly trigger soft-lockup. The patch
> adds more check on that by pci_channel_offline(), thus to avoid
> the possible soft-lockup.

Can you resend this patch "standalone" (not part of a series)
to the maintainer/author of this driver and CC the netdev list on
vger.kernel.org ?

For the CC list, check the author of the original EEH support.

Also maybe improve the explanation above explaining something like:

"When the EEH error is the result of a fenced host bridge, MMIO
accesses can be very slow (milliseconds) to timeout and return all 1's,
thus causing the driver various timeout loops to take way too long and
trigger soft-lockup warnings (in addition to taking minutes to recover).

It might be worthwhile to check if for any of these cases, ffffffff is
a valid possible value, and if not, bail early since that means the HW
is either gone or isolated.

In the meantime, checking that the PCI channel is offline will
workaround the problem".

Or something like that...

> Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
> ---
>  drivers/net/ethernet/broadcom/tg3.c |   36 +++++++++++++++++++++++++++++++++++
>  1 files changed, 36 insertions(+), 0 deletions(-)
> 
> diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
> index c777b90..a13463e 100644
> --- a/drivers/net/ethernet/broadcom/tg3.c
> +++ b/drivers/net/ethernet/broadcom/tg3.c
> @@ -744,6 +744,9 @@ static int tg3_ape_lock(struct tg3 *tp, int locknum)
>  		status = tg3_ape_read32(tp, gnt + off);
>  		if (status == bit)
>  			break;
> +		if (pci_channel_offline(tp->pdev))
> +			break;
> +
>  		udelay(10);
>  	}
>  
> @@ -1635,6 +1638,9 @@ static void tg3_wait_for_event_ack(struct tg3 *tp)
>  	for (i = 0; i < delay_cnt; i++) {
>  		if (!(tr32(GRC_RX_CPU_EVENT) & GRC_RX_CPU_DRIVER_EVENT))
>  			break;
> +		if (pci_channel_offline(tp->pdev))
> +			break;
> +
>  		udelay(8);
>  	}
>  }
> @@ -1813,6 +1819,9 @@ static int tg3_poll_fw(struct tg3 *tp)
>  		for (i = 0; i < 200; i++) {
>  			if (tr32(VCPU_STATUS) & VCPU_STATUS_INIT_DONE)
>  				return 0;
> +			if (pci_channel_offline(tp->pdev))
> +				return -ENODEV;
> +
>  			udelay(100);
>  		}
>  		return -ENODEV;
> @@ -1823,6 +1832,15 @@ static int tg3_poll_fw(struct tg3 *tp)
>  		tg3_read_mem(tp, NIC_SRAM_FIRMWARE_MBOX, &val);
>  		if (val == ~NIC_SRAM_FIRMWARE_MBOX_MAGIC1)
>  			break;
> +		if (pci_channel_offline(tp->pdev)) {
> +			if (!tg3_flag(tp, NO_FWARE_REPORTED)) {
> +				tg3_flag_set(tp, NO_FWARE_REPORTED);
> +				netdev_info(tp->dev, "No firmware running\n");
> +			}
> +
> +			break;
> +		}
> +
>  		udelay(10);
>  	}
>  
> @@ -3520,6 +3538,8 @@ static int tg3_pause_cpu(struct tg3 *tp, u32 cpu_base)
>  		tw32(cpu_base + CPU_MODE,  CPU_MODE_HALT);
>  		if (tr32(cpu_base + CPU_MODE) & CPU_MODE_HALT)
>  			break;
> +		if (pci_channel_offline(tp->pdev))
> +			return -EBUSY;
>  	}
>  
>  	return (i == iters) ? -EBUSY : 0;
> @@ -8589,6 +8609,14 @@ static int tg3_stop_block(struct tg3 *tp, unsigned long ofs, u32 enable_bit, boo
>  	tw32_f(ofs, val);
>  
>  	for (i = 0; i < MAX_WAIT_CNT; i++) {
> +		if (pci_channel_offline(tp->pdev)) {
> +			dev_err(&tp->pdev->dev,
> +				"tg3_stop_block device offline, "
> +				"ofs=%lx enable_bit=%x\n",
> +				ofs, enable_bit);
> +			return -ENODEV;
> +		}
> +
>  		udelay(100);
>  		val = tr32(ofs);
>  		if ((val & enable_bit) == 0)
> @@ -8612,6 +8640,13 @@ static int tg3_abort_hw(struct tg3 *tp, bool silent)
>  
>  	tg3_disable_ints(tp);
>  
> +	if (pci_channel_offline(tp->pdev)) {
> +		tp->rx_mode &= ~(RX_MODE_ENABLE | TX_MODE_ENABLE);
> +		tp->mac_mode &= ~MAC_MODE_TDE_ENABLE;
> +		err = -ENODEV;
> +		goto err_no_dev;
> +	}
> +
>  	tp->rx_mode &= ~RX_MODE_ENABLE;
>  	tw32_f(MAC_RX_MODE, tp->rx_mode);
>  	udelay(10);
> @@ -8660,6 +8695,7 @@ static int tg3_abort_hw(struct tg3 *tp, bool silent)
>  	err |= tg3_stop_block(tp, BUFMGR_MODE, BUFMGR_MODE_ENABLE, silent);
>  	err |= tg3_stop_block(tp, MEMARB_MODE, MEMARB_MODE_ENABLE, silent);
>  
> +err_no_dev:
>  	for (i = 0; i < tp->irq_cnt; i++) {
>  		struct tg3_napi *tnapi = &tp->napi[i];
>  		if (tnapi->hw_status)

^ permalink raw reply

* [PATCH v2 1/2] powerpc/eeh: Remove eeh_mutex
From: Gavin Shan @ 2013-06-25  6:35 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Gavin Shan

Originally, eeh_mutex was introduced to protect the PE hierarchy
tree and the attached EEH devices because EEH core was possiblly
running with multiple threads to access the PE hierarchy tree.
However, we now have only one kthread in EEH core. So we needn't
the eeh_mutex and just remove it.

Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
---
 arch/powerpc/include/asm/eeh.h |   14 --------------
 arch/powerpc/kernel/eeh.c      |    3 ---
 arch/powerpc/kernel/eeh_pe.c   |   30 +-----------------------------
 3 files changed, 1 insertions(+), 46 deletions(-)

diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
index a0b11fb..dd65e31 100644
--- a/arch/powerpc/include/asm/eeh.h
+++ b/arch/powerpc/include/asm/eeh.h
@@ -151,7 +151,6 @@ struct eeh_ops {
 
 extern struct eeh_ops *eeh_ops;
 extern int eeh_subsystem_enabled;
-extern struct mutex eeh_mutex;
 extern raw_spinlock_t confirm_error_lock;
 extern int eeh_probe_mode;
 
@@ -173,16 +172,6 @@ static inline int eeh_probe_mode_dev(void)
 	return (eeh_probe_mode == EEH_PROBE_MODE_DEV);
 }
 
-static inline void eeh_lock(void)
-{
-	mutex_lock(&eeh_mutex);
-}
-
-static inline void eeh_unlock(void)
-{
-	mutex_unlock(&eeh_mutex);
-}
-
 static inline void eeh_serialize_lock(unsigned long *flags)
 {
 	raw_spin_lock_irqsave(&confirm_error_lock, *flags);
@@ -271,9 +260,6 @@ static inline void eeh_add_sysfs_files(struct pci_bus *bus) { }
 
 static inline void eeh_remove_bus_device(struct pci_dev *dev, int purge_pe) { }
 
-static inline void eeh_lock(void) { }
-static inline void eeh_unlock(void) { }
-
 #define EEH_POSSIBLE_ERROR(val, type) (0)
 #define EEH_IO_ERROR_VALUE(size) (-1UL)
 #endif /* CONFIG_EEH */
diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index 7c567be..951a632 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -103,9 +103,6 @@ EXPORT_SYMBOL(eeh_subsystem_enabled);
  */
 int eeh_probe_mode;
 
-/* Global EEH mutex */
-DEFINE_MUTEX(eeh_mutex);
-
 /* Lock to avoid races due to multiple reports of an error */
 DEFINE_RAW_SPINLOCK(confirm_error_lock);
 
diff --git a/arch/powerpc/kernel/eeh_pe.c b/arch/powerpc/kernel/eeh_pe.c
index ae75722..55943fc 100644
--- a/arch/powerpc/kernel/eeh_pe.c
+++ b/arch/powerpc/kernel/eeh_pe.c
@@ -78,9 +78,7 @@ int eeh_phb_pe_create(struct pci_controller *phb)
 	}
 
 	/* Put it into the list */
-	eeh_lock();
 	list_add_tail(&pe->child, &eeh_phb_pe);
-	eeh_unlock();
 
 	pr_debug("EEH: Add PE for PHB#%d\n", phb->global_number);
 
@@ -185,21 +183,15 @@ void *eeh_pe_dev_traverse(struct eeh_pe *root,
 		return NULL;
 	}
 
-	eeh_lock();
-
 	/* Traverse root PE */
 	for (pe = root; pe; pe = eeh_pe_next(pe, root)) {
 		eeh_pe_for_each_dev(pe, edev) {
 			ret = fn(edev, flag);
-			if (ret) {
-				eeh_unlock();
+			if (ret)
 				return ret;
-			}
 		}
 	}
 
-	eeh_unlock();
-
 	return NULL;
 }
 
@@ -305,8 +297,6 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
 {
 	struct eeh_pe *pe, *parent;
 
-	eeh_lock();
-
 	/*
 	 * Search the PE has been existing or not according
 	 * to the PE address. If that has been existing, the
@@ -316,7 +306,6 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
 	pe = eeh_pe_get(edev);
 	if (pe && !(pe->type & EEH_PE_INVALID)) {
 		if (!edev->pe_config_addr) {
-			eeh_unlock();
 			pr_err("%s: PE with addr 0x%x already exists\n",
 				__func__, edev->config_addr);
 			return -EEXIST;
@@ -328,7 +317,6 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
 
 		/* Put the edev to PE */
 		list_add_tail(&edev->list, &pe->edevs);
-		eeh_unlock();
 		pr_debug("EEH: Add %s to Bus PE#%x\n",
 			edev->dn->full_name, pe->addr);
 
@@ -347,7 +335,6 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
 			parent->type &= ~EEH_PE_INVALID;
 			parent = parent->parent;
 		}
-		eeh_unlock();
 		pr_debug("EEH: Add %s to Device PE#%x, Parent PE#%x\n",
 			edev->dn->full_name, pe->addr, pe->parent->addr);
 
@@ -357,7 +344,6 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
 	/* Create a new EEH PE */
 	pe = eeh_pe_alloc(edev->phb, EEH_PE_DEVICE);
 	if (!pe) {
-		eeh_unlock();
 		pr_err("%s: out of memory!\n", __func__);
 		return -ENOMEM;
 	}
@@ -385,7 +371,6 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
 	if (!parent) {
 		parent = eeh_phb_pe_get(edev->phb);
 		if (!parent) {
-			eeh_unlock();
 			pr_err("%s: No PHB PE is found (PHB Domain=%d)\n",
 				__func__, edev->phb->global_number);
 			edev->pe = NULL;
@@ -402,7 +387,6 @@ int eeh_add_to_parent_pe(struct eeh_dev *edev)
 	list_add_tail(&pe->child, &parent->child_list);
 	list_add_tail(&edev->list, &pe->edevs);
 	edev->pe = pe;
-	eeh_unlock();
 	pr_debug("EEH: Add %s to Device PE#%x, Parent PE#%x\n",
 		edev->dn->full_name, pe->addr, pe->parent->addr);
 
@@ -430,8 +414,6 @@ int eeh_rmv_from_parent_pe(struct eeh_dev *edev, int purge_pe)
 		return -EEXIST;
 	}
 
-	eeh_lock();
-
 	/* Remove the EEH device */
 	pe = edev->pe;
 	edev->pe = NULL;
@@ -476,8 +458,6 @@ int eeh_rmv_from_parent_pe(struct eeh_dev *edev, int purge_pe)
 		pe = parent;
 	}
 
-	eeh_unlock();
-
 	return 0;
 }
 
@@ -550,9 +530,7 @@ static void *__eeh_pe_state_mark(void *data, void *flag)
  */
 void eeh_pe_state_mark(struct eeh_pe *pe, int state)
 {
-	eeh_lock();
 	eeh_pe_traverse(pe, __eeh_pe_state_mark, &state);
-	eeh_unlock();
 }
 
 /**
@@ -586,9 +564,7 @@ static void *__eeh_pe_state_clear(void *data, void *flag)
  */
 void eeh_pe_state_clear(struct eeh_pe *pe, int state)
 {
-	eeh_lock();
 	eeh_pe_traverse(pe, __eeh_pe_state_clear, &state);
-	eeh_unlock();
 }
 
 /**
@@ -673,8 +649,6 @@ struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe)
 	struct eeh_dev *edev;
 	struct pci_dev *pdev;
 
-	eeh_lock();
-
 	if (pe->type & EEH_PE_PHB) {
 		bus = pe->phb->bus;
 	} else if (pe->type & EEH_PE_BUS ||
@@ -691,7 +665,5 @@ struct pci_bus *eeh_pe_bus_get(struct eeh_pe *pe)
 	}
 
 out:
-	eeh_unlock();
-
 	return bus;
 }
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH v2 2/2] powerpc/eeh: Avoid warning on P8
From: Gavin Shan @ 2013-06-25  6:35 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Gavin Shan
In-Reply-To: <1372142128-18077-1-git-send-email-shangw@linux.vnet.ibm.com>

To replace down() with down_interrutible() to avoid following
warning:

[c00000007ba7b710] [c000000000014410] .__switch_to+0x1b0/0x380
[c00000007ba7b7c0] [c0000000007b408c] .__schedule+0x3ec/0x970
[c00000007ba7ba50] [c0000000007b1f24] .schedule_timeout+0x1a4/0x2b0
[c00000007ba7bb30] [c0000000007b34a4] .__down+0xa4/0x104
[c00000007ba7bbf0] [c0000000000b9230] .down+0x60/0x70
[c00000007ba7bc80] [c0000000000336d0] .eeh_event_handler+0x70/0x190
[c00000007ba7bd30] [c0000000000b1a58] .kthread+0xe8/0xf0
[c00000007ba7be30] [c00000000000a05c] .ret_from_kernel_thread+0x5c/0x8

Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
---
 arch/powerpc/kernel/eeh_event.c |    3 ++-
 1 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/arch/powerpc/kernel/eeh_event.c b/arch/powerpc/kernel/eeh_event.c
index 39bcd81..d27c5af 100644
--- a/arch/powerpc/kernel/eeh_event.c
+++ b/arch/powerpc/kernel/eeh_event.c
@@ -55,7 +55,8 @@ static int eeh_event_handler(void * dummy)
 	struct eeh_pe *pe;
 
 	while (!kthread_should_stop()) {
-		down(&eeh_eventlist_sem);
+		if (down_interruptible(&eeh_eventlist_sem))
+			break;
 
 		/* Fetch EEH event from the queue */
 		spin_lock_irqsave(&eeh_eventlist_lock, flags);
-- 
1.7.5.4

^ permalink raw reply related

* [PATCH] powerpc/mpc512x: update defconfig
From: Anatolij Gustschin @ 2013-06-25  6:37 UTC (permalink / raw)
  To: linuxppc-dev; +Cc: Gerhard Sittig

From: Gerhard Sittig <gsi@denx.de>

This patch does not change the content, it merely re-orders
configuration items and drops explicit options which already
apply as the default.

Signed-off-by: Gerhard Sittig <gsi@denx.de>
Signed-off-by: Anatolij Gustschin <agust@denx.de>
---
 arch/powerpc/configs/mpc512x_defconfig |   20 +++-----------------
 1 file changed, 3 insertions(+), 17 deletions(-)

diff --git a/arch/powerpc/configs/mpc512x_defconfig b/arch/powerpc/configs/mpc512x_defconfig
index 0d0d981..5b8ee80 100644
--- a/arch/powerpc/configs/mpc512x_defconfig
+++ b/arch/powerpc/configs/mpc512x_defconfig
@@ -1,7 +1,6 @@
-CONFIG_EXPERIMENTAL=y
 # CONFIG_SWAP is not set
 CONFIG_SYSVIPC=y
-CONFIG_SPARSE_IRQ=y
+CONFIG_NO_HZ=y
 CONFIG_LOG_BUF_SHIFT=16
 CONFIG_BLK_DEV_INITRD=y
 # CONFIG_COMPAT_BRK is not set
@@ -9,6 +8,7 @@ CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
 # CONFIG_IOSCHED_CFQ is not set
 # CONFIG_PPC_CHRP is not set
 CONFIG_PPC_MPC512x=y
@@ -16,9 +16,7 @@ CONFIG_MPC5121_ADS=y
 CONFIG_MPC512x_GENERIC=y
 CONFIG_PDM360NG=y
 # CONFIG_PPC_PMAC is not set
-CONFIG_NO_HZ=y
 CONFIG_HZ_1000=y
-# CONFIG_MIGRATION is not set
 # CONFIG_SECCOMP is not set
 # CONFIG_PCI is not set
 CONFIG_NET=y
@@ -33,8 +31,6 @@ CONFIG_IP_PNP=y
 # CONFIG_INET_DIAG is not set
 # CONFIG_IPV6 is not set
 CONFIG_CAN=y
-CONFIG_CAN_RAW=y
-CONFIG_CAN_BCM=y
 CONFIG_CAN_VCAN=y
 CONFIG_CAN_MSCAN=y
 CONFIG_CAN_DEBUG_DEVICES=y
@@ -46,7 +42,6 @@ CONFIG_DEVTMPFS_MOUNT=y
 # CONFIG_FIRMWARE_IN_KERNEL is not set
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
-CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_AMDSTD=y
@@ -60,7 +55,6 @@ CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_COUNT=1
 CONFIG_BLK_DEV_RAM_SIZE=8192
 CONFIG_BLK_DEV_XIP=y
-CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_AT24=y
 CONFIG_EEPROM_AT25=y
 CONFIG_SCSI=y
@@ -68,6 +62,7 @@ CONFIG_SCSI=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_SG=y
 CONFIG_NETDEVICES=y
+CONFIG_FS_ENET=y
 CONFIG_MARVELL_PHY=y
 CONFIG_DAVICOM_PHY=y
 CONFIG_QSEMI_PHY=y
@@ -83,10 +78,6 @@ CONFIG_STE10XP=y
 CONFIG_LSI_ET1011C_PHY=y
 CONFIG_FIXED_PHY=y
 CONFIG_MDIO_BITBANG=y
-CONFIG_NET_ETHERNET=y
-CONFIG_FS_ENET=y
-# CONFIG_NETDEV_1000 is not set
-# CONFIG_NETDEV_10000 is not set
 # CONFIG_WLAN is not set
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 CONFIG_INPUT_EVDEV=y
@@ -106,10 +97,7 @@ CONFIG_GPIO_SYSFS=y
 CONFIG_GPIO_MPC8XXX=y
 # CONFIG_HWMON is not set
 CONFIG_MEDIA_SUPPORT=y
-CONFIG_VIDEO_DEV=y
 CONFIG_VIDEO_ADV_DEBUG=y
-# CONFIG_VIDEO_HELPER_CHIPS_AUTO is not set
-CONFIG_VIDEO_SAA711X=y
 CONFIG_FB=y
 CONFIG_FB_FSL_DIU=y
 # CONFIG_VGA_CONSOLE is not set
@@ -129,9 +117,7 @@ CONFIG_TMPFS=y
 CONFIG_JFFS2_FS=y
 CONFIG_UBIFS_FS=y
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_ROOT_NFS=y
-CONFIG_PARTITION_ADVANCED=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_ISO8859_1=y
 # CONFIG_ENABLE_WARN_DEPRECATED is not set
-- 
1.7.9.5

^ permalink raw reply related

* [PATCH] powerpc/mpc512x: enable USB support in defconfig
From: Anatolij Gustschin @ 2013-06-25  6:51 UTC (permalink / raw)
  To: linuxppc-dev

Enable USB EHCI, mass storage and USB gadget support.

Signed-off-by: Anatolij Gustschin <agust@denx.de>
---
 arch/powerpc/configs/mpc512x_defconfig | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/arch/powerpc/configs/mpc512x_defconfig b/arch/powerpc/configs/mpc512x_defconfig
index 5b8ee80..ee853a1 100644
--- a/arch/powerpc/configs/mpc512x_defconfig
+++ b/arch/powerpc/configs/mpc512x_defconfig
@@ -102,6 +102,13 @@ CONFIG_FB=y
 CONFIG_FB_FSL_DIU=y
 # CONFIG_VGA_CONSOLE is not set
 CONFIG_FRAMEBUFFER_CONSOLE=y
+CONFIG_USB=y
+CONFIG_USB_EHCI_HCD=y
+CONFIG_USB_EHCI_FSL=y
+# CONFIG_USB_EHCI_HCD_PPC_OF is not set
+CONFIG_USB_STORAGE=y
+CONFIG_USB_GADGET=y
+CONFIG_USB_FSL_USB2=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_M41T80=y
 CONFIG_RTC_DRV_MPC5121=y
-- 
1.7.11.7

^ permalink raw reply related

* Re: [PATCH 3/3] powerpc/pseries: Support compression of oops text via pstore
From: Aruna Balakrishnaiah @ 2013-06-25  7:04 UTC (permalink / raw)
  To: Kees Cook
  Cc: jkenisto, Tony Luck, mahesh, Colin Cross, LKML, linuxppc-dev,
	paulus, Anton Blanchard, Anton Vorontsov
In-Reply-To: <CAGXu5jJezRynWEBmmH8wp=pt1yEjukhe6Pg_aRcZP7E6t-1R=g@mail.gmail.com>

Hi Kees,

On Monday 24 June 2013 11:27 PM, Kees Cook wrote:
> On Sun, Jun 23, 2013 at 11:23 PM, Aruna Balakrishnaiah
> <aruna@linux.vnet.ibm.com> wrote:
>> The patch set supports compression of oops messages while writing to NVRAM,
>> this helps in capturing more of oops data to lnx,oops-log. The pstore file
>> for oops messages will be in decompressed format making it readable.
>>
>> In case compression fails, the patch takes care of copying the header added
>> by pstore and last oops_data_sz bytes of big_oops_buf to NVRAM so that we
>> have recent oops messages in lnx,oops-log.
>>
>> In case decompression fails, it will result in absence of oops file but still
>> have files (in /dev/pstore) for other partitions.
>>
>> Signed-off-by: Aruna Balakrishnaiah <aruna@linux.vnet.ibm.com>
>> ---
>>   arch/powerpc/platforms/pseries/nvram.c |  132 +++++++++++++++++++++++++++++---
>>   1 file changed, 118 insertions(+), 14 deletions(-)
>>
>> diff --git a/arch/powerpc/platforms/pseries/nvram.c b/arch/powerpc/platforms/pseries/nvram.c
>> index 0159d74..b5ba5e2 100644
>> --- a/arch/powerpc/platforms/pseries/nvram.c
>> +++ b/arch/powerpc/platforms/pseries/nvram.c
>> @@ -539,6 +539,65 @@ static int zip_oops(size_t text_len)
>>   }
>>
>>   #ifdef CONFIG_PSTORE
>> +/* Derived from logfs_uncompress */
>> +int nvram_decompress(void *in, void *out, size_t inlen, size_t outlen)
>> +{
>> +       int err, ret;
>> +
>> +       ret = -EIO;
>> +       err = zlib_inflateInit(&stream);
>> +       if (err != Z_OK)
>> +               goto error;
>> +
>> +       stream.next_in = in;
>> +       stream.avail_in = inlen;
>> +       stream.total_in = 0;
>> +       stream.next_out = out;
>> +       stream.avail_out = outlen;
>> +       stream.total_out = 0;
>> +
>> +       err = zlib_inflate(&stream, Z_FINISH);
>> +       if (err != Z_STREAM_END)
>> +               goto error;
>> +
>> +       err = zlib_inflateEnd(&stream);
>> +       if (err != Z_OK)
>> +               goto error;
>> +
>> +       ret = stream.total_out;
>> +error:
>> +       return ret;
>> +}
>> +
>> +static int unzip_oops(char *oops_buf, char *big_buf)
>> +{
>> +       struct oops_log_info *oops_hdr = (struct oops_log_info *)oops_buf;
>> +       u64 timestamp = oops_hdr->timestamp;
>> +       char *big_oops_data = NULL;
>> +       char *oops_data_buf = NULL;
>> +       size_t big_oops_data_sz;
>> +       int unzipped_len;
>> +
>> +       big_oops_data = big_buf + sizeof(struct oops_log_info);
>> +       big_oops_data_sz = big_oops_buf_sz - sizeof(struct oops_log_info);
>> +       oops_data_buf = oops_buf + sizeof(struct oops_log_info);
>> +
>> +       unzipped_len = nvram_decompress(oops_data_buf, big_oops_data,
>> +                                       oops_hdr->report_length,
>> +                                       big_oops_data_sz);
>> +
>> +       if (unzipped_len < 0) {
>> +               pr_err("nvram: decompression failed; returned %d\n",
>> +                                                               unzipped_len);
>> +               return -1;
>> +       }
>> +       oops_hdr = (struct oops_log_info *)big_buf;
>> +       oops_hdr->version = OOPS_HDR_VERSION;
>> +       oops_hdr->report_length = (u16) unzipped_len;
>> +       oops_hdr->timestamp = timestamp;
>> +       return 0;
>> +}
>> +
>>   static int nvram_pstore_open(struct pstore_info *psi)
>>   {
>>          /* Reset the iterator to start reading partitions again */
>> @@ -567,6 +626,7 @@ static int nvram_pstore_write(enum pstore_type_id type,
>>                                  size_t size, struct pstore_info *psi)
>>   {
>>          int rc;
>> +       unsigned int err_type = ERR_TYPE_KERNEL_PANIC;
>>          struct oops_log_info *oops_hdr = (struct oops_log_info *) oops_buf;
>>
>>          /* part 1 has the recent messages from printk buffer */
>> @@ -577,8 +637,31 @@ static int nvram_pstore_write(enum pstore_type_id type,
>>          oops_hdr->version = OOPS_HDR_VERSION;
>>          oops_hdr->report_length = (u16) size;
>>          oops_hdr->timestamp = get_seconds();
>> +
>> +       if (big_oops_buf) {
>> +               rc = zip_oops(size);
>> +               /*
>> +                * If compression fails copy recent log messages from
>> +                * big_oops_buf to oops_data.
>> +                */
>> +               if (rc != 0) {
>> +                       int hsize = pstore_get_header_size();
> I think I would rather see the API to pstore_write() changed to
> include explicit details about header sizes. Mkaing hsize a global
> seems unwise, since it's not strictly going to be a constant value. It
> could change between calls to the writer, for example.

Introducing headersize in pstore_write() API would need changes at
multiple places whereits being called. The idea is to move the
compression support to pstore infrastructure so that other platforms
could also make use of it. Once the compression support gets in,
header size argument in pstore_write() will have to be deprecated.

Till the time compression support for pstore goes in, can't we call
pstore_header_size before every write call to knowthe header size.

> Beyond that, this all seems sensible, though it would be kind of cool
> to move this compression logic into the pstore core so it would get
> used by default (or through a module parameter).
> -Kees
>
>> +                       size_t diff = size - oops_data_sz + hsize;
>> +
>> +                       if (size > oops_data_sz) {
>> +                               memcpy(oops_data, big_oops_buf, hsize);
>> +                               memcpy(oops_data + hsize, big_oops_buf + diff,
>> +                                       oops_data_sz - hsize);
>> +
>> +                               oops_hdr->report_length = (u16) oops_data_sz;
>> +                       } else
>> +                               memcpy(oops_data, big_oops_buf, size);
>> +               } else
>> +                       err_type = ERR_TYPE_KERNEL_PANIC_GZ;
>> +       }
>> +
>>          rc = nvram_write_os_partition(&oops_log_partition, oops_buf,
>> -               (int) (sizeof(*oops_hdr) + size), ERR_TYPE_KERNEL_PANIC,
>> +               (int) (sizeof(*oops_hdr) + oops_hdr->report_length), err_type,
>>                  count);
>>
>>          if (rc != 0)
>> @@ -600,10 +683,11 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type,
>>          struct oops_log_info *oops_hdr;
>>          unsigned int err_type, id_no, size = 0;
>>          struct nvram_os_partition *part = NULL;
>> -       char *buff = NULL;
>> -       int sig = 0;
>> +       char *buff = NULL, *big_buff = NULL;
>> +       int rc, sig = 0;
>>          loff_t p;
>>
>> +read_partition:
>>          read_type++;
>>
>>          switch (nvram_type_ids[read_type]) {
>> @@ -666,6 +750,25 @@ static ssize_t nvram_pstore_read(u64 *id, enum pstore_type_id *type,
>>          if (nvram_type_ids[read_type] == PSTORE_TYPE_DMESG) {
>>                  oops_hdr = (struct oops_log_info *)buff;
>>                  *buf = buff + sizeof(*oops_hdr);
>> +
>> +               if (err_type == ERR_TYPE_KERNEL_PANIC_GZ) {
>> +                       big_buff = kmalloc(big_oops_buf_sz, GFP_KERNEL);
>> +                       if (!big_buff)
>> +                               return -ENOMEM;
>> +
>> +                       rc = unzip_oops(buff, big_buff);
>> +
>> +                       if (rc != 0) {
>> +                               kfree(buff);
>> +                               kfree(big_buff);
>> +                               goto read_partition;
>> +                       }
>> +
>> +                       oops_hdr = (struct oops_log_info *)big_buff;
>> +                       *buf = big_buff + sizeof(*oops_hdr);
>> +                       kfree(buff);
>> +               }
>> +
>>                  time->tv_sec = oops_hdr->timestamp;
>>                  time->tv_nsec = 0;
>>                  return oops_hdr->report_length;
>> @@ -687,17 +790,18 @@ static int nvram_pstore_init(void)
>>   {
>>          int rc = 0;
>>
>> -       nvram_pstore_info.buf = oops_data;
>> -       nvram_pstore_info.bufsize = oops_data_sz;
>> +       if (big_oops_buf) {
>> +               nvram_pstore_info.buf = big_oops_buf;
>> +               nvram_pstore_info.bufsize = big_oops_buf_sz;
>> +       } else {
>> +               nvram_pstore_info.buf = oops_data;
>> +               nvram_pstore_info.bufsize = oops_data_sz;
>> +       }
>>
>>          rc = pstore_register(&nvram_pstore_info);
>>          if (rc != 0)
>>                  pr_err("nvram: pstore_register() failed, defaults to "
>>                                  "kmsg_dump; returned %d\n", rc);
>> -       else
>> -               /*TODO: Support compression when pstore is configured */
>> -               pr_info("nvram: Compression of oops text supported only when "
>> -                               "pstore is not configured");
>>
>>          return rc;
>>   }
>> @@ -731,11 +835,6 @@ static void __init nvram_init_oops_partition(int rtas_partition_exists)
>>          oops_data = oops_buf + sizeof(struct oops_log_info);
>>          oops_data_sz = oops_log_partition.size - sizeof(struct oops_log_info);
>>
>> -       rc = nvram_pstore_init();
>> -
>> -       if (!rc)
>> -               return;
>> -
>>          /*
>>           * Figure compression (preceded by elimination of each line's <n>
>>           * severity prefix) will reduce the oops/panic report to at most
>> @@ -759,6 +858,11 @@ static void __init nvram_init_oops_partition(int rtas_partition_exists)
>>                  stream.workspace = NULL;
>>          }
>>
>> +       rc = nvram_pstore_init();
>> +
>> +       if (!rc)
>> +               return;
>> +
>>          rc = kmsg_dump_register(&nvram_kmsg_dumper);
>>          if (rc != 0) {
>>                  pr_err("nvram: kmsg_dump_register() failed; returned %d\n", rc);
>>
>
>
> --
> Kees Cook
> Chrome OS Security
> _______________________________________________
> Linuxppc-dev mailing list
> Linuxppc-dev@lists.ozlabs.org
> https://lists.ozlabs.org/listinfo/linuxppc-dev
>

^ permalink raw reply

* Re: [PATCH 04/10] powerpc/eeh: Backends to get/set settings
From: Gavin Shan @ 2013-06-25  7:12 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, Gavin Shan
In-Reply-To: <1372140444.3944.190.camel@pasglop>

On Tue, Jun 25, 2013 at 04:07:24PM +1000, Benjamin Herrenschmidt wrote:
>On Tue, 2013-06-25 at 13:55 +0800, Gavin Shan wrote:
>> When the PHB gets fenced, 0xFF's returns from PCI config space and
>> MMIO space in the hardware. The operations writting to them should
>> be dropped. The patch introduce backends allow to set/get flags that
>> indicate the access to PCI-CFG and MMIO should be blocked.
>
>We can't block MMIO without massive overhead. Config space can be
>blocked inside the firmware, can't it ?
>

Yep. The config space has been blocked on fenced PHB by firmware. I
almostly forgot that (struct p7ioc_phb::use_asb) :-)

Thanks,
Gavin

>
>> Signed-off-by: Gavin Shan <shangw@linux.vnet.ibm.com>
>> ---
>>  arch/powerpc/include/asm/eeh.h               |    6 +++
>>  arch/powerpc/platforms/pseries/eeh_pseries.c |   44 ++++++++++++++++++++++++++
>>  2 files changed, 50 insertions(+), 0 deletions(-)
>> 
>> diff --git a/arch/powerpc/include/asm/eeh.h b/arch/powerpc/include/asm/eeh.h
>> index dd65e31..de821c1 100644
>> --- a/arch/powerpc/include/asm/eeh.h
>> +++ b/arch/powerpc/include/asm/eeh.h
>> @@ -131,6 +131,10 @@ static inline struct pci_dev *eeh_dev_to_pci_dev(struct eeh_dev *edev)
>>  #define EEH_LOG_TEMP		1	/* EEH temporary error log	*/
>>  #define EEH_LOG_PERM		2	/* EEH permanent error log	*/
>>  
>> +/* Settings for platforms */
>> +#define EEH_SETTING_BLOCK_CFG	1	/* Blocked PCI config access	*/
>> +#define EEH_SETTING_BLOCK_IO	2	/* Blocked MMIO access		*/
>> +
>>  struct eeh_ops {
>>  	char *name;
>>  	int (*init)(void);
>> @@ -146,6 +150,8 @@ struct eeh_ops {
>>  	int (*configure_bridge)(struct eeh_pe *pe);
>>  	int (*read_config)(struct device_node *dn, int where, int size, u32 *val);
>>  	int (*write_config)(struct device_node *dn, int where, int size, u32 val);
>> +	int (*get_setting)(int option, int *value, void *data);
>> +	int (*set_setting)(int option, int value, void *data);
>>  	int (*next_error)(struct eeh_pe **pe);
>>  };
>>  
>> diff --git a/arch/powerpc/platforms/pseries/eeh_pseries.c b/arch/powerpc/platforms/pseries/eeh_pseries.c
>> index 62415f2..8c9509b 100644
>> --- a/arch/powerpc/platforms/pseries/eeh_pseries.c
>> +++ b/arch/powerpc/platforms/pseries/eeh_pseries.c
>> @@ -612,6 +612,48 @@ static int pseries_eeh_write_config(struct device_node *dn, int where, int size,
>>  	return rtas_write_config(pdn, where, size, val);
>>  }
>>  
>> +/**
>> + * pseries_eeh_get_setting - Retrieve settings that affect EEH core
>> + * @option: option
>> + * @value: value
>> + * @data: dependent data
>> + *
>> + * Retrieve the settings from the platform in order to affect the
>> + * behaviour of EEH core. We don't block PCI config or MMIO access
>> + * on pSeries platform.
>> + */
>> +static int pseries_eeh_get_setting(int option, int *value, void *data)
>> +{
>> +	int ret = 0;
>> +
>> +	switch (option) {
>> +	case EEH_SETTING_BLOCK_CFG:
>> +	case EEH_SETTING_BLOCK_IO:
>> +		*value = 0;
>> +		break;
>> +	default:
>> +		pr_warning("%s: Unrecognized option (%d)\n",
>> +			   __func__, option);
>> +		ret = -EINVAL;
>> +	}
>> +
>> +	return ret;
>> +}
>> +
>> +/**
>> + * pseries_eeh_set_setting - Configure settings to affect EEH core
>> + * @option: option
>> + * @value: value
>> + * @data: dependent data
>> + *
>> + * Configure the settings for the platform in order to affect the
>> + * behaviour of EEH core.
>> + */
>> +static int pseries_eeh_set_setting(int option, int value, void *data)
>> +{
>> +	return 0;
>> +}
>> +
>>  static struct eeh_ops pseries_eeh_ops = {
>>  	.name			= "pseries",
>>  	.init			= pseries_eeh_init,
>> @@ -626,6 +668,8 @@ static struct eeh_ops pseries_eeh_ops = {
>>  	.configure_bridge       = pseries_eeh_configure_bridge,
>>  	.read_config		= pseries_eeh_read_config,
>>  	.write_config		= pseries_eeh_write_config,
>> +	.get_setting		= pseries_eeh_get_setting,
>> +	.set_setting		= pseries_eeh_set_setting,
>>  	.next_error		= NULL
>>  };
>>  
>
>

^ permalink raw reply

* Re: Regression in RCU subsystem in latest mainline kernel
From: Michael Ellerman @ 2013-06-25  7:19 UTC (permalink / raw)
  To: Paul E. McKenney
  Cc: linuxppc-dev, Rojhalat Ibrahim, Steven Rostedt, linux-kernel
In-Reply-To: <20130619040906.GA5146@linux.vnet.ibm.com>

On Tue, Jun 18, 2013 at 09:09:06PM -0700, Paul E. McKenney wrote:
> On Mon, Jun 17, 2013 at 05:42:13PM +1000, Michael Ellerman wrote:
> > On Sat, Jun 15, 2013 at 12:02:21PM +1000, Benjamin Herrenschmidt wrote:
> > > On Fri, 2013-06-14 at 17:06 -0400, Steven Rostedt wrote:
> > > > I was pretty much able to reproduce this on my PA Semi PPC box. Funny
> > > > thing is, when I type on the console, it makes progress. Anyway, it
> > > > seems that powerpc has an issue with irq_work(). I'll try to get some
> > > > time either tonight or next week to figure it out.
> > > 
> > > Does this help ?
> > > 
> > > diff --git a/arch/powerpc/kernel/irq.c b/arch/powerpc/kernel/irq.c
> > > index 5cbcf4d..ea185e0 100644
> > > --- a/arch/powerpc/kernel/irq.c
> > > +++ b/arch/powerpc/kernel/irq.c
> > > @@ -162,7 +162,7 @@ notrace unsigned int __check_irq_replay(void)
> > >  	 * in case we also had a rollover while hard disabled
> > >  	 */
> > >  	local_paca->irq_happened &= ~PACA_IRQ_DEC;
> > > -	if (decrementer_check_overflow())
> > > +	if ((happened & PACA_IRQ_DEC) || decrementer_check_overflow())
> > >  		return 0x900;
> > >  
> > >  	/* Finally check if an external interrupt happened */
> > > 
> > 
> > This seems to help, but doesn't elminate the RCU stall warnings I am
> > seeing. I now see them less often, but not never.
> > 
> > Stack trace is something like:
 
Hi Paul,

Sorry I've been distracted with other stuff the last week.

> Hmmm...  How many CPUs are on your system?  And how much work is
> perf_event_for_each_child() having to do here?

I'm not 100% sure which system this trace is from. But it would have
~100-128 cpus.

I don't think perf_event_for_each_child() is doing much, there should
only be a single event and the smp_call_function_single() should be
degrading to a local function call.

> If the amount of work is large and your kernel is built with
> CONFIG_PREEMPT=n, the RCU CPU stall warning would be expected behavior.
> If so, we might need a preemption point in perf_event_for_each_child().

I'm using CONFIG_PREEMPT_NONE=y, which I think is what you mean.

Here's another trace from 3.10-rc7 plus a few local patches.

We suspect that the perf enable could be causing a flood of interrupts, but why
that's clogging things up so badly who knows.

INFO: rcu_sched self-detected stall on CPU { 38}  (t=2600 jiffies g=1 c=0 q=9)
cpu 0x26: Vector: 0  at [c0000007ed952b60]
    pc: c00000000014f500: .rcu_check_callbacks+0x400/0x8e0
    lr: c00000000014f500: .rcu_check_callbacks+0x400/0x8e0
    sp: c0000007ed952cd0
   msr: 9000000000009032
  current = 0xc0000007ed8b4a80
  paca    = 0xc00000000fdcab00	 softe: 0	 irq_happened: 0x00
    pid   = 2492, comm = power8-events
enter ? for help
[c0000007ed952e00] c0000000000a3e88 .update_process_times+0x48/0xa0
[c0000007ed952e90] c0000000000fd600 .tick_sched_handle.isra.13+0x40/0xd0
[c0000007ed952f20] c0000000000fd8b4 .tick_sched_timer+0x64/0xa0
[c0000007ed952fc0] c0000000000ca074 .__run_hrtimer+0x94/0x250
[c0000007ed953060] c0000000000cb0f8 .hrtimer_interrupt+0x138/0x3a0
[c0000007ed953150] c00000000001ef54 .timer_interrupt+0x124/0x2f0
[c0000007ed953200] c00000000000a5fc restore_check_irq_replay+0x68/0xa8
--- Exception: 901 (Decrementer) at c0000000000105ec .arch_local_irq_restore+0xc/0x10
[link register   ] c000000000096dac .__do_softirq+0x13c/0x380
[c0000007ed9534f0] c000000000096da0 .__do_softirq+0x130/0x380 (unreliable)
[c0000007ed953610] c000000000097228 .irq_exit+0xd8/0x120
[c0000007ed953690] c00000000001ef88 .timer_interrupt+0x158/0x2f0
[c0000007ed953740] c00000000000a5fc restore_check_irq_replay+0x68/0xa8
--- Exception: 901 (Decrementer) at c00000000010e16c .smp_call_function_single+0x13c/0x230
[c0000007ed953a30] c000000000189c64 .task_function_call+0x54/0x70 (unreliable)
[c0000007ed953ad0] c000000000189d4c .perf_event_enable+0xcc/0x150
[c0000007ed953b70] c000000000187ea0 .perf_event_for_each_child+0x60/0x100
[c0000007ed953c00] c00000000018c5e8 .perf_ioctl+0x108/0x3c0
[c0000007ed953ca0] c000000000226e94 .do_vfs_ioctl+0xc4/0x740
[c0000007ed953d90] c000000000227570 .SyS_ioctl+0x60/0xb0
[c0000007ed953e30] c000000000009e60 syscall_exit+0x0/0x98
--- Exception: c01 (System Call) at 00001fffffee03d0
SP (3fffdf0d2700) is in userspace


cheers

^ permalink raw reply

* Re: Regression in RCU subsystem in latest mainline kernel
From: Benjamin Herrenschmidt @ 2013-06-25  7:36 UTC (permalink / raw)
  To: Michael Ellerman
  Cc: Rojhalat Ibrahim, Paul E. McKenney, linuxppc-dev, linux-kernel,
	Steven Rostedt
In-Reply-To: <20130625071914.GA29957@concordia>

On Tue, 2013-06-25 at 17:19 +1000, Michael Ellerman wrote:
> Here's another trace from 3.10-rc7 plus a few local patches.
> 
> We suspect that the perf enable could be causing a flood of
> interrupts, but why
> that's clogging things up so badly who knows.

Additionally, perf being potentially NMIs , we might be hitting a bad
case of reentrance in RCU ... hard to tell.

Cheers,
Ben.

^ permalink raw reply

* Re: Regression in RCU subsystem in latest mainline kernel
From: Michael Ellerman @ 2013-06-25  7:44 UTC (permalink / raw)
  To: Paul E. McKenney
  Cc: Rojhalat Ibrahim, linuxppc-dev, linux-kernel, Steven Rostedt
In-Reply-To: <20130625071914.GA29957@concordia>

On Tue, Jun 25, 2013 at 05:19:14PM +1000, Michael Ellerman wrote:
> 
> Here's another trace from 3.10-rc7 plus a few local patches.

And here's another with CONFIG_RCU_CPU_STALL_INFO=y in case that's useful:

PASS running test_pmc5_6_overuse()
INFO: rcu_sched self-detected stall on CPU
	8: (1 GPs behind) idle=8eb/140000000000002/0 softirq=215/220 
	 (t=2100 jiffies g=18446744073709551583 c=18446744073709551582 q=13)
cpu 0x8: Vector: 0  at [c0000003ea03eae0]
    pc: c00000000011d9b0: .rcu_check_callbacks+0x450/0x910
    lr: c00000000011d9b0: .rcu_check_callbacks+0x450/0x910
    sp: c0000003ea03ec40
   msr: 9000000000009032
  current = 0xc0000003ebf9f4a0
  paca    = 0xc00000000fdc2400	 softe: 0	 irq_happened: 0x00
    pid   = 2444, comm = power8-events
enter ? for help
[c0000003ea03ed70] c000000000094cd0 .update_process_times+0x40/0x90
[c0000003ea03ee00] c0000000000df050 .tick_sched_handle.isra.13+0x20/0xa0
[c0000003ea03ee80] c0000000000df2bc .tick_sched_timer+0x5c/0xa0
[c0000003ea03ef20] c0000000000b3728 .__run_hrtimer+0x98/0x260
[c0000003ea03efc0] c0000000000b4738 .hrtimer_interrupt+0x138/0x3c0
[c0000003ea03f0d0] c00000000001cd34 .timer_interrupt+0x124/0x2f0
[c0000003ea03f180] c00000000000a4f4 restore_check_irq_replay+0x68/0xa8
--- Exception: 901 (Decrementer) at c000000000093ad4 .run_timer_softirq+0x74/0x360
[c0000003ea03f580] c000000000089ac4 .__do_softirq+0x174/0x350
[c0000003ea03f6a0] c000000000089ea8 .irq_exit+0xb8/0x100
[c0000003ea03f720] c00000000001cd68 .timer_interrupt+0x158/0x2f0
[c0000003ea03f7d0] c00000000000a4f4 restore_check_irq_replay+0x68/0xa8
--- Exception: 901 (Decrementer) at c00000000014a520 .task_function_call+0x60/0x70
[c0000003ea03fac0] c00000000014a634 .perf_event_enable+0x104/0x1c0 (unreliable)
[c0000003ea03fb70] c0000000001495ec .perf_event_for_each_child+0x5c/0xf0
[c0000003ea03fc00] c00000000014cd78 .perf_ioctl+0x108/0x400
[c0000003ea03fca0] c0000000001d9aa0 .do_vfs_ioctl+0xb0/0x740
[c0000003ea03fd80] c0000000001da188 .SyS_ioctl+0x58/0xb0
[c0000003ea03fe30] c000000000009d54 syscall_exit+0x0/0x98
--- Exception: c01 (System Call) at 00001fffffee03d0
SP (3ffff5e7cc90) is in userspace


cheers

^ permalink raw reply

* [PATCH 1/4] powerpc: Remove unreachable relocation on exception handlers
From: Michael Ellerman @ 2013-06-25  7:47 UTC (permalink / raw)
  To: linuxppc-dev

We have relocation on exception handlers defined for h_data_storage and
h_instr_storage. However we will never take relocation on exceptions for
these because they can only come from a guest, and we never take
relocation on exceptions when we transition from guest to host.

We also have a handler for hmi_exception (Hypervisor Maintenance) which
is defined in the architecture to never be delivered with relocation on,
see see v2.07 Book III-S section 6.5.

So remove the handlers, leaving a branch to self just to be double extra
paranoid.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/kernel/exceptions-64s.S |   18 +++---------------
 1 file changed, 3 insertions(+), 15 deletions(-)

diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 40e4a17..0a9fdea 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -793,14 +793,10 @@ system_call_relon_pSeries:
 	STD_RELON_EXCEPTION_PSERIES(0x4d00, 0xd00, single_step)
 
 	. = 0x4e00
-	SET_SCRATCH0(r13)
-	EXCEPTION_PROLOG_0(PACA_EXGEN)
-	b	h_data_storage_relon_hv
+	b	.	/* Can't happen, see v2.07 Book III-S section 6.5 */
 
 	. = 0x4e20
-	SET_SCRATCH0(r13)
-	EXCEPTION_PROLOG_0(PACA_EXGEN)
-	b	h_instr_storage_relon_hv
+	b	.	/* Can't happen, see v2.07 Book III-S section 6.5 */
 
 	. = 0x4e40
 	SET_SCRATCH0(r13)
@@ -808,9 +804,7 @@ system_call_relon_pSeries:
 	b	emulation_assist_relon_hv
 
 	. = 0x4e60
-	SET_SCRATCH0(r13)
-	EXCEPTION_PROLOG_0(PACA_EXGEN)
-	b	hmi_exception_relon_hv
+	b	.	/* Can't happen, see v2.07 Book III-S section 6.5 */
 
 	. = 0x4e80
 	SET_SCRATCH0(r13)
@@ -1180,14 +1174,8 @@ tm_unavailable_common:
 __end_handlers:
 
 	/* Equivalents to the above handlers for relocation-on interrupt vectors */
-	STD_RELON_EXCEPTION_HV_OOL(0xe00, h_data_storage)
-	KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe00)
-	STD_RELON_EXCEPTION_HV_OOL(0xe20, h_instr_storage)
-	KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe20)
 	STD_RELON_EXCEPTION_HV_OOL(0xe40, emulation_assist)
 	KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe40)
-	STD_RELON_EXCEPTION_HV_OOL(0xe60, hmi_exception)
-	KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe60)
 	MASKABLE_RELON_EXCEPTION_HV_OOL(0xe80, h_doorbell)
 	KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe80)
 
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 2/4] powerpc: Remove KVMTEST from RELON exception handlers
From: Michael Ellerman @ 2013-06-25  7:47 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1372146477-4338-1-git-send-email-michael@ellerman.id.au>

KVMTEST is a macro which checks whether we are taking an exception from
guest context, if so we branch out of line and eventually call into the
KVM code to handle the switch.

When running real guests on bare metal (HV KVM) the hardware ensures
that we never take a relocation on exception when transitioning from
guest to host. For PR KVM we disable relocation on exceptions ourself in
kvmppc_core_init_vm(), as of commit a413f47 "Disable relocation on
exceptions whenever PR KVM is active".

So convert all the RELON macros to use NOTEST, and drop the remaining
KVM_HANDLER() definitions we have for 0xe40 and 0xe80.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/include/asm/exception-64s.h |    8 ++++----
 arch/powerpc/kernel/exceptions-64s.S     |    2 --
 2 files changed, 4 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/include/asm/exception-64s.h b/arch/powerpc/include/asm/exception-64s.h
index 46793b5..07ca627 100644
--- a/arch/powerpc/include/asm/exception-64s.h
+++ b/arch/powerpc/include/asm/exception-64s.h
@@ -358,12 +358,12 @@ label##_relon_pSeries:					\
 	/* No guest interrupts come through here */	\
 	SET_SCRATCH0(r13);		/* save r13 */	\
 	EXCEPTION_RELON_PROLOG_PSERIES(PACA_EXGEN, label##_common, \
-				       EXC_STD, KVMTEST_PR, vec)
+				       EXC_STD, NOTEST, vec)
 
 #define STD_RELON_EXCEPTION_PSERIES_OOL(vec, label)		\
 	.globl label##_relon_pSeries;				\
 label##_relon_pSeries:						\
-	EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST_PR, vec);	\
+	EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, vec);		\
 	EXCEPTION_RELON_PROLOG_PSERIES_1(label##_common, EXC_STD)
 
 #define STD_RELON_EXCEPTION_HV(loc, vec, label)		\
@@ -374,12 +374,12 @@ label##_relon_hv:					\
 	/* No guest interrupts come through here */	\
 	SET_SCRATCH0(r13);	/* save r13 */		\
 	EXCEPTION_RELON_PROLOG_PSERIES(PACA_EXGEN, label##_common, \
-				       EXC_HV, KVMTEST, vec)
+				       EXC_HV, NOTEST, vec)
 
 #define STD_RELON_EXCEPTION_HV_OOL(vec, label)			\
 	.globl label##_relon_hv;				\
 label##_relon_hv:						\
-	EXCEPTION_PROLOG_1(PACA_EXGEN, KVMTEST, vec);		\
+	EXCEPTION_PROLOG_1(PACA_EXGEN, NOTEST, vec);		\
 	EXCEPTION_RELON_PROLOG_PSERIES_1(label##_common, EXC_HV)
 
 /* This associate vector numbers with bits in paca->irq_happened */
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 0a9fdea..6bd6763 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -1175,9 +1175,7 @@ __end_handlers:
 
 	/* Equivalents to the above handlers for relocation-on interrupt vectors */
 	STD_RELON_EXCEPTION_HV_OOL(0xe40, emulation_assist)
-	KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe40)
 	MASKABLE_RELON_EXCEPTION_HV_OOL(0xe80, h_doorbell)
-	KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xe80)
 
 	STD_RELON_EXCEPTION_PSERIES_OOL(0xf00, performance_monitor)
 	STD_RELON_EXCEPTION_PSERIES_OOL(0xf20, altivec_unavailable)
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 3/4] powerpc: Rename and flesh out the facility unavailable exception handler
From: Michael Ellerman @ 2013-06-25  7:47 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1372146477-4338-1-git-send-email-michael@ellerman.id.au>

From: Michael Ellerman <michaele@au1.ibm.com>

The exception at 0xf60 is not the TM (Transactional Memory) unavailable
exception, it is the "Facility Unavailable Exception", rename it as
such.

Flesh out the handler to acknowledge the fact that it can be called for
many reasons, one of which is TM being unavailable.

Use STD_EXCEPTION_COMMON() for the exception body, for some reason we
had it open-coded, I've checked the generated code is identical.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/kernel/exceptions-64s.S |   21 +++++++--------------
 arch/powerpc/kernel/traps.c          |   33 +++++++++++++++++++++++++--------
 2 files changed, 32 insertions(+), 22 deletions(-)

diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index 6bd6763..d55a63c 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -341,10 +341,11 @@ vsx_unavailable_pSeries_1:
 	EXCEPTION_PROLOG_0(PACA_EXGEN)
 	b	vsx_unavailable_pSeries
 
+facility_unavailable_trampoline:
 	. = 0xf60
 	SET_SCRATCH0(r13)
 	EXCEPTION_PROLOG_0(PACA_EXGEN)
-	b	tm_unavailable_pSeries
+	b	facility_unavailable_pSeries
 
 #ifdef CONFIG_CBE_RAS
 	STD_EXCEPTION_HV(0x1200, 0x1202, cbe_system_error)
@@ -522,7 +523,7 @@ denorm_done:
 	KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf20)
 	STD_EXCEPTION_PSERIES_OOL(0xf40, vsx_unavailable)
 	KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf40)
-	STD_EXCEPTION_PSERIES_OOL(0xf60, tm_unavailable)
+	STD_EXCEPTION_PSERIES_OOL(0xf60, facility_unavailable)
 	KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf60)
 
 /*
@@ -829,11 +830,11 @@ vsx_unavailable_relon_pSeries_1:
 	EXCEPTION_PROLOG_0(PACA_EXGEN)
 	b	vsx_unavailable_relon_pSeries
 
-tm_unavailable_relon_pSeries_1:
+facility_unavailable_relon_trampoline:
 	. = 0x4f60
 	SET_SCRATCH0(r13)
 	EXCEPTION_PROLOG_0(PACA_EXGEN)
-	b	tm_unavailable_relon_pSeries
+	b	facility_unavailable_relon_pSeries
 
 	STD_RELON_EXCEPTION_PSERIES(0x5300, 0x1300, instruction_breakpoint)
 #ifdef CONFIG_PPC_DENORMALISATION
@@ -1159,15 +1160,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_VSX)
 	bl	.vsx_unavailable_exception
 	b	.ret_from_except
 
-	.align	7
-	.globl tm_unavailable_common
-tm_unavailable_common:
-	EXCEPTION_PROLOG_COMMON(0xf60, PACA_EXGEN)
-	bl	.save_nvgprs
-	DISABLE_INTS
-	addi	r3,r1,STACK_FRAME_OVERHEAD
-	bl	.tm_unavailable_exception
-	b	.ret_from_except
+	STD_EXCEPTION_COMMON(0xf60, facility_unavailable, .facility_unavailable_exception)
 
 	.align	7
 	.globl	__end_handlers
@@ -1180,7 +1173,7 @@ __end_handlers:
 	STD_RELON_EXCEPTION_PSERIES_OOL(0xf00, performance_monitor)
 	STD_RELON_EXCEPTION_PSERIES_OOL(0xf20, altivec_unavailable)
 	STD_RELON_EXCEPTION_PSERIES_OOL(0xf40, vsx_unavailable)
-	STD_RELON_EXCEPTION_PSERIES_OOL(0xf60, tm_unavailable)
+	STD_RELON_EXCEPTION_PSERIES_OOL(0xf60, facility_unavailable)
 
 #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
 /*
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index c0e5caf..2053bbd 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -1282,25 +1282,42 @@ void vsx_unavailable_exception(struct pt_regs *regs)
 	die("Unrecoverable VSX Unavailable Exception", regs, SIGABRT);
 }
 
-void tm_unavailable_exception(struct pt_regs *regs)
+void facility_unavailable_exception(struct pt_regs *regs)
 {
+	static char *facility_strings[] = {
+		"FPU",
+		"VMX/VSX",
+		"DSCR",
+		"PMU SPRs",
+		"BHRB",
+		"TM",
+		"AT",
+		"EBB",
+		"TAR",
+	};
+	char *facility;
+	u64 value;
+
+	value = mfspr(SPRN_FSCR) >> 56;
+
 	/* We restore the interrupt state now */
 	if (!arch_irq_disabled_regs(regs))
 		local_irq_enable();
 
-	/* Currently we never expect a TMU exception.  Catch
-	 * this and kill the process!
-	 */
-	printk(KERN_EMERG "Unexpected TM unavailable exception at %lx "
-	       "(msr %lx)\n",
-	       regs->nip, regs->msr);
+	if (value < ARRAY_SIZE(facility_strings))
+		facility = facility_strings[value];
+	else
+		facility = "unknown";
+
+	pr_err("Facility '%s' unavailable, exception at 0x%lx, MSR=%lx\n",
+		facility, regs->nip, regs->msr);
 
 	if (user_mode(regs)) {
 		_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
 		return;
 	}
 
-	die("Unexpected TM unavailable exception", regs, SIGABRT);
+	die("Unexpected facility unavailable exception", regs, SIGABRT);
 }
 
 #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
-- 
1.7.10.4

^ permalink raw reply related

* [PATCH 4/4] powerpc: Wire up the HV facility unavailable exception
From: Michael Ellerman @ 2013-06-25  7:47 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <1372146477-4338-1-git-send-email-michael@ellerman.id.au>

Similar to the facility unavailble exception, except the facilities are
controlled by HFSCR.

Adapt the facility_unavailable_exception() so it can be called for
either the regular or Hypervisor facility unavailable exceptions.

Signed-off-by: Michael Ellerman <michael@ellerman.id.au>
---
 arch/powerpc/kernel/exceptions-64s.S |   15 +++++++++++++++
 arch/powerpc/kernel/traps.c          |   16 ++++++++++++----
 2 files changed, 27 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S
index d55a63c..4e00d22 100644
--- a/arch/powerpc/kernel/exceptions-64s.S
+++ b/arch/powerpc/kernel/exceptions-64s.S
@@ -347,6 +347,12 @@ facility_unavailable_trampoline:
 	EXCEPTION_PROLOG_0(PACA_EXGEN)
 	b	facility_unavailable_pSeries
 
+hv_facility_unavailable_trampoline:
+	. = 0xf80
+	SET_SCRATCH0(r13)
+	EXCEPTION_PROLOG_0(PACA_EXGEN)
+	b	facility_unavailable_hv
+
 #ifdef CONFIG_CBE_RAS
 	STD_EXCEPTION_HV(0x1200, 0x1202, cbe_system_error)
 	KVM_HANDLER_SKIP(PACA_EXGEN, EXC_HV, 0x1202)
@@ -525,6 +531,8 @@ denorm_done:
 	KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf40)
 	STD_EXCEPTION_PSERIES_OOL(0xf60, facility_unavailable)
 	KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xf60)
+	STD_EXCEPTION_HV_OOL(0xf82, facility_unavailable)
+	KVM_HANDLER(PACA_EXGEN, EXC_HV, 0xf82)
 
 /*
  * An interrupt came in while soft-disabled. We set paca->irq_happened, then:
@@ -836,6 +844,12 @@ facility_unavailable_relon_trampoline:
 	EXCEPTION_PROLOG_0(PACA_EXGEN)
 	b	facility_unavailable_relon_pSeries
 
+hv_facility_unavailable_relon_trampoline:
+	. = 0x4f80
+	SET_SCRATCH0(r13)
+	EXCEPTION_PROLOG_0(PACA_EXGEN)
+	b	facility_unavailable_relon_hv
+
 	STD_RELON_EXCEPTION_PSERIES(0x5300, 0x1300, instruction_breakpoint)
 #ifdef CONFIG_PPC_DENORMALISATION
 	. = 0x5500
@@ -1174,6 +1188,7 @@ __end_handlers:
 	STD_RELON_EXCEPTION_PSERIES_OOL(0xf20, altivec_unavailable)
 	STD_RELON_EXCEPTION_PSERIES_OOL(0xf40, vsx_unavailable)
 	STD_RELON_EXCEPTION_PSERIES_OOL(0xf60, facility_unavailable)
+	STD_RELON_EXCEPTION_HV_OOL(0xf80, facility_unavailable)
 
 #if defined(CONFIG_PPC_PSERIES) || defined(CONFIG_PPC_POWERNV)
 /*
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c
index 2053bbd..e4f205a 100644
--- a/arch/powerpc/kernel/traps.c
+++ b/arch/powerpc/kernel/traps.c
@@ -1295,10 +1295,18 @@ void facility_unavailable_exception(struct pt_regs *regs)
 		"EBB",
 		"TAR",
 	};
-	char *facility;
+	char *facility, *prefix;
 	u64 value;
 
-	value = mfspr(SPRN_FSCR) >> 56;
+	if (regs->trap == 0xf60) {
+		value = mfspr(SPRN_FSCR);
+		prefix = "";
+	} else {
+		value = mfspr(SPRN_HFSCR);
+		prefix = "Hypervisor ";
+	}
+
+	value = value >> 56;
 
 	/* We restore the interrupt state now */
 	if (!arch_irq_disabled_regs(regs))
@@ -1309,8 +1317,8 @@ void facility_unavailable_exception(struct pt_regs *regs)
 	else
 		facility = "unknown";
 
-	pr_err("Facility '%s' unavailable, exception at 0x%lx, MSR=%lx\n",
-		facility, regs->nip, regs->msr);
+	pr_err("%sFacility '%s' unavailable, exception at 0x%lx, MSR=%lx\n",
+		prefix, facility, regs->nip, regs->msr);
 
 	if (user_mode(regs)) {
 		_exception(SIGILL, regs, ILL_ILLOPC, regs->nip);
-- 
1.7.10.4

^ permalink raw reply related

* Re: [PATCH 03/10] powerpc/eeh: Check PCIe link after reset
From: Gavin Shan @ 2013-06-25  7:47 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, Gavin Shan
In-Reply-To: <1372140384.3944.189.camel@pasglop>

On Tue, Jun 25, 2013 at 04:06:24PM +1000, Benjamin Herrenschmidt wrote:
>On Tue, 2013-06-25 at 13:55 +0800, Gavin Shan wrote:
>>         * don't touch the other command bits
>>          */
>> -       eeh_ops->read_config(dn, PCI_COMMAND, 4, &cmd);
>> -       if (edev->config_space[1] & PCI_COMMAND_PARITY)
>> -               cmd |= PCI_COMMAND_PARITY;
>> -       else
>> -               cmd &= ~PCI_COMMAND_PARITY;
>> -       if (edev->config_space[1] & PCI_COMMAND_SERR)
>> -               cmd |= PCI_COMMAND_SERR;
>> -       else
>> -               cmd &= ~PCI_COMMAND_SERR;
>> -       eeh_ops->write_config(dn, PCI_COMMAND, 4, cmd);
>> +       if (pdev) {
>> +               eeh_ops->write_config(dn, PCI_COMMAND, 4,
>> +                                     edev->config_space[1]);
>> +       } else {
>
>That needs a much better comment. Why are you doing that instead
>of what's below ? In fact there is more to restore in a bridge
>right ? (windows etc...). Do you do that ? Should we just have a
>different function to restore a device vs. a bridge ?
>

Yeah, We should have one separate function to do that for bridge.
I'll do that in next revision.

>I also don't see a need to do thing differently between phyp and
>powernv. Bridges inside partitions would suffer the same fate in
>both cases.
>

If we just have complete reset for fenced PHB, we need restore it
from the cache (edev->config_space[1]) instead of reading that from
hardware. Fenced PHB is the special case on PowerNV :-)

Thanks,
Gavin

^ permalink raw reply

* Re: [PATCH 2/9] PTR_RET is now PTR_ERR_OR_ZERO(): Replace most.
From: Benjamin Herrenschmidt @ 2013-06-25  7:47 UTC (permalink / raw)
  To: Rusty Russell
  Cc: netdev, linuxppc-dev, linux-kernel, linux-arm-kernel,
	Julia Lawall
In-Reply-To: <1371357768-4968-2-git-send-email-rusty@rustcorp.com.au>

On Sun, 2013-06-16 at 14:12 +0930, Rusty Russell wrote:
> Sweep of the simple cases.
> 
> Cc: netdev@vger.kernel.org
> Cc: linuxppc-dev@lists.ozlabs.org
> Cc: linux-arm-kernel@lists.infradead.org
> Cc: Julia Lawall <julia.lawall@lip6.fr>
> Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>

Acked-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>

> ---
>  arch/arm/mach-omap2/i2c.c                         |  2 +-
>  arch/m68k/amiga/platform.c                        |  2 +-
>  arch/m68k/kernel/time.c                           |  2 +-
>  arch/m68k/q40/config.c                            |  2 +-
>  arch/powerpc/kernel/iommu.c                       |  2 +-
>  arch/powerpc/kernel/time.c                        |  2 +-
>  arch/powerpc/platforms/ps3/time.c                 |  2 +-
>  arch/powerpc/sysdev/rtc_cmos_setup.c              |  2 +-
>  arch/s390/hypfs/hypfs_dbfs.c                      |  2 +-
>  drivers/char/tile-srom.c                          |  2 +-
>  drivers/infiniband/core/cma.c                     |  2 +-
>  drivers/net/appletalk/cops.c                      |  2 +-
>  drivers/net/appletalk/ltpc.c                      |  2 +-
>  drivers/net/ethernet/amd/atarilance.c             |  2 +-
>  drivers/net/ethernet/amd/mvme147.c                |  2 +-
>  drivers/net/ethernet/amd/ni65.c                   |  2 +-
>  drivers/net/ethernet/amd/sun3lance.c              |  2 +-
>  drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c |  2 +-
>  drivers/net/wireless/brcm80211/brcmsmac/debug.c   |  2 +-
>  drivers/platform/x86/samsung-q10.c                |  2 +-
>  drivers/regulator/fan53555.c                      |  2 +-
>  drivers/spi/spi-fsl-spi.c                         |  2 +-
>  drivers/spi/spidev.c                              |  2 +-
>  drivers/video/omap2/dss/core.c                    |  2 +-
>  fs/btrfs/dev-replace.c                            |  2 +-
>  fs/btrfs/inode.c                                  |  2 +-
>  net/bluetooth/hci_sysfs.c                         |  2 +-
>  net/bridge/netfilter/ebtable_broute.c             |  2 +-
>  net/bridge/netfilter/ebtable_filter.c             |  2 +-
>  net/bridge/netfilter/ebtable_nat.c                |  2 +-
>  net/ipv4/netfilter/arptable_filter.c              |  2 +-
>  net/ipv4/netfilter/iptable_filter.c               |  2 +-
>  net/ipv4/netfilter/iptable_mangle.c               |  2 +-
>  net/ipv4/netfilter/iptable_nat.c                  |  2 +-
>  net/ipv4/netfilter/iptable_raw.c                  |  2 +-
>  net/ipv4/netfilter/iptable_security.c             |  2 +-
>  net/ipv6/netfilter/ip6table_filter.c              |  2 +-
>  net/ipv6/netfilter/ip6table_mangle.c              |  2 +-
>  net/ipv6/netfilter/ip6table_nat.c                 |  2 +-
>  net/ipv6/netfilter/ip6table_raw.c                 |  2 +-
>  net/ipv6/netfilter/ip6table_security.c            |  2 +-
>  scripts/coccinelle/api/ptr_ret.cocci              | 10 +++++-----
>  sound/soc/soc-io.c                                |  2 +-
>  43 files changed, 47 insertions(+), 47 deletions(-)
> 
> diff --git a/arch/arm/mach-omap2/i2c.c b/arch/arm/mach-omap2/i2c.c
> index d940e53..b456b44 100644
> --- a/arch/arm/mach-omap2/i2c.c
> +++ b/arch/arm/mach-omap2/i2c.c
> @@ -181,7 +181,7 @@ int __init omap_i2c_add_bus(struct omap_i2c_bus_platform_data *i2c_pdata,
>  				 sizeof(struct omap_i2c_bus_platform_data));
>  	WARN(IS_ERR(pdev), "Could not build omap_device for %s\n", name);
>  
> -	return PTR_RET(pdev);
> +	return PTR_ERR_OR_ZERO(pdev);
>  }
>  
>  static  int __init omap_i2c_cmdline(void)
> diff --git a/arch/m68k/amiga/platform.c b/arch/m68k/amiga/platform.c
> index 6083088..dacd9f9 100644
> --- a/arch/m68k/amiga/platform.c
> +++ b/arch/m68k/amiga/platform.c
> @@ -56,7 +56,7 @@ static int __init amiga_init_bus(void)
>  	n = AMIGAHW_PRESENT(ZORRO3) ? 4 : 2;
>  	pdev = platform_device_register_simple("amiga-zorro", -1,
>  					       zorro_resources, n);
> -	return PTR_RET(pdev);
> +	return PTR_ERR_OR_ZERO(pdev);
>  }
>  
>  subsys_initcall(amiga_init_bus);
> diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c
> index bea6bcf..7eb9792 100644
> --- a/arch/m68k/kernel/time.c
> +++ b/arch/m68k/kernel/time.c
> @@ -90,7 +90,7 @@ static int __init rtc_init(void)
>  		return -ENODEV;
>  
>  	pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0);
> -	return PTR_RET(pdev);
> +	return PTR_ERR_OR_ZERO(pdev);
>  }
>  
>  module_init(rtc_init);
> diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c
> index 658542b..078bb74 100644
> --- a/arch/m68k/q40/config.c
> +++ b/arch/m68k/q40/config.c
> @@ -338,6 +338,6 @@ static __init int q40_add_kbd_device(void)
>  		return -ENODEV;
>  
>  	pdev = platform_device_register_simple("q40kbd", -1, NULL, 0);
> -	return PTR_RET(pdev);
> +	return PTR_ERR_OR_ZERO(pdev);
>  }
>  arch_initcall(q40_add_kbd_device);
> diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
> index c0d0dbd..3a149eb 100644
> --- a/arch/powerpc/kernel/iommu.c
> +++ b/arch/powerpc/kernel/iommu.c
> @@ -102,7 +102,7 @@ static int __init fail_iommu_debugfs(void)
>  	struct dentry *dir = fault_create_debugfs_attr("fail_iommu",
>  						       NULL, &fail_iommu);
>  
> -	return PTR_RET(dir);
> +	return PTR_ERR_OR_ZERO(dir);
>  }
>  late_initcall(fail_iommu_debugfs);
>  
> diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
> index 5fc29ad..77e78ef 100644
> --- a/arch/powerpc/kernel/time.c
> +++ b/arch/powerpc/kernel/time.c
> @@ -1050,7 +1050,7 @@ static int __init rtc_init(void)
>  
>  	pdev = platform_device_register_simple("rtc-generic", -1, NULL, 0);
>  
> -	return PTR_RET(pdev);
> +	return PTR_ERR_OR_ZERO(pdev);
>  }
>  
>  module_init(rtc_init);
> diff --git a/arch/powerpc/platforms/ps3/time.c b/arch/powerpc/platforms/ps3/time.c
> index cba1e6b..ce73ce8 100644
> --- a/arch/powerpc/platforms/ps3/time.c
> +++ b/arch/powerpc/platforms/ps3/time.c
> @@ -90,7 +90,7 @@ static int __init ps3_rtc_init(void)
>  
>  	pdev = platform_device_register_simple("rtc-ps3", -1, NULL, 0);
>  
> -	return PTR_RET(pdev);
> +	return PTR_ERR_OR_ZERO(pdev);
>  }
>  
>  module_init(ps3_rtc_init);
> diff --git a/arch/powerpc/sysdev/rtc_cmos_setup.c b/arch/powerpc/sysdev/rtc_cmos_setup.c
> index af79e1e..af0f9be 100644
> --- a/arch/powerpc/sysdev/rtc_cmos_setup.c
> +++ b/arch/powerpc/sysdev/rtc_cmos_setup.c
> @@ -62,7 +62,7 @@ static int  __init add_rtc(void)
>  	pd = platform_device_register_simple("rtc_cmos", -1,
>  					     &res[0], num_res);
>  
> -	return PTR_RET(pd);
> +	return PTR_ERR_OR_ZERO(pd);
>  }
>  fs_initcall(add_rtc);
>  
> diff --git a/arch/s390/hypfs/hypfs_dbfs.c b/arch/s390/hypfs/hypfs_dbfs.c
> index bb5dd49..17ab8b7 100644
> --- a/arch/s390/hypfs/hypfs_dbfs.c
> +++ b/arch/s390/hypfs/hypfs_dbfs.c
> @@ -105,7 +105,7 @@ void hypfs_dbfs_remove_file(struct hypfs_dbfs_file *df)
>  int hypfs_dbfs_init(void)
>  {
>  	dbfs_dir = debugfs_create_dir("s390_hypfs", NULL);
> -	return PTR_RET(dbfs_dir);
> +	return PTR_ERR_OR_ZERO(dbfs_dir);
>  }
>  
>  void hypfs_dbfs_exit(void)
> diff --git a/drivers/char/tile-srom.c b/drivers/char/tile-srom.c
> index 2e2036e..a3a792f 100644
> --- a/drivers/char/tile-srom.c
> +++ b/drivers/char/tile-srom.c
> @@ -371,7 +371,7 @@ static int srom_setup_minor(struct srom_dev *srom, int index)
>  
>  	dev = device_create(srom_class, &platform_bus,
>  			    MKDEV(srom_major, index), srom, "%d", index);
> -	return PTR_RET(dev);
> +	return PTR_ERR_OR_ZERO(dev);
>  }
>  
>  /** srom_init() - Initialize the driver's module. */
> diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c
> index 71c2c71..17a6ec5 100644
> --- a/drivers/infiniband/core/cma.c
> +++ b/drivers/infiniband/core/cma.c
> @@ -3055,7 +3055,7 @@ static int cma_join_ib_multicast(struct rdma_id_private *id_priv,
>  						id_priv->id.port_num, &rec,
>  						comp_mask, GFP_KERNEL,
>  						cma_ib_mc_handler, mc);
> -	return PTR_RET(mc->multicast.ib);
> +	return PTR_ERR_OR_ZERO(mc->multicast.ib);
>  }
>  
>  static void iboe_mcast_work_handler(struct work_struct *work)
> diff --git a/drivers/net/appletalk/cops.c b/drivers/net/appletalk/cops.c
> index cff6f02..7f2a032 100644
> --- a/drivers/net/appletalk/cops.c
> +++ b/drivers/net/appletalk/cops.c
> @@ -996,7 +996,7 @@ static int __init cops_module_init(void)
>  		printk(KERN_WARNING "%s: You shouldn't autoprobe with insmod\n",
>  			cardname);
>  	cops_dev = cops_probe(-1);
> -	return PTR_RET(cops_dev);
> +	return PTR_ERR_OR_ZERO(cops_dev);
>  }
>  
>  static void __exit cops_module_exit(void)
> diff --git a/drivers/net/appletalk/ltpc.c b/drivers/net/appletalk/ltpc.c
> index b5782cd..01e2ac5 100644
> --- a/drivers/net/appletalk/ltpc.c
> +++ b/drivers/net/appletalk/ltpc.c
> @@ -1243,7 +1243,7 @@ static int __init ltpc_module_init(void)
>  		       "ltpc: Autoprobing is not recommended for modules\n");
>  
>  	dev_ltpc = ltpc_probe();
> -	return PTR_RET(dev_ltpc);
> +	return PTR_ERR_OR_ZERO(dev_ltpc);
>  }
>  module_init(ltpc_module_init);
>  #endif
> diff --git a/drivers/net/ethernet/amd/atarilance.c b/drivers/net/ethernet/amd/atarilance.c
> index e8d0ef5..10ceca5 100644
> --- a/drivers/net/ethernet/amd/atarilance.c
> +++ b/drivers/net/ethernet/amd/atarilance.c
> @@ -1147,7 +1147,7 @@ static struct net_device *atarilance_dev;
>  static int __init atarilance_module_init(void)
>  {
>  	atarilance_dev = atarilance_probe(-1);
> -	return PTR_RET(atarilance_dev);
> +	return PTR_ERR_OR_ZERO(atarilance_dev);
>  }
>  
>  static void __exit atarilance_module_exit(void)
> diff --git a/drivers/net/ethernet/amd/mvme147.c b/drivers/net/ethernet/amd/mvme147.c
> index a51497c..e108e91 100644
> --- a/drivers/net/ethernet/amd/mvme147.c
> +++ b/drivers/net/ethernet/amd/mvme147.c
> @@ -188,7 +188,7 @@ static struct net_device *dev_mvme147_lance;
>  int __init init_module(void)
>  {
>  	dev_mvme147_lance = mvme147lance_probe(-1);
> -	return PTR_RET(dev_mvme147_lance);
> +	return PTR_ERR_OR_ZERO(dev_mvme147_lance);
>  }
>  
>  void __exit cleanup_module(void)
> diff --git a/drivers/net/ethernet/amd/ni65.c b/drivers/net/ethernet/amd/ni65.c
> index 26fc0ce..1cf33ad 100644
> --- a/drivers/net/ethernet/amd/ni65.c
> +++ b/drivers/net/ethernet/amd/ni65.c
> @@ -1238,7 +1238,7 @@ MODULE_PARM_DESC(dma, "ni6510 ISA DMA channel (ignored for some cards)");
>  int __init init_module(void)
>  {
>   	dev_ni65 = ni65_probe(-1);
> -	return PTR_RET(dev_ni65);
> +	return PTR_ERR_OR_ZERO(dev_ni65);
>  }
>  
>  void __exit cleanup_module(void)
> diff --git a/drivers/net/ethernet/amd/sun3lance.c b/drivers/net/ethernet/amd/sun3lance.c
> index 4375abe..d6b2029 100644
> --- a/drivers/net/ethernet/amd/sun3lance.c
> +++ b/drivers/net/ethernet/amd/sun3lance.c
> @@ -940,7 +940,7 @@ static struct net_device *sun3lance_dev;
>  int __init init_module(void)
>  {
>  	sun3lance_dev = sun3lance_probe(-1);
> -	return PTR_RET(sun3lance_dev);
> +	return PTR_ERR_OR_ZERO(sun3lance_dev);
>  }
>  
>  void __exit cleanup_module(void)
> diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
> index 202869c..3962a7a 100644
> --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
> +++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c
> @@ -50,7 +50,7 @@ int brcmf_debugfs_attach(struct brcmf_pub *drvr)
>  		return -ENODEV;
>  
>  	drvr->dbgfs_dir = debugfs_create_dir(dev_name(dev), root_folder);
> -	return PTR_RET(drvr->dbgfs_dir);
> +	return PTR_ERR_OR_ZERO(drvr->dbgfs_dir);
>  }
>  
>  void brcmf_debugfs_detach(struct brcmf_pub *drvr)
> diff --git a/drivers/net/wireless/brcm80211/brcmsmac/debug.c b/drivers/net/wireless/brcm80211/brcmsmac/debug.c
> index 9761deb..a5d4add 100644
> --- a/drivers/net/wireless/brcm80211/brcmsmac/debug.c
> +++ b/drivers/net/wireless/brcm80211/brcmsmac/debug.c
> @@ -56,7 +56,7 @@ int brcms_debugfs_attach(struct brcms_pub *drvr)
>  
>  	drvr->dbgfs_dir = debugfs_create_dir(
>  		 dev_name(&drvr->wlc->hw->d11core->dev), root_folder);
> -	return PTR_RET(drvr->dbgfs_dir);
> +	return PTR_ERR_OR_ZERO(drvr->dbgfs_dir);
>  }
>  
>  void brcms_debugfs_detach(struct brcms_pub *drvr)
> diff --git a/drivers/platform/x86/samsung-q10.c b/drivers/platform/x86/samsung-q10.c
> index 1a90b62..4430b8c 100644
> --- a/drivers/platform/x86/samsung-q10.c
> +++ b/drivers/platform/x86/samsung-q10.c
> @@ -176,7 +176,7 @@ static int __init samsungq10_init(void)
>  						   samsungq10_probe,
>  						   NULL, 0, NULL, 0);
>  
> -	return PTR_RET(samsungq10_device);
> +	return PTR_ERR_OR_ZERO(samsungq10_device);
>  }
>  
>  static void __exit samsungq10_exit(void)
> diff --git a/drivers/regulator/fan53555.c b/drivers/regulator/fan53555.c
> index f0e1ae5..192444a 100644
> --- a/drivers/regulator/fan53555.c
> +++ b/drivers/regulator/fan53555.c
> @@ -219,7 +219,7 @@ static int fan53555_regulator_register(struct fan53555_device_info *di,
>  	rdesc->owner = THIS_MODULE;
>  
>  	di->rdev = regulator_register(&di->desc, config);
> -	return PTR_RET(di->rdev);
> +	return PTR_ERR_OR_ZERO(di->rdev);
>  
>  }
>  
> diff --git a/drivers/spi/spi-fsl-spi.c b/drivers/spi/spi-fsl-spi.c
> index 14e202e..6e80639 100644
> --- a/drivers/spi/spi-fsl-spi.c
> +++ b/drivers/spi/spi-fsl-spi.c
> @@ -901,7 +901,7 @@ static int plat_mpc8xxx_spi_probe(struct platform_device *pdev)
>  		return -EINVAL;
>  
>  	master = fsl_spi_probe(&pdev->dev, mem, irq);
> -	return PTR_RET(master);
> +	return PTR_ERR_OR_ZERO(master);
>  }
>  
>  static int plat_mpc8xxx_spi_remove(struct platform_device *pdev)
> diff --git a/drivers/spi/spidev.c b/drivers/spi/spidev.c
> index 911e9e0..ca5bcfe 100644
> --- a/drivers/spi/spidev.c
> +++ b/drivers/spi/spidev.c
> @@ -603,7 +603,7 @@ static int spidev_probe(struct spi_device *spi)
>  		dev = device_create(spidev_class, &spi->dev, spidev->devt,
>  				    spidev, "spidev%d.%d",
>  				    spi->master->bus_num, spi->chip_select);
> -		status = PTR_RET(dev);
> +		status = PTR_ERR_OR_ZERO(dev);
>  	} else {
>  		dev_dbg(&spi->dev, "no minor number available!\n");
>  		status = -ENODEV;
> diff --git a/drivers/video/omap2/dss/core.c b/drivers/video/omap2/dss/core.c
> index c9c2252..a65f1ac 100644
> --- a/drivers/video/omap2/dss/core.c
> +++ b/drivers/video/omap2/dss/core.c
> @@ -189,7 +189,7 @@ int dss_debugfs_create_file(const char *name, void (*write)(struct seq_file *))
>  	d = debugfs_create_file(name, S_IRUGO, dss_debugfs_dir,
>  			write, &dss_debug_fops);
>  
> -	return PTR_RET(d);
> +	return PTR_ERR_OR_ZERO(d);
>  }
>  #else /* CONFIG_OMAP2_DSS_DEBUGFS */
>  static inline int dss_initialize_debugfs(void)
> diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
> index 65241f3..b63903f 100644
> --- a/fs/btrfs/dev-replace.c
> +++ b/fs/btrfs/dev-replace.c
> @@ -747,7 +747,7 @@ int btrfs_resume_dev_replace_async(struct btrfs_fs_info *fs_info)
>  	WARN_ON(atomic_xchg(
>  		&fs_info->mutually_exclusive_operation_running, 1));
>  	task = kthread_run(btrfs_dev_replace_kthread, fs_info, "btrfs-devrepl");
> -	return PTR_RET(task);
> +	return PTR_ERR_OR_ZERO(task);
>  }
>  
>  static int btrfs_dev_replace_kthread(void *data)
> diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
> index af978f7..1850a96 100644
> --- a/fs/btrfs/inode.c
> +++ b/fs/btrfs/inode.c
> @@ -3140,7 +3140,7 @@ int btrfs_orphan_cleanup(struct btrfs_root *root)
>  		found_key.type = BTRFS_INODE_ITEM_KEY;
>  		found_key.offset = 0;
>  		inode = btrfs_iget(root->fs_info->sb, &found_key, root, NULL);
> -		ret = PTR_RET(inode);
> +		ret = PTR_ERR_OR_ZERO(inode);
>  		if (ret && ret != -ESTALE)
>  			goto out;
>  
> diff --git a/net/bluetooth/hci_sysfs.c b/net/bluetooth/hci_sysfs.c
> index 7ad6ecf..edf623a 100644
> --- a/net/bluetooth/hci_sysfs.c
> +++ b/net/bluetooth/hci_sysfs.c
> @@ -590,7 +590,7 @@ int __init bt_sysfs_init(void)
>  
>  	bt_class = class_create(THIS_MODULE, "bluetooth");
>  
> -	return PTR_RET(bt_class);
> +	return PTR_ERR_OR_ZERO(bt_class);
>  }
>  
>  void bt_sysfs_cleanup(void)
> diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c
> index 70f656c..dbd1c78 100644
> --- a/net/bridge/netfilter/ebtable_broute.c
> +++ b/net/bridge/netfilter/ebtable_broute.c
> @@ -64,7 +64,7 @@ static int ebt_broute(struct sk_buff *skb)
>  static int __net_init broute_net_init(struct net *net)
>  {
>  	net->xt.broute_table = ebt_register_table(net, &broute_table);
> -	return PTR_RET(net->xt.broute_table);
> +	return PTR_ERR_OR_ZERO(net->xt.broute_table);
>  }
>  
>  static void __net_exit broute_net_exit(struct net *net)
> diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c
> index 3c2e9dc..94b2b70 100644
> --- a/net/bridge/netfilter/ebtable_filter.c
> +++ b/net/bridge/netfilter/ebtable_filter.c
> @@ -100,7 +100,7 @@ static struct nf_hook_ops ebt_ops_filter[] __read_mostly = {
>  static int __net_init frame_filter_net_init(struct net *net)
>  {
>  	net->xt.frame_filter = ebt_register_table(net, &frame_filter);
> -	return PTR_RET(net->xt.frame_filter);
> +	return PTR_ERR_OR_ZERO(net->xt.frame_filter);
>  }
>  
>  static void __net_exit frame_filter_net_exit(struct net *net)
> diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c
> index 10871bc..322555a 100644
> --- a/net/bridge/netfilter/ebtable_nat.c
> +++ b/net/bridge/netfilter/ebtable_nat.c
> @@ -100,7 +100,7 @@ static struct nf_hook_ops ebt_ops_nat[] __read_mostly = {
>  static int __net_init frame_nat_net_init(struct net *net)
>  {
>  	net->xt.frame_nat = ebt_register_table(net, &frame_nat);
> -	return PTR_RET(net->xt.frame_nat);
> +	return PTR_ERR_OR_ZERO(net->xt.frame_nat);
>  }
>  
>  static void __net_exit frame_nat_net_exit(struct net *net)
> diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c
> index eadab1e..a865f6f 100644
> --- a/net/ipv4/netfilter/arptable_filter.c
> +++ b/net/ipv4/netfilter/arptable_filter.c
> @@ -48,7 +48,7 @@ static int __net_init arptable_filter_net_init(struct net *net)
>  	net->ipv4.arptable_filter =
>  		arpt_register_table(net, &packet_filter, repl);
>  	kfree(repl);
> -	return PTR_RET(net->ipv4.arptable_filter);
> +	return PTR_ERR_OR_ZERO(net->ipv4.arptable_filter);
>  }
>  
>  static void __net_exit arptable_filter_net_exit(struct net *net)
> diff --git a/net/ipv4/netfilter/iptable_filter.c b/net/ipv4/netfilter/iptable_filter.c
> index 6b3da5c..50af5b4 100644
> --- a/net/ipv4/netfilter/iptable_filter.c
> +++ b/net/ipv4/netfilter/iptable_filter.c
> @@ -69,7 +69,7 @@ static int __net_init iptable_filter_net_init(struct net *net)
>  	net->ipv4.iptable_filter =
>  		ipt_register_table(net, &packet_filter, repl);
>  	kfree(repl);
> -	return PTR_RET(net->ipv4.iptable_filter);
> +	return PTR_ERR_OR_ZERO(net->ipv4.iptable_filter);
>  }
>  
>  static void __net_exit iptable_filter_net_exit(struct net *net)
> diff --git a/net/ipv4/netfilter/iptable_mangle.c b/net/ipv4/netfilter/iptable_mangle.c
> index cba5658..0d8cd82 100644
> --- a/net/ipv4/netfilter/iptable_mangle.c
> +++ b/net/ipv4/netfilter/iptable_mangle.c
> @@ -107,7 +107,7 @@ static int __net_init iptable_mangle_net_init(struct net *net)
>  	net->ipv4.iptable_mangle =
>  		ipt_register_table(net, &packet_mangler, repl);
>  	kfree(repl);
> -	return PTR_RET(net->ipv4.iptable_mangle);
> +	return PTR_ERR_OR_ZERO(net->ipv4.iptable_mangle);
>  }
>  
>  static void __net_exit iptable_mangle_net_exit(struct net *net)
> diff --git a/net/ipv4/netfilter/iptable_nat.c b/net/ipv4/netfilter/iptable_nat.c
> index 6383273..683bfaf 100644
> --- a/net/ipv4/netfilter/iptable_nat.c
> +++ b/net/ipv4/netfilter/iptable_nat.c
> @@ -292,7 +292,7 @@ static int __net_init iptable_nat_net_init(struct net *net)
>  		return -ENOMEM;
>  	net->ipv4.nat_table = ipt_register_table(net, &nf_nat_ipv4_table, repl);
>  	kfree(repl);
> -	return PTR_RET(net->ipv4.nat_table);
> +	return PTR_ERR_OR_ZERO(net->ipv4.nat_table);
>  }
>  
>  static void __net_exit iptable_nat_net_exit(struct net *net)
> diff --git a/net/ipv4/netfilter/iptable_raw.c b/net/ipv4/netfilter/iptable_raw.c
> index 03d9696..1f82aea 100644
> --- a/net/ipv4/netfilter/iptable_raw.c
> +++ b/net/ipv4/netfilter/iptable_raw.c
> @@ -48,7 +48,7 @@ static int __net_init iptable_raw_net_init(struct net *net)
>  	net->ipv4.iptable_raw =
>  		ipt_register_table(net, &packet_raw, repl);
>  	kfree(repl);
> -	return PTR_RET(net->ipv4.iptable_raw);
> +	return PTR_ERR_OR_ZERO(net->ipv4.iptable_raw);
>  }
>  
>  static void __net_exit iptable_raw_net_exit(struct net *net)
> diff --git a/net/ipv4/netfilter/iptable_security.c b/net/ipv4/netfilter/iptable_security.c
> index b283d8e..f867a8d 100644
> --- a/net/ipv4/netfilter/iptable_security.c
> +++ b/net/ipv4/netfilter/iptable_security.c
> @@ -66,7 +66,7 @@ static int __net_init iptable_security_net_init(struct net *net)
>  	net->ipv4.iptable_security =
>  		ipt_register_table(net, &security_table, repl);
>  	kfree(repl);
> -	return PTR_RET(net->ipv4.iptable_security);
> +	return PTR_ERR_OR_ZERO(net->ipv4.iptable_security);
>  }
>  
>  static void __net_exit iptable_security_net_exit(struct net *net)
> diff --git a/net/ipv6/netfilter/ip6table_filter.c b/net/ipv6/netfilter/ip6table_filter.c
> index beb5777..29b44b1 100644
> --- a/net/ipv6/netfilter/ip6table_filter.c
> +++ b/net/ipv6/netfilter/ip6table_filter.c
> @@ -61,7 +61,7 @@ static int __net_init ip6table_filter_net_init(struct net *net)
>  	net->ipv6.ip6table_filter =
>  		ip6t_register_table(net, &packet_filter, repl);
>  	kfree(repl);
> -	return PTR_RET(net->ipv6.ip6table_filter);
> +	return PTR_ERR_OR_ZERO(net->ipv6.ip6table_filter);
>  }
>  
>  static void __net_exit ip6table_filter_net_exit(struct net *net)
> diff --git a/net/ipv6/netfilter/ip6table_mangle.c b/net/ipv6/netfilter/ip6table_mangle.c
> index e075399..c705907 100644
> --- a/net/ipv6/netfilter/ip6table_mangle.c
> +++ b/net/ipv6/netfilter/ip6table_mangle.c
> @@ -101,7 +101,7 @@ static int __net_init ip6table_mangle_net_init(struct net *net)
>  	net->ipv6.ip6table_mangle =
>  		ip6t_register_table(net, &packet_mangler, repl);
>  	kfree(repl);
> -	return PTR_RET(net->ipv6.ip6table_mangle);
> +	return PTR_ERR_OR_ZERO(net->ipv6.ip6table_mangle);
>  }
>  
>  static void __net_exit ip6table_mangle_net_exit(struct net *net)
> diff --git a/net/ipv6/netfilter/ip6table_nat.c b/net/ipv6/netfilter/ip6table_nat.c
> index 6383f90..9b076d2 100644
> --- a/net/ipv6/netfilter/ip6table_nat.c
> +++ b/net/ipv6/netfilter/ip6table_nat.c
> @@ -293,7 +293,7 @@ static int __net_init ip6table_nat_net_init(struct net *net)
>  		return -ENOMEM;
>  	net->ipv6.ip6table_nat = ip6t_register_table(net, &nf_nat_ipv6_table, repl);
>  	kfree(repl);
> -	return PTR_RET(net->ipv6.ip6table_nat);
> +	return PTR_ERR_OR_ZERO(net->ipv6.ip6table_nat);
>  }
>  
>  static void __net_exit ip6table_nat_net_exit(struct net *net)
> diff --git a/net/ipv6/netfilter/ip6table_raw.c b/net/ipv6/netfilter/ip6table_raw.c
> index 60d1bdd..9a626d8 100644
> --- a/net/ipv6/netfilter/ip6table_raw.c
> +++ b/net/ipv6/netfilter/ip6table_raw.c
> @@ -40,7 +40,7 @@ static int __net_init ip6table_raw_net_init(struct net *net)
>  	net->ipv6.ip6table_raw =
>  		ip6t_register_table(net, &packet_raw, repl);
>  	kfree(repl);
> -	return PTR_RET(net->ipv6.ip6table_raw);
> +	return PTR_ERR_OR_ZERO(net->ipv6.ip6table_raw);
>  }
>  
>  static void __net_exit ip6table_raw_net_exit(struct net *net)
> diff --git a/net/ipv6/netfilter/ip6table_security.c b/net/ipv6/netfilter/ip6table_security.c
> index db15535..ce88d1d 100644
> --- a/net/ipv6/netfilter/ip6table_security.c
> +++ b/net/ipv6/netfilter/ip6table_security.c
> @@ -58,7 +58,7 @@ static int __net_init ip6table_security_net_init(struct net *net)
>  	net->ipv6.ip6table_security =
>  		ip6t_register_table(net, &security_table, repl);
>  	kfree(repl);
> -	return PTR_RET(net->ipv6.ip6table_security);
> +	return PTR_ERR_OR_ZERO(net->ipv6.ip6table_security);
>  }
>  
>  static void __net_exit ip6table_security_net_exit(struct net *net)
> diff --git a/scripts/coccinelle/api/ptr_ret.cocci b/scripts/coccinelle/api/ptr_ret.cocci
> index 15f076f..e0981bb 100644
> --- a/scripts/coccinelle/api/ptr_ret.cocci
> +++ b/scripts/coccinelle/api/ptr_ret.cocci
> @@ -1,5 +1,5 @@
>  ///
> -/// Use PTR_RET rather than if(IS_ERR(...)) + PTR_ERR
> +/// Use PTR_ERR_OR_ZERO rather than if(IS_ERR(...)) + PTR_ERR
>  ///
>  // Confidence: High
>  // Copyright: (C) 2012 Julia Lawall, INRIA/LIP6.  GPLv2.
> @@ -7,7 +7,7 @@
>  // URL: http://coccinelle.lip6.fr/
>  // Options: -no_includes -include_headers
>  //
> -// Keywords: ERR_PTR, PTR_ERR, PTR_RET
> +// Keywords: ERR_PTR, PTR_ERR, PTR_RET, PTR_ERR_OR_ZERO
>  // Version min: 2.6.39
>  //
>  
> @@ -21,21 +21,21 @@ expression ptr;
>  @@
>  
>  - if (IS_ERR(ptr)) return PTR_ERR(ptr); else return 0;
> -+ return PTR_RET(ptr);
> ++ return PTR_ERR_OR_ZERO(ptr);
>  
>  @depends on patch@
>  expression ptr;
>  @@
>  
>  - if (IS_ERR(ptr)) return PTR_ERR(ptr); return 0;
> -+ return PTR_RET(ptr);
> ++ return PTR_ERR_OR_ZERO(ptr);
>  
>  @depends on patch@
>  expression ptr;
>  @@
>  
>  - (IS_ERR(ptr) ? PTR_ERR(ptr) : 0)
> -+ PTR_RET(ptr)
> ++ PTR_ERR_OR_ZERO(ptr)
>  
>  @r1 depends on !patch@
>  expression ptr;
> diff --git a/sound/soc/soc-io.c b/sound/soc/soc-io.c
> index 8ca9ecc..122c0c1 100644
> --- a/sound/soc/soc-io.c
> +++ b/sound/soc/soc-io.c
> @@ -158,7 +158,7 @@ int snd_soc_codec_set_cache_io(struct snd_soc_codec *codec,
>  		return -EINVAL;
>  	}
>  
> -	return PTR_RET(codec->control_data);
> +	return PTR_ERR_OR_ZERO(codec->control_data);
>  }
>  EXPORT_SYMBOL_GPL(snd_soc_codec_set_cache_io);
>  #else

^ permalink raw reply

* [git pull] Please pull powerpc.git merge branch
From: Benjamin Herrenschmidt @ 2013-06-25  7:53 UTC (permalink / raw)
  To: Linus Torvalds; +Cc: linuxppc-dev, Linux Kernel list

Hi Linus !

This is a fix for a regression causing a freescale "83xx" based platforms
to crash on boot due to some PCI breakage. Please apply.

Cheers,
Ben.

The following changes since commit 17858ca65eef148d335ffd4cfc09228a1c1cbfb5:

  Merge tag 'please-pull-fixia64' of git://git.kernel.org/pub/scm/linux/kernel/git/aegl/linux (2013-06-18 06:29:19 -1000)

are available in the git repository at:


  git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc.git merge

for you to fetch changes up to b37e161388ac3980d5dfb73050e85874b84253eb:

  powerpc/pci: Fix boot panic on mpc83xx (regression) (2013-06-24 16:54:09 -0500)

----------------------------------------------------------------
Rojhalat Ibrahim (1):
      powerpc/pci: Fix boot panic on mpc83xx (regression)

 arch/powerpc/sysdev/fsl_pci.c |   24 +++++++++---------------
 1 file changed, 9 insertions(+), 15 deletions(-)

^ permalink raw reply

* Re: [PATCH 03/10] powerpc/eeh: Check PCIe link after reset
From: Benjamin Herrenschmidt @ 2013-06-25  7:57 UTC (permalink / raw)
  To: Gavin Shan; +Cc: linuxppc-dev
In-Reply-To: <20130625074755.GA8486@shangw.(null)>

On Tue, 2013-06-25 at 15:47 +0800, Gavin Shan wrote:
> If we just have complete reset for fenced PHB, we need restore it
> from the cache (edev->config_space[1]) instead of reading that from
> hardware. Fenced PHB is the special case on PowerNV :-)

Well not really...

In general we can also end up doing a hard reset under pHyp, and bridges
can lose their state as well, which means they need to be restored from
cache.

We don't see the real PHB, but we might see the bridges if we have a PE
that contains a bridge, for example, a PCIe card with a switch on it.

If we hard reset that (because the driver requested it) or if pHyp did a
reset due to a fence behind the scene, that bridge *will* have lost its
state and will need to be reconfigured too... or is RTAS doing it all ?

Cheers,
Ben.

^ permalink raw reply

* Re: [PATCH 03/10] powerpc/eeh: Check PCIe link after reset
From: Gavin Shan @ 2013-06-25  8:04 UTC (permalink / raw)
  To: Benjamin Herrenschmidt; +Cc: linuxppc-dev, Gavin Shan
In-Reply-To: <1372147064.3944.200.camel@pasglop>

On Tue, Jun 25, 2013 at 05:57:44PM +1000, Benjamin Herrenschmidt wrote:
>On Tue, 2013-06-25 at 15:47 +0800, Gavin Shan wrote:
>> If we just have complete reset for fenced PHB, we need restore it
>> from the cache (edev->config_space[1]) instead of reading that from
>> hardware. Fenced PHB is the special case on PowerNV :-)
>
>Well not really...
>
>In general we can also end up doing a hard reset under pHyp, and bridges
>can lose their state as well, which means they need to be restored from
>cache.
>
>We don't see the real PHB, but we might see the bridges if we have a PE
>that contains a bridge, for example, a PCIe card with a switch on it.
>
>If we hard reset that (because the driver requested it) or if pHyp did a
>reset due to a fence behind the scene, that bridge *will* have lost its
>state and will need to be reconfigured too... or is RTAS doing it all ?
>

Ok. So that would be job of eeh_ops->configure_bridge(). On pSeries, it
should have done with that.

Thanks,
Gavin

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox