Commit 6681ba7e authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'linux_next' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-edac

* 'linux_next' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-edac: (21 commits)
  MAINTAINERS: add an entry for Edac Sandy Bridge driver
  edac: tag sb_edac as EXPERIMENTAL, as it requires more testing
  EDAC: Fix incorrect edac mode reporting in sb_edac
  edac: sb_edac: Add it to the building system
  edac: Add an experimental new driver to support Sandy Bridge CPU's
  i7300_edac: Fix error cleanup logic
  i7core_edac: Initialize memory name with cpu, channel, bank
  i7core_edac: Fix compilation on 32 bits arch
  i7core_edac: scrubbing fixups
  EDAC: Correct Kconfig dependencies
  i7core_edac: return -ENODEV if no MC is found
  i7core_edac: use edac's own way to print errors
  MAINTAINERS: remove dropped edac_mce.* from the file
  i7core_edac: Drop the edac_mce facility
  x86, MCE: Use notifier chain only for MCE decoding
  EDAC i7core: Use mce socketid for better compatibility
  i7core_edac: Don't enable memory scrubbing for Xeon 35xx
  i7core_edac: Add scrubbing support
  edac: Move edac main structs to include/linux/edac.h
  i7core_edac: Fix oops when trying to inject errors
  ...
parents 06ef93e1 4d096ca7
...@@ -2467,8 +2467,6 @@ L: linux-edac@vger.kernel.org ...@@ -2467,8 +2467,6 @@ L: linux-edac@vger.kernel.org
W: bluesmoke.sourceforge.net W: bluesmoke.sourceforge.net
S: Maintained S: Maintained
F: drivers/edac/i7core_edac.c F: drivers/edac/i7core_edac.c
F: drivers/edac/edac_mce.c
F: include/linux/edac_mce.h
EDAC-I82975X EDAC-I82975X
M: Ranganathan Desikan <ravi@jetztechnologies.com> M: Ranganathan Desikan <ravi@jetztechnologies.com>
...@@ -2492,6 +2490,13 @@ W: bluesmoke.sourceforge.net ...@@ -2492,6 +2490,13 @@ W: bluesmoke.sourceforge.net
S: Maintained S: Maintained
F: drivers/edac/r82600_edac.c F: drivers/edac/r82600_edac.c
EDAC-SBRIDGE
M: Mauro Carvalho Chehab <mchehab@redhat.com>
L: linux-edac@vger.kernel.org
W: bluesmoke.sourceforge.net
S: Maintained
F: drivers/edac/sb_edac.c
EDIROL UA-101/UA-1000 DRIVER EDIROL UA-101/UA-1000 DRIVER
M: Clemens Ladisch <clemens@ladisch.de> M: Clemens Ladisch <clemens@ladisch.de>
L: alsa-devel@alsa-project.org (moderated for non-subscribers) L: alsa-devel@alsa-project.org (moderated for non-subscribers)
......
...@@ -36,7 +36,6 @@ ...@@ -36,7 +36,6 @@
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/mm.h> #include <linux/mm.h>
#include <linux/debugfs.h> #include <linux/debugfs.h>
#include <linux/edac_mce.h>
#include <linux/irq_work.h> #include <linux/irq_work.h>
#include <asm/processor.h> #include <asm/processor.h>
...@@ -144,23 +143,20 @@ static struct mce_log mcelog = { ...@@ -144,23 +143,20 @@ static struct mce_log mcelog = {
void mce_log(struct mce *mce) void mce_log(struct mce *mce)
{ {
unsigned next, entry; unsigned next, entry;
int ret = 0;
/* Emit the trace record: */ /* Emit the trace record: */
trace_mce_record(mce); trace_mce_record(mce);
ret = atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, mce);
if (ret == NOTIFY_STOP)
return;
mce->finished = 0; mce->finished = 0;
wmb(); wmb();
for (;;) { for (;;) {
entry = rcu_dereference_check_mce(mcelog.next); entry = rcu_dereference_check_mce(mcelog.next);
for (;;) { for (;;) {
/*
* If edac_mce is enabled, it will check the error type
* and will process it, if it is a known error.
* Otherwise, the error will be sent through mcelog
* interface
*/
if (edac_mce_parse(mce))
return;
/* /*
* When the buffer fills up discard new entries. * When the buffer fills up discard new entries.
...@@ -556,10 +552,8 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b) ...@@ -556,10 +552,8 @@ void machine_check_poll(enum mcp_flags flags, mce_banks_t *b)
* Don't get the IP here because it's unlikely to * Don't get the IP here because it's unlikely to
* have anything to do with the actual error location. * have anything to do with the actual error location.
*/ */
if (!(flags & MCP_DONTLOG) && !mce_dont_log_ce) { if (!(flags & MCP_DONTLOG) && !mce_dont_log_ce)
mce_log(&m); mce_log(&m);
atomic_notifier_call_chain(&x86_mce_decoder_chain, 0, &m);
}
/* /*
* Clear state for this bank. * Clear state for this bank.
......
...@@ -41,7 +41,7 @@ config EDAC_DEBUG ...@@ -41,7 +41,7 @@ config EDAC_DEBUG
config EDAC_DECODE_MCE config EDAC_DECODE_MCE
tristate "Decode MCEs in human-readable form (only on AMD for now)" tristate "Decode MCEs in human-readable form (only on AMD for now)"
depends on CPU_SUP_AMD && X86_MCE depends on CPU_SUP_AMD && X86_MCE_AMD
default y default y
---help--- ---help---
Enable this option if you want to decode Machine Check Exceptions Enable this option if you want to decode Machine Check Exceptions
...@@ -71,9 +71,6 @@ config EDAC_MM_EDAC ...@@ -71,9 +71,6 @@ config EDAC_MM_EDAC
occurred so that a particular failing memory module can be occurred so that a particular failing memory module can be
replaced. If unsure, select 'Y'. replaced. If unsure, select 'Y'.
config EDAC_MCE
bool
config EDAC_AMD64 config EDAC_AMD64
tristate "AMD64 (Opteron, Athlon64) K8, F10h" tristate "AMD64 (Opteron, Athlon64) K8, F10h"
depends on EDAC_MM_EDAC && AMD_NB && X86_64 && EDAC_DECODE_MCE depends on EDAC_MM_EDAC && AMD_NB && X86_64 && EDAC_DECODE_MCE
...@@ -173,8 +170,7 @@ config EDAC_I5400 ...@@ -173,8 +170,7 @@ config EDAC_I5400
config EDAC_I7CORE config EDAC_I7CORE
tristate "Intel i7 Core (Nehalem) processors" tristate "Intel i7 Core (Nehalem) processors"
depends on EDAC_MM_EDAC && PCI && X86 depends on EDAC_MM_EDAC && PCI && X86 && X86_MCE_INTEL
select EDAC_MCE
help help
Support for error detection and correction the Intel Support for error detection and correction the Intel
i7 Core (Nehalem) Integrated Memory Controller that exists on i7 Core (Nehalem) Integrated Memory Controller that exists on
...@@ -216,6 +212,14 @@ config EDAC_I7300 ...@@ -216,6 +212,14 @@ config EDAC_I7300
Support for error detection and correction the Intel Support for error detection and correction the Intel
Clarksboro MCH (Intel 7300 chipset). Clarksboro MCH (Intel 7300 chipset).
config EDAC_SBRIDGE
tristate "Intel Sandy-Bridge Integrated MC"
depends on EDAC_MM_EDAC && PCI && X86 && X86_MCE_INTEL
depends on EXPERIMENTAL
help
Support for error detection and correction the Intel
Sandy Bridge Integrated Memory Controller.
config EDAC_MPC85XX config EDAC_MPC85XX
tristate "Freescale MPC83xx / MPC85xx" tristate "Freescale MPC83xx / MPC85xx"
depends on EDAC_MM_EDAC && FSL_SOC && (PPC_83xx || PPC_85xx) depends on EDAC_MM_EDAC && FSL_SOC && (PPC_83xx || PPC_85xx)
......
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
obj-$(CONFIG_EDAC) := edac_stub.o obj-$(CONFIG_EDAC) := edac_stub.o
obj-$(CONFIG_EDAC_MM_EDAC) += edac_core.o obj-$(CONFIG_EDAC_MM_EDAC) += edac_core.o
obj-$(CONFIG_EDAC_MCE) += edac_mce.o
edac_core-y := edac_mc.o edac_device.o edac_mc_sysfs.o edac_pci_sysfs.o edac_core-y := edac_mc.o edac_device.o edac_mc_sysfs.o edac_pci_sysfs.o
edac_core-y += edac_module.o edac_device_sysfs.o edac_core-y += edac_module.o edac_device_sysfs.o
...@@ -29,6 +28,7 @@ obj-$(CONFIG_EDAC_I5100) += i5100_edac.o ...@@ -29,6 +28,7 @@ obj-$(CONFIG_EDAC_I5100) += i5100_edac.o
obj-$(CONFIG_EDAC_I5400) += i5400_edac.o obj-$(CONFIG_EDAC_I5400) += i5400_edac.o
obj-$(CONFIG_EDAC_I7300) += i7300_edac.o obj-$(CONFIG_EDAC_I7300) += i7300_edac.o
obj-$(CONFIG_EDAC_I7CORE) += i7core_edac.o obj-$(CONFIG_EDAC_I7CORE) += i7core_edac.o
obj-$(CONFIG_EDAC_SBRIDGE) += sb_edac.o
obj-$(CONFIG_EDAC_E7XXX) += e7xxx_edac.o obj-$(CONFIG_EDAC_E7XXX) += e7xxx_edac.o
obj-$(CONFIG_EDAC_E752X) += e752x_edac.o obj-$(CONFIG_EDAC_E752X) += e752x_edac.o
obj-$(CONFIG_EDAC_I82443BXGX) += i82443bxgx_edac.o obj-$(CONFIG_EDAC_I82443BXGX) += i82443bxgx_edac.o
......
This diff is collapsed.
/* Provides edac interface to mcelog events
*
* This file may be distributed under the terms of the
* GNU General Public License version 2.
*
* Copyright (c) 2009 by:
* Mauro Carvalho Chehab <mchehab@redhat.com>
*
* Red Hat Inc. http://www.redhat.com
*/
#include <linux/module.h>
#include <linux/edac_mce.h>
#include <asm/mce.h>
int edac_mce_enabled;
EXPORT_SYMBOL_GPL(edac_mce_enabled);
/*
* Extension interface
*/
static LIST_HEAD(edac_mce_list);
static DEFINE_MUTEX(edac_mce_lock);
int edac_mce_register(struct edac_mce *edac_mce)
{
mutex_lock(&edac_mce_lock);
list_add_tail(&edac_mce->list, &edac_mce_list);
mutex_unlock(&edac_mce_lock);
return 0;
}
EXPORT_SYMBOL(edac_mce_register);
void edac_mce_unregister(struct edac_mce *edac_mce)
{
mutex_lock(&edac_mce_lock);
list_del(&edac_mce->list);
mutex_unlock(&edac_mce_lock);
}
EXPORT_SYMBOL(edac_mce_unregister);
int edac_mce_parse(struct mce *mce)
{
struct edac_mce *edac_mce;
list_for_each_entry(edac_mce, &edac_mce_list, list) {
if (edac_mce->check_error(edac_mce->priv, mce))
return 1;
}
/* Nobody queued the error */
return 0;
}
EXPORT_SYMBOL_GPL(edac_mce_parse);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
MODULE_DESCRIPTION("EDAC Driver for mcelog captured errors");
...@@ -372,7 +372,7 @@ static const char *get_err_from_table(const char *table[], int size, int pos) ...@@ -372,7 +372,7 @@ static const char *get_err_from_table(const char *table[], int size, int pos)
static void i7300_process_error_global(struct mem_ctl_info *mci) static void i7300_process_error_global(struct mem_ctl_info *mci)
{ {
struct i7300_pvt *pvt; struct i7300_pvt *pvt;
u32 errnum, value; u32 errnum, error_reg;
unsigned long errors; unsigned long errors;
const char *specific; const char *specific;
bool is_fatal; bool is_fatal;
...@@ -381,9 +381,9 @@ static void i7300_process_error_global(struct mem_ctl_info *mci) ...@@ -381,9 +381,9 @@ static void i7300_process_error_global(struct mem_ctl_info *mci)
/* read in the 1st FATAL error register */ /* read in the 1st FATAL error register */
pci_read_config_dword(pvt->pci_dev_16_2_fsb_err_regs, pci_read_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
FERR_GLOBAL_HI, &value); FERR_GLOBAL_HI, &error_reg);
if (unlikely(value)) { if (unlikely(error_reg)) {
errors = value; errors = error_reg;
errnum = find_first_bit(&errors, errnum = find_first_bit(&errors,
ARRAY_SIZE(ferr_global_hi_name)); ARRAY_SIZE(ferr_global_hi_name));
specific = GET_ERR_FROM_TABLE(ferr_global_hi_name, errnum); specific = GET_ERR_FROM_TABLE(ferr_global_hi_name, errnum);
...@@ -391,15 +391,15 @@ static void i7300_process_error_global(struct mem_ctl_info *mci) ...@@ -391,15 +391,15 @@ static void i7300_process_error_global(struct mem_ctl_info *mci)
/* Clear the error bit */ /* Clear the error bit */
pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs, pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
FERR_GLOBAL_HI, value); FERR_GLOBAL_HI, error_reg);
goto error_global; goto error_global;
} }
pci_read_config_dword(pvt->pci_dev_16_2_fsb_err_regs, pci_read_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
FERR_GLOBAL_LO, &value); FERR_GLOBAL_LO, &error_reg);
if (unlikely(value)) { if (unlikely(error_reg)) {
errors = value; errors = error_reg;
errnum = find_first_bit(&errors, errnum = find_first_bit(&errors,
ARRAY_SIZE(ferr_global_lo_name)); ARRAY_SIZE(ferr_global_lo_name));
specific = GET_ERR_FROM_TABLE(ferr_global_lo_name, errnum); specific = GET_ERR_FROM_TABLE(ferr_global_lo_name, errnum);
...@@ -407,7 +407,7 @@ static void i7300_process_error_global(struct mem_ctl_info *mci) ...@@ -407,7 +407,7 @@ static void i7300_process_error_global(struct mem_ctl_info *mci)
/* Clear the error bit */ /* Clear the error bit */
pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs, pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
FERR_GLOBAL_LO, value); FERR_GLOBAL_LO, error_reg);
goto error_global; goto error_global;
} }
...@@ -427,7 +427,7 @@ static void i7300_process_error_global(struct mem_ctl_info *mci) ...@@ -427,7 +427,7 @@ static void i7300_process_error_global(struct mem_ctl_info *mci)
static void i7300_process_fbd_error(struct mem_ctl_info *mci) static void i7300_process_fbd_error(struct mem_ctl_info *mci)
{ {
struct i7300_pvt *pvt; struct i7300_pvt *pvt;
u32 errnum, value; u32 errnum, value, error_reg;
u16 val16; u16 val16;
unsigned branch, channel, bank, rank, cas, ras; unsigned branch, channel, bank, rank, cas, ras;
u32 syndrome; u32 syndrome;
...@@ -440,14 +440,14 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci) ...@@ -440,14 +440,14 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci)
/* read in the 1st FATAL error register */ /* read in the 1st FATAL error register */
pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
FERR_FAT_FBD, &value); FERR_FAT_FBD, &error_reg);
if (unlikely(value & FERR_FAT_FBD_ERR_MASK)) { if (unlikely(error_reg & FERR_FAT_FBD_ERR_MASK)) {
errors = value & FERR_FAT_FBD_ERR_MASK ; errors = error_reg & FERR_FAT_FBD_ERR_MASK ;
errnum = find_first_bit(&errors, errnum = find_first_bit(&errors,
ARRAY_SIZE(ferr_fat_fbd_name)); ARRAY_SIZE(ferr_fat_fbd_name));
specific = GET_ERR_FROM_TABLE(ferr_fat_fbd_name, errnum); specific = GET_ERR_FROM_TABLE(ferr_fat_fbd_name, errnum);
branch = (GET_FBD_FAT_IDX(error_reg) == 2) ? 1 : 0;
branch = (GET_FBD_FAT_IDX(value) == 2) ? 1 : 0;
pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map,
NRECMEMA, &val16); NRECMEMA, &val16);
bank = NRECMEMA_BANK(val16); bank = NRECMEMA_BANK(val16);
...@@ -455,11 +455,14 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci) ...@@ -455,11 +455,14 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci)
pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
NRECMEMB, &value); NRECMEMB, &value);
is_wr = NRECMEMB_IS_WR(value); is_wr = NRECMEMB_IS_WR(value);
cas = NRECMEMB_CAS(value); cas = NRECMEMB_CAS(value);
ras = NRECMEMB_RAS(value); ras = NRECMEMB_RAS(value);
/* Clean the error register */
pci_write_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
FERR_FAT_FBD, error_reg);
snprintf(pvt->tmp_prt_buffer, PAGE_SIZE, snprintf(pvt->tmp_prt_buffer, PAGE_SIZE,
"FATAL (Branch=%d DRAM-Bank=%d %s " "FATAL (Branch=%d DRAM-Bank=%d %s "
"RAS=%d CAS=%d Err=0x%lx (%s))", "RAS=%d CAS=%d Err=0x%lx (%s))",
...@@ -476,21 +479,17 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci) ...@@ -476,21 +479,17 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci)
/* read in the 1st NON-FATAL error register */ /* read in the 1st NON-FATAL error register */
pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
FERR_NF_FBD, &value); FERR_NF_FBD, &error_reg);
if (unlikely(value & FERR_NF_FBD_ERR_MASK)) { if (unlikely(error_reg & FERR_NF_FBD_ERR_MASK)) {
errors = value & FERR_NF_FBD_ERR_MASK; errors = error_reg & FERR_NF_FBD_ERR_MASK;
errnum = find_first_bit(&errors, errnum = find_first_bit(&errors,
ARRAY_SIZE(ferr_nf_fbd_name)); ARRAY_SIZE(ferr_nf_fbd_name));
specific = GET_ERR_FROM_TABLE(ferr_nf_fbd_name, errnum); specific = GET_ERR_FROM_TABLE(ferr_nf_fbd_name, errnum);
branch = (GET_FBD_FAT_IDX(error_reg) == 2) ? 1 : 0;
/* Clear the error bit */
pci_write_config_dword(pvt->pci_dev_16_2_fsb_err_regs,
FERR_GLOBAL_LO, value);
pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
REDMEMA, &syndrome); REDMEMA, &syndrome);
branch = (GET_FBD_FAT_IDX(value) == 2) ? 1 : 0;
pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map, pci_read_config_word(pvt->pci_dev_16_1_fsb_addr_map,
RECMEMA, &val16); RECMEMA, &val16);
bank = RECMEMA_BANK(val16); bank = RECMEMA_BANK(val16);
...@@ -498,18 +497,20 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci) ...@@ -498,18 +497,20 @@ static void i7300_process_fbd_error(struct mem_ctl_info *mci)
pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
RECMEMB, &value); RECMEMB, &value);
is_wr = RECMEMB_IS_WR(value); is_wr = RECMEMB_IS_WR(value);
cas = RECMEMB_CAS(value); cas = RECMEMB_CAS(value);
ras = RECMEMB_RAS(value); ras = RECMEMB_RAS(value);
pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map, pci_read_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
REDMEMB, &value); REDMEMB, &value);
channel = (branch << 1); channel = (branch << 1);
if (IS_SECOND_CH(value)) if (IS_SECOND_CH(value))
channel++; channel++;
/* Clear the error bit */
pci_write_config_dword(pvt->pci_dev_16_1_fsb_addr_map,
FERR_NF_FBD, error_reg);
/* Form out message */ /* Form out message */
snprintf(pvt->tmp_prt_buffer, PAGE_SIZE, snprintf(pvt->tmp_prt_buffer, PAGE_SIZE,
"Corrected error (Branch=%d, Channel %d), " "Corrected error (Branch=%d, Channel %d), "
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/* Provides edac interface to mcelog events
*
* This file may be distributed under the terms of the
* GNU General Public License version 2.
*
* Copyright (c) 2009 by:
* Mauro Carvalho Chehab <mchehab@redhat.com>
*
* Red Hat Inc. http://www.redhat.com
*/
#if defined(CONFIG_EDAC_MCE) || \
(defined(CONFIG_EDAC_MCE_MODULE) && defined(MODULE))
#include <asm/mce.h>
#include <linux/list.h>
struct edac_mce {
struct list_head list;
void *priv;
int (*check_error)(void *priv, struct mce *mce);
};
int edac_mce_register(struct edac_mce *edac_mce);
void edac_mce_unregister(struct edac_mce *edac_mce);
int edac_mce_parse(struct mce *mce);
#else
#define edac_mce_parse(mce) (0)
#endif
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