aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-02-19 23:11:07 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2013-02-19 23:11:07 -0500
commitf98982ce80f9ce6db0fe841c1844cbae0a2700fb (patch)
tree9a6edd811b9b67a80b8a58b57c38dd69e68f6e03 /drivers/edac
parent29d50523298eb80742cedd9ec4d42d6d6dbfb5ee (diff)
parent7d0291256ca99cbb6124f63228003329e7a64b21 (diff)
Merge branch 'x86-platform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 platform changes from Ingo Molnar: - Support for the Technologic Systems TS-5500 platform, by Vivien Didelot - Improved NUMA support on AMD systems: Add support for federated systems where multiple memory controllers can exist and see each other over multiple PCI domains. This basically means that AMD node ids can be more than 8 now and the code handling this is taught to incorporate PCI domain into those IDs. - Support for the Goldfish virtual Android emulator, by Jun Nakajima, Intel, Google, et al. - Misc fixlets. * 'x86-platform-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: x86: Add TS-5500 platform support x86/srat: Simplify memory affinity init error handling x86/apb/timer: Remove unnecessary "if" goldfish: platform device for x86 amd64_edac: Fix type usage in NB IDs and memory ranges amd64_edac: Fix PCI function lookup x86, AMD, NB: Use u16 for northbridge IDs in amd_get_nb_id x86, AMD, NB: Add multi-domain support
Diffstat (limited to 'drivers/edac')
-rw-r--r--drivers/edac/amd64_edac.c109
-rw-r--r--drivers/edac/amd64_edac.h12
2 files changed, 60 insertions, 61 deletions
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c
index ad8bf2aa629d..2d3f8825e8b8 100644
--- a/drivers/edac/amd64_edac.c
+++ b/drivers/edac/amd64_edac.c
@@ -31,7 +31,7 @@ static struct ecc_settings **ecc_stngs;
31 * 31 *
32 *FIXME: Produce a better mapping/linearisation. 32 *FIXME: Produce a better mapping/linearisation.
33 */ 33 */
34struct scrubrate { 34static const struct scrubrate {
35 u32 scrubval; /* bit pattern for scrub rate */ 35 u32 scrubval; /* bit pattern for scrub rate */
36 u32 bandwidth; /* bandwidth consumed (bytes/sec) */ 36 u32 bandwidth; /* bandwidth consumed (bytes/sec) */
37} scrubrates[] = { 37} scrubrates[] = {
@@ -239,7 +239,7 @@ static int amd64_get_scrub_rate(struct mem_ctl_info *mci)
239 * DRAM base/limit associated with node_id 239 * DRAM base/limit associated with node_id
240 */ 240 */
241static bool amd64_base_limit_match(struct amd64_pvt *pvt, u64 sys_addr, 241static bool amd64_base_limit_match(struct amd64_pvt *pvt, u64 sys_addr,
242 unsigned nid) 242 u8 nid)
243{ 243{
244 u64 addr; 244 u64 addr;
245 245
@@ -265,7 +265,7 @@ static struct mem_ctl_info *find_mc_by_sys_addr(struct mem_ctl_info *mci,
265 u64 sys_addr) 265 u64 sys_addr)
266{ 266{
267 struct amd64_pvt *pvt; 267 struct amd64_pvt *pvt;
268 unsigned node_id; 268 u8 node_id;
269 u32 intlv_en, bits; 269 u32 intlv_en, bits;
270 270
271 /* 271 /*
@@ -939,7 +939,8 @@ static u64 get_error_address(struct mce *m)
939 struct amd64_pvt *pvt; 939 struct amd64_pvt *pvt;
940 u64 cc6_base, tmp_addr; 940 u64 cc6_base, tmp_addr;
941 u32 tmp; 941 u32 tmp;
942 u8 mce_nid, intlv_en; 942 u16 mce_nid;
943 u8 intlv_en;
943 944
944 if ((addr & GENMASK(24, 47)) >> 24 != 0x00fdf7) 945 if ((addr & GENMASK(24, 47)) >> 24 != 0x00fdf7)
945 return addr; 946 return addr;
@@ -979,10 +980,29 @@ static u64 get_error_address(struct mce *m)
979 return addr; 980 return addr;
980} 981}
981 982
983static struct pci_dev *pci_get_related_function(unsigned int vendor,
984 unsigned int device,
985 struct pci_dev *related)
986{
987 struct pci_dev *dev = NULL;
988
989 while ((dev = pci_get_device(vendor, device, dev))) {
990 if (pci_domain_nr(dev->bus) == pci_domain_nr(related->bus) &&
991 (dev->bus->number == related->bus->number) &&
992 (PCI_SLOT(dev->devfn) == PCI_SLOT(related->devfn)))
993 break;
994 }
995
996 return dev;
997}
998
982static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range) 999static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range)
983{ 1000{
1001 struct amd_northbridge *nb;
1002 struct pci_dev *misc, *f1 = NULL;
984 struct cpuinfo_x86 *c = &boot_cpu_data; 1003 struct cpuinfo_x86 *c = &boot_cpu_data;
985 int off = range << 3; 1004 int off = range << 3;
1005 u32 llim;
986 1006
987 amd64_read_pci_cfg(pvt->F1, DRAM_BASE_LO + off, &pvt->ranges[range].base.lo); 1007 amd64_read_pci_cfg(pvt->F1, DRAM_BASE_LO + off, &pvt->ranges[range].base.lo);
988 amd64_read_pci_cfg(pvt->F1, DRAM_LIMIT_LO + off, &pvt->ranges[range].lim.lo); 1008 amd64_read_pci_cfg(pvt->F1, DRAM_LIMIT_LO + off, &pvt->ranges[range].lim.lo);
@@ -996,30 +1016,32 @@ static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range)
996 amd64_read_pci_cfg(pvt->F1, DRAM_BASE_HI + off, &pvt->ranges[range].base.hi); 1016 amd64_read_pci_cfg(pvt->F1, DRAM_BASE_HI + off, &pvt->ranges[range].base.hi);
997 amd64_read_pci_cfg(pvt->F1, DRAM_LIMIT_HI + off, &pvt->ranges[range].lim.hi); 1017 amd64_read_pci_cfg(pvt->F1, DRAM_LIMIT_HI + off, &pvt->ranges[range].lim.hi);
998 1018
999 /* Factor in CC6 save area by reading dst node's limit reg */ 1019 /* F15h: factor in CC6 save area by reading dst node's limit reg */
1000 if (c->x86 == 0x15) { 1020 if (c->x86 != 0x15)
1001 struct pci_dev *f1 = NULL; 1021 return;
1002 u8 nid = dram_dst_node(pvt, range);
1003 u32 llim;
1004 1022
1005 f1 = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0x18 + nid, 1)); 1023 nb = node_to_amd_nb(dram_dst_node(pvt, range));
1006 if (WARN_ON(!f1)) 1024 if (WARN_ON(!nb))
1007 return; 1025 return;
1008 1026
1009 amd64_read_pci_cfg(f1, DRAM_LOCAL_NODE_LIM, &llim); 1027 misc = nb->misc;
1028 f1 = pci_get_related_function(misc->vendor, PCI_DEVICE_ID_AMD_15H_NB_F1, misc);
1029 if (WARN_ON(!f1))
1030 return;
1010 1031
1011 pvt->ranges[range].lim.lo &= GENMASK(0, 15); 1032 amd64_read_pci_cfg(f1, DRAM_LOCAL_NODE_LIM, &llim);
1012 1033
1013 /* {[39:27],111b} */ 1034 pvt->ranges[range].lim.lo &= GENMASK(0, 15);
1014 pvt->ranges[range].lim.lo |= ((llim & 0x1fff) << 3 | 0x7) << 16;
1015 1035
1016 pvt->ranges[range].lim.hi &= GENMASK(0, 7); 1036 /* {[39:27],111b} */
1037 pvt->ranges[range].lim.lo |= ((llim & 0x1fff) << 3 | 0x7) << 16;
1017 1038
1018 /* [47:40] */ 1039 pvt->ranges[range].lim.hi &= GENMASK(0, 7);
1019 pvt->ranges[range].lim.hi |= llim >> 13;
1020 1040
1021 pci_dev_put(f1); 1041 /* [47:40] */
1022 } 1042 pvt->ranges[range].lim.hi |= llim >> 13;
1043
1044 pci_dev_put(f1);
1023} 1045}
1024 1046
1025static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, 1047static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr,
@@ -1305,7 +1327,7 @@ static u8 f1x_determine_channel(struct amd64_pvt *pvt, u64 sys_addr,
1305} 1327}
1306 1328
1307/* Convert the sys_addr to the normalized DCT address */ 1329/* Convert the sys_addr to the normalized DCT address */
1308static u64 f1x_get_norm_dct_addr(struct amd64_pvt *pvt, unsigned range, 1330static u64 f1x_get_norm_dct_addr(struct amd64_pvt *pvt, u8 range,
1309 u64 sys_addr, bool hi_rng, 1331 u64 sys_addr, bool hi_rng,
1310 u32 dct_sel_base_addr) 1332 u32 dct_sel_base_addr)
1311{ 1333{
@@ -1381,7 +1403,7 @@ static int f10_process_possible_spare(struct amd64_pvt *pvt, u8 dct, int csrow)
1381 * -EINVAL: NOT FOUND 1403 * -EINVAL: NOT FOUND
1382 * 0..csrow = Chip-Select Row 1404 * 0..csrow = Chip-Select Row
1383 */ 1405 */
1384static int f1x_lookup_addr_in_dct(u64 in_addr, u32 nid, u8 dct) 1406static int f1x_lookup_addr_in_dct(u64 in_addr, u8 nid, u8 dct)
1385{ 1407{
1386 struct mem_ctl_info *mci; 1408 struct mem_ctl_info *mci;
1387 struct amd64_pvt *pvt; 1409 struct amd64_pvt *pvt;
@@ -1672,23 +1694,6 @@ static struct amd64_family_type amd64_family_types[] = {
1672 }, 1694 },
1673}; 1695};
1674 1696
1675static struct pci_dev *pci_get_related_function(unsigned int vendor,
1676 unsigned int device,
1677 struct pci_dev *related)
1678{
1679 struct pci_dev *dev = NULL;
1680
1681 dev = pci_get_device(vendor, device, dev);
1682 while (dev) {
1683 if ((dev->bus->number == related->bus->number) &&
1684 (PCI_SLOT(dev->devfn) == PCI_SLOT(related->devfn)))
1685 break;
1686 dev = pci_get_device(vendor, device, dev);
1687 }
1688
1689 return dev;
1690}
1691
1692/* 1697/*
1693 * These are tables of eigenvectors (one per line) which can be used for the 1698 * These are tables of eigenvectors (one per line) which can be used for the
1694 * construction of the syndrome tables. The modified syndrome search algorithm 1699 * construction of the syndrome tables. The modified syndrome search algorithm
@@ -1696,7 +1701,7 @@ static struct pci_dev *pci_get_related_function(unsigned int vendor,
1696 * 1701 *
1697 * Algorithm courtesy of Ross LaFetra from AMD. 1702 * Algorithm courtesy of Ross LaFetra from AMD.
1698 */ 1703 */
1699static u16 x4_vectors[] = { 1704static const u16 x4_vectors[] = {
1700 0x2f57, 0x1afe, 0x66cc, 0xdd88, 1705 0x2f57, 0x1afe, 0x66cc, 0xdd88,
1701 0x11eb, 0x3396, 0x7f4c, 0xeac8, 1706 0x11eb, 0x3396, 0x7f4c, 0xeac8,
1702 0x0001, 0x0002, 0x0004, 0x0008, 1707 0x0001, 0x0002, 0x0004, 0x0008,
@@ -1735,7 +1740,7 @@ static u16 x4_vectors[] = {
1735 0x19a9, 0x2efe, 0xb5cc, 0x6f88, 1740 0x19a9, 0x2efe, 0xb5cc, 0x6f88,
1736}; 1741};
1737 1742
1738static u16 x8_vectors[] = { 1743static const u16 x8_vectors[] = {
1739 0x0145, 0x028a, 0x2374, 0x43c8, 0xa1f0, 0x0520, 0x0a40, 0x1480, 1744 0x0145, 0x028a, 0x2374, 0x43c8, 0xa1f0, 0x0520, 0x0a40, 0x1480,
1740 0x0211, 0x0422, 0x0844, 0x1088, 0x01b0, 0x44e0, 0x23c0, 0xed80, 1745 0x0211, 0x0422, 0x0844, 0x1088, 0x01b0, 0x44e0, 0x23c0, 0xed80,
1741 0x1011, 0x0116, 0x022c, 0x0458, 0x08b0, 0x8c60, 0x2740, 0x4e80, 1746 0x1011, 0x0116, 0x022c, 0x0458, 0x08b0, 0x8c60, 0x2740, 0x4e80,
@@ -1757,7 +1762,7 @@ static u16 x8_vectors[] = {
1757 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, 1762 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000,
1758}; 1763};
1759 1764
1760static int decode_syndrome(u16 syndrome, u16 *vectors, unsigned num_vecs, 1765static int decode_syndrome(u16 syndrome, const u16 *vectors, unsigned num_vecs,
1761 unsigned v_dim) 1766 unsigned v_dim)
1762{ 1767{
1763 unsigned int i, err_sym; 1768 unsigned int i, err_sym;
@@ -2181,7 +2186,7 @@ static int init_csrows(struct mem_ctl_info *mci)
2181} 2186}
2182 2187
2183/* get all cores on this DCT */ 2188/* get all cores on this DCT */
2184static void get_cpus_on_this_dct_cpumask(struct cpumask *mask, unsigned nid) 2189static void get_cpus_on_this_dct_cpumask(struct cpumask *mask, u16 nid)
2185{ 2190{
2186 int cpu; 2191 int cpu;
2187 2192
@@ -2191,7 +2196,7 @@ static void get_cpus_on_this_dct_cpumask(struct cpumask *mask, unsigned nid)
2191} 2196}
2192 2197
2193/* check MCG_CTL on all the cpus on this node */ 2198/* check MCG_CTL on all the cpus on this node */
2194static bool amd64_nb_mce_bank_enabled_on_node(unsigned nid) 2199static bool amd64_nb_mce_bank_enabled_on_node(u16 nid)
2195{ 2200{
2196 cpumask_var_t mask; 2201 cpumask_var_t mask;
2197 int cpu, nbe; 2202 int cpu, nbe;
@@ -2224,7 +2229,7 @@ out:
2224 return ret; 2229 return ret;
2225} 2230}
2226 2231
2227static int toggle_ecc_err_reporting(struct ecc_settings *s, u8 nid, bool on) 2232static int toggle_ecc_err_reporting(struct ecc_settings *s, u16 nid, bool on)
2228{ 2233{
2229 cpumask_var_t cmask; 2234 cpumask_var_t cmask;
2230 int cpu; 2235 int cpu;
@@ -2262,7 +2267,7 @@ static int toggle_ecc_err_reporting(struct ecc_settings *s, u8 nid, bool on)
2262 return 0; 2267 return 0;
2263} 2268}
2264 2269
2265static bool enable_ecc_error_reporting(struct ecc_settings *s, u8 nid, 2270static bool enable_ecc_error_reporting(struct ecc_settings *s, u16 nid,
2266 struct pci_dev *F3) 2271 struct pci_dev *F3)
2267{ 2272{
2268 bool ret = true; 2273 bool ret = true;
@@ -2314,7 +2319,7 @@ static bool enable_ecc_error_reporting(struct ecc_settings *s, u8 nid,
2314 return ret; 2319 return ret;
2315} 2320}
2316 2321
2317static void restore_ecc_error_reporting(struct ecc_settings *s, u8 nid, 2322static void restore_ecc_error_reporting(struct ecc_settings *s, u16 nid,
2318 struct pci_dev *F3) 2323 struct pci_dev *F3)
2319{ 2324{
2320 u32 value, mask = 0x3; /* UECC/CECC enable */ 2325 u32 value, mask = 0x3; /* UECC/CECC enable */
@@ -2353,7 +2358,7 @@ static const char *ecc_msg =
2353 "'ecc_enable_override'.\n" 2358 "'ecc_enable_override'.\n"
2354 " (Note that use of the override may cause unknown side effects.)\n"; 2359 " (Note that use of the override may cause unknown side effects.)\n";
2355 2360
2356static bool ecc_enabled(struct pci_dev *F3, u8 nid) 2361static bool ecc_enabled(struct pci_dev *F3, u16 nid)
2357{ 2362{
2358 u32 value; 2363 u32 value;
2359 u8 ecc_en = 0; 2364 u8 ecc_en = 0;
@@ -2474,7 +2479,7 @@ static int amd64_init_one_instance(struct pci_dev *F2)
2474 struct mem_ctl_info *mci = NULL; 2479 struct mem_ctl_info *mci = NULL;
2475 struct edac_mc_layer layers[2]; 2480 struct edac_mc_layer layers[2];
2476 int err = 0, ret; 2481 int err = 0, ret;
2477 u8 nid = get_node_id(F2); 2482 u16 nid = amd_get_node_id(F2);
2478 2483
2479 ret = -ENOMEM; 2484 ret = -ENOMEM;
2480 pvt = kzalloc(sizeof(struct amd64_pvt), GFP_KERNEL); 2485 pvt = kzalloc(sizeof(struct amd64_pvt), GFP_KERNEL);
@@ -2566,7 +2571,7 @@ err_ret:
2566static int amd64_probe_one_instance(struct pci_dev *pdev, 2571static int amd64_probe_one_instance(struct pci_dev *pdev,
2567 const struct pci_device_id *mc_type) 2572 const struct pci_device_id *mc_type)
2568{ 2573{
2569 u8 nid = get_node_id(pdev); 2574 u16 nid = amd_get_node_id(pdev);
2570 struct pci_dev *F3 = node_to_amd_nb(nid)->misc; 2575 struct pci_dev *F3 = node_to_amd_nb(nid)->misc;
2571 struct ecc_settings *s; 2576 struct ecc_settings *s;
2572 int ret = 0; 2577 int ret = 0;
@@ -2616,7 +2621,7 @@ static void amd64_remove_one_instance(struct pci_dev *pdev)
2616{ 2621{
2617 struct mem_ctl_info *mci; 2622 struct mem_ctl_info *mci;
2618 struct amd64_pvt *pvt; 2623 struct amd64_pvt *pvt;
2619 u8 nid = get_node_id(pdev); 2624 u16 nid = amd_get_node_id(pdev);
2620 struct pci_dev *F3 = node_to_amd_nb(nid)->misc; 2625 struct pci_dev *F3 = node_to_amd_nb(nid)->misc;
2621 struct ecc_settings *s = ecc_stngs[nid]; 2626 struct ecc_settings *s = ecc_stngs[nid];
2622 2627
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h
index e864f407806c..35637d83f235 100644
--- a/drivers/edac/amd64_edac.h
+++ b/drivers/edac/amd64_edac.h
@@ -292,12 +292,6 @@
292/* MSRs */ 292/* MSRs */
293#define MSR_MCGCTL_NBE BIT(4) 293#define MSR_MCGCTL_NBE BIT(4)
294 294
295/* AMD sets the first MC device at device ID 0x18. */
296static inline u8 get_node_id(struct pci_dev *pdev)
297{
298 return PCI_SLOT(pdev->devfn) - 0x18;
299}
300
301enum amd_families { 295enum amd_families {
302 K8_CPUS = 0, 296 K8_CPUS = 0,
303 F10_CPUS, 297 F10_CPUS,
@@ -340,7 +334,7 @@ struct amd64_pvt {
340 /* pci_device handles which we utilize */ 334 /* pci_device handles which we utilize */
341 struct pci_dev *F1, *F2, *F3; 335 struct pci_dev *F1, *F2, *F3;
342 336
343 unsigned mc_node_id; /* MC index of this MC node */ 337 u16 mc_node_id; /* MC index of this MC node */
344 int ext_model; /* extended model value of this node */ 338 int ext_model; /* extended model value of this node */
345 int channel_count; 339 int channel_count;
346 340
@@ -393,7 +387,7 @@ struct err_info {
393 u32 offset; 387 u32 offset;
394}; 388};
395 389
396static inline u64 get_dram_base(struct amd64_pvt *pvt, unsigned i) 390static inline u64 get_dram_base(struct amd64_pvt *pvt, u8 i)
397{ 391{
398 u64 addr = ((u64)pvt->ranges[i].base.lo & 0xffff0000) << 8; 392 u64 addr = ((u64)pvt->ranges[i].base.lo & 0xffff0000) << 8;
399 393
@@ -403,7 +397,7 @@ static inline u64 get_dram_base(struct amd64_pvt *pvt, unsigned i)
403 return (((u64)pvt->ranges[i].base.hi & 0x000000ff) << 40) | addr; 397 return (((u64)pvt->ranges[i].base.hi & 0x000000ff) << 40) | addr;
404} 398}
405 399
406static inline u64 get_dram_limit(struct amd64_pvt *pvt, unsigned i) 400static inline u64 get_dram_limit(struct amd64_pvt *pvt, u8 i)
407{ 401{
408 u64 lim = (((u64)pvt->ranges[i].lim.lo & 0xffff0000) << 8) | 0x00ffffff; 402 u64 lim = (((u64)pvt->ranges[i].lim.lo & 0xffff0000) << 8) | 0x00ffffff;
409 403