From a0c36a1f0fbab42590dab3c13c10fa7d20e6c2cd Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Mon, 22 Jun 2009 22:41:15 -0300 Subject: i7core_edac: Add an EDAC memory controller driver for Nehalem chipsets This driver is meant to support i7 core/i7core extreme desktop processors and Xeon 35xx/55xx series with integrated memory controller. It is likely that it can be expanded in the future to work with other processor series based at the same Memory Controller design. For now, it has just a few MCH status reads. Signed-off-by: Mauro Carvalho Chehab --- include/linux/pci_ids.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'include/linux') diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 9f688d243b86..c5dd0994bd7c 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2532,6 +2532,22 @@ #define PCI_DEVICE_ID_INTEL_ICH9_6 0x2930 #define PCI_DEVICE_ID_INTEL_ICH9_7 0x2916 #define PCI_DEVICE_ID_INTEL_ICH9_8 0x2918 +#define PCI_DEVICE_ID_INTEL_I7_MCR 0x2c18 +#define PCI_DEVICE_ID_INTEL_I7_MC_TAD 0x2c19 +#define PCI_DEVICE_ID_INTEL_I7_MC_RAS 0x2c1a +#define PCI_DEVICE_ID_INTEL_I7_MC_TEST 0x2c1c +#define PCI_DEVICE_ID_INTEL_I7_MC_CH0_CTRL 0x2c20 +#define PCI_DEVICE_ID_INTEL_I7_MC_CH0_ADDR 0x2c21 +#define PCI_DEVICE_ID_INTEL_I7_MC_CH0_RANK 0x2c22 +#define PCI_DEVICE_ID_INTEL_I7_MC_CH0_TC 0x2c23 +#define PCI_DEVICE_ID_INTEL_I7_MC_CH1_CTRL 0x2c28 +#define PCI_DEVICE_ID_INTEL_I7_MC_CH1_ADDR 0x2c29 +#define PCI_DEVICE_ID_INTEL_I7_MC_CH1_RANK 0x2c2a +#define PCI_DEVICE_ID_INTEL_I7_MC_CH1_TC 0x2c2b +#define PCI_DEVICE_ID_INTEL_I7_MC_CH2_CTRL 0x2c30 +#define PCI_DEVICE_ID_INTEL_I7_MC_CH2_ADDR 0x2c31 +#define PCI_DEVICE_ID_INTEL_I7_MC_CH2_RANK 0x2c32 +#define PCI_DEVICE_ID_INTEL_I7_MC_CH2_TC 0x2c33 #define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340 #define PCI_DEVICE_ID_INTEL_IOAT_TBG4 0x3429 #define PCI_DEVICE_ID_INTEL_IOAT_TBG5 0x342a -- cgit v1.2.3 From 696e409dbd1ce325129c5030267365619364dfa0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 23 Jul 2009 06:57:45 -0300 Subject: 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 --- arch/x86/kernel/cpu/mcheck/mce.c | 10 +++++++ drivers/edac/Kconfig | 8 +++++- drivers/edac/Makefile | 1 + drivers/edac/edac_mce.c | 58 ++++++++++++++++++++++++++++++++++++++++ include/linux/edac_mce.h | 31 +++++++++++++++++++++ 5 files changed, 107 insertions(+), 1 deletion(-) create mode 100644 drivers/edac/edac_mce.c create mode 100644 include/linux/edac_mce.h (limited to 'include/linux') diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c index 8a6f0afa767e..6585ff07ddf5 100644 --- a/arch/x86/kernel/cpu/mcheck/mce.c +++ b/arch/x86/kernel/cpu/mcheck/mce.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -168,6 +169,15 @@ void mce_log(struct mce *mce) for (;;) { entry = rcu_dereference_check_mce(mcelog.next); 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. * Assume that the earlier errors are the more diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 391ddbfb2a34..5b7fbc5aec87 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig @@ -69,6 +69,9 @@ config EDAC_MM_EDAC occurred so that a particular failing memory module can be replaced. If unsure, select 'Y'. +config EDAC_MCE + tristate + config EDAC_AMD64 tristate "AMD64 (Opteron, Athlon64) K8, F10h, F11h" depends on EDAC_MM_EDAC && K8_NB && X86_64 && PCI && EDAC_DECODE_MCE @@ -169,9 +172,12 @@ config EDAC_I5400 config EDAC_I7CORE tristate "Intel i7 Core (Nehalem) processors" depends on EDAC_MM_EDAC && PCI && X86 + select EDAC_MCE help 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 tristate "Intel 82860" diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile index b9996195b233..ca6b1bb24ccc 100644 --- a/drivers/edac/Makefile +++ b/drivers/edac/Makefile @@ -8,6 +8,7 @@ obj-$(CONFIG_EDAC) := edac_stub.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_module.o edac_device_sysfs.o diff --git a/drivers/edac/edac_mce.c b/drivers/edac/edac_mce.c new file mode 100644 index 000000000000..b1efa8e51921 --- /dev/null +++ b/drivers/edac/edac_mce.c @@ -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 + * + * Red Hat Inc. http://www.redhat.com + */ + +#include +#include +#include + +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); diff --git a/include/linux/edac_mce.h b/include/linux/edac_mce.h new file mode 100644 index 000000000000..f974fc035363 --- /dev/null +++ b/include/linux/edac_mce.h @@ -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 + * + * Red Hat Inc. http://www.redhat.com + */ + +#if defined(CONFIG_EDAC_MCE) || \ + (defined(CONFIG_EDAC_MCE_MODULE) && defined(MODULE)) + +#include +#include + +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 -- cgit v1.2.3 From e9bd2e73793bf0f7fcd8f94b532bb8f5c5b44171 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Thu, 9 Jul 2009 22:14:35 -0300 Subject: i7core_edac: Adds write unlock to MC registers The public Intel Xeon 5500 volume 2 datasheet describes, on page 53, session 2.6.7 a register that can lock/unlock Memory Controller the configuration register, called MC_CFG_CONTROL. Adds support for it in the hope that software error injection would work. With my tests with Xeon 35xx, there's still something missing. With a program that does sequencial bit writes at dev 0.0, sometimes, it produces error injection, after unblocking the MC_CFG_CONTROL (and, sometimes, it just locks my testing machine). I'll try later to discover by trial and error what's the register that solves this issue on Xeon 35xx. Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7core_edac.c | 30 +++++++++++++++++++++++++++--- include/linux/pci_ids.h | 1 + 2 files changed, 28 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 3c7bb5f405f6..26cd5c924d56 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -33,7 +33,7 @@ #include "edac_core.h" /* To use the new pci_[read/write]_config_qword instead of two dword */ -#define USE_QWORD 1 +#define USE_QWORD 0 /* * Alter this version for the module when modifications are made @@ -58,6 +58,10 @@ * i7core Memory Controller Registers */ + /* OFFSETS for Device 0 Function 0 */ + +#define MC_CFG_CONTROL 0x90 + /* OFFSETS for Device 3 Function 0 */ #define MC_CONTROL 0x48 @@ -186,6 +190,7 @@ struct pci_id_descr { }; struct i7core_pvt { + struct pci_dev *pci_noncore; struct pci_dev *pci_mcr[MAX_MCR_FUNC + 1]; struct pci_dev *pci_ch[NUM_CHANS][MAX_CHAN_FUNC + 1]; struct i7core_info info; @@ -222,6 +227,9 @@ struct pci_id_descr pci_devs[] = { { PCI_DESCR(3, 2, PCI_DEVICE_ID_INTEL_I7_MC_RAS) }, /* if RDIMM is supported */ { PCI_DESCR(3, 4, PCI_DEVICE_ID_INTEL_I7_MC_TEST) }, + /* Generic Non-core registers */ + { PCI_DESCR(0, 0, PCI_DEVICE_ID_INTEL_I7_NOCORE) }, + /* Channel 0 */ { PCI_DESCR(4, 0, PCI_DEVICE_ID_INTEL_I7_MC_CH0_CTRL) }, { PCI_DESCR(4, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH0_ADDR) }, @@ -882,6 +890,16 @@ static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci, else mask |= (pvt->inject.col & 0x3fffL); + /* Unlock writes to registers */ + pci_write_config_dword(pvt->pci_noncore, MC_CFG_CONTROL, 0x2); + msleep(100); + + /* Zeroes error count registers */ + pci_write_config_dword(pvt->pci_mcr[4], MC_TEST_ERR_RCV1, 0); + pci_write_config_dword(pvt->pci_mcr[4], MC_TEST_ERR_RCV0, 0); + pvt->ce_count_available = 0; + + #if USE_QWORD pci_write_config_qword(pvt->pci_ch[pvt->inject.channel][0], MC_CHANNEL_ADDR_MATCH, mask); @@ -929,12 +947,15 @@ static ssize_t i7core_inject_enable_store(struct mem_ctl_info *mci, pci_write_config_dword(pvt->pci_ch[pvt->inject.channel][0], MC_CHANNEL_ERROR_MASK, injectmask); +#if 0 + /* lock writes to registers */ + pci_write_config_dword(pvt->pci_noncore, MC_CFG_CONTROL, 0); +#endif debugf0("Error inject addr match 0x%016llx, ecc 0x%08x," " inject 0x%08x\n", mask, pvt->inject.eccmask, injectmask); - return count; } @@ -1124,12 +1145,15 @@ static int mci_bind_devs(struct mem_ctl_info *mci) if (unlikely(func > MAX_CHAN_FUNC)) goto error; pvt->pci_ch[slot - 4][func] = pdev; - } else + } else if (!slot && !func) + pvt->pci_noncore = pdev; + else goto error; debugf0("Associated fn %d.%d, dev = %p\n", PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn), pdev); } + return 0; error: diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index c5dd0994bd7c..9d5bfe86ba73 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2548,6 +2548,7 @@ #define PCI_DEVICE_ID_INTEL_I7_MC_CH2_ADDR 0x2c31 #define PCI_DEVICE_ID_INTEL_I7_MC_CH2_RANK 0x2c32 #define PCI_DEVICE_ID_INTEL_I7_MC_CH2_TC 0x2c33 +#define PCI_DEVICE_ID_INTEL_I7_NOCORE 0x2c41 #define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340 #define PCI_DEVICE_ID_INTEL_IOAT_TBG4 0x3429 #define PCI_DEVICE_ID_INTEL_IOAT_TBG5 0x342a -- cgit v1.2.3 From d1fd4fb69eeeb7db0693df58b9116db498d5bfe1 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 10 Jul 2009 18:39:53 -0300 Subject: i7core_edac: Add a code to probe Xeon 55xx bus This code changes the detection procedure of i7core_edac. Instead of directly probing for MC registers, it probes for another register found on Nehalem. If found, it tries to pick the first MC PCI BUS. This should work fine with Xeon 35xx, but, on Xeon 55xx, this is at bus 254 and 255 that are not properly detected by the non-legacy PCI methods. The new detection code scans specifically at buses 254 and 255 for the Xeon 55xx devices. This code has not tested yet. After working, a change at the code will be needed, since the i7core is not yet ready for working with 2 sets of MC. Signed-off-by: Mauro Carvalho Chehab --- arch/x86/pci/legacy.c | 1 + drivers/edac/i7core_edac.c | 17 +++++++++++++---- include/linux/pci.h | 1 + include/linux/pci_ids.h | 1 + 4 files changed, 16 insertions(+), 4 deletions(-) (limited to 'include/linux') diff --git a/arch/x86/pci/legacy.c b/arch/x86/pci/legacy.c index c734c277b116..d6cc2eddf339 100644 --- a/arch/x86/pci/legacy.c +++ b/arch/x86/pci/legacy.c @@ -57,6 +57,7 @@ void pcibios_scan_specific_bus(int busn) } } } +EXPORT_SYMBOL_GPL(pcibios_scan_specific_bus); int __init pci_subsys_init(void) { diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 26cd5c924d56..eec0c13c0205 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -221,15 +221,15 @@ struct i7core_dev_info { .dev_id = (device_id) struct pci_id_descr pci_devs[] = { + /* Generic Non-core registers */ + { PCI_DESCR(0, 0, PCI_DEVICE_ID_INTEL_I7_NOCORE) }, + /* Memory controller */ { PCI_DESCR(3, 0, PCI_DEVICE_ID_INTEL_I7_MCR) }, { PCI_DESCR(3, 1, PCI_DEVICE_ID_INTEL_I7_MC_TAD) }, { PCI_DESCR(3, 2, PCI_DEVICE_ID_INTEL_I7_MC_RAS) }, /* if RDIMM is supported */ { PCI_DESCR(3, 4, PCI_DEVICE_ID_INTEL_I7_MC_TEST) }, - /* Generic Non-core registers */ - { PCI_DESCR(0, 0, PCI_DEVICE_ID_INTEL_I7_NOCORE) }, - /* Channel 0 */ { PCI_DESCR(4, 0, PCI_DEVICE_ID_INTEL_I7_MC_CH0_CTRL) }, { PCI_DESCR(4, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH0_ADDR) }, @@ -255,7 +255,7 @@ struct pci_id_descr pci_devs[] = { * This should match the first device at pci_devs table */ static const struct pci_device_id i7core_pci_tbl[] __devinitdata = { - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I7_MCR)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_X58_HUB_MGMT)}, {0,} /* 0 terminated list. */ }; @@ -1069,6 +1069,15 @@ static int i7core_get_devices(void) for (i = 0; i < N_DEVS; i++) { pdev = pci_get_device(PCI_VENDOR_ID_INTEL, pci_devs[i].dev_id, NULL); + + if (!pdev && !i) { + pcibios_scan_specific_bus(254); + pcibios_scan_specific_bus(255); + + pdev = pci_get_device(PCI_VENDOR_ID_INTEL, + pci_devs[i].dev_id, NULL); + } + if (likely(pdev)) pci_devs[i].pdev = pdev; else { diff --git a/include/linux/pci.h b/include/linux/pci.h index a788fa12ff31..5e2c7e15187d 100644 --- a/include/linux/pci.h +++ b/include/linux/pci.h @@ -621,6 +621,7 @@ void pci_fixup_cardbus(struct pci_bus *); /* Generic PCI functions used internally */ +void pcibios_scan_specific_bus(int busn); extern struct pci_bus *pci_find_bus(int domain, int busnr); void pci_bus_add_devices(const struct pci_bus *bus); struct pci_bus *pci_scan_bus_parented(struct device *parent, int bus, diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 9d5bfe86ba73..12c3da6ef14d 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2554,6 +2554,7 @@ #define PCI_DEVICE_ID_INTEL_IOAT_TBG5 0x342a #define PCI_DEVICE_ID_INTEL_IOAT_TBG6 0x342b #define PCI_DEVICE_ID_INTEL_IOAT_TBG7 0x342c +#define PCI_DEVICE_ID_INTEL_X58_HUB_MGMT 0x342e #define PCI_DEVICE_ID_INTEL_IOAT_TBG0 0x3430 #define PCI_DEVICE_ID_INTEL_IOAT_TBG1 0x3431 #define PCI_DEVICE_ID_INTEL_IOAT_TBG2 0x3432 -- cgit v1.2.3 From 310cbb7284fab9fc9cbb6bb893e51c414e15bba3 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 17 Jul 2009 00:09:10 -0300 Subject: i7core: fix probing on Xeon55xx Xeon55xx fails to probe with this error message: EDAC DEBUG: in drivers/edac/i7core_edac.c, line at 1660: MC: drivers/edac/i7core_edac.c: i7core_init() EDAC i7core: Device not found: dev 00:00.0 PCI ID 8086:2c41 i7core_edac: probe of 0000:00:14.0 failed with error -22 This is due to the fact that, on Xeon35xx (and i7core), device 00.0 has PCI ID 8086:2c40. Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7core_edac.c | 23 ++++++++++++++++++++--- include/linux/pci_ids.h | 1 + 2 files changed, 21 insertions(+), 3 deletions(-) (limited to 'include/linux') diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 67822976992e..e2f6dfdca841 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -227,9 +227,6 @@ struct i7core_dev_info { .dev_id = (device_id) struct pci_id_descr pci_devs[] = { - /* Generic Non-core registers */ - { PCI_DESCR(0, 0, PCI_DEVICE_ID_INTEL_I7_NOCORE) }, - /* Memory controller */ { PCI_DESCR(3, 0, PCI_DEVICE_ID_INTEL_I7_MCR) }, { PCI_DESCR(3, 1, PCI_DEVICE_ID_INTEL_I7_MC_TAD) }, @@ -253,6 +250,16 @@ struct pci_id_descr pci_devs[] = { { PCI_DESCR(6, 1, PCI_DEVICE_ID_INTEL_I7_MC_CH2_ADDR) }, { PCI_DESCR(6, 2, PCI_DEVICE_ID_INTEL_I7_MC_CH2_RANK) }, { PCI_DESCR(6, 3, PCI_DEVICE_ID_INTEL_I7_MC_CH2_TC) }, + + /* Generic Non-core registers */ + /* + * This is the PCI device on i7core and on Xeon 35xx (8086:2c41) + * On Xeon 55xx, however, it has a different id (8086:2c40). So, + * the probing code needs to test for the other address in case of + * failure of this one + */ + { PCI_DESCR(0, 0, PCI_DEVICE_ID_INTEL_I7_NOCORE) }, + }; #define N_DEVS ARRAY_SIZE(pci_devs) @@ -1138,6 +1145,16 @@ static int i7core_get_devices(void) pci_devs[i].dev_id, NULL); } + /* + * On Xeon 55xx, the Intel Quckpath Arch Generic Non-core regs + * is at addr 8086:2c40, instead of 8086:2c41. So, we need + * to probe for the alternate address in case of failure + */ + if (pci_devs[i].dev_id == PCI_DEVICE_ID_INTEL_I7_NOCORE + && !pdev) + pdev = pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_I7_NOCORE_ALT, NULL); + if (likely(pdev)) { bus = pdev->bus->number; diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 12c3da6ef14d..bf6db4814c27 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2549,6 +2549,7 @@ #define PCI_DEVICE_ID_INTEL_I7_MC_CH2_RANK 0x2c32 #define PCI_DEVICE_ID_INTEL_I7_MC_CH2_TC 0x2c33 #define PCI_DEVICE_ID_INTEL_I7_NOCORE 0x2c41 +#define PCI_DEVICE_ID_INTEL_I7_NOCORE_ALT 0x2c40 #define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340 #define PCI_DEVICE_ID_INTEL_IOAT_TBG4 0x3429 #define PCI_DEVICE_ID_INTEL_IOAT_TBG5 0x342a -- cgit v1.2.3 From fd3826549db7f73d22b9c9abb80e01effb95c2ba Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 14 Oct 2009 06:07:07 -0300 Subject: i7core_edac: PCI device is called NONCORE, instead of NOCORE Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7core_edac.c | 6 +++--- include/linux/pci_ids.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) (limited to 'include/linux') diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index c2857f60ae6a..bb538dfbdc6c 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -291,7 +291,7 @@ struct pci_id_descr pci_dev_descr[] = { * the probing code needs to test for the other address in case of * failure of this one */ - { PCI_DESCR(0, 0, PCI_DEVICE_ID_INTEL_I7_NOCORE) }, + { PCI_DESCR(0, 0, PCI_DEVICE_ID_INTEL_I7_NONCORE) }, }; #define N_DEVS ARRAY_SIZE(pci_dev_descr) @@ -1177,9 +1177,9 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno) * is at addr 8086:2c40, instead of 8086:2c41. So, we need * to probe for the alternate address in case of failure */ - if (pci_dev_descr[devno].dev_id == PCI_DEVICE_ID_INTEL_I7_NOCORE && !pdev) + if (pci_dev_descr[devno].dev_id == PCI_DEVICE_ID_INTEL_I7_NONCORE && !pdev) pdev = pci_get_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_I7_NOCORE_ALT, *prev); + PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT, *prev); if (!pdev) { if (*prev) { diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index bf6db4814c27..382476a8a339 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2548,8 +2548,8 @@ #define PCI_DEVICE_ID_INTEL_I7_MC_CH2_ADDR 0x2c31 #define PCI_DEVICE_ID_INTEL_I7_MC_CH2_RANK 0x2c32 #define PCI_DEVICE_ID_INTEL_I7_MC_CH2_TC 0x2c33 -#define PCI_DEVICE_ID_INTEL_I7_NOCORE 0x2c41 -#define PCI_DEVICE_ID_INTEL_I7_NOCORE_ALT 0x2c40 +#define PCI_DEVICE_ID_INTEL_I7_NONCORE 0x2c41 +#define PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT 0x2c40 #define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340 #define PCI_DEVICE_ID_INTEL_IOAT_TBG4 0x3429 #define PCI_DEVICE_ID_INTEL_IOAT_TBG5 0x342a -- cgit v1.2.3 From 52a2e4fc3712d12888decd386d78ad526078a1fa Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 14 Oct 2009 11:21:58 -0300 Subject: i7core_edac: Add initial support for Lynnfield Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7core_edac.c | 39 +++++++++++++++++++++++++++++++++++++-- include/linux/pci_ids.h | 15 +++++++++++++++ 2 files changed, 52 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index e944b63d9f06..e525d571cb25 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -299,11 +299,30 @@ struct pci_id_descr pci_dev_descr_i7core[] = { }; +struct pci_id_descr pci_dev_descr_lynnfield[] = { + { PCI_DESCR( 3, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MCR) }, + { PCI_DESCR( 3, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TAD) }, + { PCI_DESCR( 3, 4, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TEST) }, + + { PCI_DESCR( 4, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_CTRL) }, + { PCI_DESCR( 4, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_ADDR) }, + { PCI_DESCR( 4, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_RANK) }, + { PCI_DESCR( 4, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_TC) }, + + { PCI_DESCR( 4, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_CTRL) }, + { PCI_DESCR( 4, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_ADDR) }, + { PCI_DESCR( 4, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_RANK) }, + { PCI_DESCR( 4, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_TC) }, + + { PCI_DESCR( 0, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE) }, +}; + /* * pci_device_id table for which devices we are looking for */ static const struct pci_device_id i7core_pci_tbl[] __devinitdata = { {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_X58_HUB_MGMT)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE)}, {0,} /* 0 terminated list. */ }; @@ -522,6 +541,9 @@ static int get_dimm_config(struct mem_ctl_info *mci, int *csrow) for (i = 0; i < NUM_CHANS; i++) { u32 data, dimm_dod[3], value[8]; + if (!pvt->pci_ch[i][0]) + continue; + if (!CH_ACTIVE(pvt, i)) { debugf0("Channel %i is not active\n", i); continue; @@ -1001,6 +1023,9 @@ static ssize_t i7core_inject_enable_show(struct mem_ctl_info *mci, struct i7core_pvt *pvt = mci->pvt_info; u32 injectmask; + if (!pvt->pci_ch[pvt->inject.channel][0]) + return 0; + pci_read_config_dword(pvt->pci_ch[pvt->inject.channel][0], MC_CHANNEL_ERROR_INJECT, &injectmask); @@ -1841,8 +1866,18 @@ static int __devinit i7core_probe(struct pci_dev *pdev, /* get the pci devices we want to reserve for our use */ mutex_lock(&i7core_edac_lock); - rc = i7core_get_devices(pci_dev_descr_i7core, - ARRAY_SIZE(pci_dev_descr_i7core)); + if (pdev->device == PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE) { + printk(KERN_INFO "i7core_edac: detected a " + "Lynnfield processor\n"); + rc = i7core_get_devices(pci_dev_descr_lynnfield, + ARRAY_SIZE(pci_dev_descr_lynnfield)); + } else { + printk(KERN_INFO "i7core_edac: detected a " + "Nehalem/Nehalem-EP processor\n"); + rc = i7core_get_devices(pci_dev_descr_i7core, + ARRAY_SIZE(pci_dev_descr_i7core)); + } + if (unlikely(rc < 0)) goto fail0; diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 382476a8a339..ebc0fa4c7a66 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2550,6 +2550,21 @@ #define PCI_DEVICE_ID_INTEL_I7_MC_CH2_TC 0x2c33 #define PCI_DEVICE_ID_INTEL_I7_NONCORE 0x2c41 #define PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT 0x2c40 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE 0x2c50 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_SAD 0x2c81 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_QPI_LINK0 0x2c90 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_QPI_PHY0 0x2c91 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MCR 0x2c98 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TAD 0x2c99 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TEST 0x2c9C +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_CTRL 0x2ca0 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_ADDR 0x2ca1 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_RANK 0x2ca2 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_TC 0x2ca3 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_CTRL 0x2ca8 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_ADDR 0x2ca9 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_RANK 0x2caa +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_TC 0x2cab #define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340 #define PCI_DEVICE_ID_INTEL_IOAT_TBG4 0x3429 #define PCI_DEVICE_ID_INTEL_IOAT_TBG5 0x342a -- cgit v1.2.3 From f05da2f7855b3b88a831ca79e037245872549ec0 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Wed, 14 Oct 2009 13:31:06 -0300 Subject: i7core: add support for Lynnfield alternate address Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7core_edac.c | 13 +++++++++++-- include/linux/pci_ids.h | 1 + 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index e525d571cb25..d3f5c016c5eb 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -314,6 +314,10 @@ struct pci_id_descr pci_dev_descr_lynnfield[] = { { PCI_DESCR( 4, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_RANK) }, { PCI_DESCR( 4, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_TC) }, + /* + * This is the PCI device has an alternate address on some + * processors like Core i7 860 + */ { PCI_DESCR( 0, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE) }, }; @@ -322,7 +326,7 @@ struct pci_id_descr pci_dev_descr_lynnfield[] = { */ static const struct pci_device_id i7core_pci_tbl[] __devinitdata = { {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_X58_HUB_MGMT)}, - {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE)}, + {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNNFIELD_QPI_LINK0)}, {0,} /* 0 terminated list. */ }; @@ -1209,6 +1213,11 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno, pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT, *prev); + if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE && !pdev) + pdev = pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_ALT, + *prev); + if (!pdev) { if (*prev) { *prev = pdev; @@ -1866,7 +1875,7 @@ static int __devinit i7core_probe(struct pci_dev *pdev, /* get the pci devices we want to reserve for our use */ mutex_lock(&i7core_edac_lock); - if (pdev->device == PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE) { + if (pdev->device == PCI_DEVICE_ID_INTEL_LYNNFIELD_QPI_LINK0) { printk(KERN_INFO "i7core_edac: detected a " "Lynnfield processor\n"); rc = i7core_get_devices(pci_dev_descr_lynnfield, diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index ebc0fa4c7a66..e67cb20b8401 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2551,6 +2551,7 @@ #define PCI_DEVICE_ID_INTEL_I7_NONCORE 0x2c41 #define PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT 0x2c40 #define PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE 0x2c50 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_ALT 0x2c51 #define PCI_DEVICE_ID_INTEL_LYNNFIELD_SAD 0x2c81 #define PCI_DEVICE_ID_INTEL_LYNNFIELD_QPI_LINK0 0x2c90 #define PCI_DEVICE_ID_INTEL_LYNNFIELD_QPI_PHY0 0x2c91 -- cgit v1.2.3 From ac1ececea995fd77c8da6a1299674f22991cecaa Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Tue, 18 May 2010 13:00:31 -0300 Subject: i7core_edac: Add support for X5670 As reported by Vernon Mauery , X5670 (Westmere-EP) uses a different register for one of the uncore PCI devices. Add support for it. Those are the PCI ID's on this new chipset: fe:00.0 0600: 8086:2c70 (rev 02) fe:00.1 0600: 8086:2d81 (rev 02) fe:02.0 0600: 8086:2d90 (rev 02) fe:02.1 0600: 8086:2d91 (rev 02) fe:02.2 0600: 8086:2d92 (rev 02) fe:02.3 0600: 8086:2d93 (rev 02) fe:02.4 0600: 8086:2d94 (rev 02) fe:02.5 0600: 8086:2d95 (rev 02) fe:03.0 0600: 8086:2d98 (rev 02) fe:03.1 0600: 8086:2d99 (rev 02) fe:03.2 0600: 8086:2d9a (rev 02) fe:03.4 0600: 8086:2d9c (rev 02) fe:04.0 0600: 8086:2da0 (rev 02) fe:04.1 0600: 8086:2da1 (rev 02) fe:04.2 0600: 8086:2da2 (rev 02) fe:04.3 0600: 8086:2da3 (rev 02) fe:05.0 0600: 8086:2da8 (rev 02) fe:05.1 0600: 8086:2da9 (rev 02) fe:05.2 0600: 8086:2daa (rev 02) fe:05.3 0600: 8086:2dab (rev 02) fe:06.0 0600: 8086:2db0 (rev 02) fe:06.1 0600: 8086:2db1 (rev 02) fe:06.2 0600: 8086:2db2 (rev 02) fe:06.3 0600: 8086:2db3 (rev 02) (as usual, the same PCI devices repeat at ff: bus) The PCI device 8086:2c70 is shown as: fe:00.0 Host bridge: Intel Corporation QuickPath Architecture Generic Non-core Registers (rev 02) So, for this device to be recognized, it is only a matter of adding this new PCI ID to the driver. Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7core_edac.c | 7 ++++++- include/linux/pci_ids.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'include/linux') diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index cd51709c4d89..82acfbd01779 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -1213,10 +1213,15 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno, pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT, *prev); - if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE && !pdev) + if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE && !pdev) { pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_ALT, *prev); + if (!pdev) + pdev = pci_get_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_REV2, + *prev); + } if (!pdev) { if (*prev) { diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index e67cb20b8401..46d76e985bac 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2552,6 +2552,7 @@ #define PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT 0x2c40 #define PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE 0x2c50 #define PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_ALT 0x2c51 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_REV2 0x2c70 #define PCI_DEVICE_ID_INTEL_LYNNFIELD_SAD 0x2c81 #define PCI_DEVICE_ID_INTEL_LYNNFIELD_QPI_LINK0 0x2c90 #define PCI_DEVICE_ID_INTEL_LYNNFIELD_QPI_PHY0 0x2c91 -- cgit v1.2.3 From bd9e19ca46b54fa85141c4d20afd668379d94c81 Mon Sep 17 00:00:00 2001 From: Vernon Mauery Date: Tue, 18 May 2010 19:02:50 -0300 Subject: Add support for Westmere to i7core_edac driver This adds new PCI IDs for the Westmere's memory controller devices and modifies the i7core_edac driver to be able to probe both Nehalem and Westmere processors. Signed-off-by: Vernon Mauery Signed-off-by: Mauro Carvalho Chehab --- drivers/edac/i7core_edac.c | 117 +++++++++++++++++++++++++++++++-------------- include/linux/pci_ids.h | 16 +++++++ 2 files changed, 96 insertions(+), 37 deletions(-) (limited to 'include/linux') diff --git a/drivers/edac/i7core_edac.c b/drivers/edac/i7core_edac.c index 3e2b5379bc05..8d63b0046480 100644 --- a/drivers/edac/i7core_edac.c +++ b/drivers/edac/i7core_edac.c @@ -206,6 +206,11 @@ struct pci_id_descr { int optional; }; +struct pci_id_table { + struct pci_id_descr *descr; + int n_devs; +}; + struct i7core_dev { struct list_head list; u8 socket; @@ -262,7 +267,7 @@ static DEFINE_MUTEX(i7core_edac_lock); .func = (function), \ .dev_id = (device_id) -struct pci_id_descr pci_dev_descr_i7core[] = { +struct pci_id_descr pci_dev_descr_i7core_nehalem[] = { /* Memory controller */ { PCI_DESCR(3, 0, PCI_DEVICE_ID_INTEL_I7_MCR) }, { PCI_DESCR(3, 1, PCI_DEVICE_ID_INTEL_I7_MC_TAD) }, @@ -321,6 +326,44 @@ struct pci_id_descr pci_dev_descr_lynnfield[] = { { PCI_DESCR( 0, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE) }, }; +struct pci_id_descr pci_dev_descr_i7core_westmere[] = { + /* Memory controller */ + { PCI_DESCR(3, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MCR_REV2) }, + { PCI_DESCR(3, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TAD_REV2) }, + /* Exists only for RDIMM */ + { PCI_DESCR(3, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_RAS_REV2), .optional = 1 }, + { PCI_DESCR(3, 4, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TEST_REV2) }, + + /* Channel 0 */ + { PCI_DESCR(4, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_CTRL_REV2) }, + { PCI_DESCR(4, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_ADDR_REV2) }, + { PCI_DESCR(4, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_RANK_REV2) }, + { PCI_DESCR(4, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_TC_REV2) }, + + /* Channel 1 */ + { PCI_DESCR(5, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_CTRL_REV2) }, + { PCI_DESCR(5, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_ADDR_REV2) }, + { PCI_DESCR(5, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_RANK_REV2) }, + { PCI_DESCR(5, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_TC_REV2) }, + + /* Channel 2 */ + { PCI_DESCR(6, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_CTRL_REV2) }, + { PCI_DESCR(6, 1, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_ADDR_REV2) }, + { PCI_DESCR(6, 2, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_RANK_REV2) }, + { PCI_DESCR(6, 3, PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_TC_REV2) }, + + /* Generic Non-core registers */ + { PCI_DESCR(0, 0, PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_REV2) }, + +}; + +#define PCI_ID_TABLE_ENTRY(A) { A, ARRAY_SIZE(A) } +struct pci_id_table pci_dev_table[] = { + PCI_ID_TABLE_ENTRY(pci_dev_descr_i7core_nehalem), + PCI_ID_TABLE_ENTRY(pci_dev_descr_lynnfield), + PCI_ID_TABLE_ENTRY(pci_dev_descr_i7core_westmere), +}; + /* * pci_device_id table for which devices we are looking for */ @@ -1170,7 +1213,7 @@ static void i7core_put_all_devices(void) i7core_put_devices(i7core_dev); } -static void __init i7core_xeon_pci_fixup(int dev_id) +static void __init i7core_xeon_pci_fixup(struct pci_id_table *table) { struct pci_dev *pdev = NULL; int i; @@ -1179,10 +1222,13 @@ static void __init i7core_xeon_pci_fixup(int dev_id) * aren't announced by acpi. So, we need to use a legacy scan probing * to detect them */ - pdev = pci_get_device(PCI_VENDOR_ID_INTEL, dev_id, NULL); - if (unlikely(!pdev)) { - for (i = 0; i < MAX_SOCKET_BUSES; i++) - pcibios_scan_specific_bus(255-i); + while (table && table->descr) { + pdev = pci_get_device(PCI_VENDOR_ID_INTEL, table->descr[0].dev_id, NULL); + if (unlikely(!pdev)) { + for (i = 0; i < MAX_SOCKET_BUSES; i++) + pcibios_scan_specific_bus(255-i); + } + table++; } } @@ -1213,15 +1259,10 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno, pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_I7_NONCORE_ALT, *prev); - if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE && !pdev) { + if (dev_descr->dev_id == PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE && !pdev) pdev = pci_get_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_ALT, *prev); - if (!pdev) - pdev = pci_get_device(PCI_VENDOR_ID_INTEL, - PCI_DEVICE_ID_INTEL_LYNNFIELD_NONCORE_REV2, - *prev); - } if (!pdev) { if (*prev) { @@ -1232,6 +1273,9 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno, if (dev_descr->optional) return 0; + if (devno == 0) + return -ENODEV; + i7core_printk(KERN_ERR, "Device not found: dev %02x.%d PCI ID %04x:%04x\n", dev_descr->dev, dev_descr->func, @@ -1307,24 +1351,34 @@ int i7core_get_onedevice(struct pci_dev **prev, int devno, return 0; } -static int i7core_get_devices(struct pci_id_descr dev_descr[], unsigned n_devs) +static int i7core_get_devices(struct pci_id_table *table) { int i, rc; struct pci_dev *pdev = NULL; - - for (i = 0; i < n_devs; i++) { - pdev = NULL; - do { - rc = i7core_get_onedevice(&pdev, i, &dev_descr[i], - n_devs); - if (rc < 0) { - i7core_put_all_devices(); - return -ENODEV; - } - } while (pdev); + struct pci_id_descr *dev_descr; + + while (table && table->descr) { + dev_descr = table->descr; + for (i = 0; i < table->n_devs; i++) { + pdev = NULL; + do { + rc = i7core_get_onedevice(&pdev, i, &dev_descr[i], + table->n_devs); + if (rc < 0) { + if (i == 0) { + i = table->n_devs; + break; + } + i7core_put_all_devices(); + return -ENODEV; + } + } while (pdev); + } + table++; } return 0; + return 0; } static int mci_bind_devs(struct mem_ctl_info *mci, @@ -1884,18 +1938,7 @@ static int __devinit i7core_probe(struct pci_dev *pdev, /* get the pci devices we want to reserve for our use */ mutex_lock(&i7core_edac_lock); - if (pdev->device == PCI_DEVICE_ID_INTEL_LYNNFIELD_QPI_LINK0) { - printk(KERN_INFO "i7core_edac: detected a " - "Lynnfield processor\n"); - rc = i7core_get_devices(pci_dev_descr_lynnfield, - ARRAY_SIZE(pci_dev_descr_lynnfield)); - } else { - printk(KERN_INFO "i7core_edac: detected a " - "Nehalem/Nehalem-EP processor\n"); - rc = i7core_get_devices(pci_dev_descr_i7core, - ARRAY_SIZE(pci_dev_descr_i7core)); - } - + rc = i7core_get_devices(pci_dev_table); if (unlikely(rc < 0)) goto fail0; @@ -1994,7 +2037,7 @@ static int __init i7core_init(void) /* Ensure that the OPSTATE is set correctly for POLL or NMI */ opstate_init(); - i7core_xeon_pci_fixup(pci_dev_descr_i7core[0].dev_id); + i7core_xeon_pci_fixup(pci_dev_table); pci_rc = pci_register_driver(&i7core_driver); diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h index 46d76e985bac..413fab765a5f 100644 --- a/include/linux/pci_ids.h +++ b/include/linux/pci_ids.h @@ -2567,6 +2567,22 @@ #define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_ADDR 0x2ca9 #define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_RANK 0x2caa #define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_TC 0x2cab +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MCR_REV2 0x2d98 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TAD_REV2 0x2d99 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_RAS_REV2 0x2d9a +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_TEST_REV2 0x2d9c +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_CTRL_REV2 0x2da0 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_ADDR_REV2 0x2da1 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_RANK_REV2 0x2da2 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH0_TC_REV2 0x2da3 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_CTRL_REV2 0x2da8 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_ADDR_REV2 0x2da9 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_RANK_REV2 0x2daa +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH1_TC_REV2 0x2dab +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_CTRL_REV2 0x2db0 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_ADDR_REV2 0x2db1 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_RANK_REV2 0x2db2 +#define PCI_DEVICE_ID_INTEL_LYNNFIELD_MC_CH2_TC_REV2 0x2db3 #define PCI_DEVICE_ID_INTEL_82855PM_HB 0x3340 #define PCI_DEVICE_ID_INTEL_IOAT_TBG4 0x3429 #define PCI_DEVICE_ID_INTEL_IOAT_TBG5 0x342a -- cgit v1.2.3