diff options
Diffstat (limited to 'drivers/edac')
-rw-r--r-- | drivers/edac/Kconfig | 4 | ||||
-rw-r--r-- | drivers/edac/amd64_edac.c | 214 | ||||
-rw-r--r-- | drivers/edac/amd64_edac.h | 12 | ||||
-rw-r--r-- | drivers/edac/mce_amd.c | 166 | ||||
-rw-r--r-- | drivers/edac/mce_amd.h | 13 | ||||
-rw-r--r-- | drivers/edac/mpc85xx_edac.c | 4 |
6 files changed, 182 insertions, 231 deletions
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 7e38e5e576e8..e443f2c1dfd1 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig | |||
@@ -181,7 +181,7 @@ config EDAC_I3000 | |||
181 | 181 | ||
182 | config EDAC_I3200 | 182 | config EDAC_I3200 |
183 | tristate "Intel 3200" | 183 | tristate "Intel 3200" |
184 | depends on EDAC_MM_EDAC && PCI && X86 && EXPERIMENTAL | 184 | depends on EDAC_MM_EDAC && PCI && X86 |
185 | help | 185 | help |
186 | Support for error detection and correction on the Intel | 186 | Support for error detection and correction on the Intel |
187 | 3200 and 3210 server chipsets. | 187 | 3200 and 3210 server chipsets. |
@@ -247,7 +247,7 @@ config EDAC_I7300 | |||
247 | config EDAC_SBRIDGE | 247 | config EDAC_SBRIDGE |
248 | tristate "Intel Sandy-Bridge Integrated MC" | 248 | tristate "Intel Sandy-Bridge Integrated MC" |
249 | depends on EDAC_MM_EDAC && PCI && X86_64 && X86_MCE_INTEL | 249 | depends on EDAC_MM_EDAC && PCI && X86_64 && X86_MCE_INTEL |
250 | depends on PCI_MMCONFIG && EXPERIMENTAL | 250 | depends on PCI_MMCONFIG |
251 | help | 251 | help |
252 | Support for error detection and correction the Intel | 252 | Support for error detection and correction the Intel |
253 | Sandy Bridge Integrated Memory Controller. | 253 | Sandy Bridge Integrated Memory Controller. |
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index ad8bf2aa629d..910b0116c128 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 | */ |
34 | struct scrubrate { | 34 | static 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 | */ |
241 | static bool amd64_base_limit_match(struct amd64_pvt *pvt, u64 sys_addr, | 241 | static 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 | /* |
@@ -602,111 +602,6 @@ static u64 sys_addr_to_input_addr(struct mem_ctl_info *mci, u64 sys_addr) | |||
602 | return input_addr; | 602 | return input_addr; |
603 | } | 603 | } |
604 | 604 | ||
605 | |||
606 | /* | ||
607 | * @input_addr is an InputAddr associated with the node represented by mci. | ||
608 | * Translate @input_addr to a DramAddr and return the result. | ||
609 | */ | ||
610 | static u64 input_addr_to_dram_addr(struct mem_ctl_info *mci, u64 input_addr) | ||
611 | { | ||
612 | struct amd64_pvt *pvt; | ||
613 | unsigned node_id, intlv_shift; | ||
614 | u64 bits, dram_addr; | ||
615 | u32 intlv_sel; | ||
616 | |||
617 | /* | ||
618 | * Near the start of section 3.4.4 (p. 70, BKDG #26094, K8, revA-E) | ||
619 | * shows how to translate a DramAddr to an InputAddr. Here we reverse | ||
620 | * this procedure. When translating from a DramAddr to an InputAddr, the | ||
621 | * bits used for node interleaving are discarded. Here we recover these | ||
622 | * bits from the IntlvSel field of the DRAM Limit register (section | ||
623 | * 3.4.4.2) for the node that input_addr is associated with. | ||
624 | */ | ||
625 | pvt = mci->pvt_info; | ||
626 | node_id = pvt->mc_node_id; | ||
627 | |||
628 | BUG_ON(node_id > 7); | ||
629 | |||
630 | intlv_shift = num_node_interleave_bits(dram_intlv_en(pvt, 0)); | ||
631 | if (intlv_shift == 0) { | ||
632 | edac_dbg(1, " InputAddr 0x%lx translates to DramAddr of same value\n", | ||
633 | (unsigned long)input_addr); | ||
634 | |||
635 | return input_addr; | ||
636 | } | ||
637 | |||
638 | bits = ((input_addr & GENMASK(12, 35)) << intlv_shift) + | ||
639 | (input_addr & 0xfff); | ||
640 | |||
641 | intlv_sel = dram_intlv_sel(pvt, node_id) & ((1 << intlv_shift) - 1); | ||
642 | dram_addr = bits + (intlv_sel << 12); | ||
643 | |||
644 | edac_dbg(1, "InputAddr 0x%lx translates to DramAddr 0x%lx (%d node interleave bits)\n", | ||
645 | (unsigned long)input_addr, | ||
646 | (unsigned long)dram_addr, intlv_shift); | ||
647 | |||
648 | return dram_addr; | ||
649 | } | ||
650 | |||
651 | /* | ||
652 | * @dram_addr is a DramAddr that maps to the node represented by mci. Convert | ||
653 | * @dram_addr to a SysAddr. | ||
654 | */ | ||
655 | static u64 dram_addr_to_sys_addr(struct mem_ctl_info *mci, u64 dram_addr) | ||
656 | { | ||
657 | struct amd64_pvt *pvt = mci->pvt_info; | ||
658 | u64 hole_base, hole_offset, hole_size, base, sys_addr; | ||
659 | int ret = 0; | ||
660 | |||
661 | ret = amd64_get_dram_hole_info(mci, &hole_base, &hole_offset, | ||
662 | &hole_size); | ||
663 | if (!ret) { | ||
664 | if ((dram_addr >= hole_base) && | ||
665 | (dram_addr < (hole_base + hole_size))) { | ||
666 | sys_addr = dram_addr + hole_offset; | ||
667 | |||
668 | edac_dbg(1, "using DHAR to translate DramAddr 0x%lx to SysAddr 0x%lx\n", | ||
669 | (unsigned long)dram_addr, | ||
670 | (unsigned long)sys_addr); | ||
671 | |||
672 | return sys_addr; | ||
673 | } | ||
674 | } | ||
675 | |||
676 | base = get_dram_base(pvt, pvt->mc_node_id); | ||
677 | sys_addr = dram_addr + base; | ||
678 | |||
679 | /* | ||
680 | * The sys_addr we have computed up to this point is a 40-bit value | ||
681 | * because the k8 deals with 40-bit values. However, the value we are | ||
682 | * supposed to return is a full 64-bit physical address. The AMD | ||
683 | * x86-64 architecture specifies that the most significant implemented | ||
684 | * address bit through bit 63 of a physical address must be either all | ||
685 | * 0s or all 1s. Therefore we sign-extend the 40-bit sys_addr to a | ||
686 | * 64-bit value below. See section 3.4.2 of AMD publication 24592: | ||
687 | * AMD x86-64 Architecture Programmer's Manual Volume 1 Application | ||
688 | * Programming. | ||
689 | */ | ||
690 | sys_addr |= ~((sys_addr & (1ull << 39)) - 1); | ||
691 | |||
692 | edac_dbg(1, " Node %d, DramAddr 0x%lx to SysAddr 0x%lx\n", | ||
693 | pvt->mc_node_id, (unsigned long)dram_addr, | ||
694 | (unsigned long)sys_addr); | ||
695 | |||
696 | return sys_addr; | ||
697 | } | ||
698 | |||
699 | /* | ||
700 | * @input_addr is an InputAddr associated with the node given by mci. Translate | ||
701 | * @input_addr to a SysAddr. | ||
702 | */ | ||
703 | static inline u64 input_addr_to_sys_addr(struct mem_ctl_info *mci, | ||
704 | u64 input_addr) | ||
705 | { | ||
706 | return dram_addr_to_sys_addr(mci, | ||
707 | input_addr_to_dram_addr(mci, input_addr)); | ||
708 | } | ||
709 | |||
710 | /* Map the Error address to a PAGE and PAGE OFFSET. */ | 605 | /* Map the Error address to a PAGE and PAGE OFFSET. */ |
711 | static inline void error_address_to_page_and_offset(u64 error_address, | 606 | static inline void error_address_to_page_and_offset(u64 error_address, |
712 | struct err_info *err) | 607 | struct err_info *err) |
@@ -939,7 +834,8 @@ static u64 get_error_address(struct mce *m) | |||
939 | struct amd64_pvt *pvt; | 834 | struct amd64_pvt *pvt; |
940 | u64 cc6_base, tmp_addr; | 835 | u64 cc6_base, tmp_addr; |
941 | u32 tmp; | 836 | u32 tmp; |
942 | u8 mce_nid, intlv_en; | 837 | u16 mce_nid; |
838 | u8 intlv_en; | ||
943 | 839 | ||
944 | if ((addr & GENMASK(24, 47)) >> 24 != 0x00fdf7) | 840 | if ((addr & GENMASK(24, 47)) >> 24 != 0x00fdf7) |
945 | return addr; | 841 | return addr; |
@@ -979,10 +875,29 @@ static u64 get_error_address(struct mce *m) | |||
979 | return addr; | 875 | return addr; |
980 | } | 876 | } |
981 | 877 | ||
878 | static struct pci_dev *pci_get_related_function(unsigned int vendor, | ||
879 | unsigned int device, | ||
880 | struct pci_dev *related) | ||
881 | { | ||
882 | struct pci_dev *dev = NULL; | ||
883 | |||
884 | while ((dev = pci_get_device(vendor, device, dev))) { | ||
885 | if (pci_domain_nr(dev->bus) == pci_domain_nr(related->bus) && | ||
886 | (dev->bus->number == related->bus->number) && | ||
887 | (PCI_SLOT(dev->devfn) == PCI_SLOT(related->devfn))) | ||
888 | break; | ||
889 | } | ||
890 | |||
891 | return dev; | ||
892 | } | ||
893 | |||
982 | static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range) | 894 | static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range) |
983 | { | 895 | { |
896 | struct amd_northbridge *nb; | ||
897 | struct pci_dev *misc, *f1 = NULL; | ||
984 | struct cpuinfo_x86 *c = &boot_cpu_data; | 898 | struct cpuinfo_x86 *c = &boot_cpu_data; |
985 | int off = range << 3; | 899 | int off = range << 3; |
900 | u32 llim; | ||
986 | 901 | ||
987 | amd64_read_pci_cfg(pvt->F1, DRAM_BASE_LO + off, &pvt->ranges[range].base.lo); | 902 | 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); | 903 | amd64_read_pci_cfg(pvt->F1, DRAM_LIMIT_LO + off, &pvt->ranges[range].lim.lo); |
@@ -996,30 +911,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); | 911 | 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); | 912 | amd64_read_pci_cfg(pvt->F1, DRAM_LIMIT_HI + off, &pvt->ranges[range].lim.hi); |
998 | 913 | ||
999 | /* Factor in CC6 save area by reading dst node's limit reg */ | 914 | /* F15h: factor in CC6 save area by reading dst node's limit reg */ |
1000 | if (c->x86 == 0x15) { | 915 | if (c->x86 != 0x15) |
1001 | struct pci_dev *f1 = NULL; | 916 | return; |
1002 | u8 nid = dram_dst_node(pvt, range); | ||
1003 | u32 llim; | ||
1004 | 917 | ||
1005 | f1 = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0x18 + nid, 1)); | 918 | nb = node_to_amd_nb(dram_dst_node(pvt, range)); |
1006 | if (WARN_ON(!f1)) | 919 | if (WARN_ON(!nb)) |
1007 | return; | 920 | return; |
921 | |||
922 | misc = nb->misc; | ||
923 | f1 = pci_get_related_function(misc->vendor, PCI_DEVICE_ID_AMD_15H_NB_F1, misc); | ||
924 | if (WARN_ON(!f1)) | ||
925 | return; | ||
1008 | 926 | ||
1009 | amd64_read_pci_cfg(f1, DRAM_LOCAL_NODE_LIM, &llim); | 927 | amd64_read_pci_cfg(f1, DRAM_LOCAL_NODE_LIM, &llim); |
1010 | 928 | ||
1011 | pvt->ranges[range].lim.lo &= GENMASK(0, 15); | 929 | pvt->ranges[range].lim.lo &= GENMASK(0, 15); |
1012 | 930 | ||
1013 | /* {[39:27],111b} */ | 931 | /* {[39:27],111b} */ |
1014 | pvt->ranges[range].lim.lo |= ((llim & 0x1fff) << 3 | 0x7) << 16; | 932 | pvt->ranges[range].lim.lo |= ((llim & 0x1fff) << 3 | 0x7) << 16; |
1015 | 933 | ||
1016 | pvt->ranges[range].lim.hi &= GENMASK(0, 7); | 934 | pvt->ranges[range].lim.hi &= GENMASK(0, 7); |
1017 | 935 | ||
1018 | /* [47:40] */ | 936 | /* [47:40] */ |
1019 | pvt->ranges[range].lim.hi |= llim >> 13; | 937 | pvt->ranges[range].lim.hi |= llim >> 13; |
1020 | 938 | ||
1021 | pci_dev_put(f1); | 939 | pci_dev_put(f1); |
1022 | } | ||
1023 | } | 940 | } |
1024 | 941 | ||
1025 | static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, | 942 | static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, |
@@ -1305,7 +1222,7 @@ static u8 f1x_determine_channel(struct amd64_pvt *pvt, u64 sys_addr, | |||
1305 | } | 1222 | } |
1306 | 1223 | ||
1307 | /* Convert the sys_addr to the normalized DCT address */ | 1224 | /* Convert the sys_addr to the normalized DCT address */ |
1308 | static u64 f1x_get_norm_dct_addr(struct amd64_pvt *pvt, unsigned range, | 1225 | static u64 f1x_get_norm_dct_addr(struct amd64_pvt *pvt, u8 range, |
1309 | u64 sys_addr, bool hi_rng, | 1226 | u64 sys_addr, bool hi_rng, |
1310 | u32 dct_sel_base_addr) | 1227 | u32 dct_sel_base_addr) |
1311 | { | 1228 | { |
@@ -1381,7 +1298,7 @@ static int f10_process_possible_spare(struct amd64_pvt *pvt, u8 dct, int csrow) | |||
1381 | * -EINVAL: NOT FOUND | 1298 | * -EINVAL: NOT FOUND |
1382 | * 0..csrow = Chip-Select Row | 1299 | * 0..csrow = Chip-Select Row |
1383 | */ | 1300 | */ |
1384 | static int f1x_lookup_addr_in_dct(u64 in_addr, u32 nid, u8 dct) | 1301 | static int f1x_lookup_addr_in_dct(u64 in_addr, u8 nid, u8 dct) |
1385 | { | 1302 | { |
1386 | struct mem_ctl_info *mci; | 1303 | struct mem_ctl_info *mci; |
1387 | struct amd64_pvt *pvt; | 1304 | struct amd64_pvt *pvt; |
@@ -1672,23 +1589,6 @@ static struct amd64_family_type amd64_family_types[] = { | |||
1672 | }, | 1589 | }, |
1673 | }; | 1590 | }; |
1674 | 1591 | ||
1675 | static 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 | /* | 1592 | /* |
1693 | * These are tables of eigenvectors (one per line) which can be used for the | 1593 | * 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 | 1594 | * construction of the syndrome tables. The modified syndrome search algorithm |
@@ -1696,7 +1596,7 @@ static struct pci_dev *pci_get_related_function(unsigned int vendor, | |||
1696 | * | 1596 | * |
1697 | * Algorithm courtesy of Ross LaFetra from AMD. | 1597 | * Algorithm courtesy of Ross LaFetra from AMD. |
1698 | */ | 1598 | */ |
1699 | static u16 x4_vectors[] = { | 1599 | static const u16 x4_vectors[] = { |
1700 | 0x2f57, 0x1afe, 0x66cc, 0xdd88, | 1600 | 0x2f57, 0x1afe, 0x66cc, 0xdd88, |
1701 | 0x11eb, 0x3396, 0x7f4c, 0xeac8, | 1601 | 0x11eb, 0x3396, 0x7f4c, 0xeac8, |
1702 | 0x0001, 0x0002, 0x0004, 0x0008, | 1602 | 0x0001, 0x0002, 0x0004, 0x0008, |
@@ -1735,7 +1635,7 @@ static u16 x4_vectors[] = { | |||
1735 | 0x19a9, 0x2efe, 0xb5cc, 0x6f88, | 1635 | 0x19a9, 0x2efe, 0xb5cc, 0x6f88, |
1736 | }; | 1636 | }; |
1737 | 1637 | ||
1738 | static u16 x8_vectors[] = { | 1638 | static const u16 x8_vectors[] = { |
1739 | 0x0145, 0x028a, 0x2374, 0x43c8, 0xa1f0, 0x0520, 0x0a40, 0x1480, | 1639 | 0x0145, 0x028a, 0x2374, 0x43c8, 0xa1f0, 0x0520, 0x0a40, 0x1480, |
1740 | 0x0211, 0x0422, 0x0844, 0x1088, 0x01b0, 0x44e0, 0x23c0, 0xed80, | 1640 | 0x0211, 0x0422, 0x0844, 0x1088, 0x01b0, 0x44e0, 0x23c0, 0xed80, |
1741 | 0x1011, 0x0116, 0x022c, 0x0458, 0x08b0, 0x8c60, 0x2740, 0x4e80, | 1641 | 0x1011, 0x0116, 0x022c, 0x0458, 0x08b0, 0x8c60, 0x2740, 0x4e80, |
@@ -1757,7 +1657,7 @@ static u16 x8_vectors[] = { | |||
1757 | 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, | 1657 | 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000, |
1758 | }; | 1658 | }; |
1759 | 1659 | ||
1760 | static int decode_syndrome(u16 syndrome, u16 *vectors, unsigned num_vecs, | 1660 | static int decode_syndrome(u16 syndrome, const u16 *vectors, unsigned num_vecs, |
1761 | unsigned v_dim) | 1661 | unsigned v_dim) |
1762 | { | 1662 | { |
1763 | unsigned int i, err_sym; | 1663 | unsigned int i, err_sym; |
@@ -2181,7 +2081,7 @@ static int init_csrows(struct mem_ctl_info *mci) | |||
2181 | } | 2081 | } |
2182 | 2082 | ||
2183 | /* get all cores on this DCT */ | 2083 | /* get all cores on this DCT */ |
2184 | static void get_cpus_on_this_dct_cpumask(struct cpumask *mask, unsigned nid) | 2084 | static void get_cpus_on_this_dct_cpumask(struct cpumask *mask, u16 nid) |
2185 | { | 2085 | { |
2186 | int cpu; | 2086 | int cpu; |
2187 | 2087 | ||
@@ -2191,7 +2091,7 @@ static void get_cpus_on_this_dct_cpumask(struct cpumask *mask, unsigned nid) | |||
2191 | } | 2091 | } |
2192 | 2092 | ||
2193 | /* check MCG_CTL on all the cpus on this node */ | 2093 | /* check MCG_CTL on all the cpus on this node */ |
2194 | static bool amd64_nb_mce_bank_enabled_on_node(unsigned nid) | 2094 | static bool amd64_nb_mce_bank_enabled_on_node(u16 nid) |
2195 | { | 2095 | { |
2196 | cpumask_var_t mask; | 2096 | cpumask_var_t mask; |
2197 | int cpu, nbe; | 2097 | int cpu, nbe; |
@@ -2224,7 +2124,7 @@ out: | |||
2224 | return ret; | 2124 | return ret; |
2225 | } | 2125 | } |
2226 | 2126 | ||
2227 | static int toggle_ecc_err_reporting(struct ecc_settings *s, u8 nid, bool on) | 2127 | static int toggle_ecc_err_reporting(struct ecc_settings *s, u16 nid, bool on) |
2228 | { | 2128 | { |
2229 | cpumask_var_t cmask; | 2129 | cpumask_var_t cmask; |
2230 | int cpu; | 2130 | int cpu; |
@@ -2262,7 +2162,7 @@ static int toggle_ecc_err_reporting(struct ecc_settings *s, u8 nid, bool on) | |||
2262 | return 0; | 2162 | return 0; |
2263 | } | 2163 | } |
2264 | 2164 | ||
2265 | static bool enable_ecc_error_reporting(struct ecc_settings *s, u8 nid, | 2165 | static bool enable_ecc_error_reporting(struct ecc_settings *s, u16 nid, |
2266 | struct pci_dev *F3) | 2166 | struct pci_dev *F3) |
2267 | { | 2167 | { |
2268 | bool ret = true; | 2168 | bool ret = true; |
@@ -2314,7 +2214,7 @@ static bool enable_ecc_error_reporting(struct ecc_settings *s, u8 nid, | |||
2314 | return ret; | 2214 | return ret; |
2315 | } | 2215 | } |
2316 | 2216 | ||
2317 | static void restore_ecc_error_reporting(struct ecc_settings *s, u8 nid, | 2217 | static void restore_ecc_error_reporting(struct ecc_settings *s, u16 nid, |
2318 | struct pci_dev *F3) | 2218 | struct pci_dev *F3) |
2319 | { | 2219 | { |
2320 | u32 value, mask = 0x3; /* UECC/CECC enable */ | 2220 | u32 value, mask = 0x3; /* UECC/CECC enable */ |
@@ -2353,7 +2253,7 @@ static const char *ecc_msg = | |||
2353 | "'ecc_enable_override'.\n" | 2253 | "'ecc_enable_override'.\n" |
2354 | " (Note that use of the override may cause unknown side effects.)\n"; | 2254 | " (Note that use of the override may cause unknown side effects.)\n"; |
2355 | 2255 | ||
2356 | static bool ecc_enabled(struct pci_dev *F3, u8 nid) | 2256 | static bool ecc_enabled(struct pci_dev *F3, u16 nid) |
2357 | { | 2257 | { |
2358 | u32 value; | 2258 | u32 value; |
2359 | u8 ecc_en = 0; | 2259 | u8 ecc_en = 0; |
@@ -2474,7 +2374,7 @@ static int amd64_init_one_instance(struct pci_dev *F2) | |||
2474 | struct mem_ctl_info *mci = NULL; | 2374 | struct mem_ctl_info *mci = NULL; |
2475 | struct edac_mc_layer layers[2]; | 2375 | struct edac_mc_layer layers[2]; |
2476 | int err = 0, ret; | 2376 | int err = 0, ret; |
2477 | u8 nid = get_node_id(F2); | 2377 | u16 nid = amd_get_node_id(F2); |
2478 | 2378 | ||
2479 | ret = -ENOMEM; | 2379 | ret = -ENOMEM; |
2480 | pvt = kzalloc(sizeof(struct amd64_pvt), GFP_KERNEL); | 2380 | pvt = kzalloc(sizeof(struct amd64_pvt), GFP_KERNEL); |
@@ -2566,7 +2466,7 @@ err_ret: | |||
2566 | static int amd64_probe_one_instance(struct pci_dev *pdev, | 2466 | static int amd64_probe_one_instance(struct pci_dev *pdev, |
2567 | const struct pci_device_id *mc_type) | 2467 | const struct pci_device_id *mc_type) |
2568 | { | 2468 | { |
2569 | u8 nid = get_node_id(pdev); | 2469 | u16 nid = amd_get_node_id(pdev); |
2570 | struct pci_dev *F3 = node_to_amd_nb(nid)->misc; | 2470 | struct pci_dev *F3 = node_to_amd_nb(nid)->misc; |
2571 | struct ecc_settings *s; | 2471 | struct ecc_settings *s; |
2572 | int ret = 0; | 2472 | int ret = 0; |
@@ -2616,7 +2516,7 @@ static void amd64_remove_one_instance(struct pci_dev *pdev) | |||
2616 | { | 2516 | { |
2617 | struct mem_ctl_info *mci; | 2517 | struct mem_ctl_info *mci; |
2618 | struct amd64_pvt *pvt; | 2518 | struct amd64_pvt *pvt; |
2619 | u8 nid = get_node_id(pdev); | 2519 | u16 nid = amd_get_node_id(pdev); |
2620 | struct pci_dev *F3 = node_to_amd_nb(nid)->misc; | 2520 | struct pci_dev *F3 = node_to_amd_nb(nid)->misc; |
2621 | struct ecc_settings *s = ecc_stngs[nid]; | 2521 | struct ecc_settings *s = ecc_stngs[nid]; |
2622 | 2522 | ||
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. */ | ||
296 | static inline u8 get_node_id(struct pci_dev *pdev) | ||
297 | { | ||
298 | return PCI_SLOT(pdev->devfn) - 0x18; | ||
299 | } | ||
300 | |||
301 | enum amd_families { | 295 | enum 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 | ||
396 | static inline u64 get_dram_base(struct amd64_pvt *pvt, unsigned i) | 390 | static 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 | ||
406 | static inline u64 get_dram_limit(struct amd64_pvt *pvt, unsigned i) | 400 | static 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 | ||
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c index ad637572d8c7..f3f0c930d550 100644 --- a/drivers/edac/mce_amd.c +++ b/drivers/edac/mce_amd.c | |||
@@ -39,30 +39,28 @@ EXPORT_SYMBOL_GPL(amd_unregister_ecc_decoder); | |||
39 | */ | 39 | */ |
40 | 40 | ||
41 | /* transaction type */ | 41 | /* transaction type */ |
42 | const char * const tt_msgs[] = { "INSN", "DATA", "GEN", "RESV" }; | 42 | static const char * const tt_msgs[] = { "INSN", "DATA", "GEN", "RESV" }; |
43 | EXPORT_SYMBOL_GPL(tt_msgs); | ||
44 | 43 | ||
45 | /* cache level */ | 44 | /* cache level */ |
46 | const char * const ll_msgs[] = { "RESV", "L1", "L2", "L3/GEN" }; | 45 | static const char * const ll_msgs[] = { "RESV", "L1", "L2", "L3/GEN" }; |
47 | EXPORT_SYMBOL_GPL(ll_msgs); | ||
48 | 46 | ||
49 | /* memory transaction type */ | 47 | /* memory transaction type */ |
50 | const char * const rrrr_msgs[] = { | 48 | static const char * const rrrr_msgs[] = { |
51 | "GEN", "RD", "WR", "DRD", "DWR", "IRD", "PRF", "EV", "SNP" | 49 | "GEN", "RD", "WR", "DRD", "DWR", "IRD", "PRF", "EV", "SNP" |
52 | }; | 50 | }; |
53 | EXPORT_SYMBOL_GPL(rrrr_msgs); | ||
54 | 51 | ||
55 | /* participating processor */ | 52 | /* participating processor */ |
56 | const char * const pp_msgs[] = { "SRC", "RES", "OBS", "GEN" }; | 53 | const char * const pp_msgs[] = { "SRC", "RES", "OBS", "GEN" }; |
57 | EXPORT_SYMBOL_GPL(pp_msgs); | 54 | EXPORT_SYMBOL_GPL(pp_msgs); |
58 | 55 | ||
59 | /* request timeout */ | 56 | /* request timeout */ |
60 | const char * const to_msgs[] = { "no timeout", "timed out" }; | 57 | static const char * const to_msgs[] = { "no timeout", "timed out" }; |
61 | EXPORT_SYMBOL_GPL(to_msgs); | ||
62 | 58 | ||
63 | /* memory or i/o */ | 59 | /* memory or i/o */ |
64 | const char * const ii_msgs[] = { "MEM", "RESV", "IO", "GEN" }; | 60 | static const char * const ii_msgs[] = { "MEM", "RESV", "IO", "GEN" }; |
65 | EXPORT_SYMBOL_GPL(ii_msgs); | 61 | |
62 | /* internal error type */ | ||
63 | static const char * const uu_msgs[] = { "RESV", "RESV", "HWA", "RESV" }; | ||
66 | 64 | ||
67 | static const char * const f15h_mc1_mce_desc[] = { | 65 | static const char * const f15h_mc1_mce_desc[] = { |
68 | "UC during a demand linefill from L2", | 66 | "UC during a demand linefill from L2", |
@@ -176,7 +174,7 @@ static bool k8_mc0_mce(u16 ec, u8 xec) | |||
176 | return f10h_mc0_mce(ec, xec); | 174 | return f10h_mc0_mce(ec, xec); |
177 | } | 175 | } |
178 | 176 | ||
179 | static bool f14h_mc0_mce(u16 ec, u8 xec) | 177 | static bool cat_mc0_mce(u16 ec, u8 xec) |
180 | { | 178 | { |
181 | u8 r4 = R4(ec); | 179 | u8 r4 = R4(ec); |
182 | bool ret = true; | 180 | bool ret = true; |
@@ -330,22 +328,28 @@ static bool k8_mc1_mce(u16 ec, u8 xec) | |||
330 | return ret; | 328 | return ret; |
331 | } | 329 | } |
332 | 330 | ||
333 | static bool f14h_mc1_mce(u16 ec, u8 xec) | 331 | static bool cat_mc1_mce(u16 ec, u8 xec) |
334 | { | 332 | { |
335 | u8 r4 = R4(ec); | 333 | u8 r4 = R4(ec); |
336 | bool ret = true; | 334 | bool ret = true; |
337 | 335 | ||
338 | if (MEM_ERROR(ec)) { | 336 | if (!MEM_ERROR(ec)) |
339 | if (TT(ec) != 0 || LL(ec) != 1) | 337 | return false; |
340 | ret = false; | 338 | |
339 | if (TT(ec) != TT_INSTR) | ||
340 | return false; | ||
341 | |||
342 | if (r4 == R4_IRD) | ||
343 | pr_cont("Data/tag array parity error for a tag hit.\n"); | ||
344 | else if (r4 == R4_SNOOP) | ||
345 | pr_cont("Tag error during snoop/victimization.\n"); | ||
346 | else if (xec == 0x0) | ||
347 | pr_cont("Tag parity error from victim castout.\n"); | ||
348 | else if (xec == 0x2) | ||
349 | pr_cont("Microcode patch RAM parity error.\n"); | ||
350 | else | ||
351 | ret = false; | ||
341 | 352 | ||
342 | if (r4 == R4_IRD) | ||
343 | pr_cont("Data/tag array parity error for a tag hit.\n"); | ||
344 | else if (r4 == R4_SNOOP) | ||
345 | pr_cont("Tag error during snoop/victimization.\n"); | ||
346 | else | ||
347 | ret = false; | ||
348 | } | ||
349 | return ret; | 353 | return ret; |
350 | } | 354 | } |
351 | 355 | ||
@@ -399,12 +403,9 @@ static void decode_mc1_mce(struct mce *m) | |||
399 | pr_emerg(HW_ERR "Corrupted MC1 MCE info?\n"); | 403 | pr_emerg(HW_ERR "Corrupted MC1 MCE info?\n"); |
400 | } | 404 | } |
401 | 405 | ||
402 | static void decode_mc2_mce(struct mce *m) | 406 | static bool k8_mc2_mce(u16 ec, u8 xec) |
403 | { | 407 | { |
404 | u16 ec = EC(m->status); | 408 | bool ret = true; |
405 | u8 xec = XEC(m->status, xec_mask); | ||
406 | |||
407 | pr_emerg(HW_ERR "MC2 Error"); | ||
408 | 409 | ||
409 | if (xec == 0x1) | 410 | if (xec == 0x1) |
410 | pr_cont(" in the write data buffers.\n"); | 411 | pr_cont(" in the write data buffers.\n"); |
@@ -429,24 +430,18 @@ static void decode_mc2_mce(struct mce *m) | |||
429 | pr_cont(": %s parity/ECC error during data " | 430 | pr_cont(": %s parity/ECC error during data " |
430 | "access from L2.\n", R4_MSG(ec)); | 431 | "access from L2.\n", R4_MSG(ec)); |
431 | else | 432 | else |
432 | goto wrong_mc2_mce; | 433 | ret = false; |
433 | } else | 434 | } else |
434 | goto wrong_mc2_mce; | 435 | ret = false; |
435 | } else | 436 | } else |
436 | goto wrong_mc2_mce; | 437 | ret = false; |
437 | |||
438 | return; | ||
439 | 438 | ||
440 | wrong_mc2_mce: | 439 | return ret; |
441 | pr_emerg(HW_ERR "Corrupted MC2 MCE info?\n"); | ||
442 | } | 440 | } |
443 | 441 | ||
444 | static void decode_f15_mc2_mce(struct mce *m) | 442 | static bool f15h_mc2_mce(u16 ec, u8 xec) |
445 | { | 443 | { |
446 | u16 ec = EC(m->status); | 444 | bool ret = true; |
447 | u8 xec = XEC(m->status, xec_mask); | ||
448 | |||
449 | pr_emerg(HW_ERR "MC2 Error: "); | ||
450 | 445 | ||
451 | if (TLB_ERROR(ec)) { | 446 | if (TLB_ERROR(ec)) { |
452 | if (xec == 0x0) | 447 | if (xec == 0x0) |
@@ -454,10 +449,10 @@ static void decode_f15_mc2_mce(struct mce *m) | |||
454 | else if (xec == 0x1) | 449 | else if (xec == 0x1) |
455 | pr_cont("Poison data provided for TLB fill.\n"); | 450 | pr_cont("Poison data provided for TLB fill.\n"); |
456 | else | 451 | else |
457 | goto wrong_f15_mc2_mce; | 452 | ret = false; |
458 | } else if (BUS_ERROR(ec)) { | 453 | } else if (BUS_ERROR(ec)) { |
459 | if (xec > 2) | 454 | if (xec > 2) |
460 | goto wrong_f15_mc2_mce; | 455 | ret = false; |
461 | 456 | ||
462 | pr_cont("Error during attempted NB data read.\n"); | 457 | pr_cont("Error during attempted NB data read.\n"); |
463 | } else if (MEM_ERROR(ec)) { | 458 | } else if (MEM_ERROR(ec)) { |
@@ -471,14 +466,63 @@ static void decode_f15_mc2_mce(struct mce *m) | |||
471 | break; | 466 | break; |
472 | 467 | ||
473 | default: | 468 | default: |
474 | goto wrong_f15_mc2_mce; | 469 | ret = false; |
475 | } | 470 | } |
476 | } | 471 | } |
477 | 472 | ||
478 | return; | 473 | return ret; |
474 | } | ||
479 | 475 | ||
480 | wrong_f15_mc2_mce: | 476 | static bool f16h_mc2_mce(u16 ec, u8 xec) |
481 | pr_emerg(HW_ERR "Corrupted MC2 MCE info?\n"); | 477 | { |
478 | u8 r4 = R4(ec); | ||
479 | |||
480 | if (!MEM_ERROR(ec)) | ||
481 | return false; | ||
482 | |||
483 | switch (xec) { | ||
484 | case 0x04 ... 0x05: | ||
485 | pr_cont("%cBUFF parity error.\n", (r4 == R4_RD) ? 'I' : 'O'); | ||
486 | break; | ||
487 | |||
488 | case 0x09 ... 0x0b: | ||
489 | case 0x0d ... 0x0f: | ||
490 | pr_cont("ECC error in L2 tag (%s).\n", | ||
491 | ((r4 == R4_GEN) ? "BankReq" : | ||
492 | ((r4 == R4_SNOOP) ? "Prb" : "Fill"))); | ||
493 | break; | ||
494 | |||
495 | case 0x10 ... 0x19: | ||
496 | case 0x1b: | ||
497 | pr_cont("ECC error in L2 data array (%s).\n", | ||
498 | (((r4 == R4_RD) && !(xec & 0x3)) ? "Hit" : | ||
499 | ((r4 == R4_GEN) ? "Attr" : | ||
500 | ((r4 == R4_EVICT) ? "Vict" : "Fill")))); | ||
501 | break; | ||
502 | |||
503 | case 0x1c ... 0x1d: | ||
504 | case 0x1f: | ||
505 | pr_cont("Parity error in L2 attribute bits (%s).\n", | ||
506 | ((r4 == R4_RD) ? "Hit" : | ||
507 | ((r4 == R4_GEN) ? "Attr" : "Fill"))); | ||
508 | break; | ||
509 | |||
510 | default: | ||
511 | return false; | ||
512 | } | ||
513 | |||
514 | return true; | ||
515 | } | ||
516 | |||
517 | static void decode_mc2_mce(struct mce *m) | ||
518 | { | ||
519 | u16 ec = EC(m->status); | ||
520 | u8 xec = XEC(m->status, xec_mask); | ||
521 | |||
522 | pr_emerg(HW_ERR "MC2 Error: "); | ||
523 | |||
524 | if (!fam_ops->mc2_mce(ec, xec)) | ||
525 | pr_cont(HW_ERR "Corrupted MC2 MCE info?\n"); | ||
482 | } | 526 | } |
483 | 527 | ||
484 | static void decode_mc3_mce(struct mce *m) | 528 | static void decode_mc3_mce(struct mce *m) |
@@ -547,7 +591,7 @@ static void decode_mc4_mce(struct mce *m) | |||
547 | return; | 591 | return; |
548 | 592 | ||
549 | case 0x19: | 593 | case 0x19: |
550 | if (boot_cpu_data.x86 == 0x15) | 594 | if (boot_cpu_data.x86 == 0x15 || boot_cpu_data.x86 == 0x16) |
551 | pr_cont("Compute Unit Data Error.\n"); | 595 | pr_cont("Compute Unit Data Error.\n"); |
552 | else | 596 | else |
553 | goto wrong_mc4_mce; | 597 | goto wrong_mc4_mce; |
@@ -633,6 +677,10 @@ static void decode_mc6_mce(struct mce *m) | |||
633 | 677 | ||
634 | static inline void amd_decode_err_code(u16 ec) | 678 | static inline void amd_decode_err_code(u16 ec) |
635 | { | 679 | { |
680 | if (INT_ERROR(ec)) { | ||
681 | pr_emerg(HW_ERR "internal: %s\n", UU_MSG(ec)); | ||
682 | return; | ||
683 | } | ||
636 | 684 | ||
637 | pr_emerg(HW_ERR "cache level: %s", LL_MSG(ec)); | 685 | pr_emerg(HW_ERR "cache level: %s", LL_MSG(ec)); |
638 | 686 | ||
@@ -702,10 +750,7 @@ int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data) | |||
702 | break; | 750 | break; |
703 | 751 | ||
704 | case 2: | 752 | case 2: |
705 | if (c->x86 == 0x15) | 753 | decode_mc2_mce(m); |
706 | decode_f15_mc2_mce(m); | ||
707 | else | ||
708 | decode_mc2_mce(m); | ||
709 | break; | 754 | break; |
710 | 755 | ||
711 | case 3: | 756 | case 3: |
@@ -740,7 +785,7 @@ int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data) | |||
740 | ((m->status & MCI_STATUS_PCC) ? "PCC" : "-"), | 785 | ((m->status & MCI_STATUS_PCC) ? "PCC" : "-"), |
741 | ((m->status & MCI_STATUS_ADDRV) ? "AddrV" : "-")); | 786 | ((m->status & MCI_STATUS_ADDRV) ? "AddrV" : "-")); |
742 | 787 | ||
743 | if (c->x86 == 0x15) | 788 | if (c->x86 == 0x15 || c->x86 == 0x16) |
744 | pr_cont("|%s|%s", | 789 | pr_cont("|%s|%s", |
745 | ((m->status & MCI_STATUS_DEFERRED) ? "Deferred" : "-"), | 790 | ((m->status & MCI_STATUS_DEFERRED) ? "Deferred" : "-"), |
746 | ((m->status & MCI_STATUS_POISON) ? "Poison" : "-")); | 791 | ((m->status & MCI_STATUS_POISON) ? "Poison" : "-")); |
@@ -772,7 +817,7 @@ static int __init mce_amd_init(void) | |||
772 | if (c->x86_vendor != X86_VENDOR_AMD) | 817 | if (c->x86_vendor != X86_VENDOR_AMD) |
773 | return 0; | 818 | return 0; |
774 | 819 | ||
775 | if (c->x86 < 0xf || c->x86 > 0x15) | 820 | if (c->x86 < 0xf || c->x86 > 0x16) |
776 | return 0; | 821 | return 0; |
777 | 822 | ||
778 | fam_ops = kzalloc(sizeof(struct amd_decoder_ops), GFP_KERNEL); | 823 | fam_ops = kzalloc(sizeof(struct amd_decoder_ops), GFP_KERNEL); |
@@ -783,33 +828,46 @@ static int __init mce_amd_init(void) | |||
783 | case 0xf: | 828 | case 0xf: |
784 | fam_ops->mc0_mce = k8_mc0_mce; | 829 | fam_ops->mc0_mce = k8_mc0_mce; |
785 | fam_ops->mc1_mce = k8_mc1_mce; | 830 | fam_ops->mc1_mce = k8_mc1_mce; |
831 | fam_ops->mc2_mce = k8_mc2_mce; | ||
786 | break; | 832 | break; |
787 | 833 | ||
788 | case 0x10: | 834 | case 0x10: |
789 | fam_ops->mc0_mce = f10h_mc0_mce; | 835 | fam_ops->mc0_mce = f10h_mc0_mce; |
790 | fam_ops->mc1_mce = k8_mc1_mce; | 836 | fam_ops->mc1_mce = k8_mc1_mce; |
837 | fam_ops->mc2_mce = k8_mc2_mce; | ||
791 | break; | 838 | break; |
792 | 839 | ||
793 | case 0x11: | 840 | case 0x11: |
794 | fam_ops->mc0_mce = k8_mc0_mce; | 841 | fam_ops->mc0_mce = k8_mc0_mce; |
795 | fam_ops->mc1_mce = k8_mc1_mce; | 842 | fam_ops->mc1_mce = k8_mc1_mce; |
843 | fam_ops->mc2_mce = k8_mc2_mce; | ||
796 | break; | 844 | break; |
797 | 845 | ||
798 | case 0x12: | 846 | case 0x12: |
799 | fam_ops->mc0_mce = f12h_mc0_mce; | 847 | fam_ops->mc0_mce = f12h_mc0_mce; |
800 | fam_ops->mc1_mce = k8_mc1_mce; | 848 | fam_ops->mc1_mce = k8_mc1_mce; |
849 | fam_ops->mc2_mce = k8_mc2_mce; | ||
801 | break; | 850 | break; |
802 | 851 | ||
803 | case 0x14: | 852 | case 0x14: |
804 | nb_err_cpumask = 0x3; | 853 | nb_err_cpumask = 0x3; |
805 | fam_ops->mc0_mce = f14h_mc0_mce; | 854 | fam_ops->mc0_mce = cat_mc0_mce; |
806 | fam_ops->mc1_mce = f14h_mc1_mce; | 855 | fam_ops->mc1_mce = cat_mc1_mce; |
856 | fam_ops->mc2_mce = k8_mc2_mce; | ||
807 | break; | 857 | break; |
808 | 858 | ||
809 | case 0x15: | 859 | case 0x15: |
810 | xec_mask = 0x1f; | 860 | xec_mask = 0x1f; |
811 | fam_ops->mc0_mce = f15h_mc0_mce; | 861 | fam_ops->mc0_mce = f15h_mc0_mce; |
812 | fam_ops->mc1_mce = f15h_mc1_mce; | 862 | fam_ops->mc1_mce = f15h_mc1_mce; |
863 | fam_ops->mc2_mce = f15h_mc2_mce; | ||
864 | break; | ||
865 | |||
866 | case 0x16: | ||
867 | xec_mask = 0x1f; | ||
868 | fam_ops->mc0_mce = cat_mc0_mce; | ||
869 | fam_ops->mc1_mce = cat_mc1_mce; | ||
870 | fam_ops->mc2_mce = f16h_mc2_mce; | ||
813 | break; | 871 | break; |
814 | 872 | ||
815 | default: | 873 | default: |
diff --git a/drivers/edac/mce_amd.h b/drivers/edac/mce_amd.h index 679679951e23..51b7e3a36e37 100644 --- a/drivers/edac/mce_amd.h +++ b/drivers/edac/mce_amd.h | |||
@@ -14,6 +14,7 @@ | |||
14 | #define TLB_ERROR(x) (((x) & 0xFFF0) == 0x0010) | 14 | #define TLB_ERROR(x) (((x) & 0xFFF0) == 0x0010) |
15 | #define MEM_ERROR(x) (((x) & 0xFF00) == 0x0100) | 15 | #define MEM_ERROR(x) (((x) & 0xFF00) == 0x0100) |
16 | #define BUS_ERROR(x) (((x) & 0xF800) == 0x0800) | 16 | #define BUS_ERROR(x) (((x) & 0xF800) == 0x0800) |
17 | #define INT_ERROR(x) (((x) & 0xF4FF) == 0x0400) | ||
17 | 18 | ||
18 | #define TT(x) (((x) >> 2) & 0x3) | 19 | #define TT(x) (((x) >> 2) & 0x3) |
19 | #define TT_MSG(x) tt_msgs[TT(x)] | 20 | #define TT_MSG(x) tt_msgs[TT(x)] |
@@ -25,6 +26,8 @@ | |||
25 | #define TO_MSG(x) to_msgs[TO(x)] | 26 | #define TO_MSG(x) to_msgs[TO(x)] |
26 | #define PP(x) (((x) >> 9) & 0x3) | 27 | #define PP(x) (((x) >> 9) & 0x3) |
27 | #define PP_MSG(x) pp_msgs[PP(x)] | 28 | #define PP_MSG(x) pp_msgs[PP(x)] |
29 | #define UU(x) (((x) >> 8) & 0x3) | ||
30 | #define UU_MSG(x) uu_msgs[UU(x)] | ||
28 | 31 | ||
29 | #define R4(x) (((x) >> 4) & 0xf) | 32 | #define R4(x) (((x) >> 4) & 0xf) |
30 | #define R4_MSG(x) ((R4(x) < 9) ? rrrr_msgs[R4(x)] : "Wrong R4!") | 33 | #define R4_MSG(x) ((R4(x) < 9) ? rrrr_msgs[R4(x)] : "Wrong R4!") |
@@ -32,6 +35,8 @@ | |||
32 | #define MCI_STATUS_DEFERRED BIT_64(44) | 35 | #define MCI_STATUS_DEFERRED BIT_64(44) |
33 | #define MCI_STATUS_POISON BIT_64(43) | 36 | #define MCI_STATUS_POISON BIT_64(43) |
34 | 37 | ||
38 | extern const char * const pp_msgs[]; | ||
39 | |||
35 | enum tt_ids { | 40 | enum tt_ids { |
36 | TT_INSTR = 0, | 41 | TT_INSTR = 0, |
37 | TT_DATA, | 42 | TT_DATA, |
@@ -65,19 +70,13 @@ enum rrrr_ids { | |||
65 | R4_SNOOP, | 70 | R4_SNOOP, |
66 | }; | 71 | }; |
67 | 72 | ||
68 | extern const char * const tt_msgs[]; | ||
69 | extern const char * const ll_msgs[]; | ||
70 | extern const char * const rrrr_msgs[]; | ||
71 | extern const char * const pp_msgs[]; | ||
72 | extern const char * const to_msgs[]; | ||
73 | extern const char * const ii_msgs[]; | ||
74 | |||
75 | /* | 73 | /* |
76 | * per-family decoder ops | 74 | * per-family decoder ops |
77 | */ | 75 | */ |
78 | struct amd_decoder_ops { | 76 | struct amd_decoder_ops { |
79 | bool (*mc0_mce)(u16, u8); | 77 | bool (*mc0_mce)(u16, u8); |
80 | bool (*mc1_mce)(u16, u8); | 78 | bool (*mc1_mce)(u16, u8); |
79 | bool (*mc2_mce)(u16, u8); | ||
81 | }; | 80 | }; |
82 | 81 | ||
83 | void amd_report_gart_errors(bool); | 82 | void amd_report_gart_errors(bool); |
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index 42a840d530a5..3eb32f62d72a 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c | |||
@@ -301,7 +301,7 @@ int mpc85xx_pci_err_probe(struct platform_device *op) | |||
301 | "[EDAC] PCI err", pci); | 301 | "[EDAC] PCI err", pci); |
302 | if (res < 0) { | 302 | if (res < 0) { |
303 | printk(KERN_ERR | 303 | printk(KERN_ERR |
304 | "%s: Unable to requiest irq %d for " | 304 | "%s: Unable to request irq %d for " |
305 | "MPC85xx PCI err\n", __func__, pdata->irq); | 305 | "MPC85xx PCI err\n", __func__, pdata->irq); |
306 | irq_dispose_mapping(pdata->irq); | 306 | irq_dispose_mapping(pdata->irq); |
307 | res = -ENODEV; | 307 | res = -ENODEV; |
@@ -583,7 +583,7 @@ static int mpc85xx_l2_err_probe(struct platform_device *op) | |||
583 | "[EDAC] L2 err", edac_dev); | 583 | "[EDAC] L2 err", edac_dev); |
584 | if (res < 0) { | 584 | if (res < 0) { |
585 | printk(KERN_ERR | 585 | printk(KERN_ERR |
586 | "%s: Unable to requiest irq %d for " | 586 | "%s: Unable to request irq %d for " |
587 | "MPC85xx L2 err\n", __func__, pdata->irq); | 587 | "MPC85xx L2 err\n", __func__, pdata->irq); |
588 | irq_dispose_mapping(pdata->irq); | 588 | irq_dispose_mapping(pdata->irq); |
589 | res = -ENODEV; | 589 | res = -ENODEV; |