aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/edac')
-rw-r--r--drivers/edac/Kconfig3
-rw-r--r--drivers/edac/Makefile1
-rw-r--r--drivers/edac/edac_mce.c61
-rw-r--r--drivers/edac/i7core_edac.c51
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
71 occurred so that a particular failing memory module can be 71 occurred so that a particular failing memory module can be
72 replaced. If unsure, select 'Y'. 72 replaced. If unsure, select 'Y'.
73 73
74config EDAC_MCE
75 bool
76
77config EDAC_AMD64 74config EDAC_AMD64
78 tristate "AMD64 (Opteron, Athlon64) K8, F10h" 75 tristate "AMD64 (Opteron, Athlon64) K8, F10h"
79 depends on EDAC_MM_EDAC && AMD_NB && X86_64 && EDAC_DECODE_MCE 76 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 @@
8 8
9obj-$(CONFIG_EDAC) := edac_stub.o 9obj-$(CONFIG_EDAC) := edac_stub.o
10obj-$(CONFIG_EDAC_MM_EDAC) += edac_core.o 10obj-$(CONFIG_EDAC_MM_EDAC) += edac_core.o
11obj-$(CONFIG_EDAC_MCE) += edac_mce.o
12 11
13edac_core-y := edac_mc.o edac_device.o edac_mc_sysfs.o edac_pci_sysfs.o 12edac_core-y := edac_mc.o edac_device.o edac_mc_sysfs.o edac_pci_sysfs.o
14edac_core-y += edac_module.o edac_device_sysfs.o 13edac_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 @@
1/* Provides edac interface to mcelog events
2 *
3 * This file may be distributed under the terms of the
4 * GNU General Public License version 2.
5 *
6 * Copyright (c) 2009 by:
7 * Mauro Carvalho Chehab <mchehab@redhat.com>
8 *
9 * Red Hat Inc. http://www.redhat.com
10 */
11
12#include <linux/module.h>
13#include <linux/edac_mce.h>
14#include <asm/mce.h>
15
16int edac_mce_enabled;
17EXPORT_SYMBOL_GPL(edac_mce_enabled);
18
19
20/*
21 * Extension interface
22 */
23
24static LIST_HEAD(edac_mce_list);
25static DEFINE_MUTEX(edac_mce_lock);
26
27int edac_mce_register(struct edac_mce *edac_mce)
28{
29 mutex_lock(&edac_mce_lock);
30 list_add_tail(&edac_mce->list, &edac_mce_list);
31 mutex_unlock(&edac_mce_lock);
32 return 0;
33}
34EXPORT_SYMBOL(edac_mce_register);
35
36void edac_mce_unregister(struct edac_mce *edac_mce)
37{
38 mutex_lock(&edac_mce_lock);
39 list_del(&edac_mce->list);
40 mutex_unlock(&edac_mce_lock);
41}
42EXPORT_SYMBOL(edac_mce_unregister);
43
44int edac_mce_parse(struct mce *mce)
45{
46 struct edac_mce *edac_mce;
47
48 list_for_each_entry(edac_mce, &edac_mce_list, list) {
49 if (edac_mce->check_error(edac_mce->priv, mce))
50 return 1;
51 }
52
53 /* Nobody queued the error */
54 return 0;
55}
56EXPORT_SYMBOL_GPL(edac_mce_parse);
57
58MODULE_LICENSE("GPL");
59MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
60MODULE_AUTHOR("Red Hat Inc. (http://www.redhat.com)");
61MODULE_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 @@
33#include <linux/delay.h> 33#include <linux/delay.h>
34#include <linux/edac.h> 34#include <linux/edac.h>
35#include <linux/mmzone.h> 35#include <linux/mmzone.h>
36#include <linux/edac_mce.h>
37#include <linux/smp.h> 36#include <linux/smp.h>
37#include <asm/mce.h>
38#include <asm/processor.h> 38#include <asm/processor.h>
39 39
40#include "edac_core.h" 40#include "edac_core.h"
@@ -265,9 +265,6 @@ struct i7core_pvt {
265 265
266 bool is_registered, enable_scrub; 266 bool is_registered, enable_scrub;
267 267
268 /* mcelog glue */
269 struct edac_mce edac_mce;
270
271 /* Fifo double buffers */ 268 /* Fifo double buffers */
272 struct mce mce_entry[MCE_LOG_LEN]; 269 struct mce mce_entry[MCE_LOG_LEN];
273 struct mce mce_outentry[MCE_LOG_LEN]; 270 struct mce mce_outentry[MCE_LOG_LEN];
@@ -1899,33 +1896,43 @@ check_ce_error:
1899 * WARNING: As this routine should be called at NMI time, extra care should 1896 * WARNING: As this routine should be called at NMI time, extra care should
1900 * be taken to avoid deadlocks, and to be as fast as possible. 1897 * be taken to avoid deadlocks, and to be as fast as possible.
1901 */ 1898 */
1902static int i7core_mce_check_error(void *priv, struct mce *mce) 1899static int i7core_mce_check_error(struct notifier_block *nb, unsigned long val,
1900 void *data)
1903{ 1901{
1904 struct mem_ctl_info *mci = priv; 1902 struct mce *mce = (struct mce *)data;
1905 struct i7core_pvt *pvt = mci->pvt_info; 1903 struct i7core_dev *i7_dev;
1904 struct mem_ctl_info *mci;
1905 struct i7core_pvt *pvt;
1906
1907 i7_dev = get_i7core_dev(mce->socketid);
1908 if (!i7_dev)
1909 return NOTIFY_BAD;
1910
1911 mci = i7_dev->mci;
1912 pvt = mci->pvt_info;
1906 1913
1907 /* 1914 /*
1908 * Just let mcelog handle it if the error is 1915 * Just let mcelog handle it if the error is
1909 * outside the memory controller 1916 * outside the memory controller
1910 */ 1917 */
1911 if (((mce->status & 0xffff) >> 7) != 1) 1918 if (((mce->status & 0xffff) >> 7) != 1)
1912 return 0; 1919 return NOTIFY_DONE;
1913 1920
1914 /* Bank 8 registers are the only ones that we know how to handle */ 1921 /* Bank 8 registers are the only ones that we know how to handle */
1915 if (mce->bank != 8) 1922 if (mce->bank != 8)
1916 return 0; 1923 return NOTIFY_DONE;
1917 1924
1918#ifdef CONFIG_SMP 1925#ifdef CONFIG_SMP
1919 /* Only handle if it is the right mc controller */ 1926 /* Only handle if it is the right mc controller */
1920 if (mce->socketid != pvt->i7core_dev->socket) 1927 if (mce->socketid != pvt->i7core_dev->socket)
1921 return 0; 1928 return NOTIFY_DONE;
1922#endif 1929#endif
1923 1930
1924 smp_rmb(); 1931 smp_rmb();
1925 if ((pvt->mce_out + 1) % MCE_LOG_LEN == pvt->mce_in) { 1932 if ((pvt->mce_out + 1) % MCE_LOG_LEN == pvt->mce_in) {
1926 smp_wmb(); 1933 smp_wmb();
1927 pvt->mce_overrun++; 1934 pvt->mce_overrun++;
1928 return 0; 1935 return NOTIFY_DONE;
1929 } 1936 }
1930 1937
1931 /* Copy memory error at the ringbuffer */ 1938 /* Copy memory error at the ringbuffer */
@@ -1938,9 +1945,13 @@ static int i7core_mce_check_error(void *priv, struct mce *mce)
1938 i7core_check_error(mci); 1945 i7core_check_error(mci);
1939 1946
1940 /* Advise mcelog that the errors were handled */ 1947 /* Advise mcelog that the errors were handled */
1941 return 1; 1948 return NOTIFY_STOP;
1942} 1949}
1943 1950
1951static struct notifier_block i7_mce_dec = {
1952 .notifier_call = i7core_mce_check_error,
1953};
1954
1944/* 1955/*
1945 * set_sdram_scrub_rate This routine sets byte/sec bandwidth scrub rate 1956 * set_sdram_scrub_rate This routine sets byte/sec bandwidth scrub rate
1946 * to hardware according to SCRUBINTERVAL formula 1957 * to hardware according to SCRUBINTERVAL formula
@@ -2093,8 +2104,7 @@ static void i7core_unregister_mci(struct i7core_dev *i7core_dev)
2093 if (pvt->enable_scrub) 2104 if (pvt->enable_scrub)
2094 disable_sdram_scrub_setting(mci); 2105 disable_sdram_scrub_setting(mci);
2095 2106
2096 /* Disable MCE NMI handler */ 2107 atomic_notifier_chain_unregister(&x86_mce_decoder_chain, &i7_mce_dec);
2097 edac_mce_unregister(&pvt->edac_mce);
2098 2108
2099 /* Disable EDAC polling */ 2109 /* Disable EDAC polling */
2100 i7core_pci_ctl_release(pvt); 2110 i7core_pci_ctl_release(pvt);
@@ -2193,21 +2203,10 @@ static int i7core_register_mci(struct i7core_dev *i7core_dev)
2193 /* allocating generic PCI control info */ 2203 /* allocating generic PCI control info */
2194 i7core_pci_ctl_create(pvt); 2204 i7core_pci_ctl_create(pvt);
2195 2205
2196 /* Registers on edac_mce in order to receive memory errors */ 2206 atomic_notifier_chain_register(&x86_mce_decoder_chain, &i7_mce_dec);
2197 pvt->edac_mce.priv = mci;
2198 pvt->edac_mce.check_error = i7core_mce_check_error;
2199 rc = edac_mce_register(&pvt->edac_mce);
2200 if (unlikely(rc < 0)) {
2201 debugf0("MC: " __FILE__
2202 ": %s(): failed edac_mce_register()\n", __func__);
2203 goto fail1;
2204 }
2205 2207
2206 return 0; 2208 return 0;
2207 2209
2208fail1:
2209 i7core_pci_ctl_release(pvt);
2210 edac_mc_del_mc(mci->dev);
2211fail0: 2210fail0:
2212 kfree(mci->ctl_name); 2211 kfree(mci->ctl_name);
2213 edac_mc_free(mci); 2212 edac_mc_free(mci);