edac_mce: Add an interface driver to report mce errors via edac
edac_mce module is an interface module that gets mcelog data and forwards to any registered edac module that expects to receive data via mce. Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
This commit is contained in:
@@ -36,6 +36,7 @@
|
|||||||
#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 <asm/processor.h>
|
#include <asm/processor.h>
|
||||||
#include <asm/hw_irq.h>
|
#include <asm/hw_irq.h>
|
||||||
@@ -168,6 +169,15 @@ void mce_log(struct mce *mce)
|
|||||||
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.
|
||||||
* Assume that the earlier errors are the more
|
* Assume that the earlier errors are the more
|
||||||
|
@@ -69,6 +69,9 @@ 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
|
||||||
|
tristate
|
||||||
|
|
||||||
config EDAC_AMD64
|
config EDAC_AMD64
|
||||||
tristate "AMD64 (Opteron, Athlon64) K8, F10h, F11h"
|
tristate "AMD64 (Opteron, Athlon64) K8, F10h, F11h"
|
||||||
depends on EDAC_MM_EDAC && K8_NB && X86_64 && PCI && EDAC_DECODE_MCE
|
depends on EDAC_MM_EDAC && K8_NB && X86_64 && PCI && EDAC_DECODE_MCE
|
||||||
@@ -169,9 +172,12 @@ 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
|
||||||
|
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
|
i7 Core (Nehalem) Integrated Memory Controller that exists on
|
||||||
|
newer processors like i7 Core, i7 Core Extreme, Xeon 35xx
|
||||||
|
and Xeon 55xx processors.
|
||||||
|
|
||||||
config EDAC_I82860
|
config EDAC_I82860
|
||||||
tristate "Intel 82860"
|
tristate "Intel 82860"
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
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-objs := edac_mc.o edac_device.o edac_mc_sysfs.o edac_pci_sysfs.o
|
edac_core-objs := edac_mc.o edac_device.o edac_mc_sysfs.o edac_pci_sysfs.o
|
||||||
edac_core-objs += edac_module.o edac_device_sysfs.o
|
edac_core-objs += edac_module.o edac_device_sysfs.o
|
||||||
|
58
drivers/edac/edac_mce.c
Normal file
58
drivers/edac/edac_mce.c
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
/* 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_queue(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_queue);
|
31
include/linux/edac_mce.h
Normal file
31
include/linux/edac_mce.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/* 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
|
Reference in New Issue
Block a user