Commit c2df436b authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'edac_for_3.17' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp

Pull EDAC changes from Borislav Petkov:
 "EDAC queue for 3.17:

   - One new edac driver for Intel E3-12xx DRAM controllers.

   - Out-of-subsystem changes are making the non-atomic iomem 64-bit
     accessors' naming explicit to show both exact order of the 32-bit
     accesses and the non-atomicity of the 64-bit access.

     Usage locations are more verbose now as to what access is exactly
     being done vs having a not-very telling "readq" there, for example.

     This is needed by E3-12xx hardware where certain mmapped registers
     cannot be accessed with requests crossing a dword boundary.

     From Jason Baron.

   - Extending AMD MCE signatures to a new model 60h in family 15h, from
     Aravind Gopalakrishnan.

   - An unsigned check cleanup, from Fabian Frederick"

* tag 'edac_for_3.17' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp:
  EDAC, MCE, AMD: Add MCE decoding for F15h M60h
  MAINTAINERS: add ie31200_edac entry
  ie31200_edac: Allocate mci and map mchbar first
  ie31200_edac: Introduce the driver
  x38_edac: make use of lo_hi_readq()
  readq/writeq: Add explicit lo_hi_[read|write]_q and hi_lo_[read|write]_q
  EDAC, edac_module.c: Remove unnecessary test on unsigned value
