diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/edac/Kconfig | 3 | ||||
-rw-r--r-- | drivers/edac/Makefile | 1 | ||||
-rw-r--r-- | drivers/edac/edac_mce.c | 61 | ||||
-rw-r--r-- | drivers/edac/i7core_edac.c | 51 |
4 files changed, 25 insertions, 91 deletions
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index af1a17d42bd7..f888fb599184 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -71,9 +71,6 @@ config EDAC_MM_EDAC occurred so that a particular failing memory module can be replaced. If unsure, select 'Y'. -config EDAC_MCE - bool - config EDAC_AMD64 tristate "AMD64 (Opteron, Athlon64) K8, F10h" depends on EDAC_MM_EDAC && AMD_NB && X86_64 && EDAC_DECODE_MCE diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile index 3e239133e29e..b06a9b11a5f6 100644 --- a/drivers/edac/Makefile +++ b/drivers/edac/Makefile @@ -8,7 +8,6 @@ obj-$(CONFIG_EDAC) := edac_stub.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_module.o edac_device_sysfs.o diff --git a/drivers/edac/edac_mce.c b/drivers/edac/edac_mce.c deleted file mode 100644 index 9ccdc5b140e7..000000000000 --- a/drivers/edac/edac_mce.c +++ /dev/null @@ -1,61 +0,0 @@ -/* 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"); diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 764207ed6d44..0bddc27362c1 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -33,8 +33,8 @@ #include <linux/delay.h> #include <linux/edac.h> #include <linux/mmzone.h> -#include <linux/edac_mce.h> #include <linux/smp.h> +#include <asm/mce.h> #include <asm/processor.h> #include "edac_core.h" @@ -265,9 +265,6 @@ struct i7core_pvt { bool is_registered, enable_scrub; - /* mcelog glue */ - struct edac_mce edac_mce; - /* Fifo double buffers */ struct mce mce_entry[MCE_LOG_LEN]; struct mce mce_outentry[MCE_LOG_LEN]; @@ -1899,33 +1896,43 @@ check_ce_error: * WARNING: As this routine should be called at NMI time, extra care should * be taken to avoid deadlocks, and to be as fast as possible. */ -static int i7core_mce_check_error(void *priv, struct mce *mce) +static int i7core_mce_check_error(struct notifier_block *nb, unsigned long val, + void *data) { - struct mem_ctl_info *mci = priv; - struct i7core_pvt *pvt = mci->pvt_info; + struct mce *mce = (struct mce *)data; + struct i7core_dev *i7_dev; + struct mem_ctl_info *mci; + struct i7core_pvt *pvt; + + i7_dev = get_i7core_dev(mce->socketid); + if (!i7_dev) + return NOTIFY_BAD; + + mci = i7_dev->mci; + pvt = mci->pvt_info; /* * Just let mcelog handle it if the error is * outside the memory controller */ if (((mce->status & 0xffff) >> 7) != 1) - return 0; + return NOTIFY_DONE; /* Bank 8 registers are the only ones that we know how to handle */ if (mce->bank != 8) - return 0; + return NOTIFY_DONE; #ifdef CONFIG_SMP /* Only handle if it is the right mc controller */ if (mce->socketid != pvt->i7core_dev->socket) - return 0; + return NOTIFY_DONE; #endif smp_rmb(); if ((pvt->mce_out + 1) % MCE_LOG_LEN == pvt->mce_in) { smp_wmb(); pvt->mce_overrun++; - return 0; + return NOTIFY_DONE; } /* Copy memory error at the ringbuffer */ @@ -1938,9 +1945,13 @@ static int i7core_mce_check_error(void *priv, struct mce *mce) i7core_check_error(mci); /* Advise mcelog that the errors were handled */ - return 1; + return NOTIFY_STOP; } +static struct notifier_block i7_mce_dec = { + .notifier_call = i7core_mce_check_error, +}; + /* * set_sdram_scrub_rate This routine sets byte/sec bandwidth scrub rate * to hardware according to SCRUBINTERVAL formula @@ -2093,8 +2104,7 @@ static void i7core_unregister_mci(struct i7core_dev *i7core_dev) if (pvt->enable_scrub) disable_sdram_scrub_setting(mci); - /* Disable MCE NMI handler */ - edac_mce_unregister(&pvt->edac_mce); + atomic_notifier_chain_unregister(&x86_mce_decoder_chain, &i7_mce_dec); /* Disable EDAC polling */ i7core_pci_ctl_release(pvt); @@ -2193,21 +2203,10 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev) /* allocating generic PCI control info */ i7core_pci_ctl_create(pvt); - /* Registers on edac_mce in order to receive memory errors */ - pvt->edac_mce.priv = mci; - pvt->edac_mce.check_error = i7core_mce_check_error; - rc = edac_mce_register(&pvt->edac_mce); - if (unlikely(rc < 0)) { - debugf0("MC: " __FILE__ - ": %s(): failed edac_mce_register()\n", __func__); - goto fail1; - } + atomic_notifier_chain_register(&x86_mce_decoder_chain, &i7_mce_dec); return 0; -fail1: - i7core_pci_ctl_release(pvt); - edac_mc_del_mc(mci->dev); fail0: kfree(mci->ctl_name); edac_mc_free(mci); |