parents f74ad8df eba4bfb3
...@@ -3350,6 +3350,13 @@ W: bluesmoke.sourceforge.net ...@@ -3350,6 +3350,13 @@ W: bluesmoke.sourceforge.net
S: Maintained S: Maintained
F: drivers/edac/i82975x_edac.c F: drivers/edac/i82975x_edac.c
EDAC-IE31200
M: Jason Baron <jbaron@akamai.com>
L: linux-edac@vger.kernel.org
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/ie31200_edac.c
EDAC-MPC85XX EDAC-MPC85XX
M: Johannes Thumshirn <johannes.thumshirn@men.de> M: Johannes Thumshirn <johannes.thumshirn@men.de>
L: linux-edac@vger.kernel.org L: linux-edac@vger.kernel.org
......
...@@ -186,6 +186,13 @@ config EDAC_I3200 ...@@ -186,6 +186,13 @@ config EDAC_I3200
Support for error detection and correction on the Intel Support for error detection and correction on the Intel
3200 and 3210 server chipsets. 3200 and 3210 server chipsets.
config EDAC_IE31200
tristate "Intel e312xx"
depends on EDAC_MM_EDAC && PCI && X86
help
Support for error detection and correction on the Intel
E3-1200 based DRAM controllers.
config EDAC_X38 config EDAC_X38
tristate "Intel X38" tristate "Intel X38"
depends on EDAC_MM_EDAC && PCI && X86 depends on EDAC_MM_EDAC && PCI && X86
......
...@@ -37,6 +37,7 @@ obj-$(CONFIG_EDAC_I82875P) += i82875p_edac.o ...@@ -37,6 +37,7 @@ obj-$(CONFIG_EDAC_I82875P) += i82875p_edac.o
obj-$(CONFIG_EDAC_I82975X) += i82975x_edac.o obj-$(CONFIG_EDAC_I82975X) += i82975x_edac.o
obj-$(CONFIG_EDAC_I3000) += i3000_edac.o obj-$(CONFIG_EDAC_I3000) += i3000_edac.o
obj-$(CONFIG_EDAC_I3200) += i3200_edac.o obj-$(CONFIG_EDAC_I3200) += i3200_edac.o
obj-$(CONFIG_EDAC_IE31200) += ie31200_edac.o
obj-$(CONFIG_EDAC_X38) += x38_edac.o obj-$(CONFIG_EDAC_X38) += x38_edac.o
obj-$(CONFIG_EDAC_I82860) += i82860_edac.o obj-$(CONFIG_EDAC_I82860) += i82860_edac.o
obj-$(CONFIG_EDAC_R82600) += r82600_edac.o obj-$(CONFIG_EDAC_R82600) += r82600_edac.o
......
...@@ -28,7 +28,7 @@ static int edac_set_debug_level(const char *buf, struct kernel_param *kp) ...@@ -28,7 +28,7 @@ static int edac_set_debug_level(const char *buf, struct kernel_param *kp)
if (ret) if (ret)
return ret; return ret;
if (val < 0 || val > 4) if (val > 4)
return -EINVAL; return -EINVAL;
return param_set_int(buf, kp); return param_set_int(buf, kp);
......
This diff is collapsed.
...@@ -78,7 +78,8 @@ static const char * const f15h_mc1_mce_desc[] = { ...@@ -78,7 +78,8 @@ static const char * const f15h_mc1_mce_desc[] = {
"uop queue", "uop queue",
"insn buffer", "insn buffer",
"predecode buffer", "predecode buffer",
"fetch address FIFO" "fetch address FIFO",
"dispatch uop queue"
}; };
static const char * const f15h_mc2_mce_desc[] = { static const char * const f15h_mc2_mce_desc[] = {
...@@ -267,6 +268,12 @@ static bool f15h_mc0_mce(u16 ec, u8 xec) ...@@ -267,6 +268,12 @@ static bool f15h_mc0_mce(u16 ec, u8 xec)
pr_cont("System Read Data Error.\n"); pr_cont("System Read Data Error.\n");
else else
pr_cont(" Internal error condition type %d.\n", xec); pr_cont(" Internal error condition type %d.\n", xec);
} else if (INT_ERROR(ec)) {
if (xec <= 0x1f)
pr_cont("Hardware Assert.\n");
else
ret = false;
} else } else
ret = false; ret = false;
...@@ -373,7 +380,7 @@ static bool f15h_mc1_mce(u16 ec, u8 xec) ...@@ -373,7 +380,7 @@ static bool f15h_mc1_mce(u16 ec, u8 xec)
pr_cont("%s.\n", f15h_mc1_mce_desc[xec-4]); pr_cont("%s.\n", f15h_mc1_mce_desc[xec-4]);
break; break;
case 0x11 ... 0x14: case 0x11 ... 0x15:
pr_cont("Decoder %s parity error.\n", f15h_mc1_mce_desc[xec-4]); pr_cont("Decoder %s parity error.\n", f15h_mc1_mce_desc[xec-4]);
break; break;
...@@ -397,10 +404,20 @@ static void decode_mc1_mce(struct mce *m) ...@@ -397,10 +404,20 @@ static void decode_mc1_mce(struct mce *m)
bool k8 = (boot_cpu_data.x86 == 0xf && (m->status & BIT_64(58))); bool k8 = (boot_cpu_data.x86 == 0xf && (m->status & BIT_64(58)));
pr_cont("during %s.\n", (k8 ? "system linefill" : "NB data read")); pr_cont("during %s.\n", (k8 ? "system linefill" : "NB data read"));
} else if (INT_ERROR(ec)) {
if (xec <= 0x3f)
pr_cont("Hardware Assert.\n");
else
goto wrong_mc1_mce;
} else if (fam_ops->mc1_mce(ec, xec)) } else if (fam_ops->mc1_mce(ec, xec))
; ;
else else
pr_emerg(HW_ERR "Corrupted MC1 MCE info?\n"); goto wrong_mc1_mce;
return;
wrong_mc1_mce:
pr_emerg(HW_ERR "Corrupted MC1 MCE info?\n");
} }
static bool k8_mc2_mce(u16 ec, u8 xec) static bool k8_mc2_mce(u16 ec, u8 xec)
...@@ -468,6 +485,11 @@ static bool f15h_mc2_mce(u16 ec, u8 xec) ...@@ -468,6 +485,11 @@ static bool f15h_mc2_mce(u16 ec, u8 xec)
default: default:
ret = false; ret = false;
} }
} else if (INT_ERROR(ec)) {
if (xec <= 0x3f)
pr_cont("Hardware Assert.\n");
else
ret = false;
} }
return ret; return ret;
...@@ -615,6 +637,7 @@ static void decode_mc4_mce(struct mce *m) ...@@ -615,6 +637,7 @@ static void decode_mc4_mce(struct mce *m)
static void decode_mc5_mce(struct mce *m) static void decode_mc5_mce(struct mce *m)
{ {
struct cpuinfo_x86 *c = &boot_cpu_data; struct cpuinfo_x86 *c = &boot_cpu_data;
u16 ec = EC(m->status);
u8 xec = XEC(m->status, xec_mask); u8 xec = XEC(m->status, xec_mask);
if (c->x86 == 0xf || c->x86 == 0x11) if (c->x86 == 0xf || c->x86 == 0x11)
...@@ -622,6 +645,14 @@ static void decode_mc5_mce(struct mce *m) ...@@ -622,6 +645,14 @@ static void decode_mc5_mce(struct mce *m)
pr_emerg(HW_ERR "MC5 Error: "); pr_emerg(HW_ERR "MC5 Error: ");
if (INT_ERROR(ec)) {
if (xec <= 0x1f) {
pr_cont("Hardware Assert.\n");
return;
} else
goto wrong_mc5_mce;
}
if (xec == 0x0 || xec == 0xc) if (xec == 0x0 || xec == 0xc)
pr_cont("%s.\n", mc5_mce_desc[xec]); pr_cont("%s.\n", mc5_mce_desc[xec]);
else if (xec <= 0xd) else if (xec <= 0xd)
...@@ -642,6 +673,10 @@ static void decode_mc6_mce(struct mce *m) ...@@ -642,6 +673,10 @@ static void decode_mc6_mce(struct mce *m)
pr_emerg(HW_ERR "MC6 Error: "); pr_emerg(HW_ERR "MC6 Error: ");
switch (xec) { switch (xec) {
case 0x0:
pr_cont("Hardware Assertion");
break;
case 0x1: case 0x1:
pr_cont("Free List"); pr_cont("Free List");
break; break;
...@@ -857,7 +892,8 @@ static int __init mce_amd_init(void) ...@@ -857,7 +892,8 @@ static int __init mce_amd_init(void)
break; break;
case 0x15: case 0x15:
xec_mask = 0x1f; xec_mask = c->x86_model == 0x60 ? 0x3f : 0x1f;
fam_ops->mc0_mce = f15h_mc0_mce; fam_ops->mc0_mce = f15h_mc0_mce;
fam_ops->mc1_mce = f15h_mc1_mce; fam_ops->mc1_mce = f15h_mc1_mce;
fam_ops->mc2_mce = f15h_mc2_mce; fam_ops->mc2_mce = f15h_mc2_mce;
......
...@@ -14,6 +14,8 @@ ...@@ -14,6 +14,8 @@
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/pci_ids.h> #include <linux/pci_ids.h>
#include <linux/edac.h> #include <linux/edac.h>
#include <asm-generic/io-64-nonatomic-lo-hi.h>
#include "edac_core.h" #include "edac_core.h"
#define X38_REVISION "1.1" #define X38_REVISION "1.1"
...@@ -161,11 +163,6 @@ static void x38_clear_error_info(struct mem_ctl_info *mci) ...@@ -161,11 +163,6 @@ static void x38_clear_error_info(struct mem_ctl_info *mci)
X38_ERRSTS_BITS); X38_ERRSTS_BITS);
} }
static u64 x38_readq(const void __iomem *addr)
{
return readl(addr) | (((u64)readl(addr + 4)) << 32);
}
static void x38_get_and_clear_error_info(struct mem_ctl_info *mci, static void x38_get_and_clear_error_info(struct mem_ctl_info *mci,
struct x38_error_info *info) struct x38_error_info *info)
{ {
...@@ -183,9 +180,9 @@ static void x38_get_and_clear_error_info(struct mem_ctl_info *mci, ...@@ -183,9 +180,9 @@ static void x38_get_and_clear_error_info(struct mem_ctl_info *mci,
if (!(info->errsts & X38_ERRSTS_BITS)) if (!(info->errsts & X38_ERRSTS_BITS))
return; return;
info->eccerrlog[0] = x38_readq(window + X38_C0ECCERRLOG); info->eccerrlog[0] = lo_hi_readq(window + X38_C0ECCERRLOG);
if (x38_channel_num == 2) if (x38_channel_num == 2)
info->eccerrlog[1] = x38_readq(window + X38_C1ECCERRLOG); info->eccerrlog[1] = lo_hi_readq(window + X38_C1ECCERRLOG);
pci_read_config_word(pdev, X38_ERRSTS, &info->errsts2); pci_read_config_word(pdev, X38_ERRSTS, &info->errsts2);
...@@ -196,10 +193,10 @@ static void x38_get_and_clear_error_info(struct mem_ctl_info *mci, ...@@ -196,10 +193,10 @@ static void x38_get_and_clear_error_info(struct mem_ctl_info *mci,
* should be UE info. * should be UE info.
*/ */
if ((info->errsts ^ info->errsts2) & X38_ERRSTS_BITS) { if ((info->errsts ^ info->errsts2) & X38_ERRSTS_BITS) {
info->eccerrlog[0] = x38_readq(window + X38_C0ECCERRLOG); info->eccerrlog[0] = lo_hi_readq(window + X38_C0ECCERRLOG);
if (x38_channel_num == 2) if (x38_channel_num == 2)
info->eccerrlog[1] = info->eccerrlog[1] =
x38_readq(window + X38_C1ECCERRLOG); lo_hi_readq(window + X38_C1ECCERRLOG);
} }
x38_clear_error_info(mci); x38_clear_error_info(mci);
......
...@@ -4,8 +4,7 @@ ...@@ -4,8 +4,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <asm-generic/int-ll64.h> #include <asm-generic/int-ll64.h>
#ifndef readq static inline __u64 hi_lo_readq(const volatile void __iomem *addr)
static inline __u64 readq(const volatile void __iomem *addr)
{ {
const volatile u32 __iomem *p = addr; const volatile u32 __iomem *p = addr;
u32 low, high; u32 low, high;
...@@ -15,14 +14,19 @@ static inline __u64 readq(const volatile void __iomem *addr) ...@@ -15,14 +14,19 @@ static inline __u64 readq(const volatile void __iomem *addr)
return low + ((u64)high << 32); return low + ((u64)high << 32);
} }
#endif
#ifndef writeq static inline void hi_lo_writeq(__u64 val, volatile void __iomem *addr)
static inline void writeq(__u64 val, volatile void __iomem *addr)
{ {
writel(val >> 32, addr + 4); writel(val >> 32, addr + 4);
writel(val, addr); writel(val, addr);
} }
#ifndef readq
#define readq hi_lo_readq
#endif
#ifndef writeq
#define writeq hi_lo_writeq
#endif #endif
#endif /* _ASM_IO_64_NONATOMIC_HI_LO_H_ */ #endif /* _ASM_IO_64_NONATOMIC_HI_LO_H_ */
...@@ -4,8 +4,7 @@ ...@@ -4,8 +4,7 @@
#include <linux/io.h> #include <linux/io.h>
#include <asm-generic/int-ll64.h> #include <asm-generic/int-ll64.h>
#ifndef readq static inline __u64 lo_hi_readq(const volatile void __iomem *addr)
static inline __u64 readq(const volatile void __iomem *addr)
{ {
const volatile u32 __iomem *p = addr; const volatile u32 __iomem *p = addr;
u32 low, high; u32 low, high;
...@@ -15,14 +14,19 @@ static inline __u64 readq(const volatile void __iomem *addr) ...@@ -15,14 +14,19 @@ static inline __u64 readq(const volatile void __iomem *addr)
return low + ((u64)high << 32); return low + ((u64)high << 32);
} }
#endif
#ifndef writeq static inline void lo_hi_writeq(__u64 val, volatile void __iomem *addr)
static inline void writeq(__u64 val, volatile void __iomem *addr)
{ {
writel(val, addr); writel(val, addr);
writel(val >> 32, addr + 4); writel(val >> 32, addr + 4);
} }
#ifndef readq
#define readq lo_hi_readq
#endif
#ifndef writeq
#define writeq lo_hi_writeq
#endif #endif
#endif /* _ASM_IO_64_NONATOMIC_LO_HI_H_ */ #endif /* _ASM_IO_64_NONATOMIC_LO_HI_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment