diff options
Diffstat (limited to 'drivers/edac')
-rw-r--r-- | drivers/edac/Kconfig | 8 | ||||
-rw-r--r-- | drivers/edac/amd64_edac.c | 829 | ||||
-rw-r--r-- | drivers/edac/amd64_edac.h | 86 | ||||
-rw-r--r-- | drivers/edac/amd64_edac_inj.c | 25 | ||||
-rw-r--r-- | drivers/edac/cpc925_edac.c | 9 | ||||
-rw-r--r-- | drivers/edac/e752x_edac.c | 8 | ||||
-rw-r--r-- | drivers/edac/edac_core.h | 5 | ||||
-rw-r--r-- | drivers/edac/edac_mc.c | 4 | ||||
-rw-r--r-- | drivers/edac/edac_mc_sysfs.c | 57 | ||||
-rw-r--r-- | drivers/edac/i5100_edac.c | 9 | ||||
-rw-r--r-- | drivers/edac/mce_amd.c | 450 | ||||
-rw-r--r-- | drivers/edac/mce_amd.h | 14 | ||||
-rw-r--r-- | drivers/edac/mce_amd_inj.c | 9 |
13 files changed, 796 insertions, 717 deletions
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index f436a2fa9f38..fe70a341bd8b 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig | |||
@@ -75,11 +75,11 @@ config EDAC_MCE | |||
75 | bool | 75 | bool |
76 | 76 | ||
77 | config EDAC_AMD64 | 77 | config EDAC_AMD64 |
78 | tristate "AMD64 (Opteron, Athlon64) K8, F10h, F11h" | 78 | tristate "AMD64 (Opteron, Athlon64) K8, F10h" |
79 | depends on EDAC_MM_EDAC && AMD_NB && X86_64 && PCI && EDAC_DECODE_MCE | 79 | depends on EDAC_MM_EDAC && AMD_NB && X86_64 && EDAC_DECODE_MCE |
80 | help | 80 | help |
81 | Support for error detection and correction on the AMD 64 | 81 | Support for error detection and correction of DRAM ECC errors on |
82 | Families of Memory Controllers (K8, F10h and F11h) | 82 | the AMD64 families of memory controllers (K8 and F10h) |
83 | 83 | ||
84 | config EDAC_AMD64_ERROR_INJECTION | 84 | config EDAC_AMD64_ERROR_INJECTION |
85 | bool "Sysfs HW Error injection facilities" | 85 | bool "Sysfs HW Error injection facilities" |
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index eca9ba193e94..4a5ecc58025d 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c | |||
@@ -15,10 +15,14 @@ module_param(ecc_enable_override, int, 0644); | |||
15 | 15 | ||
16 | static struct msr __percpu *msrs; | 16 | static struct msr __percpu *msrs; |
17 | 17 | ||
18 | /* Lookup table for all possible MC control instances */ | 18 | /* |
19 | struct amd64_pvt; | 19 | * count successfully initialized driver instances for setup_pci_device() |
20 | static struct mem_ctl_info *mci_lookup[EDAC_MAX_NUMNODES]; | 20 | */ |
21 | static struct amd64_pvt *pvt_lookup[EDAC_MAX_NUMNODES]; | 21 | static atomic_t drv_instances = ATOMIC_INIT(0); |
22 | |||
23 | /* Per-node driver instances */ | ||
24 | static struct mem_ctl_info **mcis; | ||
25 | static struct ecc_settings **ecc_stngs; | ||
22 | 26 | ||
23 | /* | 27 | /* |
24 | * Address to DRAM bank mapping: see F2x80 for K8 and F2x[1,0]80 for Fam10 and | 28 | * Address to DRAM bank mapping: see F2x80 for K8 and F2x[1,0]80 for Fam10 and |
@@ -62,7 +66,7 @@ static int ddr3_dbam[] = { [0] = -1, | |||
62 | [5 ... 6] = 1024, | 66 | [5 ... 6] = 1024, |
63 | [7 ... 8] = 2048, | 67 | [7 ... 8] = 2048, |
64 | [9 ... 10] = 4096, | 68 | [9 ... 10] = 4096, |
65 | [11] = 8192, | 69 | [11] = 8192, |
66 | }; | 70 | }; |
67 | 71 | ||
68 | /* | 72 | /* |
@@ -73,7 +77,11 @@ static int ddr3_dbam[] = { [0] = -1, | |||
73 | *FIXME: Produce a better mapping/linearisation. | 77 | *FIXME: Produce a better mapping/linearisation. |
74 | */ | 78 | */ |
75 | 79 | ||
76 | struct scrubrate scrubrates[] = { | 80 | |
81 | struct scrubrate { | ||
82 | u32 scrubval; /* bit pattern for scrub rate */ | ||
83 | u32 bandwidth; /* bandwidth consumed (bytes/sec) */ | ||
84 | } scrubrates[] = { | ||
77 | { 0x01, 1600000000UL}, | 85 | { 0x01, 1600000000UL}, |
78 | { 0x02, 800000000UL}, | 86 | { 0x02, 800000000UL}, |
79 | { 0x03, 400000000UL}, | 87 | { 0x03, 400000000UL}, |
@@ -117,8 +125,7 @@ struct scrubrate scrubrates[] = { | |||
117 | * scan the scrub rate mapping table for a close or matching bandwidth value to | 125 | * scan the scrub rate mapping table for a close or matching bandwidth value to |
118 | * issue. If requested is too big, then use last maximum value found. | 126 | * issue. If requested is too big, then use last maximum value found. |
119 | */ | 127 | */ |
120 | static int amd64_search_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, | 128 | static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate) |
121 | u32 min_scrubrate) | ||
122 | { | 129 | { |
123 | u32 scrubval; | 130 | u32 scrubval; |
124 | int i; | 131 | int i; |
@@ -134,7 +141,7 @@ static int amd64_search_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, | |||
134 | * skip scrub rates which aren't recommended | 141 | * skip scrub rates which aren't recommended |
135 | * (see F10 BKDG, F3x58) | 142 | * (see F10 BKDG, F3x58) |
136 | */ | 143 | */ |
137 | if (scrubrates[i].scrubval < min_scrubrate) | 144 | if (scrubrates[i].scrubval < min_rate) |
138 | continue; | 145 | continue; |
139 | 146 | ||
140 | if (scrubrates[i].bandwidth <= new_bw) | 147 | if (scrubrates[i].bandwidth <= new_bw) |
@@ -148,64 +155,41 @@ static int amd64_search_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, | |||
148 | } | 155 | } |
149 | 156 | ||
150 | scrubval = scrubrates[i].scrubval; | 157 | scrubval = scrubrates[i].scrubval; |
151 | if (scrubval) | ||
152 | edac_printk(KERN_DEBUG, EDAC_MC, | ||
153 | "Setting scrub rate bandwidth: %u\n", | ||
154 | scrubrates[i].bandwidth); | ||
155 | else | ||
156 | edac_printk(KERN_DEBUG, EDAC_MC, "Turning scrubbing off.\n"); | ||
157 | 158 | ||
158 | pci_write_bits32(ctl, K8_SCRCTRL, scrubval, 0x001F); | 159 | pci_write_bits32(ctl, K8_SCRCTRL, scrubval, 0x001F); |
159 | 160 | ||
161 | if (scrubval) | ||
162 | return scrubrates[i].bandwidth; | ||
163 | |||
160 | return 0; | 164 | return 0; |
161 | } | 165 | } |
162 | 166 | ||
163 | static int amd64_set_scrub_rate(struct mem_ctl_info *mci, u32 bandwidth) | 167 | static int amd64_set_scrub_rate(struct mem_ctl_info *mci, u32 bw) |
164 | { | 168 | { |
165 | struct amd64_pvt *pvt = mci->pvt_info; | 169 | struct amd64_pvt *pvt = mci->pvt_info; |
166 | u32 min_scrubrate = 0x0; | ||
167 | |||
168 | switch (boot_cpu_data.x86) { | ||
169 | case 0xf: | ||
170 | min_scrubrate = K8_MIN_SCRUB_RATE_BITS; | ||
171 | break; | ||
172 | case 0x10: | ||
173 | min_scrubrate = F10_MIN_SCRUB_RATE_BITS; | ||
174 | break; | ||
175 | case 0x11: | ||
176 | min_scrubrate = F11_MIN_SCRUB_RATE_BITS; | ||
177 | break; | ||
178 | 170 | ||
179 | default: | 171 | return __amd64_set_scrub_rate(pvt->F3, bw, pvt->min_scrubrate); |
180 | amd64_printk(KERN_ERR, "Unsupported family!\n"); | ||
181 | return -EINVAL; | ||
182 | } | ||
183 | return amd64_search_set_scrub_rate(pvt->misc_f3_ctl, bandwidth, | ||
184 | min_scrubrate); | ||
185 | } | 172 | } |
186 | 173 | ||
187 | static int amd64_get_scrub_rate(struct mem_ctl_info *mci, u32 *bw) | 174 | static int amd64_get_scrub_rate(struct mem_ctl_info *mci) |
188 | { | 175 | { |
189 | struct amd64_pvt *pvt = mci->pvt_info; | 176 | struct amd64_pvt *pvt = mci->pvt_info; |
190 | u32 scrubval = 0; | 177 | u32 scrubval = 0; |
191 | int status = -1, i; | 178 | int i, retval = -EINVAL; |
192 | 179 | ||
193 | amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_SCRCTRL, &scrubval); | 180 | amd64_read_pci_cfg(pvt->F3, K8_SCRCTRL, &scrubval); |
194 | 181 | ||
195 | scrubval = scrubval & 0x001F; | 182 | scrubval = scrubval & 0x001F; |
196 | 183 | ||
197 | edac_printk(KERN_DEBUG, EDAC_MC, | 184 | amd64_debug("pci-read, sdram scrub control value: %d\n", scrubval); |
198 | "pci-read, sdram scrub control value: %d \n", scrubval); | ||
199 | 185 | ||
200 | for (i = 0; i < ARRAY_SIZE(scrubrates); i++) { | 186 | for (i = 0; i < ARRAY_SIZE(scrubrates); i++) { |
201 | if (scrubrates[i].scrubval == scrubval) { | 187 | if (scrubrates[i].scrubval == scrubval) { |
202 | *bw = scrubrates[i].bandwidth; | 188 | retval = scrubrates[i].bandwidth; |
203 | status = 0; | ||
204 | break; | 189 | break; |
205 | } | 190 | } |
206 | } | 191 | } |
207 | 192 | return retval; | |
208 | return status; | ||
209 | } | 193 | } |
210 | 194 | ||
211 | /* Map from a CSROW entry to the mask entry that operates on it */ | 195 | /* Map from a CSROW entry to the mask entry that operates on it */ |
@@ -314,9 +298,7 @@ static struct mem_ctl_info *find_mc_by_sys_addr(struct mem_ctl_info *mci, | |||
314 | if (unlikely((intlv_en != 0x01) && | 298 | if (unlikely((intlv_en != 0x01) && |
315 | (intlv_en != 0x03) && | 299 | (intlv_en != 0x03) && |
316 | (intlv_en != 0x07))) { | 300 | (intlv_en != 0x07))) { |
317 | amd64_printk(KERN_WARNING, "junk value of 0x%x extracted from " | 301 | amd64_warn("DRAM Base[IntlvEn] junk value: 0x%x, BIOS bug?\n", intlv_en); |
318 | "IntlvEn field of DRAM Base Register for node 0: " | ||
319 | "this probably indicates a BIOS bug.\n", intlv_en); | ||
320 | return NULL; | 302 | return NULL; |
321 | } | 303 | } |
322 | 304 | ||
@@ -332,11 +314,9 @@ static struct mem_ctl_info *find_mc_by_sys_addr(struct mem_ctl_info *mci, | |||
332 | 314 | ||
333 | /* sanity test for sys_addr */ | 315 | /* sanity test for sys_addr */ |
334 | if (unlikely(!amd64_base_limit_match(pvt, sys_addr, node_id))) { | 316 | if (unlikely(!amd64_base_limit_match(pvt, sys_addr, node_id))) { |
335 | amd64_printk(KERN_WARNING, | 317 | amd64_warn("%s: sys_addr 0x%llx falls outside base/limit address" |
336 | "%s(): sys_addr 0x%llx falls outside base/limit " | 318 | "range for node %d with node interleaving enabled.\n", |
337 | "address range for node %d with node interleaving " | 319 | __func__, sys_addr, node_id); |
338 | "enabled.\n", | ||
339 | __func__, sys_addr, node_id); | ||
340 | return NULL; | 320 | return NULL; |
341 | } | 321 | } |
342 | 322 | ||
@@ -788,9 +768,8 @@ static int sys_addr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr) | |||
788 | csrow = input_addr_to_csrow(mci, sys_addr_to_input_addr(mci, sys_addr)); | 768 | csrow = input_addr_to_csrow(mci, sys_addr_to_input_addr(mci, sys_addr)); |
789 | 769 | ||
790 | if (csrow == -1) | 770 | if (csrow == -1) |
791 | amd64_mc_printk(mci, KERN_ERR, | 771 | amd64_mc_err(mci, "Failed to translate InputAddr to csrow for " |
792 | "Failed to translate InputAddr to csrow for " | 772 | "address 0x%lx\n", (unsigned long)sys_addr); |
793 | "address 0x%lx\n", (unsigned long)sys_addr); | ||
794 | return csrow; | 773 | return csrow; |
795 | } | 774 | } |
796 | 775 | ||
@@ -801,21 +780,6 @@ static u16 extract_syndrome(struct err_regs *err) | |||
801 | return ((err->nbsh >> 15) & 0xff) | ((err->nbsl >> 16) & 0xff00); | 780 | return ((err->nbsh >> 15) & 0xff) | ((err->nbsl >> 16) & 0xff00); |
802 | } | 781 | } |
803 | 782 | ||
804 | static void amd64_cpu_display_info(struct amd64_pvt *pvt) | ||
805 | { | ||
806 | if (boot_cpu_data.x86 == 0x11) | ||
807 | edac_printk(KERN_DEBUG, EDAC_MC, "F11h CPU detected\n"); | ||
808 | else if (boot_cpu_data.x86 == 0x10) | ||
809 | edac_printk(KERN_DEBUG, EDAC_MC, "F10h CPU detected\n"); | ||
810 | else if (boot_cpu_data.x86 == 0xf) | ||
811 | edac_printk(KERN_DEBUG, EDAC_MC, "%s detected\n", | ||
812 | (pvt->ext_model >= K8_REV_F) ? | ||
813 | "Rev F or later" : "Rev E or earlier"); | ||
814 | else | ||
815 | /* we'll hardly ever ever get here */ | ||
816 | edac_printk(KERN_ERR, EDAC_MC, "Unknown cpu!\n"); | ||
817 | } | ||
818 | |||
819 | /* | 783 | /* |
820 | * Determine if the DIMMs have ECC enabled. ECC is enabled ONLY if all the DIMMs | 784 | * Determine if the DIMMs have ECC enabled. ECC is enabled ONLY if all the DIMMs |
821 | * are ECC capable. | 785 | * are ECC capable. |
@@ -893,8 +857,7 @@ static void amd64_dump_misc_regs(struct amd64_pvt *pvt) | |||
893 | return; | 857 | return; |
894 | } | 858 | } |
895 | 859 | ||
896 | amd64_printk(KERN_INFO, "using %s syndromes.\n", | 860 | amd64_info("using %s syndromes.\n", ((pvt->syn_type == 8) ? "x8" : "x4")); |
897 | ((pvt->syn_type == 8) ? "x8" : "x4")); | ||
898 | 861 | ||
899 | /* Only if NOT ganged does dclr1 have valid info */ | 862 | /* Only if NOT ganged does dclr1 have valid info */ |
900 | if (!dct_ganging_enabled(pvt)) | 863 | if (!dct_ganging_enabled(pvt)) |
@@ -915,10 +878,10 @@ static void amd64_dump_misc_regs(struct amd64_pvt *pvt) | |||
915 | /* Read in both of DBAM registers */ | 878 | /* Read in both of DBAM registers */ |
916 | static void amd64_read_dbam_reg(struct amd64_pvt *pvt) | 879 | static void amd64_read_dbam_reg(struct amd64_pvt *pvt) |
917 | { | 880 | { |
918 | amd64_read_pci_cfg(pvt->dram_f2_ctl, DBAM0, &pvt->dbam0); | 881 | amd64_read_pci_cfg(pvt->F2, DBAM0, &pvt->dbam0); |
919 | 882 | ||
920 | if (boot_cpu_data.x86 >= 0x10) | 883 | if (boot_cpu_data.x86 >= 0x10) |
921 | amd64_read_pci_cfg(pvt->dram_f2_ctl, DBAM1, &pvt->dbam1); | 884 | amd64_read_pci_cfg(pvt->F2, DBAM1, &pvt->dbam1); |
922 | } | 885 | } |
923 | 886 | ||
924 | /* | 887 | /* |
@@ -965,14 +928,8 @@ static void amd64_set_dct_base_and_mask(struct amd64_pvt *pvt) | |||
965 | pvt->dcsm_mask = REV_F_F1Xh_DCSM_MASK_BITS; | 928 | pvt->dcsm_mask = REV_F_F1Xh_DCSM_MASK_BITS; |
966 | pvt->dcs_mask_notused = REV_F_F1Xh_DCS_NOTUSED_BITS; | 929 | pvt->dcs_mask_notused = REV_F_F1Xh_DCS_NOTUSED_BITS; |
967 | pvt->dcs_shift = REV_F_F1Xh_DCS_SHIFT; | 930 | pvt->dcs_shift = REV_F_F1Xh_DCS_SHIFT; |
968 | 931 | pvt->cs_count = 8; | |
969 | if (boot_cpu_data.x86 == 0x11) { | 932 | pvt->num_dcsm = 4; |
970 | pvt->cs_count = 4; | ||
971 | pvt->num_dcsm = 2; | ||
972 | } else { | ||
973 | pvt->cs_count = 8; | ||
974 | pvt->num_dcsm = 4; | ||
975 | } | ||
976 | } | 933 | } |
977 | } | 934 | } |
978 | 935 | ||
@@ -987,14 +944,14 @@ static void amd64_read_dct_base_mask(struct amd64_pvt *pvt) | |||
987 | 944 | ||
988 | for (cs = 0; cs < pvt->cs_count; cs++) { | 945 | for (cs = 0; cs < pvt->cs_count; cs++) { |
989 | reg = K8_DCSB0 + (cs * 4); | 946 | reg = K8_DCSB0 + (cs * 4); |
990 | if (!amd64_read_pci_cfg(pvt->dram_f2_ctl, reg, &pvt->dcsb0[cs])) | 947 | if (!amd64_read_pci_cfg(pvt->F2, reg, &pvt->dcsb0[cs])) |
991 | debugf0(" DCSB0[%d]=0x%08x reg: F2x%x\n", | 948 | debugf0(" DCSB0[%d]=0x%08x reg: F2x%x\n", |
992 | cs, pvt->dcsb0[cs], reg); | 949 | cs, pvt->dcsb0[cs], reg); |
993 | 950 | ||
994 | /* If DCT are NOT ganged, then read in DCT1's base */ | 951 | /* If DCT are NOT ganged, then read in DCT1's base */ |
995 | if (boot_cpu_data.x86 >= 0x10 && !dct_ganging_enabled(pvt)) { | 952 | if (boot_cpu_data.x86 >= 0x10 && !dct_ganging_enabled(pvt)) { |
996 | reg = F10_DCSB1 + (cs * 4); | 953 | reg = F10_DCSB1 + (cs * 4); |
997 | if (!amd64_read_pci_cfg(pvt->dram_f2_ctl, reg, | 954 | if (!amd64_read_pci_cfg(pvt->F2, reg, |
998 | &pvt->dcsb1[cs])) | 955 | &pvt->dcsb1[cs])) |
999 | debugf0(" DCSB1[%d]=0x%08x reg: F2x%x\n", | 956 | debugf0(" DCSB1[%d]=0x%08x reg: F2x%x\n", |
1000 | cs, pvt->dcsb1[cs], reg); | 957 | cs, pvt->dcsb1[cs], reg); |
@@ -1005,14 +962,14 @@ static void amd64_read_dct_base_mask(struct amd64_pvt *pvt) | |||
1005 | 962 | ||
1006 | for (cs = 0; cs < pvt->num_dcsm; cs++) { | 963 | for (cs = 0; cs < pvt->num_dcsm; cs++) { |
1007 | reg = K8_DCSM0 + (cs * 4); | 964 | reg = K8_DCSM0 + (cs * 4); |
1008 | if (!amd64_read_pci_cfg(pvt->dram_f2_ctl, reg, &pvt->dcsm0[cs])) | 965 | if (!amd64_read_pci_cfg(pvt->F2, reg, &pvt->dcsm0[cs])) |
1009 | debugf0(" DCSM0[%d]=0x%08x reg: F2x%x\n", | 966 | debugf0(" DCSM0[%d]=0x%08x reg: F2x%x\n", |
1010 | cs, pvt->dcsm0[cs], reg); | 967 | cs, pvt->dcsm0[cs], reg); |
1011 | 968 | ||
1012 | /* If DCT are NOT ganged, then read in DCT1's mask */ | 969 | /* If DCT are NOT ganged, then read in DCT1's mask */ |
1013 | if (boot_cpu_data.x86 >= 0x10 && !dct_ganging_enabled(pvt)) { | 970 | if (boot_cpu_data.x86 >= 0x10 && !dct_ganging_enabled(pvt)) { |
1014 | reg = F10_DCSM1 + (cs * 4); | 971 | reg = F10_DCSM1 + (cs * 4); |
1015 | if (!amd64_read_pci_cfg(pvt->dram_f2_ctl, reg, | 972 | if (!amd64_read_pci_cfg(pvt->F2, reg, |
1016 | &pvt->dcsm1[cs])) | 973 | &pvt->dcsm1[cs])) |
1017 | debugf0(" DCSM1[%d]=0x%08x reg: F2x%x\n", | 974 | debugf0(" DCSM1[%d]=0x%08x reg: F2x%x\n", |
1018 | cs, pvt->dcsm1[cs], reg); | 975 | cs, pvt->dcsm1[cs], reg); |
@@ -1022,7 +979,7 @@ static void amd64_read_dct_base_mask(struct amd64_pvt *pvt) | |||
1022 | } | 979 | } |
1023 | } | 980 | } |
1024 | 981 | ||
1025 | static enum mem_type amd64_determine_memory_type(struct amd64_pvt *pvt) | 982 | static enum mem_type amd64_determine_memory_type(struct amd64_pvt *pvt, int cs) |
1026 | { | 983 | { |
1027 | enum mem_type type; | 984 | enum mem_type type; |
1028 | 985 | ||
@@ -1035,7 +992,7 @@ static enum mem_type amd64_determine_memory_type(struct amd64_pvt *pvt) | |||
1035 | type = (pvt->dclr0 & BIT(18)) ? MEM_DDR : MEM_RDDR; | 992 | type = (pvt->dclr0 & BIT(18)) ? MEM_DDR : MEM_RDDR; |
1036 | } | 993 | } |
1037 | 994 | ||
1038 | debugf1(" Memory type is: %s\n", edac_mem_types[type]); | 995 | amd64_info("CS%d: %s\n", cs, edac_mem_types[type]); |
1039 | 996 | ||
1040 | return type; | 997 | return type; |
1041 | } | 998 | } |
@@ -1053,17 +1010,16 @@ static int k8_early_channel_count(struct amd64_pvt *pvt) | |||
1053 | { | 1010 | { |
1054 | int flag, err = 0; | 1011 | int flag, err = 0; |
1055 | 1012 | ||
1056 | err = amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCLR_0, &pvt->dclr0); | 1013 | err = amd64_read_pci_cfg(pvt->F2, F10_DCLR_0, &pvt->dclr0); |
1057 | if (err) | 1014 | if (err) |
1058 | return err; | 1015 | return err; |
1059 | 1016 | ||
1060 | if ((boot_cpu_data.x86_model >> 4) >= K8_REV_F) { | 1017 | if (pvt->ext_model >= K8_REV_F) |
1061 | /* RevF (NPT) and later */ | 1018 | /* RevF (NPT) and later */ |
1062 | flag = pvt->dclr0 & F10_WIDTH_128; | 1019 | flag = pvt->dclr0 & F10_WIDTH_128; |
1063 | } else { | 1020 | else |
1064 | /* RevE and earlier */ | 1021 | /* RevE and earlier */ |
1065 | flag = pvt->dclr0 & REVE_WIDTH_128; | 1022 | flag = pvt->dclr0 & REVE_WIDTH_128; |
1066 | } | ||
1067 | 1023 | ||
1068 | /* not used */ | 1024 | /* not used */ |
1069 | pvt->dclr1 = 0; | 1025 | pvt->dclr1 = 0; |
@@ -1090,14 +1046,14 @@ static void k8_read_dram_base_limit(struct amd64_pvt *pvt, int dram) | |||
1090 | u32 low; | 1046 | u32 low; |
1091 | u32 off = dram << 3; /* 8 bytes between DRAM entries */ | 1047 | u32 off = dram << 3; /* 8 bytes between DRAM entries */ |
1092 | 1048 | ||
1093 | amd64_read_pci_cfg(pvt->addr_f1_ctl, K8_DRAM_BASE_LOW + off, &low); | 1049 | amd64_read_pci_cfg(pvt->F1, K8_DRAM_BASE_LOW + off, &low); |
1094 | 1050 | ||
1095 | /* Extract parts into separate data entries */ | 1051 | /* Extract parts into separate data entries */ |
1096 | pvt->dram_base[dram] = ((u64) low & 0xFFFF0000) << 8; | 1052 | pvt->dram_base[dram] = ((u64) low & 0xFFFF0000) << 8; |
1097 | pvt->dram_IntlvEn[dram] = (low >> 8) & 0x7; | 1053 | pvt->dram_IntlvEn[dram] = (low >> 8) & 0x7; |
1098 | pvt->dram_rw_en[dram] = (low & 0x3); | 1054 | pvt->dram_rw_en[dram] = (low & 0x3); |
1099 | 1055 | ||
1100 | amd64_read_pci_cfg(pvt->addr_f1_ctl, K8_DRAM_LIMIT_LOW + off, &low); | 1056 | amd64_read_pci_cfg(pvt->F1, K8_DRAM_LIMIT_LOW + off, &low); |
1101 | 1057 | ||
1102 | /* | 1058 | /* |
1103 | * Extract parts into separate data entries. Limit is the HIGHEST memory | 1059 | * Extract parts into separate data entries. Limit is the HIGHEST memory |
@@ -1127,9 +1083,8 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, | |||
1127 | * 2 DIMMs is in error. So we need to ID 'both' of them | 1083 | * 2 DIMMs is in error. So we need to ID 'both' of them |
1128 | * as suspect. | 1084 | * as suspect. |
1129 | */ | 1085 | */ |
1130 | amd64_mc_printk(mci, KERN_WARNING, | 1086 | amd64_mc_warn(mci, "unknown syndrome 0x%04x - possible " |
1131 | "unknown syndrome 0x%04x - possible " | 1087 | "error reporting race\n", syndrome); |
1132 | "error reporting race\n", syndrome); | ||
1133 | edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR); | 1088 | edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR); |
1134 | return; | 1089 | return; |
1135 | } | 1090 | } |
@@ -1151,8 +1106,7 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, | |||
1151 | */ | 1106 | */ |
1152 | src_mci = find_mc_by_sys_addr(mci, sys_addr); | 1107 | src_mci = find_mc_by_sys_addr(mci, sys_addr); |
1153 | if (!src_mci) { | 1108 | if (!src_mci) { |
1154 | amd64_mc_printk(mci, KERN_ERR, | 1109 | amd64_mc_err(mci, "failed to map error addr 0x%lx to a node\n", |
1155 | "failed to map error address 0x%lx to a node\n", | ||
1156 | (unsigned long)sys_addr); | 1110 | (unsigned long)sys_addr); |
1157 | edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR); | 1111 | edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR); |
1158 | return; | 1112 | return; |
@@ -1220,7 +1174,7 @@ static int f10_early_channel_count(struct amd64_pvt *pvt) | |||
1220 | * both controllers since DIMMs can be placed in either one. | 1174 | * both controllers since DIMMs can be placed in either one. |
1221 | */ | 1175 | */ |
1222 | for (i = 0; i < ARRAY_SIZE(dbams); i++) { | 1176 | for (i = 0; i < ARRAY_SIZE(dbams); i++) { |
1223 | if (amd64_read_pci_cfg(pvt->dram_f2_ctl, dbams[i], &dbam)) | 1177 | if (amd64_read_pci_cfg(pvt->F2, dbams[i], &dbam)) |
1224 | goto err_reg; | 1178 | goto err_reg; |
1225 | 1179 | ||
1226 | for (j = 0; j < 4; j++) { | 1180 | for (j = 0; j < 4; j++) { |
@@ -1234,7 +1188,7 @@ static int f10_early_channel_count(struct amd64_pvt *pvt) | |||
1234 | if (channels > 2) | 1188 | if (channels > 2) |
1235 | channels = 2; | 1189 | channels = 2; |
1236 | 1190 | ||
1237 | debugf0("MCT channel count: %d\n", channels); | 1191 | amd64_info("MCT channel count: %d\n", channels); |
1238 | 1192 | ||
1239 | return channels; | 1193 | return channels; |
1240 | 1194 | ||
@@ -1255,31 +1209,6 @@ static int f10_dbam_to_chip_select(struct amd64_pvt *pvt, int cs_mode) | |||
1255 | return dbam_map[cs_mode]; | 1209 | return dbam_map[cs_mode]; |
1256 | } | 1210 | } |
1257 | 1211 | ||
1258 | /* Enable extended configuration access via 0xCF8 feature */ | ||
1259 | static void amd64_setup(struct amd64_pvt *pvt) | ||
1260 | { | ||
1261 | u32 reg; | ||
1262 | |||
1263 | amd64_read_pci_cfg(pvt->misc_f3_ctl, F10_NB_CFG_HIGH, ®); | ||
1264 | |||
1265 | pvt->flags.cf8_extcfg = !!(reg & F10_NB_CFG_LOW_ENABLE_EXT_CFG); | ||
1266 | reg |= F10_NB_CFG_LOW_ENABLE_EXT_CFG; | ||
1267 | pci_write_config_dword(pvt->misc_f3_ctl, F10_NB_CFG_HIGH, reg); | ||
1268 | } | ||
1269 | |||
1270 | /* Restore the extended configuration access via 0xCF8 feature */ | ||
1271 | static void amd64_teardown(struct amd64_pvt *pvt) | ||
1272 | { | ||
1273 | u32 reg; | ||
1274 | |||
1275 | amd64_read_pci_cfg(pvt->misc_f3_ctl, F10_NB_CFG_HIGH, ®); | ||
1276 | |||
1277 | reg &= ~F10_NB_CFG_LOW_ENABLE_EXT_CFG; | ||
1278 | if (pvt->flags.cf8_extcfg) | ||
1279 | reg |= F10_NB_CFG_LOW_ENABLE_EXT_CFG; | ||
1280 | pci_write_config_dword(pvt->misc_f3_ctl, F10_NB_CFG_HIGH, reg); | ||
1281 | } | ||
1282 | |||
1283 | static u64 f10_get_error_address(struct mem_ctl_info *mci, | 1212 | static u64 f10_get_error_address(struct mem_ctl_info *mci, |
1284 | struct err_regs *info) | 1213 | struct err_regs *info) |
1285 | { | 1214 | { |
@@ -1301,10 +1230,8 @@ static void f10_read_dram_base_limit(struct amd64_pvt *pvt, int dram) | |||
1301 | high_offset = F10_DRAM_BASE_HIGH + (dram << 3); | 1230 | high_offset = F10_DRAM_BASE_HIGH + (dram << 3); |
1302 | 1231 | ||
1303 | /* read the 'raw' DRAM BASE Address register */ | 1232 | /* read the 'raw' DRAM BASE Address register */ |
1304 | amd64_read_pci_cfg(pvt->addr_f1_ctl, low_offset, &low_base); | 1233 | amd64_read_pci_cfg(pvt->F1, low_offset, &low_base); |
1305 | 1234 | amd64_read_pci_cfg(pvt->F1, high_offset, &high_base); | |
1306 | /* Read from the ECS data register */ | ||
1307 | amd64_read_pci_cfg(pvt->addr_f1_ctl, high_offset, &high_base); | ||
1308 | 1235 | ||
1309 | /* Extract parts into separate data entries */ | 1236 | /* Extract parts into separate data entries */ |
1310 | pvt->dram_rw_en[dram] = (low_base & 0x3); | 1237 | pvt->dram_rw_en[dram] = (low_base & 0x3); |
@@ -1321,10 +1248,8 @@ static void f10_read_dram_base_limit(struct amd64_pvt *pvt, int dram) | |||
1321 | high_offset = F10_DRAM_LIMIT_HIGH + (dram << 3); | 1248 | high_offset = F10_DRAM_LIMIT_HIGH + (dram << 3); |
1322 | 1249 | ||
1323 | /* read the 'raw' LIMIT registers */ | 1250 | /* read the 'raw' LIMIT registers */ |
1324 | amd64_read_pci_cfg(pvt->addr_f1_ctl, low_offset, &low_limit); | 1251 | amd64_read_pci_cfg(pvt->F1, low_offset, &low_limit); |
1325 | 1252 | amd64_read_pci_cfg(pvt->F1, high_offset, &high_limit); | |
1326 | /* Read from the ECS data register for the HIGH portion */ | ||
1327 | amd64_read_pci_cfg(pvt->addr_f1_ctl, high_offset, &high_limit); | ||
1328 | 1253 | ||
1329 | pvt->dram_DstNode[dram] = (low_limit & 0x7); | 1254 | pvt->dram_DstNode[dram] = (low_limit & 0x7); |
1330 | pvt->dram_IntlvSel[dram] = (low_limit >> 8) & 0x7; | 1255 | pvt->dram_IntlvSel[dram] = (low_limit >> 8) & 0x7; |
@@ -1341,7 +1266,7 @@ static void f10_read_dram_base_limit(struct amd64_pvt *pvt, int dram) | |||
1341 | static void f10_read_dram_ctl_register(struct amd64_pvt *pvt) | 1266 | static void f10_read_dram_ctl_register(struct amd64_pvt *pvt) |
1342 | { | 1267 | { |
1343 | 1268 | ||
1344 | if (!amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCTL_SEL_LOW, | 1269 | if (!amd64_read_pci_cfg(pvt->F2, F10_DCTL_SEL_LOW, |
1345 | &pvt->dram_ctl_select_low)) { | 1270 | &pvt->dram_ctl_select_low)) { |
1346 | debugf0("F2x110 (DCTL Sel. Low): 0x%08x, " | 1271 | debugf0("F2x110 (DCTL Sel. Low): 0x%08x, " |
1347 | "High range addresses at: 0x%x\n", | 1272 | "High range addresses at: 0x%x\n", |
@@ -1367,7 +1292,7 @@ static void f10_read_dram_ctl_register(struct amd64_pvt *pvt) | |||
1367 | dct_sel_interleave_addr(pvt)); | 1292 | dct_sel_interleave_addr(pvt)); |
1368 | } | 1293 | } |
1369 | 1294 | ||
1370 | amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCTL_SEL_HIGH, | 1295 | amd64_read_pci_cfg(pvt->F2, F10_DCTL_SEL_HIGH, |
1371 | &pvt->dram_ctl_select_high); | 1296 | &pvt->dram_ctl_select_high); |
1372 | } | 1297 | } |
1373 | 1298 | ||
@@ -1496,7 +1421,7 @@ static int f10_lookup_addr_in_dct(u32 in_addr, u32 nid, u32 cs) | |||
1496 | int cs_found = -EINVAL; | 1421 | int cs_found = -EINVAL; |
1497 | int csrow; | 1422 | int csrow; |
1498 | 1423 | ||
1499 | mci = mci_lookup[nid]; | 1424 | mci = mcis[nid]; |
1500 | if (!mci) | 1425 | if (!mci) |
1501 | return cs_found; | 1426 | return cs_found; |
1502 | 1427 | ||
@@ -1738,28 +1663,17 @@ static void amd64_debug_display_dimm_sizes(int ctrl, struct amd64_pvt *pvt) | |||
1738 | if (dcsb[dimm*2 + 1] & K8_DCSB_CS_ENABLE) | 1663 | if (dcsb[dimm*2 + 1] & K8_DCSB_CS_ENABLE) |
1739 | size1 = pvt->ops->dbam_to_cs(pvt, DBAM_DIMM(dimm, dbam)); | 1664 | size1 = pvt->ops->dbam_to_cs(pvt, DBAM_DIMM(dimm, dbam)); |
1740 | 1665 | ||
1741 | edac_printk(KERN_DEBUG, EDAC_MC, " %d: %5dMB %d: %5dMB\n", | 1666 | amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n", |
1742 | dimm * 2, size0 << factor, | 1667 | dimm * 2, size0 << factor, |
1743 | dimm * 2 + 1, size1 << factor); | 1668 | dimm * 2 + 1, size1 << factor); |
1744 | } | 1669 | } |
1745 | } | 1670 | } |
1746 | 1671 | ||
1747 | /* | ||
1748 | * There currently are 3 types type of MC devices for AMD Athlon/Opterons | ||
1749 | * (as per PCI DEVICE_IDs): | ||
1750 | * | ||
1751 | * Family K8: That is the Athlon64 and Opteron CPUs. They all have the same PCI | ||
1752 | * DEVICE ID, even though there is differences between the different Revisions | ||
1753 | * (CG,D,E,F). | ||
1754 | * | ||
1755 | * Family F10h and F11h. | ||
1756 | * | ||
1757 | */ | ||
1758 | static struct amd64_family_type amd64_family_types[] = { | 1672 | static struct amd64_family_type amd64_family_types[] = { |
1759 | [K8_CPUS] = { | 1673 | [K8_CPUS] = { |
1760 | .ctl_name = "RevF", | 1674 | .ctl_name = "K8", |
1761 | .addr_f1_ctl = PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP, | 1675 | .f1_id = PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP, |
1762 | .misc_f3_ctl = PCI_DEVICE_ID_AMD_K8_NB_MISC, | 1676 | .f3_id = PCI_DEVICE_ID_AMD_K8_NB_MISC, |
1763 | .ops = { | 1677 | .ops = { |
1764 | .early_channel_count = k8_early_channel_count, | 1678 | .early_channel_count = k8_early_channel_count, |
1765 | .get_error_address = k8_get_error_address, | 1679 | .get_error_address = k8_get_error_address, |
@@ -1769,22 +1683,9 @@ static struct amd64_family_type amd64_family_types[] = { | |||
1769 | } | 1683 | } |
1770 | }, | 1684 | }, |
1771 | [F10_CPUS] = { | 1685 | [F10_CPUS] = { |
1772 | .ctl_name = "Family 10h", | 1686 | .ctl_name = "F10h", |
1773 | .addr_f1_ctl = PCI_DEVICE_ID_AMD_10H_NB_MAP, | 1687 | .f1_id = PCI_DEVICE_ID_AMD_10H_NB_MAP, |
1774 | .misc_f3_ctl = PCI_DEVICE_ID_AMD_10H_NB_MISC, | 1688 | .f3_id = PCI_DEVICE_ID_AMD_10H_NB_MISC, |
1775 | .ops = { | ||
1776 | .early_channel_count = f10_early_channel_count, | ||
1777 | .get_error_address = f10_get_error_address, | ||
1778 | .read_dram_base_limit = f10_read_dram_base_limit, | ||
1779 | .read_dram_ctl_register = f10_read_dram_ctl_register, | ||
1780 | .map_sysaddr_to_csrow = f10_map_sysaddr_to_csrow, | ||
1781 | .dbam_to_cs = f10_dbam_to_chip_select, | ||
1782 | } | ||
1783 | }, | ||
1784 | [F11_CPUS] = { | ||
1785 | .ctl_name = "Family 11h", | ||
1786 | .addr_f1_ctl = PCI_DEVICE_ID_AMD_11H_NB_MAP, | ||
1787 | .misc_f3_ctl = PCI_DEVICE_ID_AMD_11H_NB_MISC, | ||
1788 | .ops = { | 1689 | .ops = { |
1789 | .early_channel_count = f10_early_channel_count, | 1690 | .early_channel_count = f10_early_channel_count, |
1790 | .get_error_address = f10_get_error_address, | 1691 | .get_error_address = f10_get_error_address, |
@@ -1970,8 +1871,7 @@ static int get_channel_from_ecc_syndrome(struct mem_ctl_info *mci, u16 syndrome) | |||
1970 | ARRAY_SIZE(x4_vectors), | 1871 | ARRAY_SIZE(x4_vectors), |
1971 | pvt->syn_type); | 1872 | pvt->syn_type); |
1972 | else { | 1873 | else { |
1973 | amd64_printk(KERN_WARNING, "%s: Illegal syndrome type: %u\n", | 1874 | amd64_warn("Illegal syndrome type: %u\n", pvt->syn_type); |
1974 | __func__, pvt->syn_type); | ||
1975 | return err_sym; | 1875 | return err_sym; |
1976 | } | 1876 | } |
1977 | 1877 | ||
@@ -1989,17 +1889,15 @@ static void amd64_handle_ce(struct mem_ctl_info *mci, | |||
1989 | u64 sys_addr; | 1889 | u64 sys_addr; |
1990 | 1890 | ||
1991 | /* Ensure that the Error Address is VALID */ | 1891 | /* Ensure that the Error Address is VALID */ |
1992 | if ((info->nbsh & K8_NBSH_VALID_ERROR_ADDR) == 0) { | 1892 | if (!(info->nbsh & K8_NBSH_VALID_ERROR_ADDR)) { |
1993 | amd64_mc_printk(mci, KERN_ERR, | 1893 | amd64_mc_err(mci, "HW has no ERROR_ADDRESS available\n"); |
1994 | "HW has no ERROR_ADDRESS available\n"); | ||
1995 | edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR); | 1894 | edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR); |
1996 | return; | 1895 | return; |
1997 | } | 1896 | } |
1998 | 1897 | ||
1999 | sys_addr = pvt->ops->get_error_address(mci, info); | 1898 | sys_addr = pvt->ops->get_error_address(mci, info); |
2000 | 1899 | ||
2001 | amd64_mc_printk(mci, KERN_ERR, | 1900 | amd64_mc_err(mci, "CE ERROR_ADDRESS= 0x%llx\n", sys_addr); |
2002 | "CE ERROR_ADDRESS= 0x%llx\n", sys_addr); | ||
2003 | 1901 | ||
2004 | pvt->ops->map_sysaddr_to_csrow(mci, info, sys_addr); | 1902 | pvt->ops->map_sysaddr_to_csrow(mci, info, sys_addr); |
2005 | } | 1903 | } |
@@ -2016,9 +1914,8 @@ static void amd64_handle_ue(struct mem_ctl_info *mci, | |||
2016 | 1914 | ||
2017 | log_mci = mci; | 1915 | log_mci = mci; |
2018 | 1916 | ||
2019 | if ((info->nbsh & K8_NBSH_VALID_ERROR_ADDR) == 0) { | 1917 | if (!(info->nbsh & K8_NBSH_VALID_ERROR_ADDR)) { |
2020 | amd64_mc_printk(mci, KERN_CRIT, | 1918 | amd64_mc_err(mci, "HW has no ERROR_ADDRESS available\n"); |
2021 | "HW has no ERROR_ADDRESS available\n"); | ||
2022 | edac_mc_handle_ue_no_info(log_mci, EDAC_MOD_STR); | 1919 | edac_mc_handle_ue_no_info(log_mci, EDAC_MOD_STR); |
2023 | return; | 1920 | return; |
2024 | } | 1921 | } |
@@ -2031,9 +1928,8 @@ static void amd64_handle_ue(struct mem_ctl_info *mci, | |||
2031 | */ | 1928 | */ |
2032 | src_mci = find_mc_by_sys_addr(mci, sys_addr); | 1929 | src_mci = find_mc_by_sys_addr(mci, sys_addr); |
2033 | if (!src_mci) { | 1930 | if (!src_mci) { |
2034 | amd64_mc_printk(mci, KERN_CRIT, | 1931 | amd64_mc_err(mci, "ERROR ADDRESS (0x%lx) NOT mapped to a MC\n", |
2035 | "ERROR ADDRESS (0x%lx) value NOT mapped to a MC\n", | 1932 | (unsigned long)sys_addr); |
2036 | (unsigned long)sys_addr); | ||
2037 | edac_mc_handle_ue_no_info(log_mci, EDAC_MOD_STR); | 1933 | edac_mc_handle_ue_no_info(log_mci, EDAC_MOD_STR); |
2038 | return; | 1934 | return; |
2039 | } | 1935 | } |
@@ -2042,9 +1938,8 @@ static void amd64_handle_ue(struct mem_ctl_info *mci, | |||
2042 | 1938 | ||
2043 | csrow = sys_addr_to_csrow(log_mci, sys_addr); | 1939 | csrow = sys_addr_to_csrow(log_mci, sys_addr); |
2044 | if (csrow < 0) { | 1940 | if (csrow < 0) { |
2045 | amd64_mc_printk(mci, KERN_CRIT, | 1941 | amd64_mc_err(mci, "ERROR_ADDRESS (0x%lx) NOT mapped to CS\n", |
2046 | "ERROR_ADDRESS (0x%lx) value NOT mapped to 'csrow'\n", | 1942 | (unsigned long)sys_addr); |
2047 | (unsigned long)sys_addr); | ||
2048 | edac_mc_handle_ue_no_info(log_mci, EDAC_MOD_STR); | 1943 | edac_mc_handle_ue_no_info(log_mci, EDAC_MOD_STR); |
2049 | } else { | 1944 | } else { |
2050 | error_address_to_page_and_offset(sys_addr, &page, &offset); | 1945 | error_address_to_page_and_offset(sys_addr, &page, &offset); |
@@ -2055,8 +1950,8 @@ static void amd64_handle_ue(struct mem_ctl_info *mci, | |||
2055 | static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci, | 1950 | static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci, |
2056 | struct err_regs *info) | 1951 | struct err_regs *info) |
2057 | { | 1952 | { |
2058 | u32 ec = ERROR_CODE(info->nbsl); | 1953 | u16 ec = EC(info->nbsl); |
2059 | u32 xec = EXT_ERROR_CODE(info->nbsl); | 1954 | u8 xec = XEC(info->nbsl, 0x1f); |
2060 | int ecc_type = (info->nbsh >> 13) & 0x3; | 1955 | int ecc_type = (info->nbsh >> 13) & 0x3; |
2061 | 1956 | ||
2062 | /* Bail early out if this was an 'observed' error */ | 1957 | /* Bail early out if this was an 'observed' error */ |
@@ -2075,7 +1970,7 @@ static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci, | |||
2075 | 1970 | ||
2076 | void amd64_decode_bus_error(int node_id, struct mce *m, u32 nbcfg) | 1971 | void amd64_decode_bus_error(int node_id, struct mce *m, u32 nbcfg) |
2077 | { | 1972 | { |
2078 | struct mem_ctl_info *mci = mci_lookup[node_id]; | 1973 | struct mem_ctl_info *mci = mcis[node_id]; |
2079 | struct err_regs regs; | 1974 | struct err_regs regs; |
2080 | 1975 | ||
2081 | regs.nbsl = (u32) m->status; | 1976 | regs.nbsl = (u32) m->status; |
@@ -2099,75 +1994,50 @@ void amd64_decode_bus_error(int node_id, struct mce *m, u32 nbcfg) | |||
2099 | } | 1994 | } |
2100 | 1995 | ||
2101 | /* | 1996 | /* |
2102 | * Input: | 1997 | * Use pvt->F2 which contains the F2 CPU PCI device to get the related |
2103 | * 1) struct amd64_pvt which contains pvt->dram_f2_ctl pointer | 1998 | * F1 (AddrMap) and F3 (Misc) devices. Return negative value on error. |
2104 | * 2) AMD Family index value | ||
2105 | * | ||
2106 | * Ouput: | ||
2107 | * Upon return of 0, the following filled in: | ||
2108 | * | ||
2109 | * struct pvt->addr_f1_ctl | ||
2110 | * struct pvt->misc_f3_ctl | ||
2111 | * | ||
2112 | * Filled in with related device funcitions of 'dram_f2_ctl' | ||
2113 | * These devices are "reserved" via the pci_get_device() | ||
2114 | * | ||
2115 | * Upon return of 1 (error status): | ||
2116 | * | ||
2117 | * Nothing reserved | ||
2118 | */ | 1999 | */ |
2119 | static int amd64_reserve_mc_sibling_devices(struct amd64_pvt *pvt, int mc_idx) | 2000 | static int reserve_mc_sibling_devs(struct amd64_pvt *pvt, u16 f1_id, u16 f3_id) |
2120 | { | 2001 | { |
2121 | const struct amd64_family_type *amd64_dev = &amd64_family_types[mc_idx]; | ||
2122 | |||
2123 | /* Reserve the ADDRESS MAP Device */ | 2002 | /* Reserve the ADDRESS MAP Device */ |
2124 | pvt->addr_f1_ctl = pci_get_related_function(pvt->dram_f2_ctl->vendor, | 2003 | pvt->F1 = pci_get_related_function(pvt->F2->vendor, f1_id, pvt->F2); |
2125 | amd64_dev->addr_f1_ctl, | 2004 | if (!pvt->F1) { |
2126 | pvt->dram_f2_ctl); | 2005 | amd64_err("error address map device not found: " |
2127 | 2006 | "vendor %x device 0x%x (broken BIOS?)\n", | |
2128 | if (!pvt->addr_f1_ctl) { | 2007 | PCI_VENDOR_ID_AMD, f1_id); |
2129 | amd64_printk(KERN_ERR, "error address map device not found: " | 2008 | return -ENODEV; |
2130 | "vendor %x device 0x%x (broken BIOS?)\n", | ||
2131 | PCI_VENDOR_ID_AMD, amd64_dev->addr_f1_ctl); | ||
2132 | return 1; | ||
2133 | } | 2009 | } |
2134 | 2010 | ||
2135 | /* Reserve the MISC Device */ | 2011 | /* Reserve the MISC Device */ |
2136 | pvt->misc_f3_ctl = pci_get_related_function(pvt->dram_f2_ctl->vendor, | 2012 | pvt->F3 = pci_get_related_function(pvt->F2->vendor, f3_id, pvt->F2); |
2137 | amd64_dev->misc_f3_ctl, | 2013 | if (!pvt->F3) { |
2138 | pvt->dram_f2_ctl); | 2014 | pci_dev_put(pvt->F1); |
2015 | pvt->F1 = NULL; | ||
2139 | 2016 | ||
2140 | if (!pvt->misc_f3_ctl) { | 2017 | amd64_err("error F3 device not found: " |
2141 | pci_dev_put(pvt->addr_f1_ctl); | 2018 | "vendor %x device 0x%x (broken BIOS?)\n", |
2142 | pvt->addr_f1_ctl = NULL; | 2019 | PCI_VENDOR_ID_AMD, f3_id); |
2143 | 2020 | ||
2144 | amd64_printk(KERN_ERR, "error miscellaneous device not found: " | 2021 | return -ENODEV; |
2145 | "vendor %x device 0x%x (broken BIOS?)\n", | ||
2146 | PCI_VENDOR_ID_AMD, amd64_dev->misc_f3_ctl); | ||
2147 | return 1; | ||
2148 | } | 2022 | } |
2149 | 2023 | debugf1("F1: %s\n", pci_name(pvt->F1)); | |
2150 | debugf1(" Addr Map device PCI Bus ID:\t%s\n", | 2024 | debugf1("F2: %s\n", pci_name(pvt->F2)); |
2151 | pci_name(pvt->addr_f1_ctl)); | 2025 | debugf1("F3: %s\n", pci_name(pvt->F3)); |
2152 | debugf1(" DRAM MEM-CTL PCI Bus ID:\t%s\n", | ||
2153 | pci_name(pvt->dram_f2_ctl)); | ||
2154 | debugf1(" Misc device PCI Bus ID:\t%s\n", | ||
2155 | pci_name(pvt->misc_f3_ctl)); | ||
2156 | 2026 | ||
2157 | return 0; | 2027 | return 0; |
2158 | } | 2028 | } |
2159 | 2029 | ||
2160 | static void amd64_free_mc_sibling_devices(struct amd64_pvt *pvt) | 2030 | static void free_mc_sibling_devs(struct amd64_pvt *pvt) |
2161 | { | 2031 | { |
2162 | pci_dev_put(pvt->addr_f1_ctl); | 2032 | pci_dev_put(pvt->F1); |
2163 | pci_dev_put(pvt->misc_f3_ctl); | 2033 | pci_dev_put(pvt->F3); |
2164 | } | 2034 | } |
2165 | 2035 | ||
2166 | /* | 2036 | /* |
2167 | * Retrieve the hardware registers of the memory controller (this includes the | 2037 | * Retrieve the hardware registers of the memory controller (this includes the |
2168 | * 'Address Map' and 'Misc' device regs) | 2038 | * 'Address Map' and 'Misc' device regs) |
2169 | */ | 2039 | */ |
2170 | static void amd64_read_mc_registers(struct amd64_pvt *pvt) | 2040 | static void read_mc_regs(struct amd64_pvt *pvt) |
2171 | { | 2041 | { |
2172 | u64 msr_val; | 2042 | u64 msr_val; |
2173 | u32 tmp; | 2043 | u32 tmp; |
@@ -2188,9 +2058,7 @@ static void amd64_read_mc_registers(struct amd64_pvt *pvt) | |||
2188 | } else | 2058 | } else |
2189 | debugf0(" TOP_MEM2 disabled.\n"); | 2059 | debugf0(" TOP_MEM2 disabled.\n"); |
2190 | 2060 | ||
2191 | amd64_cpu_display_info(pvt); | 2061 | amd64_read_pci_cfg(pvt->F3, K8_NBCAP, &pvt->nbcap); |
2192 | |||
2193 | amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCAP, &pvt->nbcap); | ||
2194 | 2062 | ||
2195 | if (pvt->ops->read_dram_ctl_register) | 2063 | if (pvt->ops->read_dram_ctl_register) |
2196 | pvt->ops->read_dram_ctl_register(pvt); | 2064 | pvt->ops->read_dram_ctl_register(pvt); |
@@ -2227,21 +2095,20 @@ static void amd64_read_mc_registers(struct amd64_pvt *pvt) | |||
2227 | 2095 | ||
2228 | amd64_read_dct_base_mask(pvt); | 2096 | amd64_read_dct_base_mask(pvt); |
2229 | 2097 | ||
2230 | amd64_read_pci_cfg(pvt->addr_f1_ctl, K8_DHAR, &pvt->dhar); | 2098 | amd64_read_pci_cfg(pvt->F1, K8_DHAR, &pvt->dhar); |
2231 | amd64_read_dbam_reg(pvt); | 2099 | amd64_read_dbam_reg(pvt); |
2232 | 2100 | ||
2233 | amd64_read_pci_cfg(pvt->misc_f3_ctl, | 2101 | amd64_read_pci_cfg(pvt->F3, F10_ONLINE_SPARE, &pvt->online_spare); |
2234 | F10_ONLINE_SPARE, &pvt->online_spare); | ||
2235 | 2102 | ||
2236 | amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCLR_0, &pvt->dclr0); | 2103 | amd64_read_pci_cfg(pvt->F2, F10_DCLR_0, &pvt->dclr0); |
2237 | amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCHR_0, &pvt->dchr0); | 2104 | amd64_read_pci_cfg(pvt->F2, F10_DCHR_0, &pvt->dchr0); |
2238 | 2105 | ||
2239 | if (boot_cpu_data.x86 >= 0x10) { | 2106 | if (boot_cpu_data.x86 >= 0x10) { |
2240 | if (!dct_ganging_enabled(pvt)) { | 2107 | if (!dct_ganging_enabled(pvt)) { |
2241 | amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCLR_1, &pvt->dclr1); | 2108 | amd64_read_pci_cfg(pvt->F2, F10_DCLR_1, &pvt->dclr1); |
2242 | amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCHR_1, &pvt->dchr1); | 2109 | amd64_read_pci_cfg(pvt->F2, F10_DCHR_1, &pvt->dchr1); |
2243 | } | 2110 | } |
2244 | amd64_read_pci_cfg(pvt->misc_f3_ctl, EXT_NB_MCA_CFG, &tmp); | 2111 | amd64_read_pci_cfg(pvt->F3, EXT_NB_MCA_CFG, &tmp); |
2245 | } | 2112 | } |
2246 | 2113 | ||
2247 | if (boot_cpu_data.x86 == 0x10 && | 2114 | if (boot_cpu_data.x86 == 0x10 && |
@@ -2321,21 +2188,22 @@ static u32 amd64_csrow_nr_pages(int csrow_nr, struct amd64_pvt *pvt) | |||
2321 | * Initialize the array of csrow attribute instances, based on the values | 2188 | * Initialize the array of csrow attribute instances, based on the values |
2322 | * from pci config hardware registers. | 2189 | * from pci config hardware registers. |
2323 | */ | 2190 | */ |
2324 | static int amd64_init_csrows(struct mem_ctl_info *mci) | 2191 | static int init_csrows(struct mem_ctl_info *mci) |
2325 | { | 2192 | { |
2326 | struct csrow_info *csrow; | 2193 | struct csrow_info *csrow; |
2327 | struct amd64_pvt *pvt; | 2194 | struct amd64_pvt *pvt = mci->pvt_info; |
2328 | u64 input_addr_min, input_addr_max, sys_addr; | 2195 | u64 input_addr_min, input_addr_max, sys_addr; |
2196 | u32 val; | ||
2329 | int i, empty = 1; | 2197 | int i, empty = 1; |
2330 | 2198 | ||
2331 | pvt = mci->pvt_info; | 2199 | amd64_read_pci_cfg(pvt->F3, K8_NBCFG, &val); |
2332 | 2200 | ||
2333 | amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCFG, &pvt->nbcfg); | 2201 | pvt->nbcfg = val; |
2202 | pvt->ctl_error_info.nbcfg = val; | ||
2334 | 2203 | ||
2335 | debugf0("NBCFG= 0x%x CHIPKILL= %s DRAM ECC= %s\n", pvt->nbcfg, | 2204 | debugf0("node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n", |
2336 | (pvt->nbcfg & K8_NBCFG_CHIPKILL) ? "Enabled" : "Disabled", | 2205 | pvt->mc_node_id, val, |
2337 | (pvt->nbcfg & K8_NBCFG_ECC_ENABLE) ? "Enabled" : "Disabled" | 2206 | !!(val & K8_NBCFG_CHIPKILL), !!(val & K8_NBCFG_ECC_ENABLE)); |
2338 | ); | ||
2339 | 2207 | ||
2340 | for (i = 0; i < pvt->cs_count; i++) { | 2208 | for (i = 0; i < pvt->cs_count; i++) { |
2341 | csrow = &mci->csrows[i]; | 2209 | csrow = &mci->csrows[i]; |
@@ -2359,7 +2227,7 @@ static int amd64_init_csrows(struct mem_ctl_info *mci) | |||
2359 | csrow->page_mask = ~mask_from_dct_mask(pvt, i); | 2227 | csrow->page_mask = ~mask_from_dct_mask(pvt, i); |
2360 | /* 8 bytes of resolution */ | 2228 | /* 8 bytes of resolution */ |
2361 | 2229 | ||
2362 | csrow->mtype = amd64_determine_memory_type(pvt); | 2230 | csrow->mtype = amd64_determine_memory_type(pvt, i); |
2363 | 2231 | ||
2364 | debugf1(" for MC node %d csrow %d:\n", pvt->mc_node_id, i); | 2232 | debugf1(" for MC node %d csrow %d:\n", pvt->mc_node_id, i); |
2365 | debugf1(" input_addr_min: 0x%lx input_addr_max: 0x%lx\n", | 2233 | debugf1(" input_addr_min: 0x%lx input_addr_max: 0x%lx\n", |
@@ -2404,8 +2272,7 @@ static bool amd64_nb_mce_bank_enabled_on_node(int nid) | |||
2404 | bool ret = false; | 2272 | bool ret = false; |
2405 | 2273 | ||
2406 | if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) { | 2274 | if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) { |
2407 | amd64_printk(KERN_WARNING, "%s: error allocating mask\n", | 2275 | amd64_warn("%s: Error allocating mask\n", __func__); |
2408 | __func__); | ||
2409 | return false; | 2276 | return false; |
2410 | } | 2277 | } |
2411 | 2278 | ||
@@ -2431,18 +2298,17 @@ out: | |||
2431 | return ret; | 2298 | return ret; |
2432 | } | 2299 | } |
2433 | 2300 | ||
2434 | static int amd64_toggle_ecc_err_reporting(struct amd64_pvt *pvt, bool on) | 2301 | static int toggle_ecc_err_reporting(struct ecc_settings *s, u8 nid, bool on) |
2435 | { | 2302 | { |
2436 | cpumask_var_t cmask; | 2303 | cpumask_var_t cmask; |
2437 | int cpu; | 2304 | int cpu; |
2438 | 2305 | ||
2439 | if (!zalloc_cpumask_var(&cmask, GFP_KERNEL)) { | 2306 | if (!zalloc_cpumask_var(&cmask, GFP_KERNEL)) { |
2440 | amd64_printk(KERN_WARNING, "%s: error allocating mask\n", | 2307 | amd64_warn("%s: error allocating mask\n", __func__); |
2441 | __func__); | ||
2442 | return false; | 2308 | return false; |
2443 | } | 2309 | } |
2444 | 2310 | ||
2445 | get_cpus_on_this_dct_cpumask(cmask, pvt->mc_node_id); | 2311 | get_cpus_on_this_dct_cpumask(cmask, nid); |
2446 | 2312 | ||
2447 | rdmsr_on_cpus(cmask, MSR_IA32_MCG_CTL, msrs); | 2313 | rdmsr_on_cpus(cmask, MSR_IA32_MCG_CTL, msrs); |
2448 | 2314 | ||
@@ -2452,14 +2318,14 @@ static int amd64_toggle_ecc_err_reporting(struct amd64_pvt *pvt, bool on) | |||
2452 | 2318 | ||
2453 | if (on) { | 2319 | if (on) { |
2454 | if (reg->l & K8_MSR_MCGCTL_NBE) | 2320 | if (reg->l & K8_MSR_MCGCTL_NBE) |
2455 | pvt->flags.nb_mce_enable = 1; | 2321 | s->flags.nb_mce_enable = 1; |
2456 | 2322 | ||
2457 | reg->l |= K8_MSR_MCGCTL_NBE; | 2323 | reg->l |= K8_MSR_MCGCTL_NBE; |
2458 | } else { | 2324 | } else { |
2459 | /* | 2325 | /* |
2460 | * Turn off NB MCE reporting only when it was off before | 2326 | * Turn off NB MCE reporting only when it was off before |
2461 | */ | 2327 | */ |
2462 | if (!pvt->flags.nb_mce_enable) | 2328 | if (!s->flags.nb_mce_enable) |
2463 | reg->l &= ~K8_MSR_MCGCTL_NBE; | 2329 | reg->l &= ~K8_MSR_MCGCTL_NBE; |
2464 | } | 2330 | } |
2465 | } | 2331 | } |
@@ -2470,92 +2336,92 @@ static int amd64_toggle_ecc_err_reporting(struct amd64_pvt *pvt, bool on) | |||
2470 | return 0; | 2336 | return 0; |
2471 | } | 2337 | } |
2472 | 2338 | ||
2473 | static void amd64_enable_ecc_error_reporting(struct mem_ctl_info *mci) | 2339 | static bool enable_ecc_error_reporting(struct ecc_settings *s, u8 nid, |
2340 | struct pci_dev *F3) | ||
2474 | { | 2341 | { |
2475 | struct amd64_pvt *pvt = mci->pvt_info; | 2342 | bool ret = true; |
2476 | u32 value, mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn; | 2343 | u32 value, mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn; |
2477 | 2344 | ||
2478 | amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCTL, &value); | 2345 | if (toggle_ecc_err_reporting(s, nid, ON)) { |
2346 | amd64_warn("Error enabling ECC reporting over MCGCTL!\n"); | ||
2347 | return false; | ||
2348 | } | ||
2349 | |||
2350 | amd64_read_pci_cfg(F3, K8_NBCTL, &value); | ||
2479 | 2351 | ||
2480 | /* turn on UECCn and CECCEn bits */ | 2352 | /* turn on UECCEn and CECCEn bits */ |
2481 | pvt->old_nbctl = value & mask; | 2353 | s->old_nbctl = value & mask; |
2482 | pvt->nbctl_mcgctl_saved = 1; | 2354 | s->nbctl_valid = true; |
2483 | 2355 | ||
2484 | value |= mask; | 2356 | value |= mask; |
2485 | pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCTL, value); | 2357 | pci_write_config_dword(F3, K8_NBCTL, value); |
2486 | |||
2487 | if (amd64_toggle_ecc_err_reporting(pvt, ON)) | ||
2488 | amd64_printk(KERN_WARNING, "Error enabling ECC reporting over " | ||
2489 | "MCGCTL!\n"); | ||
2490 | 2358 | ||
2491 | amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCFG, &value); | 2359 | amd64_read_pci_cfg(F3, K8_NBCFG, &value); |
2492 | 2360 | ||
2493 | debugf0("NBCFG(1)= 0x%x CHIPKILL= %s ECC_ENABLE= %s\n", value, | 2361 | debugf0("1: node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n", |
2494 | (value & K8_NBCFG_CHIPKILL) ? "Enabled" : "Disabled", | 2362 | nid, value, |
2495 | (value & K8_NBCFG_ECC_ENABLE) ? "Enabled" : "Disabled"); | 2363 | !!(value & K8_NBCFG_CHIPKILL), !!(value & K8_NBCFG_ECC_ENABLE)); |
2496 | 2364 | ||
2497 | if (!(value & K8_NBCFG_ECC_ENABLE)) { | 2365 | if (!(value & K8_NBCFG_ECC_ENABLE)) { |
2498 | amd64_printk(KERN_WARNING, | 2366 | amd64_warn("DRAM ECC disabled on this node, enabling...\n"); |
2499 | "This node reports that DRAM ECC is " | ||
2500 | "currently Disabled; ENABLING now\n"); | ||
2501 | 2367 | ||
2502 | pvt->flags.nb_ecc_prev = 0; | 2368 | s->flags.nb_ecc_prev = 0; |
2503 | 2369 | ||
2504 | /* Attempt to turn on DRAM ECC Enable */ | 2370 | /* Attempt to turn on DRAM ECC Enable */ |
2505 | value |= K8_NBCFG_ECC_ENABLE; | 2371 | value |= K8_NBCFG_ECC_ENABLE; |
2506 | pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCFG, value); | 2372 | pci_write_config_dword(F3, K8_NBCFG, value); |
2507 | 2373 | ||
2508 | amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCFG, &value); | 2374 | amd64_read_pci_cfg(F3, K8_NBCFG, &value); |
2509 | 2375 | ||
2510 | if (!(value & K8_NBCFG_ECC_ENABLE)) { | 2376 | if (!(value & K8_NBCFG_ECC_ENABLE)) { |
2511 | amd64_printk(KERN_WARNING, | 2377 | amd64_warn("Hardware rejected DRAM ECC enable," |
2512 | "Hardware rejects Enabling DRAM ECC checking\n" | 2378 | "check memory DIMM configuration.\n"); |
2513 | "Check memory DIMM configuration\n"); | 2379 | ret = false; |
2514 | } else { | 2380 | } else { |
2515 | amd64_printk(KERN_DEBUG, | 2381 | amd64_info("Hardware accepted DRAM ECC Enable\n"); |
2516 | "Hardware accepted DRAM ECC Enable\n"); | ||
2517 | } | 2382 | } |
2518 | } else { | 2383 | } else { |
2519 | pvt->flags.nb_ecc_prev = 1; | 2384 | s->flags.nb_ecc_prev = 1; |
2520 | } | 2385 | } |
2521 | 2386 | ||
2522 | debugf0("NBCFG(2)= 0x%x CHIPKILL= %s ECC_ENABLE= %s\n", value, | 2387 | debugf0("2: node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n", |
2523 | (value & K8_NBCFG_CHIPKILL) ? "Enabled" : "Disabled", | 2388 | nid, value, |
2524 | (value & K8_NBCFG_ECC_ENABLE) ? "Enabled" : "Disabled"); | 2389 | !!(value & K8_NBCFG_CHIPKILL), !!(value & K8_NBCFG_ECC_ENABLE)); |
2525 | 2390 | ||
2526 | pvt->ctl_error_info.nbcfg = value; | 2391 | return ret; |
2527 | } | 2392 | } |
2528 | 2393 | ||
2529 | static void amd64_restore_ecc_error_reporting(struct amd64_pvt *pvt) | 2394 | static void restore_ecc_error_reporting(struct ecc_settings *s, u8 nid, |
2395 | struct pci_dev *F3) | ||
2530 | { | 2396 | { |
2531 | u32 value, mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn; | 2397 | u32 value, mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn; |
2532 | 2398 | ||
2533 | if (!pvt->nbctl_mcgctl_saved) | 2399 | if (!s->nbctl_valid) |
2534 | return; | 2400 | return; |
2535 | 2401 | ||
2536 | amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCTL, &value); | 2402 | amd64_read_pci_cfg(F3, K8_NBCTL, &value); |
2537 | value &= ~mask; | 2403 | value &= ~mask; |
2538 | value |= pvt->old_nbctl; | 2404 | value |= s->old_nbctl; |
2539 | 2405 | ||
2540 | pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCTL, value); | 2406 | pci_write_config_dword(F3, K8_NBCTL, value); |
2541 | 2407 | ||
2542 | /* restore previous BIOS DRAM ECC "off" setting which we force-enabled */ | 2408 | /* restore previous BIOS DRAM ECC "off" setting we force-enabled */ |
2543 | if (!pvt->flags.nb_ecc_prev) { | 2409 | if (!s->flags.nb_ecc_prev) { |
2544 | amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCFG, &value); | 2410 | amd64_read_pci_cfg(F3, K8_NBCFG, &value); |
2545 | value &= ~K8_NBCFG_ECC_ENABLE; | 2411 | value &= ~K8_NBCFG_ECC_ENABLE; |
2546 | pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCFG, value); | 2412 | pci_write_config_dword(F3, K8_NBCFG, value); |
2547 | } | 2413 | } |
2548 | 2414 | ||
2549 | /* restore the NB Enable MCGCTL bit */ | 2415 | /* restore the NB Enable MCGCTL bit */ |
2550 | if (amd64_toggle_ecc_err_reporting(pvt, OFF)) | 2416 | if (toggle_ecc_err_reporting(s, nid, OFF)) |
2551 | amd64_printk(KERN_WARNING, "Error restoring NB MCGCTL settings!\n"); | 2417 | amd64_warn("Error restoring NB MCGCTL settings!\n"); |
2552 | } | 2418 | } |
2553 | 2419 | ||
2554 | /* | 2420 | /* |
2555 | * EDAC requires that the BIOS have ECC enabled before taking over the | 2421 | * EDAC requires that the BIOS have ECC enabled before |
2556 | * processing of ECC errors. This is because the BIOS can properly initialize | 2422 | * taking over the processing of ECC errors. A command line |
2557 | * the memory system completely. A command line option allows to force-enable | 2423 | * option allows to force-enable hardware ECC later in |
2558 | * hardware ECC later in amd64_enable_ecc_error_reporting(). | 2424 | * enable_ecc_error_reporting(). |
2559 | */ | 2425 | */ |
2560 | static const char *ecc_msg = | 2426 | static const char *ecc_msg = |
2561 | "ECC disabled in the BIOS or no ECC capability, module will not load.\n" | 2427 | "ECC disabled in the BIOS or no ECC capability, module will not load.\n" |
@@ -2563,38 +2429,28 @@ static const char *ecc_msg = | |||
2563 | "'ecc_enable_override'.\n" | 2429 | "'ecc_enable_override'.\n" |
2564 | " (Note that use of the override may cause unknown side effects.)\n"; | 2430 | " (Note that use of the override may cause unknown side effects.)\n"; |
2565 | 2431 | ||
2566 | static int amd64_check_ecc_enabled(struct amd64_pvt *pvt) | 2432 | static bool ecc_enabled(struct pci_dev *F3, u8 nid) |
2567 | { | 2433 | { |
2568 | u32 value; | 2434 | u32 value; |
2569 | u8 ecc_enabled = 0; | 2435 | u8 ecc_en = 0; |
2570 | bool nb_mce_en = false; | 2436 | bool nb_mce_en = false; |
2571 | 2437 | ||
2572 | amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCFG, &value); | 2438 | amd64_read_pci_cfg(F3, K8_NBCFG, &value); |
2573 | 2439 | ||
2574 | ecc_enabled = !!(value & K8_NBCFG_ECC_ENABLE); | 2440 | ecc_en = !!(value & K8_NBCFG_ECC_ENABLE); |
2575 | if (!ecc_enabled) | 2441 | amd64_info("DRAM ECC %s.\n", (ecc_en ? "enabled" : "disabled")); |
2576 | amd64_printk(KERN_NOTICE, "This node reports that Memory ECC " | ||
2577 | "is currently disabled, set F3x%x[22] (%s).\n", | ||
2578 | K8_NBCFG, pci_name(pvt->misc_f3_ctl)); | ||
2579 | else | ||
2580 | amd64_printk(KERN_INFO, "ECC is enabled by BIOS.\n"); | ||
2581 | 2442 | ||
2582 | nb_mce_en = amd64_nb_mce_bank_enabled_on_node(pvt->mc_node_id); | 2443 | nb_mce_en = amd64_nb_mce_bank_enabled_on_node(nid); |
2583 | if (!nb_mce_en) | 2444 | if (!nb_mce_en) |
2584 | amd64_printk(KERN_NOTICE, "NB MCE bank disabled, set MSR " | 2445 | amd64_notice("NB MCE bank disabled, set MSR " |
2585 | "0x%08x[4] on node %d to enable.\n", | 2446 | "0x%08x[4] on node %d to enable.\n", |
2586 | MSR_IA32_MCG_CTL, pvt->mc_node_id); | 2447 | MSR_IA32_MCG_CTL, nid); |
2587 | 2448 | ||
2588 | if (!ecc_enabled || !nb_mce_en) { | 2449 | if (!ecc_en || !nb_mce_en) { |
2589 | if (!ecc_enable_override) { | 2450 | amd64_notice("%s", ecc_msg); |
2590 | amd64_printk(KERN_NOTICE, "%s", ecc_msg); | 2451 | return false; |
2591 | return -ENODEV; | ||
2592 | } else { | ||
2593 | amd64_printk(KERN_WARNING, "Forcing ECC checking on!\n"); | ||
2594 | } | ||
2595 | } | 2452 | } |
2596 | 2453 | return true; | |
2597 | return 0; | ||
2598 | } | 2454 | } |
2599 | 2455 | ||
2600 | struct mcidev_sysfs_attribute sysfs_attrs[ARRAY_SIZE(amd64_dbg_attrs) + | 2456 | struct mcidev_sysfs_attribute sysfs_attrs[ARRAY_SIZE(amd64_dbg_attrs) + |
@@ -2603,22 +2459,23 @@ struct mcidev_sysfs_attribute sysfs_attrs[ARRAY_SIZE(amd64_dbg_attrs) + | |||
2603 | 2459 | ||
2604 | struct mcidev_sysfs_attribute terminator = { .attr = { .name = NULL } }; | 2460 | struct mcidev_sysfs_attribute terminator = { .attr = { .name = NULL } }; |
2605 | 2461 | ||
2606 | static void amd64_set_mc_sysfs_attributes(struct mem_ctl_info *mci) | 2462 | static void set_mc_sysfs_attrs(struct mem_ctl_info *mci) |
2607 | { | 2463 | { |
2608 | unsigned int i = 0, j = 0; | 2464 | unsigned int i = 0, j = 0; |
2609 | 2465 | ||
2610 | for (; i < ARRAY_SIZE(amd64_dbg_attrs); i++) | 2466 | for (; i < ARRAY_SIZE(amd64_dbg_attrs); i++) |
2611 | sysfs_attrs[i] = amd64_dbg_attrs[i]; | 2467 | sysfs_attrs[i] = amd64_dbg_attrs[i]; |
2612 | 2468 | ||
2613 | for (j = 0; j < ARRAY_SIZE(amd64_inj_attrs); j++, i++) | 2469 | if (boot_cpu_data.x86 >= 0x10) |
2614 | sysfs_attrs[i] = amd64_inj_attrs[j]; | 2470 | for (j = 0; j < ARRAY_SIZE(amd64_inj_attrs); j++, i++) |
2471 | sysfs_attrs[i] = amd64_inj_attrs[j]; | ||
2615 | 2472 | ||
2616 | sysfs_attrs[i] = terminator; | 2473 | sysfs_attrs[i] = terminator; |
2617 | 2474 | ||
2618 | mci->mc_driver_sysfs_attributes = sysfs_attrs; | 2475 | mci->mc_driver_sysfs_attributes = sysfs_attrs; |
2619 | } | 2476 | } |
2620 | 2477 | ||
2621 | static void amd64_setup_mci_misc_attributes(struct mem_ctl_info *mci) | 2478 | static void setup_mci_misc_attrs(struct mem_ctl_info *mci) |
2622 | { | 2479 | { |
2623 | struct amd64_pvt *pvt = mci->pvt_info; | 2480 | struct amd64_pvt *pvt = mci->pvt_info; |
2624 | 2481 | ||
@@ -2634,8 +2491,8 @@ static void amd64_setup_mci_misc_attributes(struct mem_ctl_info *mci) | |||
2634 | mci->edac_cap = amd64_determine_edac_cap(pvt); | 2491 | mci->edac_cap = amd64_determine_edac_cap(pvt); |
2635 | mci->mod_name = EDAC_MOD_STR; | 2492 | mci->mod_name = EDAC_MOD_STR; |
2636 | mci->mod_ver = EDAC_AMD64_VERSION; | 2493 | mci->mod_ver = EDAC_AMD64_VERSION; |
2637 | mci->ctl_name = get_amd_family_name(pvt->mc_type_index); | 2494 | mci->ctl_name = pvt->ctl_name; |
2638 | mci->dev_name = pci_name(pvt->dram_f2_ctl); | 2495 | mci->dev_name = pci_name(pvt->F2); |
2639 | mci->ctl_page_to_phys = NULL; | 2496 | mci->ctl_page_to_phys = NULL; |
2640 | 2497 | ||
2641 | /* memory scrubber interface */ | 2498 | /* memory scrubber interface */ |
@@ -2644,111 +2501,94 @@ static void amd64_setup_mci_misc_attributes(struct mem_ctl_info *mci) | |||
2644 | } | 2501 | } |
2645 | 2502 | ||
2646 | /* | 2503 | /* |
2647 | * Init stuff for this DRAM Controller device. | 2504 | * returns a pointer to the family descriptor on success, NULL otherwise. |
2648 | * | ||
2649 | * Due to a hardware feature on Fam10h CPUs, the Enable Extended Configuration | ||
2650 | * Space feature MUST be enabled on ALL Processors prior to actually reading | ||
2651 | * from the ECS registers. Since the loading of the module can occur on any | ||
2652 | * 'core', and cores don't 'see' all the other processors ECS data when the | ||
2653 | * others are NOT enabled. Our solution is to first enable ECS access in this | ||
2654 | * routine on all processors, gather some data in a amd64_pvt structure and | ||
2655 | * later come back in a finish-setup function to perform that final | ||
2656 | * initialization. See also amd64_init_2nd_stage() for that. | ||
2657 | */ | 2505 | */ |
2658 | static int amd64_probe_one_instance(struct pci_dev *dram_f2_ctl, | 2506 | static struct amd64_family_type *amd64_per_family_init(struct amd64_pvt *pvt) |
2659 | int mc_type_index) | 2507 | { |
2508 | u8 fam = boot_cpu_data.x86; | ||
2509 | struct amd64_family_type *fam_type = NULL; | ||
2510 | |||
2511 | switch (fam) { | ||
2512 | case 0xf: | ||
2513 | fam_type = &amd64_family_types[K8_CPUS]; | ||
2514 | pvt->ops = &amd64_family_types[K8_CPUS].ops; | ||
2515 | pvt->ctl_name = fam_type->ctl_name; | ||
2516 | pvt->min_scrubrate = K8_MIN_SCRUB_RATE_BITS; | ||
2517 | break; | ||
2518 | case 0x10: | ||
2519 | fam_type = &amd64_family_types[F10_CPUS]; | ||
2520 | pvt->ops = &amd64_family_types[F10_CPUS].ops; | ||
2521 | pvt->ctl_name = fam_type->ctl_name; | ||
2522 | pvt->min_scrubrate = F10_MIN_SCRUB_RATE_BITS; | ||
2523 | break; | ||
2524 | |||
2525 | default: | ||
2526 | amd64_err("Unsupported family!\n"); | ||
2527 | return NULL; | ||
2528 | } | ||
2529 | |||
2530 | pvt->ext_model = boot_cpu_data.x86_model >> 4; | ||
2531 | |||
2532 | amd64_info("%s %sdetected (node %d).\n", pvt->ctl_name, | ||
2533 | (fam == 0xf ? | ||
2534 | (pvt->ext_model >= K8_REV_F ? "revF or later " | ||
2535 | : "revE or earlier ") | ||
2536 | : ""), pvt->mc_node_id); | ||
2537 | return fam_type; | ||
2538 | } | ||
2539 | |||
2540 | static int amd64_init_one_instance(struct pci_dev *F2) | ||
2660 | { | 2541 | { |
2661 | struct amd64_pvt *pvt = NULL; | 2542 | struct amd64_pvt *pvt = NULL; |
2543 | struct amd64_family_type *fam_type = NULL; | ||
2544 | struct mem_ctl_info *mci = NULL; | ||
2662 | int err = 0, ret; | 2545 | int err = 0, ret; |
2546 | u8 nid = get_node_id(F2); | ||
2663 | 2547 | ||
2664 | ret = -ENOMEM; | 2548 | ret = -ENOMEM; |
2665 | pvt = kzalloc(sizeof(struct amd64_pvt), GFP_KERNEL); | 2549 | pvt = kzalloc(sizeof(struct amd64_pvt), GFP_KERNEL); |
2666 | if (!pvt) | 2550 | if (!pvt) |
2667 | goto err_exit; | 2551 | goto err_ret; |
2668 | 2552 | ||
2669 | pvt->mc_node_id = get_node_id(dram_f2_ctl); | 2553 | pvt->mc_node_id = nid; |
2554 | pvt->F2 = F2; | ||
2670 | 2555 | ||
2671 | pvt->dram_f2_ctl = dram_f2_ctl; | 2556 | ret = -EINVAL; |
2672 | pvt->ext_model = boot_cpu_data.x86_model >> 4; | 2557 | fam_type = amd64_per_family_init(pvt); |
2673 | pvt->mc_type_index = mc_type_index; | 2558 | if (!fam_type) |
2674 | pvt->ops = family_ops(mc_type_index); | 2559 | goto err_free; |
2675 | 2560 | ||
2676 | /* | ||
2677 | * We have the dram_f2_ctl device as an argument, now go reserve its | ||
2678 | * sibling devices from the PCI system. | ||
2679 | */ | ||
2680 | ret = -ENODEV; | 2561 | ret = -ENODEV; |
2681 | err = amd64_reserve_mc_sibling_devices(pvt, mc_type_index); | 2562 | err = reserve_mc_sibling_devs(pvt, fam_type->f1_id, fam_type->f3_id); |
2682 | if (err) | 2563 | if (err) |
2683 | goto err_free; | 2564 | goto err_free; |
2684 | 2565 | ||
2685 | ret = -EINVAL; | 2566 | read_mc_regs(pvt); |
2686 | err = amd64_check_ecc_enabled(pvt); | ||
2687 | if (err) | ||
2688 | goto err_put; | ||
2689 | |||
2690 | /* | ||
2691 | * Key operation here: setup of HW prior to performing ops on it. Some | ||
2692 | * setup is required to access ECS data. After this is performed, the | ||
2693 | * 'teardown' function must be called upon error and normal exit paths. | ||
2694 | */ | ||
2695 | if (boot_cpu_data.x86 >= 0x10) | ||
2696 | amd64_setup(pvt); | ||
2697 | |||
2698 | /* | ||
2699 | * Save the pointer to the private data for use in 2nd initialization | ||
2700 | * stage | ||
2701 | */ | ||
2702 | pvt_lookup[pvt->mc_node_id] = pvt; | ||
2703 | |||
2704 | return 0; | ||
2705 | |||
2706 | err_put: | ||
2707 | amd64_free_mc_sibling_devices(pvt); | ||
2708 | |||
2709 | err_free: | ||
2710 | kfree(pvt); | ||
2711 | |||
2712 | err_exit: | ||
2713 | return ret; | ||
2714 | } | ||
2715 | |||
2716 | /* | ||
2717 | * This is the finishing stage of the init code. Needs to be performed after all | ||
2718 | * MCs' hardware have been prepped for accessing extended config space. | ||
2719 | */ | ||
2720 | static int amd64_init_2nd_stage(struct amd64_pvt *pvt) | ||
2721 | { | ||
2722 | int node_id = pvt->mc_node_id; | ||
2723 | struct mem_ctl_info *mci; | ||
2724 | int ret = -ENODEV; | ||
2725 | |||
2726 | amd64_read_mc_registers(pvt); | ||
2727 | 2567 | ||
2728 | /* | 2568 | /* |
2729 | * We need to determine how many memory channels there are. Then use | 2569 | * We need to determine how many memory channels there are. Then use |
2730 | * that information for calculating the size of the dynamic instance | 2570 | * that information for calculating the size of the dynamic instance |
2731 | * tables in the 'mci' structure | 2571 | * tables in the 'mci' structure. |
2732 | */ | 2572 | */ |
2573 | ret = -EINVAL; | ||
2733 | pvt->channel_count = pvt->ops->early_channel_count(pvt); | 2574 | pvt->channel_count = pvt->ops->early_channel_count(pvt); |
2734 | if (pvt->channel_count < 0) | 2575 | if (pvt->channel_count < 0) |
2735 | goto err_exit; | 2576 | goto err_siblings; |
2736 | 2577 | ||
2737 | ret = -ENOMEM; | 2578 | ret = -ENOMEM; |
2738 | mci = edac_mc_alloc(0, pvt->cs_count, pvt->channel_count, node_id); | 2579 | mci = edac_mc_alloc(0, pvt->cs_count, pvt->channel_count, nid); |
2739 | if (!mci) | 2580 | if (!mci) |
2740 | goto err_exit; | 2581 | goto err_siblings; |
2741 | 2582 | ||
2742 | mci->pvt_info = pvt; | 2583 | mci->pvt_info = pvt; |
2584 | mci->dev = &pvt->F2->dev; | ||
2743 | 2585 | ||
2744 | mci->dev = &pvt->dram_f2_ctl->dev; | 2586 | setup_mci_misc_attrs(mci); |
2745 | amd64_setup_mci_misc_attributes(mci); | ||
2746 | 2587 | ||
2747 | if (amd64_init_csrows(mci)) | 2588 | if (init_csrows(mci)) |
2748 | mci->edac_cap = EDAC_FLAG_NONE; | 2589 | mci->edac_cap = EDAC_FLAG_NONE; |
2749 | 2590 | ||
2750 | amd64_enable_ecc_error_reporting(mci); | 2591 | set_mc_sysfs_attrs(mci); |
2751 | amd64_set_mc_sysfs_attributes(mci); | ||
2752 | 2592 | ||
2753 | ret = -ENODEV; | 2593 | ret = -ENODEV; |
2754 | if (edac_mc_add_mc(mci)) { | 2594 | if (edac_mc_add_mc(mci)) { |
@@ -2756,54 +2596,77 @@ static int amd64_init_2nd_stage(struct amd64_pvt *pvt) | |||
2756 | goto err_add_mc; | 2596 | goto err_add_mc; |
2757 | } | 2597 | } |
2758 | 2598 | ||
2759 | mci_lookup[node_id] = mci; | ||
2760 | pvt_lookup[node_id] = NULL; | ||
2761 | |||
2762 | /* register stuff with EDAC MCE */ | 2599 | /* register stuff with EDAC MCE */ |
2763 | if (report_gart_errors) | 2600 | if (report_gart_errors) |
2764 | amd_report_gart_errors(true); | 2601 | amd_report_gart_errors(true); |
2765 | 2602 | ||
2766 | amd_register_ecc_decoder(amd64_decode_bus_error); | 2603 | amd_register_ecc_decoder(amd64_decode_bus_error); |
2767 | 2604 | ||
2605 | mcis[nid] = mci; | ||
2606 | |||
2607 | atomic_inc(&drv_instances); | ||
2608 | |||
2768 | return 0; | 2609 | return 0; |
2769 | 2610 | ||
2770 | err_add_mc: | 2611 | err_add_mc: |
2771 | edac_mc_free(mci); | 2612 | edac_mc_free(mci); |
2772 | 2613 | ||
2773 | err_exit: | 2614 | err_siblings: |
2774 | debugf0("failure to init 2nd stage: ret=%d\n", ret); | 2615 | free_mc_sibling_devs(pvt); |
2775 | |||
2776 | amd64_restore_ecc_error_reporting(pvt); | ||
2777 | |||
2778 | if (boot_cpu_data.x86 > 0xf) | ||
2779 | amd64_teardown(pvt); | ||
2780 | 2616 | ||
2781 | amd64_free_mc_sibling_devices(pvt); | 2617 | err_free: |
2782 | 2618 | kfree(pvt); | |
2783 | kfree(pvt_lookup[pvt->mc_node_id]); | ||
2784 | pvt_lookup[node_id] = NULL; | ||
2785 | 2619 | ||
2620 | err_ret: | ||
2786 | return ret; | 2621 | return ret; |
2787 | } | 2622 | } |
2788 | 2623 | ||
2789 | 2624 | static int __devinit amd64_probe_one_instance(struct pci_dev *pdev, | |
2790 | static int __devinit amd64_init_one_instance(struct pci_dev *pdev, | 2625 | const struct pci_device_id *mc_type) |
2791 | const struct pci_device_id *mc_type) | ||
2792 | { | 2626 | { |
2627 | u8 nid = get_node_id(pdev); | ||
2628 | struct pci_dev *F3 = node_to_amd_nb(nid)->misc; | ||
2629 | struct ecc_settings *s; | ||
2793 | int ret = 0; | 2630 | int ret = 0; |
2794 | 2631 | ||
2795 | debugf0("(MC node=%d,mc_type='%s')\n", get_node_id(pdev), | ||
2796 | get_amd_family_name(mc_type->driver_data)); | ||
2797 | |||
2798 | ret = pci_enable_device(pdev); | 2632 | ret = pci_enable_device(pdev); |
2799 | if (ret < 0) | 2633 | if (ret < 0) { |
2800 | ret = -EIO; | ||
2801 | else | ||
2802 | ret = amd64_probe_one_instance(pdev, mc_type->driver_data); | ||
2803 | |||
2804 | if (ret < 0) | ||
2805 | debugf0("ret=%d\n", ret); | 2634 | debugf0("ret=%d\n", ret); |
2635 | return -EIO; | ||
2636 | } | ||
2637 | |||
2638 | ret = -ENOMEM; | ||
2639 | s = kzalloc(sizeof(struct ecc_settings), GFP_KERNEL); | ||
2640 | if (!s) | ||
2641 | goto err_out; | ||
2642 | |||
2643 | ecc_stngs[nid] = s; | ||
2644 | |||
2645 | if (!ecc_enabled(F3, nid)) { | ||
2646 | ret = -ENODEV; | ||
2647 | |||
2648 | if (!ecc_enable_override) | ||
2649 | goto err_enable; | ||
2650 | |||
2651 | amd64_warn("Forcing ECC on!\n"); | ||
2652 | |||
2653 | if (!enable_ecc_error_reporting(s, nid, F3)) | ||
2654 | goto err_enable; | ||
2655 | } | ||
2806 | 2656 | ||
2657 | ret = amd64_init_one_instance(pdev); | ||
2658 | if (ret < 0) { | ||
2659 | amd64_err("Error probing instance: %d\n", nid); | ||
2660 | restore_ecc_error_reporting(s, nid, F3); | ||
2661 | } | ||
2662 | |||
2663 | return ret; | ||
2664 | |||
2665 | err_enable: | ||
2666 | kfree(s); | ||
2667 | ecc_stngs[nid] = NULL; | ||
2668 | |||
2669 | err_out: | ||
2807 | return ret; | 2670 | return ret; |
2808 | } | 2671 | } |
2809 | 2672 | ||
@@ -2811,6 +2674,9 @@ static void __devexit amd64_remove_one_instance(struct pci_dev *pdev) | |||
2811 | { | 2674 | { |
2812 | struct mem_ctl_info *mci; | 2675 | struct mem_ctl_info *mci; |
2813 | struct amd64_pvt *pvt; | 2676 | struct amd64_pvt *pvt; |
2677 | u8 nid = get_node_id(pdev); | ||
2678 | struct pci_dev *F3 = node_to_amd_nb(nid)->misc; | ||
2679 | struct ecc_settings *s = ecc_stngs[nid]; | ||
2814 | 2680 | ||
2815 | /* Remove from EDAC CORE tracking list */ | 2681 | /* Remove from EDAC CORE tracking list */ |
2816 | mci = edac_mc_del_mc(&pdev->dev); | 2682 | mci = edac_mc_del_mc(&pdev->dev); |
@@ -2819,20 +2685,20 @@ static void __devexit amd64_remove_one_instance(struct pci_dev *pdev) | |||
2819 | 2685 | ||
2820 | pvt = mci->pvt_info; | 2686 | pvt = mci->pvt_info; |
2821 | 2687 | ||
2822 | amd64_restore_ecc_error_reporting(pvt); | 2688 | restore_ecc_error_reporting(s, nid, F3); |
2823 | 2689 | ||
2824 | if (boot_cpu_data.x86 > 0xf) | 2690 | free_mc_sibling_devs(pvt); |
2825 | amd64_teardown(pvt); | ||
2826 | |||
2827 | amd64_free_mc_sibling_devices(pvt); | ||
2828 | 2691 | ||
2829 | /* unregister from EDAC MCE */ | 2692 | /* unregister from EDAC MCE */ |
2830 | amd_report_gart_errors(false); | 2693 | amd_report_gart_errors(false); |
2831 | amd_unregister_ecc_decoder(amd64_decode_bus_error); | 2694 | amd_unregister_ecc_decoder(amd64_decode_bus_error); |
2832 | 2695 | ||
2696 | kfree(ecc_stngs[nid]); | ||
2697 | ecc_stngs[nid] = NULL; | ||
2698 | |||
2833 | /* Free the EDAC CORE resources */ | 2699 | /* Free the EDAC CORE resources */ |
2834 | mci->pvt_info = NULL; | 2700 | mci->pvt_info = NULL; |
2835 | mci_lookup[pvt->mc_node_id] = NULL; | 2701 | mcis[nid] = NULL; |
2836 | 2702 | ||
2837 | kfree(pvt); | 2703 | kfree(pvt); |
2838 | edac_mc_free(mci); | 2704 | edac_mc_free(mci); |
@@ -2851,7 +2717,6 @@ static const struct pci_device_id amd64_pci_table[] __devinitdata = { | |||
2851 | .subdevice = PCI_ANY_ID, | 2717 | .subdevice = PCI_ANY_ID, |
2852 | .class = 0, | 2718 | .class = 0, |
2853 | .class_mask = 0, | 2719 | .class_mask = 0, |
2854 | .driver_data = K8_CPUS | ||
2855 | }, | 2720 | }, |
2856 | { | 2721 | { |
2857 | .vendor = PCI_VENDOR_ID_AMD, | 2722 | .vendor = PCI_VENDOR_ID_AMD, |
@@ -2860,16 +2725,6 @@ static const struct pci_device_id amd64_pci_table[] __devinitdata = { | |||
2860 | .subdevice = PCI_ANY_ID, | 2725 | .subdevice = PCI_ANY_ID, |
2861 | .class = 0, | 2726 | .class = 0, |
2862 | .class_mask = 0, | 2727 | .class_mask = 0, |
2863 | .driver_data = F10_CPUS | ||
2864 | }, | ||
2865 | { | ||
2866 | .vendor = PCI_VENDOR_ID_AMD, | ||
2867 | .device = PCI_DEVICE_ID_AMD_11H_NB_DRAM, | ||
2868 | .subvendor = PCI_ANY_ID, | ||
2869 | .subdevice = PCI_ANY_ID, | ||
2870 | .class = 0, | ||
2871 | .class_mask = 0, | ||
2872 | .driver_data = F11_CPUS | ||
2873 | }, | 2728 | }, |
2874 | {0, } | 2729 | {0, } |
2875 | }; | 2730 | }; |
@@ -2877,12 +2732,12 @@ MODULE_DEVICE_TABLE(pci, amd64_pci_table); | |||
2877 | 2732 | ||
2878 | static struct pci_driver amd64_pci_driver = { | 2733 | static struct pci_driver amd64_pci_driver = { |
2879 | .name = EDAC_MOD_STR, | 2734 | .name = EDAC_MOD_STR, |
2880 | .probe = amd64_init_one_instance, | 2735 | .probe = amd64_probe_one_instance, |
2881 | .remove = __devexit_p(amd64_remove_one_instance), | 2736 | .remove = __devexit_p(amd64_remove_one_instance), |
2882 | .id_table = amd64_pci_table, | 2737 | .id_table = amd64_pci_table, |
2883 | }; | 2738 | }; |
2884 | 2739 | ||
2885 | static void amd64_setup_pci_device(void) | 2740 | static void setup_pci_device(void) |
2886 | { | 2741 | { |
2887 | struct mem_ctl_info *mci; | 2742 | struct mem_ctl_info *mci; |
2888 | struct amd64_pvt *pvt; | 2743 | struct amd64_pvt *pvt; |
@@ -2890,13 +2745,12 @@ static void amd64_setup_pci_device(void) | |||
2890 | if (amd64_ctl_pci) | 2745 | if (amd64_ctl_pci) |
2891 | return; | 2746 | return; |
2892 | 2747 | ||
2893 | mci = mci_lookup[0]; | 2748 | mci = mcis[0]; |
2894 | if (mci) { | 2749 | if (mci) { |
2895 | 2750 | ||
2896 | pvt = mci->pvt_info; | 2751 | pvt = mci->pvt_info; |
2897 | amd64_ctl_pci = | 2752 | amd64_ctl_pci = |
2898 | edac_pci_create_generic_ctl(&pvt->dram_f2_ctl->dev, | 2753 | edac_pci_create_generic_ctl(&pvt->F2->dev, EDAC_MOD_STR); |
2899 | EDAC_MOD_STR); | ||
2900 | 2754 | ||
2901 | if (!amd64_ctl_pci) { | 2755 | if (!amd64_ctl_pci) { |
2902 | pr_warning("%s(): Unable to create PCI control\n", | 2756 | pr_warning("%s(): Unable to create PCI control\n", |
@@ -2910,51 +2764,50 @@ static void amd64_setup_pci_device(void) | |||
2910 | 2764 | ||
2911 | static int __init amd64_edac_init(void) | 2765 | static int __init amd64_edac_init(void) |
2912 | { | 2766 | { |
2913 | int nb, err = -ENODEV; | 2767 | int err = -ENODEV; |
2914 | bool load_ok = false; | ||
2915 | 2768 | ||
2916 | edac_printk(KERN_INFO, EDAC_MOD_STR, EDAC_AMD64_VERSION "\n"); | 2769 | edac_printk(KERN_INFO, EDAC_MOD_STR, EDAC_AMD64_VERSION "\n"); |
2917 | 2770 | ||
2918 | opstate_init(); | 2771 | opstate_init(); |
2919 | 2772 | ||
2920 | if (cache_k8_northbridges() < 0) | 2773 | if (amd_cache_northbridges() < 0) |
2774 | goto err_ret; | ||
2775 | |||
2776 | err = -ENOMEM; | ||
2777 | mcis = kzalloc(amd_nb_num() * sizeof(mcis[0]), GFP_KERNEL); | ||
2778 | ecc_stngs = kzalloc(amd_nb_num() * sizeof(ecc_stngs[0]), GFP_KERNEL); | ||
2779 | if (!(mcis && ecc_stngs)) | ||
2921 | goto err_ret; | 2780 | goto err_ret; |
2922 | 2781 | ||
2923 | msrs = msrs_alloc(); | 2782 | msrs = msrs_alloc(); |
2924 | if (!msrs) | 2783 | if (!msrs) |
2925 | goto err_ret; | 2784 | goto err_free; |
2926 | 2785 | ||
2927 | err = pci_register_driver(&amd64_pci_driver); | 2786 | err = pci_register_driver(&amd64_pci_driver); |
2928 | if (err) | 2787 | if (err) |
2929 | goto err_pci; | 2788 | goto err_pci; |
2930 | 2789 | ||
2931 | /* | ||
2932 | * At this point, the array 'pvt_lookup[]' contains pointers to alloc'd | ||
2933 | * amd64_pvt structs. These will be used in the 2nd stage init function | ||
2934 | * to finish initialization of the MC instances. | ||
2935 | */ | ||
2936 | err = -ENODEV; | 2790 | err = -ENODEV; |
2937 | for (nb = 0; nb < k8_northbridges.num; nb++) { | 2791 | if (!atomic_read(&drv_instances)) |
2938 | if (!pvt_lookup[nb]) | 2792 | goto err_no_instances; |
2939 | continue; | ||
2940 | |||
2941 | err = amd64_init_2nd_stage(pvt_lookup[nb]); | ||
2942 | if (err) | ||
2943 | goto err_2nd_stage; | ||
2944 | 2793 | ||
2945 | load_ok = true; | 2794 | setup_pci_device(); |
2946 | } | 2795 | return 0; |
2947 | |||
2948 | if (load_ok) { | ||
2949 | amd64_setup_pci_device(); | ||
2950 | return 0; | ||
2951 | } | ||
2952 | 2796 | ||
2953 | err_2nd_stage: | 2797 | err_no_instances: |
2954 | pci_unregister_driver(&amd64_pci_driver); | 2798 | pci_unregister_driver(&amd64_pci_driver); |
2799 | |||
2955 | err_pci: | 2800 | err_pci: |
2956 | msrs_free(msrs); | 2801 | msrs_free(msrs); |
2957 | msrs = NULL; | 2802 | msrs = NULL; |
2803 | |||
2804 | err_free: | ||
2805 | kfree(mcis); | ||
2806 | mcis = NULL; | ||
2807 | |||
2808 | kfree(ecc_stngs); | ||
2809 | ecc_stngs = NULL; | ||
2810 | |||
2958 | err_ret: | 2811 | err_ret: |
2959 | return err; | 2812 | return err; |
2960 | } | 2813 | } |
@@ -2966,6 +2819,12 @@ static void __exit amd64_edac_exit(void) | |||
2966 | 2819 | ||
2967 | pci_unregister_driver(&amd64_pci_driver); | 2820 | pci_unregister_driver(&amd64_pci_driver); |
2968 | 2821 | ||
2822 | kfree(ecc_stngs); | ||
2823 | ecc_stngs = NULL; | ||
2824 | |||
2825 | kfree(mcis); | ||
2826 | mcis = NULL; | ||
2827 | |||
2969 | msrs_free(msrs); | 2828 | msrs_free(msrs); |
2970 | msrs = NULL; | 2829 | msrs = NULL; |
2971 | } | 2830 | } |
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index 044aee4f944d..613ec72b0f65 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h | |||
@@ -74,11 +74,26 @@ | |||
74 | #include "edac_core.h" | 74 | #include "edac_core.h" |
75 | #include "mce_amd.h" | 75 | #include "mce_amd.h" |
76 | 76 | ||
77 | #define amd64_printk(level, fmt, arg...) \ | 77 | #define amd64_debug(fmt, arg...) \ |
78 | edac_printk(level, "amd64", fmt, ##arg) | 78 | edac_printk(KERN_DEBUG, "amd64", fmt, ##arg) |
79 | 79 | ||
80 | #define amd64_mc_printk(mci, level, fmt, arg...) \ | 80 | #define amd64_info(fmt, arg...) \ |
81 | edac_mc_chipset_printk(mci, level, "amd64", fmt, ##arg) | 81 | edac_printk(KERN_INFO, "amd64", fmt, ##arg) |
82 | |||
83 | #define amd64_notice(fmt, arg...) \ | ||
84 | edac_printk(KERN_NOTICE, "amd64", fmt, ##arg) | ||
85 | |||
86 | #define amd64_warn(fmt, arg...) \ | ||
87 | edac_printk(KERN_WARNING, "amd64", fmt, ##arg) | ||
88 | |||
89 | #define amd64_err(fmt, arg...) \ | ||
90 | edac_printk(KERN_ERR, "amd64", fmt, ##arg) | ||
91 | |||
92 | #define amd64_mc_warn(mci, fmt, arg...) \ | ||
93 | edac_mc_chipset_printk(mci, KERN_WARNING, "amd64", fmt, ##arg) | ||
94 | |||
95 | #define amd64_mc_err(mci, fmt, arg...) \ | ||
96 | edac_mc_chipset_printk(mci, KERN_ERR, "amd64", fmt, ##arg) | ||
82 | 97 | ||
83 | /* | 98 | /* |
84 | * Throughout the comments in this code, the following terms are used: | 99 | * Throughout the comments in this code, the following terms are used: |
@@ -129,11 +144,9 @@ | |||
129 | * sections 3.5.4 and 3.5.5 for more information. | 144 | * sections 3.5.4 and 3.5.5 for more information. |
130 | */ | 145 | */ |
131 | 146 | ||
132 | #define EDAC_AMD64_VERSION " Ver: 3.3.0 " __DATE__ | 147 | #define EDAC_AMD64_VERSION "v3.3.0" |
133 | #define EDAC_MOD_STR "amd64_edac" | 148 | #define EDAC_MOD_STR "amd64_edac" |
134 | 149 | ||
135 | #define EDAC_MAX_NUMNODES 8 | ||
136 | |||
137 | /* Extended Model from CPUID, for CPU Revision numbers */ | 150 | /* Extended Model from CPUID, for CPU Revision numbers */ |
138 | #define K8_REV_D 1 | 151 | #define K8_REV_D 1 |
139 | #define K8_REV_E 2 | 152 | #define K8_REV_E 2 |
@@ -322,9 +335,6 @@ | |||
322 | #define K8_SCRCTRL 0x58 | 335 | #define K8_SCRCTRL 0x58 |
323 | 336 | ||
324 | #define F10_NB_CFG_LOW 0x88 | 337 | #define F10_NB_CFG_LOW 0x88 |
325 | #define F10_NB_CFG_LOW_ENABLE_EXT_CFG BIT(14) | ||
326 | |||
327 | #define F10_NB_CFG_HIGH 0x8C | ||
328 | 338 | ||
329 | #define F10_ONLINE_SPARE 0xB0 | 339 | #define F10_ONLINE_SPARE 0xB0 |
330 | #define F10_ONLINE_SPARE_SWAPDONE0(x) ((x) & BIT(1)) | 340 | #define F10_ONLINE_SPARE_SWAPDONE0(x) ((x) & BIT(1)) |
@@ -373,7 +383,6 @@ static inline int get_node_id(struct pci_dev *pdev) | |||
373 | enum amd64_chipset_families { | 383 | enum amd64_chipset_families { |
374 | K8_CPUS = 0, | 384 | K8_CPUS = 0, |
375 | F10_CPUS, | 385 | F10_CPUS, |
376 | F11_CPUS, | ||
377 | }; | 386 | }; |
378 | 387 | ||
379 | /* Error injection control structure */ | 388 | /* Error injection control structure */ |
@@ -384,16 +393,13 @@ struct error_injection { | |||
384 | }; | 393 | }; |
385 | 394 | ||
386 | struct amd64_pvt { | 395 | struct amd64_pvt { |
396 | struct low_ops *ops; | ||
397 | |||
387 | /* pci_device handles which we utilize */ | 398 | /* pci_device handles which we utilize */ |
388 | struct pci_dev *addr_f1_ctl; | 399 | struct pci_dev *F1, *F2, *F3; |
389 | struct pci_dev *dram_f2_ctl; | ||
390 | struct pci_dev *misc_f3_ctl; | ||
391 | 400 | ||
392 | int mc_node_id; /* MC index of this MC node */ | 401 | int mc_node_id; /* MC index of this MC node */ |
393 | int ext_model; /* extended model value of this node */ | 402 | int ext_model; /* extended model value of this node */ |
394 | |||
395 | struct low_ops *ops; /* pointer to per PCI Device ID func table */ | ||
396 | |||
397 | int channel_count; | 403 | int channel_count; |
398 | 404 | ||
399 | /* Raw registers */ | 405 | /* Raw registers */ |
@@ -455,27 +461,27 @@ struct amd64_pvt { | |||
455 | /* place to store error injection parameters prior to issue */ | 461 | /* place to store error injection parameters prior to issue */ |
456 | struct error_injection injection; | 462 | struct error_injection injection; |
457 | 463 | ||
458 | /* Save old hw registers' values before we modified them */ | 464 | /* DCT per-family scrubrate setting */ |
459 | u32 nbctl_mcgctl_saved; /* When true, following 2 are valid */ | 465 | u32 min_scrubrate; |
460 | u32 old_nbctl; | ||
461 | 466 | ||
462 | /* MC Type Index value: socket F vs Family 10h */ | 467 | /* family name this instance is running on */ |
463 | u32 mc_type_index; | 468 | const char *ctl_name; |
469 | |||
470 | }; | ||
471 | |||
472 | /* | ||
473 | * per-node ECC settings descriptor | ||
474 | */ | ||
475 | struct ecc_settings { | ||
476 | u32 old_nbctl; | ||
477 | bool nbctl_valid; | ||
464 | 478 | ||
465 | /* misc settings */ | ||
466 | struct flags { | 479 | struct flags { |
467 | unsigned long cf8_extcfg:1; | ||
468 | unsigned long nb_mce_enable:1; | 480 | unsigned long nb_mce_enable:1; |
469 | unsigned long nb_ecc_prev:1; | 481 | unsigned long nb_ecc_prev:1; |
470 | } flags; | 482 | } flags; |
471 | }; | 483 | }; |
472 | 484 | ||
473 | struct scrubrate { | ||
474 | u32 scrubval; /* bit pattern for scrub rate */ | ||
475 | u32 bandwidth; /* bandwidth consumed (bytes/sec) */ | ||
476 | }; | ||
477 | |||
478 | extern struct scrubrate scrubrates[23]; | ||
479 | extern const char *tt_msgs[4]; | 485 | extern const char *tt_msgs[4]; |
480 | extern const char *ll_msgs[4]; | 486 | extern const char *ll_msgs[4]; |
481 | extern const char *rrrr_msgs[16]; | 487 | extern const char *rrrr_msgs[16]; |
@@ -517,23 +523,10 @@ struct low_ops { | |||
517 | 523 | ||
518 | struct amd64_family_type { | 524 | struct amd64_family_type { |
519 | const char *ctl_name; | 525 | const char *ctl_name; |
520 | u16 addr_f1_ctl; | 526 | u16 f1_id, f3_id; |
521 | u16 misc_f3_ctl; | ||
522 | struct low_ops ops; | 527 | struct low_ops ops; |
523 | }; | 528 | }; |
524 | 529 | ||
525 | static struct amd64_family_type amd64_family_types[]; | ||
526 | |||
527 | static inline const char *get_amd_family_name(int index) | ||
528 | { | ||
529 | return amd64_family_types[index].ctl_name; | ||
530 | } | ||
531 | |||
532 | static inline struct low_ops *family_ops(int index) | ||
533 | { | ||
534 | return &amd64_family_types[index].ops; | ||
535 | } | ||
536 | |||
537 | static inline int amd64_read_pci_cfg_dword(struct pci_dev *pdev, int offset, | 530 | static inline int amd64_read_pci_cfg_dword(struct pci_dev *pdev, int offset, |
538 | u32 *val, const char *func) | 531 | u32 *val, const char *func) |
539 | { | 532 | { |
@@ -541,8 +534,8 @@ static inline int amd64_read_pci_cfg_dword(struct pci_dev *pdev, int offset, | |||
541 | 534 | ||
542 | err = pci_read_config_dword(pdev, offset, val); | 535 | err = pci_read_config_dword(pdev, offset, val); |
543 | if (err) | 536 | if (err) |
544 | amd64_printk(KERN_WARNING, "%s: error reading F%dx%x.\n", | 537 | amd64_warn("%s: error reading F%dx%x.\n", |
545 | func, PCI_FUNC(pdev->devfn), offset); | 538 | func, PCI_FUNC(pdev->devfn), offset); |
546 | 539 | ||
547 | return err; | 540 | return err; |
548 | } | 541 | } |
@@ -556,7 +549,6 @@ static inline int amd64_read_pci_cfg_dword(struct pci_dev *pdev, int offset, | |||
556 | */ | 549 | */ |
557 | #define K8_MIN_SCRUB_RATE_BITS 0x0 | 550 | #define K8_MIN_SCRUB_RATE_BITS 0x0 |
558 | #define F10_MIN_SCRUB_RATE_BITS 0x5 | 551 | #define F10_MIN_SCRUB_RATE_BITS 0x5 |
559 | #define F11_MIN_SCRUB_RATE_BITS 0x6 | ||
560 | 552 | ||
561 | int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base, | 553 | int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base, |
562 | u64 *hole_offset, u64 *hole_size); | 554 | u64 *hole_offset, u64 *hole_size); |
diff --git a/drivers/edac/amd64_edac_inj.c b/drivers/edac/amd64_edac_inj.c index 29f1f7a612d9..688478de1cbd 100644 --- a/drivers/edac/amd64_edac_inj.c +++ b/drivers/edac/amd64_edac_inj.c | |||
@@ -23,9 +23,7 @@ static ssize_t amd64_inject_section_store(struct mem_ctl_info *mci, | |||
23 | if (ret != -EINVAL) { | 23 | if (ret != -EINVAL) { |
24 | 24 | ||
25 | if (value > 3) { | 25 | if (value > 3) { |
26 | amd64_printk(KERN_WARNING, | 26 | amd64_warn("%s: invalid section 0x%lx\n", __func__, value); |
27 | "%s: invalid section 0x%lx\n", | ||
28 | __func__, value); | ||
29 | return -EINVAL; | 27 | return -EINVAL; |
30 | } | 28 | } |
31 | 29 | ||
@@ -58,9 +56,7 @@ static ssize_t amd64_inject_word_store(struct mem_ctl_info *mci, | |||
58 | if (ret != -EINVAL) { | 56 | if (ret != -EINVAL) { |
59 | 57 | ||
60 | if (value > 8) { | 58 | if (value > 8) { |
61 | amd64_printk(KERN_WARNING, | 59 | amd64_warn("%s: invalid word 0x%lx\n", __func__, value); |
62 | "%s: invalid word 0x%lx\n", | ||
63 | __func__, value); | ||
64 | return -EINVAL; | 60 | return -EINVAL; |
65 | } | 61 | } |
66 | 62 | ||
@@ -92,9 +88,8 @@ static ssize_t amd64_inject_ecc_vector_store(struct mem_ctl_info *mci, | |||
92 | if (ret != -EINVAL) { | 88 | if (ret != -EINVAL) { |
93 | 89 | ||
94 | if (value & 0xFFFF0000) { | 90 | if (value & 0xFFFF0000) { |
95 | amd64_printk(KERN_WARNING, | 91 | amd64_warn("%s: invalid EccVector: 0x%lx\n", |
96 | "%s: invalid EccVector: 0x%lx\n", | 92 | __func__, value); |
97 | __func__, value); | ||
98 | return -EINVAL; | 93 | return -EINVAL; |
99 | } | 94 | } |
100 | 95 | ||
@@ -122,15 +117,13 @@ static ssize_t amd64_inject_read_store(struct mem_ctl_info *mci, | |||
122 | /* Form value to choose 16-byte section of cacheline */ | 117 | /* Form value to choose 16-byte section of cacheline */ |
123 | section = F10_NB_ARRAY_DRAM_ECC | | 118 | section = F10_NB_ARRAY_DRAM_ECC | |
124 | SET_NB_ARRAY_ADDRESS(pvt->injection.section); | 119 | SET_NB_ARRAY_ADDRESS(pvt->injection.section); |
125 | pci_write_config_dword(pvt->misc_f3_ctl, | 120 | pci_write_config_dword(pvt->F3, F10_NB_ARRAY_ADDR, section); |
126 | F10_NB_ARRAY_ADDR, section); | ||
127 | 121 | ||
128 | word_bits = SET_NB_DRAM_INJECTION_READ(pvt->injection.word, | 122 | word_bits = SET_NB_DRAM_INJECTION_READ(pvt->injection.word, |
129 | pvt->injection.bit_map); | 123 | pvt->injection.bit_map); |
130 | 124 | ||
131 | /* Issue 'word' and 'bit' along with the READ request */ | 125 | /* Issue 'word' and 'bit' along with the READ request */ |
132 | pci_write_config_dword(pvt->misc_f3_ctl, | 126 | pci_write_config_dword(pvt->F3, F10_NB_ARRAY_DATA, word_bits); |
133 | F10_NB_ARRAY_DATA, word_bits); | ||
134 | 127 | ||
135 | debugf0("section=0x%x word_bits=0x%x\n", section, word_bits); | 128 | debugf0("section=0x%x word_bits=0x%x\n", section, word_bits); |
136 | 129 | ||
@@ -157,15 +150,13 @@ static ssize_t amd64_inject_write_store(struct mem_ctl_info *mci, | |||
157 | /* Form value to choose 16-byte section of cacheline */ | 150 | /* Form value to choose 16-byte section of cacheline */ |
158 | section = F10_NB_ARRAY_DRAM_ECC | | 151 | section = F10_NB_ARRAY_DRAM_ECC | |
159 | SET_NB_ARRAY_ADDRESS(pvt->injection.section); | 152 | SET_NB_ARRAY_ADDRESS(pvt->injection.section); |
160 | pci_write_config_dword(pvt->misc_f3_ctl, | 153 | pci_write_config_dword(pvt->F3, F10_NB_ARRAY_ADDR, section); |
161 | F10_NB_ARRAY_ADDR, section); | ||
162 | 154 | ||
163 | word_bits = SET_NB_DRAM_INJECTION_WRITE(pvt->injection.word, | 155 | word_bits = SET_NB_DRAM_INJECTION_WRITE(pvt->injection.word, |
164 | pvt->injection.bit_map); | 156 | pvt->injection.bit_map); |
165 | 157 | ||
166 | /* Issue 'word' and 'bit' along with the READ request */ | 158 | /* Issue 'word' and 'bit' along with the READ request */ |
167 | pci_write_config_dword(pvt->misc_f3_ctl, | 159 | pci_write_config_dword(pvt->F3, F10_NB_ARRAY_DATA, word_bits); |
168 | F10_NB_ARRAY_DATA, word_bits); | ||
169 | 160 | ||
170 | debugf0("section=0x%x word_bits=0x%x\n", section, word_bits); | 161 | debugf0("section=0x%x word_bits=0x%x\n", section, word_bits); |
171 | 162 | ||
diff --git a/drivers/edac/cpc925_edac.c b/drivers/edac/cpc925_edac.c index 1609a19df495..b9a781c47e3c 100644 --- a/drivers/edac/cpc925_edac.c +++ b/drivers/edac/cpc925_edac.c | |||
@@ -818,9 +818,10 @@ static void cpc925_del_edac_devices(void) | |||
818 | } | 818 | } |
819 | 819 | ||
820 | /* Convert current back-ground scrub rate into byte/sec bandwith */ | 820 | /* Convert current back-ground scrub rate into byte/sec bandwith */ |
821 | static int cpc925_get_sdram_scrub_rate(struct mem_ctl_info *mci, u32 *bw) | 821 | static int cpc925_get_sdram_scrub_rate(struct mem_ctl_info *mci) |
822 | { | 822 | { |
823 | struct cpc925_mc_pdata *pdata = mci->pvt_info; | 823 | struct cpc925_mc_pdata *pdata = mci->pvt_info; |
824 | int bw; | ||
824 | u32 mscr; | 825 | u32 mscr; |
825 | u8 si; | 826 | u8 si; |
826 | 827 | ||
@@ -832,11 +833,11 @@ static int cpc925_get_sdram_scrub_rate(struct mem_ctl_info *mci, u32 *bw) | |||
832 | if (((mscr & MSCR_SCRUB_MOD_MASK) != MSCR_BACKGR_SCRUB) || | 833 | if (((mscr & MSCR_SCRUB_MOD_MASK) != MSCR_BACKGR_SCRUB) || |
833 | (si == 0)) { | 834 | (si == 0)) { |
834 | cpc925_mc_printk(mci, KERN_INFO, "Scrub mode not enabled\n"); | 835 | cpc925_mc_printk(mci, KERN_INFO, "Scrub mode not enabled\n"); |
835 | *bw = 0; | 836 | bw = 0; |
836 | } else | 837 | } else |
837 | *bw = CPC925_SCRUB_BLOCK_SIZE * 0xFA67 / si; | 838 | bw = CPC925_SCRUB_BLOCK_SIZE * 0xFA67 / si; |
838 | 839 | ||
839 | return 0; | 840 | return bw; |
840 | } | 841 | } |
841 | 842 | ||
842 | /* Return 0 for single channel; 1 for dual channel */ | 843 | /* Return 0 for single channel; 1 for dual channel */ |
diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index 073f5a06d238..ec302d426589 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c | |||
@@ -983,11 +983,11 @@ static int set_sdram_scrub_rate(struct mem_ctl_info *mci, u32 new_bw) | |||
983 | 983 | ||
984 | pci_write_config_word(pdev, E752X_MCHSCRB, scrubrates[i].scrubval); | 984 | pci_write_config_word(pdev, E752X_MCHSCRB, scrubrates[i].scrubval); |
985 | 985 | ||
986 | return 0; | 986 | return scrubrates[i].bandwidth; |
987 | } | 987 | } |
988 | 988 | ||
989 | /* Convert current scrub rate value into byte/sec bandwidth */ | 989 | /* Convert current scrub rate value into byte/sec bandwidth */ |
990 | static int get_sdram_scrub_rate(struct mem_ctl_info *mci, u32 *bw) | 990 | static int get_sdram_scrub_rate(struct mem_ctl_info *mci) |
991 | { | 991 | { |
992 | const struct scrubrate *scrubrates; | 992 | const struct scrubrate *scrubrates; |
993 | struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info; | 993 | struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info; |
@@ -1013,10 +1013,8 @@ static int get_sdram_scrub_rate(struct mem_ctl_info *mci, u32 *bw) | |||
1013 | "Invalid sdram scrub control value: 0x%x\n", scrubval); | 1013 | "Invalid sdram scrub control value: 0x%x\n", scrubval); |
1014 | return -1; | 1014 | return -1; |
1015 | } | 1015 | } |
1016 | return scrubrates[i].bandwidth; | ||
1016 | 1017 | ||
1017 | *bw = scrubrates[i].bandwidth; | ||
1018 | |||
1019 | return 0; | ||
1020 | } | 1018 | } |
1021 | 1019 | ||
1022 | /* Return 1 if dual channel mode is active. Else return 0. */ | 1020 | /* Return 1 if dual channel mode is active. Else return 0. */ |
diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h index 26db9ec5c44f..3d965347a673 100644 --- a/drivers/edac/edac_core.h +++ b/drivers/edac/edac_core.h | |||
@@ -68,9 +68,10 @@ | |||
68 | #define EDAC_PCI "PCI" | 68 | #define EDAC_PCI "PCI" |
69 | #define EDAC_DEBUG "DEBUG" | 69 | #define EDAC_DEBUG "DEBUG" |
70 | 70 | ||
71 | extern const char *edac_mem_types[]; | ||
72 | |||
71 | #ifdef CONFIG_EDAC_DEBUG | 73 | #ifdef CONFIG_EDAC_DEBUG |
72 | extern int edac_debug_level; | 74 | extern int edac_debug_level; |
73 | extern const char *edac_mem_types[]; | ||
74 | 75 | ||
75 | #define edac_debug_printk(level, fmt, arg...) \ | 76 | #define edac_debug_printk(level, fmt, arg...) \ |
76 | do { \ | 77 | do { \ |
@@ -386,7 +387,7 @@ struct mem_ctl_info { | |||
386 | representation and converts it to the closest matching | 387 | representation and converts it to the closest matching |
387 | bandwith in bytes/sec. | 388 | bandwith in bytes/sec. |
388 | */ | 389 | */ |
389 | int (*get_sdram_scrub_rate) (struct mem_ctl_info * mci, u32 * bw); | 390 | int (*get_sdram_scrub_rate) (struct mem_ctl_info * mci); |
390 | 391 | ||
391 | 392 | ||
392 | /* pointer to edac checking routine */ | 393 | /* pointer to edac checking routine */ |
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 795ea69c4d8f..a4e9db2d6524 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c | |||
@@ -76,6 +76,8 @@ static void edac_mc_dump_mci(struct mem_ctl_info *mci) | |||
76 | debugf3("\tpvt_info = %p\n\n", mci->pvt_info); | 76 | debugf3("\tpvt_info = %p\n\n", mci->pvt_info); |
77 | } | 77 | } |
78 | 78 | ||
79 | #endif /* CONFIG_EDAC_DEBUG */ | ||
80 | |||
79 | /* | 81 | /* |
80 | * keep those in sync with the enum mem_type | 82 | * keep those in sync with the enum mem_type |
81 | */ | 83 | */ |
@@ -100,8 +102,6 @@ const char *edac_mem_types[] = { | |||
100 | }; | 102 | }; |
101 | EXPORT_SYMBOL_GPL(edac_mem_types); | 103 | EXPORT_SYMBOL_GPL(edac_mem_types); |
102 | 104 | ||
103 | #endif /* CONFIG_EDAC_DEBUG */ | ||
104 | |||
105 | /* 'ptr' points to a possibly unaligned item X such that sizeof(X) is 'size'. | 105 | /* 'ptr' points to a possibly unaligned item X such that sizeof(X) is 'size'. |
106 | * Adjust 'ptr' so that its alignment is at least as stringent as what the | 106 | * Adjust 'ptr' so that its alignment is at least as stringent as what the |
107 | * compiler would provide for X and return the aligned result. | 107 | * compiler would provide for X and return the aligned result. |
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index dce61f7ba38b..39d97cfdf58c 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c | |||
@@ -436,56 +436,55 @@ static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci, | |||
436 | return count; | 436 | return count; |
437 | } | 437 | } |
438 | 438 | ||
439 | /* memory scrubbing */ | 439 | /* Memory scrubbing interface: |
440 | * | ||
441 | * A MC driver can limit the scrubbing bandwidth based on the CPU type. | ||
442 | * Therefore, ->set_sdram_scrub_rate should be made to return the actual | ||
443 | * bandwidth that is accepted or 0 when scrubbing is to be disabled. | ||
444 | * | ||
445 | * Negative value still means that an error has occurred while setting | ||
446 | * the scrub rate. | ||
447 | */ | ||
440 | static ssize_t mci_sdram_scrub_rate_store(struct mem_ctl_info *mci, | 448 | static ssize_t mci_sdram_scrub_rate_store(struct mem_ctl_info *mci, |
441 | const char *data, size_t count) | 449 | const char *data, size_t count) |
442 | { | 450 | { |
443 | unsigned long bandwidth = 0; | 451 | unsigned long bandwidth = 0; |
444 | int err; | 452 | int new_bw = 0; |
445 | 453 | ||
446 | if (!mci->set_sdram_scrub_rate) { | 454 | if (!mci->set_sdram_scrub_rate) |
447 | edac_printk(KERN_WARNING, EDAC_MC, | ||
448 | "Memory scrub rate setting not implemented!\n"); | ||
449 | return -EINVAL; | 455 | return -EINVAL; |
450 | } | ||
451 | 456 | ||
452 | if (strict_strtoul(data, 10, &bandwidth) < 0) | 457 | if (strict_strtoul(data, 10, &bandwidth) < 0) |
453 | return -EINVAL; | 458 | return -EINVAL; |
454 | 459 | ||
455 | err = mci->set_sdram_scrub_rate(mci, (u32)bandwidth); | 460 | new_bw = mci->set_sdram_scrub_rate(mci, bandwidth); |
456 | if (err) { | 461 | if (new_bw >= 0) { |
457 | edac_printk(KERN_DEBUG, EDAC_MC, | 462 | edac_printk(KERN_DEBUG, EDAC_MC, "Scrub rate set to %d\n", new_bw); |
458 | "Failed setting scrub rate to %lu\n", bandwidth); | ||
459 | return -EINVAL; | ||
460 | } | ||
461 | else { | ||
462 | edac_printk(KERN_DEBUG, EDAC_MC, | ||
463 | "Scrub rate set to: %lu\n", bandwidth); | ||
464 | return count; | 463 | return count; |
465 | } | 464 | } |
465 | |||
466 | edac_printk(KERN_DEBUG, EDAC_MC, "Error setting scrub rate to: %lu\n", bandwidth); | ||
467 | return -EINVAL; | ||
466 | } | 468 | } |
467 | 469 | ||
470 | /* | ||
471 | * ->get_sdram_scrub_rate() return value semantics same as above. | ||
472 | */ | ||
468 | static ssize_t mci_sdram_scrub_rate_show(struct mem_ctl_info *mci, char *data) | 473 | static ssize_t mci_sdram_scrub_rate_show(struct mem_ctl_info *mci, char *data) |
469 | { | 474 | { |
470 | u32 bandwidth = 0; | 475 | int bandwidth = 0; |
471 | int err; | ||
472 | 476 | ||
473 | if (!mci->get_sdram_scrub_rate) { | 477 | if (!mci->get_sdram_scrub_rate) |
474 | edac_printk(KERN_WARNING, EDAC_MC, | ||
475 | "Memory scrub rate reading not implemented\n"); | ||
476 | return -EINVAL; | 478 | return -EINVAL; |
477 | } | ||
478 | 479 | ||
479 | err = mci->get_sdram_scrub_rate(mci, &bandwidth); | 480 | bandwidth = mci->get_sdram_scrub_rate(mci); |
480 | if (err) { | 481 | if (bandwidth < 0) { |
481 | edac_printk(KERN_DEBUG, EDAC_MC, "Error reading scrub rate\n"); | 482 | edac_printk(KERN_DEBUG, EDAC_MC, "Error reading scrub rate\n"); |
482 | return err; | 483 | return bandwidth; |
483 | } | ||
484 | else { | ||
485 | edac_printk(KERN_DEBUG, EDAC_MC, | ||
486 | "Read scrub rate: %d\n", bandwidth); | ||
487 | return sprintf(data, "%d\n", bandwidth); | ||
488 | } | 484 | } |
485 | |||
486 | edac_printk(KERN_DEBUG, EDAC_MC, "Read scrub rate: %d\n", bandwidth); | ||
487 | return sprintf(data, "%d\n", bandwidth); | ||
489 | } | 488 | } |
490 | 489 | ||
491 | /* default attribute files for the MCI object */ | 490 | /* default attribute files for the MCI object */ |
diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c index f459a6c0886b..0448da0af75d 100644 --- a/drivers/edac/i5100_edac.c +++ b/drivers/edac/i5100_edac.c | |||
@@ -611,20 +611,17 @@ static int i5100_set_scrub_rate(struct mem_ctl_info *mci, u32 bandwidth) | |||
611 | 611 | ||
612 | bandwidth = 5900000 * i5100_mc_scrben(dw); | 612 | bandwidth = 5900000 * i5100_mc_scrben(dw); |
613 | 613 | ||
614 | return 0; | 614 | return bandwidth; |
615 | } | 615 | } |
616 | 616 | ||
617 | static int i5100_get_scrub_rate(struct mem_ctl_info *mci, | 617 | static int i5100_get_scrub_rate(struct mem_ctl_info *mci) |
618 | u32 *bandwidth) | ||
619 | { | 618 | { |
620 | struct i5100_priv *priv = mci->pvt_info; | 619 | struct i5100_priv *priv = mci->pvt_info; |
621 | u32 dw; | 620 | u32 dw; |
622 | 621 | ||
623 | pci_read_config_dword(priv->mc, I5100_MC, &dw); | 622 | pci_read_config_dword(priv->mc, I5100_MC, &dw); |
624 | 623 | ||
625 | *bandwidth = 5900000 * i5100_mc_scrben(dw); | 624 | return 5900000 * i5100_mc_scrben(dw); |
626 | |||
627 | return 0; | ||
628 | } | 625 | } |
629 | 626 | ||
630 | static struct pci_dev *pci_get_device_func(unsigned vendor, | 627 | static struct pci_dev *pci_get_device_func(unsigned vendor, |
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c index c0181093b490..f6cf73d93359 100644 --- a/drivers/edac/mce_amd.c +++ b/drivers/edac/mce_amd.c | |||
@@ -5,6 +5,7 @@ | |||
5 | 5 | ||
6 | static struct amd_decoder_ops *fam_ops; | 6 | static struct amd_decoder_ops *fam_ops; |
7 | 7 | ||
8 | static u8 xec_mask = 0xf; | ||
8 | static u8 nb_err_cpumask = 0xf; | 9 | static u8 nb_err_cpumask = 0xf; |
9 | 10 | ||
10 | static bool report_gart_errors; | 11 | static bool report_gart_errors; |
@@ -74,57 +75,104 @@ static const char *f10h_nb_mce_desc[] = { | |||
74 | "ECC Error in the Probe Filter directory" | 75 | "ECC Error in the Probe Filter directory" |
75 | }; | 76 | }; |
76 | 77 | ||
77 | static bool f12h_dc_mce(u16 ec) | 78 | static const char * const f15h_ic_mce_desc[] = { |
79 | "UC during a demand linefill from L2", | ||
80 | "Parity error during data load from IC", | ||
81 | "Parity error for IC valid bit", | ||
82 | "Main tag parity error", | ||
83 | "Parity error in prediction queue", | ||
84 | "PFB data/address parity error", | ||
85 | "Parity error in the branch status reg", | ||
86 | "PFB promotion address error", | ||
87 | "Tag error during probe/victimization", | ||
88 | "Parity error for IC probe tag valid bit", | ||
89 | "PFB non-cacheable bit parity error", | ||
90 | "PFB valid bit parity error", /* xec = 0xd */ | ||
91 | "patch RAM", /* xec = 010 */ | ||
92 | "uop queue", | ||
93 | "insn buffer", | ||
94 | "predecode buffer", | ||
95 | "fetch address FIFO" | ||
96 | }; | ||
97 | |||
98 | static const char * const f15h_cu_mce_desc[] = { | ||
99 | "Fill ECC error on data fills", /* xec = 0x4 */ | ||
100 | "Fill parity error on insn fills", | ||
101 | "Prefetcher request FIFO parity error", | ||
102 | "PRQ address parity error", | ||
103 | "PRQ data parity error", | ||
104 | "WCC Tag ECC error", | ||
105 | "WCC Data ECC error", | ||
106 | "WCB Data parity error", | ||
107 | "VB Data/ECC error", | ||
108 | "L2 Tag ECC error", /* xec = 0x10 */ | ||
109 | "Hard L2 Tag ECC error", | ||
110 | "Multiple hits on L2 tag", | ||
111 | "XAB parity error", | ||
112 | "PRB address parity error" | ||
113 | }; | ||
114 | |||
115 | static const char * const fr_ex_mce_desc[] = { | ||
116 | "CPU Watchdog timer expire", | ||
117 | "Wakeup array dest tag", | ||
118 | "AG payload array", | ||
119 | "EX payload array", | ||
120 | "IDRF array", | ||
121 | "Retire dispatch queue", | ||
122 | "Mapper checkpoint array", | ||
123 | "Physical register file EX0 port", | ||
124 | "Physical register file EX1 port", | ||
125 | "Physical register file AG0 port", | ||
126 | "Physical register file AG1 port", | ||
127 | "Flag register file", | ||
128 | "DE correctable error could not be corrected" | ||
129 | }; | ||
130 | |||
131 | static bool f12h_dc_mce(u16 ec, u8 xec) | ||
78 | { | 132 | { |
79 | bool ret = false; | 133 | bool ret = false; |
80 | 134 | ||
81 | if (MEM_ERROR(ec)) { | 135 | if (MEM_ERROR(ec)) { |
82 | u8 ll = ec & 0x3; | 136 | u8 ll = LL(ec); |
83 | ret = true; | 137 | ret = true; |
84 | 138 | ||
85 | if (ll == LL_L2) | 139 | if (ll == LL_L2) |
86 | pr_cont("during L1 linefill from L2.\n"); | 140 | pr_cont("during L1 linefill from L2.\n"); |
87 | else if (ll == LL_L1) | 141 | else if (ll == LL_L1) |
88 | pr_cont("Data/Tag %s error.\n", RRRR_MSG(ec)); | 142 | pr_cont("Data/Tag %s error.\n", R4_MSG(ec)); |
89 | else | 143 | else |
90 | ret = false; | 144 | ret = false; |
91 | } | 145 | } |
92 | return ret; | 146 | return ret; |
93 | } | 147 | } |
94 | 148 | ||
95 | static bool f10h_dc_mce(u16 ec) | 149 | static bool f10h_dc_mce(u16 ec, u8 xec) |
96 | { | 150 | { |
97 | u8 r4 = (ec >> 4) & 0xf; | 151 | if (R4(ec) == R4_GEN && LL(ec) == LL_L1) { |
98 | u8 ll = ec & 0x3; | ||
99 | |||
100 | if (r4 == R4_GEN && ll == LL_L1) { | ||
101 | pr_cont("during data scrub.\n"); | 152 | pr_cont("during data scrub.\n"); |
102 | return true; | 153 | return true; |
103 | } | 154 | } |
104 | return f12h_dc_mce(ec); | 155 | return f12h_dc_mce(ec, xec); |
105 | } | 156 | } |
106 | 157 | ||
107 | static bool k8_dc_mce(u16 ec) | 158 | static bool k8_dc_mce(u16 ec, u8 xec) |
108 | { | 159 | { |
109 | if (BUS_ERROR(ec)) { | 160 | if (BUS_ERROR(ec)) { |
110 | pr_cont("during system linefill.\n"); | 161 | pr_cont("during system linefill.\n"); |
111 | return true; | 162 | return true; |
112 | } | 163 | } |
113 | 164 | ||
114 | return f10h_dc_mce(ec); | 165 | return f10h_dc_mce(ec, xec); |
115 | } | 166 | } |
116 | 167 | ||
117 | static bool f14h_dc_mce(u16 ec) | 168 | static bool f14h_dc_mce(u16 ec, u8 xec) |
118 | { | 169 | { |
119 | u8 r4 = (ec >> 4) & 0xf; | 170 | u8 r4 = R4(ec); |
120 | u8 ll = ec & 0x3; | ||
121 | u8 tt = (ec >> 2) & 0x3; | ||
122 | u8 ii = tt; | ||
123 | bool ret = true; | 171 | bool ret = true; |
124 | 172 | ||
125 | if (MEM_ERROR(ec)) { | 173 | if (MEM_ERROR(ec)) { |
126 | 174 | ||
127 | if (tt != TT_DATA || ll != LL_L1) | 175 | if (TT(ec) != TT_DATA || LL(ec) != LL_L1) |
128 | return false; | 176 | return false; |
129 | 177 | ||
130 | switch (r4) { | 178 | switch (r4) { |
@@ -144,7 +192,7 @@ static bool f14h_dc_mce(u16 ec) | |||
144 | } | 192 | } |
145 | } else if (BUS_ERROR(ec)) { | 193 | } else if (BUS_ERROR(ec)) { |
146 | 194 | ||
147 | if ((ii != II_MEM && ii != II_IO) || ll != LL_LG) | 195 | if ((II(ec) != II_MEM && II(ec) != II_IO) || LL(ec) != LL_LG) |
148 | return false; | 196 | return false; |
149 | 197 | ||
150 | pr_cont("System read data error on a "); | 198 | pr_cont("System read data error on a "); |
@@ -169,39 +217,78 @@ static bool f14h_dc_mce(u16 ec) | |||
169 | return ret; | 217 | return ret; |
170 | } | 218 | } |
171 | 219 | ||
220 | static bool f15h_dc_mce(u16 ec, u8 xec) | ||
221 | { | ||
222 | bool ret = true; | ||
223 | |||
224 | if (MEM_ERROR(ec)) { | ||
225 | |||
226 | switch (xec) { | ||
227 | case 0x0: | ||
228 | pr_cont("Data Array access error.\n"); | ||
229 | break; | ||
230 | |||
231 | case 0x1: | ||
232 | pr_cont("UC error during a linefill from L2/NB.\n"); | ||
233 | break; | ||
234 | |||
235 | case 0x2: | ||
236 | case 0x11: | ||
237 | pr_cont("STQ access error.\n"); | ||
238 | break; | ||
239 | |||
240 | case 0x3: | ||
241 | pr_cont("SCB access error.\n"); | ||
242 | break; | ||
243 | |||
244 | case 0x10: | ||
245 | pr_cont("Tag error.\n"); | ||
246 | break; | ||
247 | |||
248 | case 0x12: | ||
249 | pr_cont("LDQ access error.\n"); | ||
250 | break; | ||
251 | |||
252 | default: | ||
253 | ret = false; | ||
254 | } | ||
255 | } else if (BUS_ERROR(ec)) { | ||
256 | |||
257 | if (!xec) | ||
258 | pr_cont("during system linefill.\n"); | ||
259 | else | ||
260 | pr_cont(" Internal %s condition.\n", | ||
261 | ((xec == 1) ? "livelock" : "deadlock")); | ||
262 | } else | ||
263 | ret = false; | ||
264 | |||
265 | return ret; | ||
266 | } | ||
267 | |||
172 | static void amd_decode_dc_mce(struct mce *m) | 268 | static void amd_decode_dc_mce(struct mce *m) |
173 | { | 269 | { |
174 | u16 ec = m->status & 0xffff; | 270 | u16 ec = EC(m->status); |
175 | u8 xec = (m->status >> 16) & 0xf; | 271 | u8 xec = XEC(m->status, xec_mask); |
176 | 272 | ||
177 | pr_emerg(HW_ERR "Data Cache Error: "); | 273 | pr_emerg(HW_ERR "Data Cache Error: "); |
178 | 274 | ||
179 | /* TLB error signatures are the same across families */ | 275 | /* TLB error signatures are the same across families */ |
180 | if (TLB_ERROR(ec)) { | 276 | if (TLB_ERROR(ec)) { |
181 | u8 tt = (ec >> 2) & 0x3; | 277 | if (TT(ec) == TT_DATA) { |
182 | |||
183 | if (tt == TT_DATA) { | ||
184 | pr_cont("%s TLB %s.\n", LL_MSG(ec), | 278 | pr_cont("%s TLB %s.\n", LL_MSG(ec), |
185 | (xec ? "multimatch" : "parity error")); | 279 | ((xec == 2) ? "locked miss" |
280 | : (xec ? "multimatch" : "parity"))); | ||
186 | return; | 281 | return; |
187 | } | 282 | } |
188 | else | 283 | } else if (fam_ops->dc_mce(ec, xec)) |
189 | goto wrong_dc_mce; | 284 | ; |
190 | } | 285 | else |
191 | 286 | pr_emerg(HW_ERR "Corrupted DC MCE info?\n"); | |
192 | if (!fam_ops->dc_mce(ec)) | ||
193 | goto wrong_dc_mce; | ||
194 | |||
195 | return; | ||
196 | |||
197 | wrong_dc_mce: | ||
198 | pr_emerg(HW_ERR "Corrupted DC MCE info?\n"); | ||
199 | } | 287 | } |
200 | 288 | ||
201 | static bool k8_ic_mce(u16 ec) | 289 | static bool k8_ic_mce(u16 ec, u8 xec) |
202 | { | 290 | { |
203 | u8 ll = ec & 0x3; | 291 | u8 ll = LL(ec); |
204 | u8 r4 = (ec >> 4) & 0xf; | ||
205 | bool ret = true; | 292 | bool ret = true; |
206 | 293 | ||
207 | if (!MEM_ERROR(ec)) | 294 | if (!MEM_ERROR(ec)) |
@@ -210,7 +297,7 @@ static bool k8_ic_mce(u16 ec) | |||
210 | if (ll == 0x2) | 297 | if (ll == 0x2) |
211 | pr_cont("during a linefill from L2.\n"); | 298 | pr_cont("during a linefill from L2.\n"); |
212 | else if (ll == 0x1) { | 299 | else if (ll == 0x1) { |
213 | switch (r4) { | 300 | switch (R4(ec)) { |
214 | case R4_IRD: | 301 | case R4_IRD: |
215 | pr_cont("Parity error during data load.\n"); | 302 | pr_cont("Parity error during data load.\n"); |
216 | break; | 303 | break; |
@@ -233,15 +320,13 @@ static bool k8_ic_mce(u16 ec) | |||
233 | return ret; | 320 | return ret; |
234 | } | 321 | } |
235 | 322 | ||
236 | static bool f14h_ic_mce(u16 ec) | 323 | static bool f14h_ic_mce(u16 ec, u8 xec) |
237 | { | 324 | { |
238 | u8 ll = ec & 0x3; | 325 | u8 r4 = R4(ec); |
239 | u8 tt = (ec >> 2) & 0x3; | ||
240 | u8 r4 = (ec >> 4) & 0xf; | ||
241 | bool ret = true; | 326 | bool ret = true; |
242 | 327 | ||
243 | if (MEM_ERROR(ec)) { | 328 | if (MEM_ERROR(ec)) { |
244 | if (tt != 0 || ll != 1) | 329 | if (TT(ec) != 0 || LL(ec) != 1) |
245 | ret = false; | 330 | ret = false; |
246 | 331 | ||
247 | if (r4 == R4_IRD) | 332 | if (r4 == R4_IRD) |
@@ -254,10 +339,36 @@ static bool f14h_ic_mce(u16 ec) | |||
254 | return ret; | 339 | return ret; |
255 | } | 340 | } |
256 | 341 | ||
342 | static bool f15h_ic_mce(u16 ec, u8 xec) | ||
343 | { | ||
344 | bool ret = true; | ||
345 | |||
346 | if (!MEM_ERROR(ec)) | ||
347 | return false; | ||
348 | |||
349 | switch (xec) { | ||
350 | case 0x0 ... 0xa: | ||
351 | pr_cont("%s.\n", f15h_ic_mce_desc[xec]); | ||
352 | break; | ||
353 | |||
354 | case 0xd: | ||
355 | pr_cont("%s.\n", f15h_ic_mce_desc[xec-2]); | ||
356 | break; | ||
357 | |||
358 | case 0x10 ... 0x14: | ||
359 | pr_cont("Decoder %s parity error.\n", f15h_ic_mce_desc[xec-4]); | ||
360 | break; | ||
361 | |||
362 | default: | ||
363 | ret = false; | ||
364 | } | ||
365 | return ret; | ||
366 | } | ||
367 | |||
257 | static void amd_decode_ic_mce(struct mce *m) | 368 | static void amd_decode_ic_mce(struct mce *m) |
258 | { | 369 | { |
259 | u16 ec = m->status & 0xffff; | 370 | u16 ec = EC(m->status); |
260 | u8 xec = (m->status >> 16) & 0xf; | 371 | u8 xec = XEC(m->status, xec_mask); |
261 | 372 | ||
262 | pr_emerg(HW_ERR "Instruction Cache Error: "); | 373 | pr_emerg(HW_ERR "Instruction Cache Error: "); |
263 | 374 | ||
@@ -268,7 +379,7 @@ static void amd_decode_ic_mce(struct mce *m) | |||
268 | bool k8 = (boot_cpu_data.x86 == 0xf && (m->status & BIT_64(58))); | 379 | bool k8 = (boot_cpu_data.x86 == 0xf && (m->status & BIT_64(58))); |
269 | 380 | ||
270 | pr_cont("during %s.\n", (k8 ? "system linefill" : "NB data read")); | 381 | pr_cont("during %s.\n", (k8 ? "system linefill" : "NB data read")); |
271 | } else if (fam_ops->ic_mce(ec)) | 382 | } else if (fam_ops->ic_mce(ec, xec)) |
272 | ; | 383 | ; |
273 | else | 384 | else |
274 | pr_emerg(HW_ERR "Corrupted IC MCE info?\n"); | 385 | pr_emerg(HW_ERR "Corrupted IC MCE info?\n"); |
@@ -276,8 +387,8 @@ static void amd_decode_ic_mce(struct mce *m) | |||
276 | 387 | ||
277 | static void amd_decode_bu_mce(struct mce *m) | 388 | static void amd_decode_bu_mce(struct mce *m) |
278 | { | 389 | { |
279 | u32 ec = m->status & 0xffff; | 390 | u16 ec = EC(m->status); |
280 | u32 xec = (m->status >> 16) & 0xf; | 391 | u8 xec = XEC(m->status, xec_mask); |
281 | 392 | ||
282 | pr_emerg(HW_ERR "Bus Unit Error"); | 393 | pr_emerg(HW_ERR "Bus Unit Error"); |
283 | 394 | ||
@@ -286,23 +397,23 @@ static void amd_decode_bu_mce(struct mce *m) | |||
286 | else if (xec == 0x3) | 397 | else if (xec == 0x3) |
287 | pr_cont(" in the victim data buffers.\n"); | 398 | pr_cont(" in the victim data buffers.\n"); |
288 | else if (xec == 0x2 && MEM_ERROR(ec)) | 399 | else if (xec == 0x2 && MEM_ERROR(ec)) |
289 | pr_cont(": %s error in the L2 cache tags.\n", RRRR_MSG(ec)); | 400 | pr_cont(": %s error in the L2 cache tags.\n", R4_MSG(ec)); |
290 | else if (xec == 0x0) { | 401 | else if (xec == 0x0) { |
291 | if (TLB_ERROR(ec)) | 402 | if (TLB_ERROR(ec)) |
292 | pr_cont(": %s error in a Page Descriptor Cache or " | 403 | pr_cont(": %s error in a Page Descriptor Cache or " |
293 | "Guest TLB.\n", TT_MSG(ec)); | 404 | "Guest TLB.\n", TT_MSG(ec)); |
294 | else if (BUS_ERROR(ec)) | 405 | else if (BUS_ERROR(ec)) |
295 | pr_cont(": %s/ECC error in data read from NB: %s.\n", | 406 | pr_cont(": %s/ECC error in data read from NB: %s.\n", |
296 | RRRR_MSG(ec), PP_MSG(ec)); | 407 | R4_MSG(ec), PP_MSG(ec)); |
297 | else if (MEM_ERROR(ec)) { | 408 | else if (MEM_ERROR(ec)) { |
298 | u8 rrrr = (ec >> 4) & 0xf; | 409 | u8 r4 = R4(ec); |
299 | 410 | ||
300 | if (rrrr >= 0x7) | 411 | if (r4 >= 0x7) |
301 | pr_cont(": %s error during data copyback.\n", | 412 | pr_cont(": %s error during data copyback.\n", |
302 | RRRR_MSG(ec)); | 413 | R4_MSG(ec)); |
303 | else if (rrrr <= 0x1) | 414 | else if (r4 <= 0x1) |
304 | pr_cont(": %s parity/ECC error during data " | 415 | pr_cont(": %s parity/ECC error during data " |
305 | "access from L2.\n", RRRR_MSG(ec)); | 416 | "access from L2.\n", R4_MSG(ec)); |
306 | else | 417 | else |
307 | goto wrong_bu_mce; | 418 | goto wrong_bu_mce; |
308 | } else | 419 | } else |
@@ -316,12 +427,52 @@ wrong_bu_mce: | |||
316 | pr_emerg(HW_ERR "Corrupted BU MCE info?\n"); | 427 | pr_emerg(HW_ERR "Corrupted BU MCE info?\n"); |
317 | } | 428 | } |
318 | 429 | ||
430 | static void amd_decode_cu_mce(struct mce *m) | ||
431 | { | ||
432 | u16 ec = EC(m->status); | ||
433 | u8 xec = XEC(m->status, xec_mask); | ||
434 | |||
435 | pr_emerg(HW_ERR "Combined Unit Error: "); | ||
436 | |||
437 | if (TLB_ERROR(ec)) { | ||
438 | if (xec == 0x0) | ||
439 | pr_cont("Data parity TLB read error.\n"); | ||
440 | else if (xec == 0x1) | ||
441 | pr_cont("Poison data provided for TLB fill.\n"); | ||
442 | else | ||
443 | goto wrong_cu_mce; | ||
444 | } else if (BUS_ERROR(ec)) { | ||
445 | if (xec > 2) | ||
446 | goto wrong_cu_mce; | ||
447 | |||
448 | pr_cont("Error during attempted NB data read.\n"); | ||
449 | } else if (MEM_ERROR(ec)) { | ||
450 | switch (xec) { | ||
451 | case 0x4 ... 0xc: | ||
452 | pr_cont("%s.\n", f15h_cu_mce_desc[xec - 0x4]); | ||
453 | break; | ||
454 | |||
455 | case 0x10 ... 0x14: | ||
456 | pr_cont("%s.\n", f15h_cu_mce_desc[xec - 0x7]); | ||
457 | break; | ||
458 | |||
459 | default: | ||
460 | goto wrong_cu_mce; | ||
461 | } | ||
462 | } | ||
463 | |||
464 | return; | ||
465 | |||
466 | wrong_cu_mce: | ||
467 | pr_emerg(HW_ERR "Corrupted CU MCE info?\n"); | ||
468 | } | ||
469 | |||
319 | static void amd_decode_ls_mce(struct mce *m) | 470 | static void amd_decode_ls_mce(struct mce *m) |
320 | { | 471 | { |
321 | u16 ec = m->status & 0xffff; | 472 | u16 ec = EC(m->status); |
322 | u8 xec = (m->status >> 16) & 0xf; | 473 | u8 xec = XEC(m->status, xec_mask); |
323 | 474 | ||
324 | if (boot_cpu_data.x86 == 0x14) { | 475 | if (boot_cpu_data.x86 >= 0x14) { |
325 | pr_emerg("You shouldn't be seeing an LS MCE on this cpu family," | 476 | pr_emerg("You shouldn't be seeing an LS MCE on this cpu family," |
326 | " please report on LKML.\n"); | 477 | " please report on LKML.\n"); |
327 | return; | 478 | return; |
@@ -330,12 +481,12 @@ static void amd_decode_ls_mce(struct mce *m) | |||
330 | pr_emerg(HW_ERR "Load Store Error"); | 481 | pr_emerg(HW_ERR "Load Store Error"); |
331 | 482 | ||
332 | if (xec == 0x0) { | 483 | if (xec == 0x0) { |
333 | u8 r4 = (ec >> 4) & 0xf; | 484 | u8 r4 = R4(ec); |
334 | 485 | ||
335 | if (!BUS_ERROR(ec) || (r4 != R4_DRD && r4 != R4_DWR)) | 486 | if (!BUS_ERROR(ec) || (r4 != R4_DRD && r4 != R4_DWR)) |
336 | goto wrong_ls_mce; | 487 | goto wrong_ls_mce; |
337 | 488 | ||
338 | pr_cont(" during %s.\n", RRRR_MSG(ec)); | 489 | pr_cont(" during %s.\n", R4_MSG(ec)); |
339 | } else | 490 | } else |
340 | goto wrong_ls_mce; | 491 | goto wrong_ls_mce; |
341 | 492 | ||
@@ -410,6 +561,15 @@ static bool f10h_nb_mce(u16 ec, u8 xec) | |||
410 | goto out; | 561 | goto out; |
411 | break; | 562 | break; |
412 | 563 | ||
564 | case 0x19: | ||
565 | if (boot_cpu_data.x86 == 0x15) | ||
566 | pr_cont("Compute Unit Data Error.\n"); | ||
567 | else | ||
568 | ret = false; | ||
569 | |||
570 | goto out; | ||
571 | break; | ||
572 | |||
413 | case 0x1c ... 0x1f: | 573 | case 0x1c ... 0x1f: |
414 | offset = 24; | 574 | offset = 24; |
415 | break; | 575 | break; |
@@ -434,27 +594,30 @@ static bool nb_noop_mce(u16 ec, u8 xec) | |||
434 | 594 | ||
435 | void amd_decode_nb_mce(int node_id, struct mce *m, u32 nbcfg) | 595 | void amd_decode_nb_mce(int node_id, struct mce *m, u32 nbcfg) |
436 | { | 596 | { |
437 | u8 xec = (m->status >> 16) & 0x1f; | 597 | u16 ec = EC(m->status); |
438 | u16 ec = m->status & 0xffff; | 598 | u8 xec = XEC(m->status, 0x1f); |
439 | u32 nbsh = (u32)(m->status >> 32); | 599 | u32 nbsh = (u32)(m->status >> 32); |
600 | int core = -1; | ||
440 | 601 | ||
441 | pr_emerg(HW_ERR "Northbridge Error, node %d: ", node_id); | 602 | pr_emerg(HW_ERR "Northbridge Error (node %d", node_id); |
442 | 603 | ||
443 | /* | 604 | /* F10h, revD can disable ErrCpu[3:0] through ErrCpuVal */ |
444 | * F10h, revD can disable ErrCpu[3:0] so check that first and also the | ||
445 | * value encoding has changed so interpret those differently | ||
446 | */ | ||
447 | if ((boot_cpu_data.x86 == 0x10) && | 605 | if ((boot_cpu_data.x86 == 0x10) && |
448 | (boot_cpu_data.x86_model > 7)) { | 606 | (boot_cpu_data.x86_model > 7)) { |
449 | if (nbsh & K8_NBSH_ERR_CPU_VAL) | 607 | if (nbsh & K8_NBSH_ERR_CPU_VAL) |
450 | pr_cont(", core: %u", (u8)(nbsh & nb_err_cpumask)); | 608 | core = nbsh & nb_err_cpumask; |
451 | } else { | 609 | } else { |
452 | u8 assoc_cpus = nbsh & nb_err_cpumask; | 610 | u8 assoc_cpus = nbsh & nb_err_cpumask; |
453 | 611 | ||
454 | if (assoc_cpus > 0) | 612 | if (assoc_cpus > 0) |
455 | pr_cont(", core: %d", fls(assoc_cpus) - 1); | 613 | core = fls(assoc_cpus) - 1; |
456 | } | 614 | } |
457 | 615 | ||
616 | if (core >= 0) | ||
617 | pr_cont(", core %d): ", core); | ||
618 | else | ||
619 | pr_cont("): "); | ||
620 | |||
458 | switch (xec) { | 621 | switch (xec) { |
459 | case 0x2: | 622 | case 0x2: |
460 | pr_cont("Sync error (sync packets on HT link detected).\n"); | 623 | pr_cont("Sync error (sync packets on HT link detected).\n"); |
@@ -496,35 +659,89 @@ EXPORT_SYMBOL_GPL(amd_decode_nb_mce); | |||
496 | 659 | ||
497 | static void amd_decode_fr_mce(struct mce *m) | 660 | static void amd_decode_fr_mce(struct mce *m) |
498 | { | 661 | { |
499 | if (boot_cpu_data.x86 == 0xf || | 662 | struct cpuinfo_x86 *c = &boot_cpu_data; |
500 | boot_cpu_data.x86 == 0x11) | 663 | u8 xec = XEC(m->status, xec_mask); |
664 | |||
665 | if (c->x86 == 0xf || c->x86 == 0x11) | ||
501 | goto wrong_fr_mce; | 666 | goto wrong_fr_mce; |
502 | 667 | ||
503 | /* we have only one error signature so match all fields at once. */ | 668 | if (c->x86 != 0x15 && xec != 0x0) |
504 | if ((m->status & 0xffff) == 0x0f0f) { | 669 | goto wrong_fr_mce; |
505 | pr_emerg(HW_ERR "FR Error: CPU Watchdog timer expire.\n"); | 670 | |
506 | return; | 671 | pr_emerg(HW_ERR "%s Error: ", |
507 | } | 672 | (c->x86 == 0x15 ? "Execution Unit" : "FIROB")); |
673 | |||
674 | if (xec == 0x0 || xec == 0xc) | ||
675 | pr_cont("%s.\n", fr_ex_mce_desc[xec]); | ||
676 | else if (xec < 0xd) | ||
677 | pr_cont("%s parity error.\n", fr_ex_mce_desc[xec]); | ||
678 | else | ||
679 | goto wrong_fr_mce; | ||
680 | |||
681 | return; | ||
508 | 682 | ||
509 | wrong_fr_mce: | 683 | wrong_fr_mce: |
510 | pr_emerg(HW_ERR "Corrupted FR MCE info?\n"); | 684 | pr_emerg(HW_ERR "Corrupted FR MCE info?\n"); |
511 | } | 685 | } |
512 | 686 | ||
687 | static void amd_decode_fp_mce(struct mce *m) | ||
688 | { | ||
689 | u8 xec = XEC(m->status, xec_mask); | ||
690 | |||
691 | pr_emerg(HW_ERR "Floating Point Unit Error: "); | ||
692 | |||
693 | switch (xec) { | ||
694 | case 0x1: | ||
695 | pr_cont("Free List"); | ||
696 | break; | ||
697 | |||
698 | case 0x2: | ||
699 | pr_cont("Physical Register File"); | ||
700 | break; | ||
701 | |||
702 | case 0x3: | ||
703 | pr_cont("Retire Queue"); | ||
704 | break; | ||
705 | |||
706 | case 0x4: | ||
707 | pr_cont("Scheduler table"); | ||
708 | break; | ||
709 | |||
710 | case 0x5: | ||
711 | pr_cont("Status Register File"); | ||
712 | break; | ||
713 | |||
714 | default: | ||
715 | goto wrong_fp_mce; | ||
716 | break; | ||
717 | } | ||
718 | |||
719 | pr_cont(" parity error.\n"); | ||
720 | |||
721 | return; | ||
722 | |||
723 | wrong_fp_mce: | ||
724 | pr_emerg(HW_ERR "Corrupted FP MCE info?\n"); | ||
725 | } | ||
726 | |||
513 | static inline void amd_decode_err_code(u16 ec) | 727 | static inline void amd_decode_err_code(u16 ec) |
514 | { | 728 | { |
515 | if (TLB_ERROR(ec)) { | 729 | |
516 | pr_emerg(HW_ERR "Transaction: %s, Cache Level: %s\n", | 730 | pr_emerg(HW_ERR "cache level: %s", LL_MSG(ec)); |
517 | TT_MSG(ec), LL_MSG(ec)); | 731 | |
518 | } else if (MEM_ERROR(ec)) { | 732 | if (BUS_ERROR(ec)) |
519 | pr_emerg(HW_ERR "Transaction: %s, Type: %s, Cache Level: %s\n", | 733 | pr_cont(", mem/io: %s", II_MSG(ec)); |
520 | RRRR_MSG(ec), TT_MSG(ec), LL_MSG(ec)); | 734 | else |
521 | } else if (BUS_ERROR(ec)) { | 735 | pr_cont(", tx: %s", TT_MSG(ec)); |
522 | pr_emerg(HW_ERR "Transaction: %s (%s), %s, Cache Level: %s, " | 736 | |
523 | "Participating Processor: %s\n", | 737 | if (MEM_ERROR(ec) || BUS_ERROR(ec)) { |
524 | RRRR_MSG(ec), II_MSG(ec), TO_MSG(ec), LL_MSG(ec), | 738 | pr_cont(", mem-tx: %s", R4_MSG(ec)); |
525 | PP_MSG(ec)); | 739 | |
526 | } else | 740 | if (BUS_ERROR(ec)) |
527 | pr_emerg(HW_ERR "Huh? Unknown MCE error 0x%x\n", ec); | 741 | pr_cont(", part-proc: %s (%s)", PP_MSG(ec), TO_MSG(ec)); |
742 | } | ||
743 | |||
744 | pr_cont("\n"); | ||
528 | } | 745 | } |
529 | 746 | ||
530 | /* | 747 | /* |
@@ -546,25 +763,32 @@ static bool amd_filter_mce(struct mce *m) | |||
546 | int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data) | 763 | int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data) |
547 | { | 764 | { |
548 | struct mce *m = (struct mce *)data; | 765 | struct mce *m = (struct mce *)data; |
766 | struct cpuinfo_x86 *c = &boot_cpu_data; | ||
549 | int node, ecc; | 767 | int node, ecc; |
550 | 768 | ||
551 | if (amd_filter_mce(m)) | 769 | if (amd_filter_mce(m)) |
552 | return NOTIFY_STOP; | 770 | return NOTIFY_STOP; |
553 | 771 | ||
554 | pr_emerg(HW_ERR "MC%d_STATUS: ", m->bank); | 772 | pr_emerg(HW_ERR "MC%d_STATUS[%s|%s|%s|%s|%s", |
773 | m->bank, | ||
774 | ((m->status & MCI_STATUS_OVER) ? "Over" : "-"), | ||
775 | ((m->status & MCI_STATUS_UC) ? "UE" : "CE"), | ||
776 | ((m->status & MCI_STATUS_MISCV) ? "MiscV" : "-"), | ||
777 | ((m->status & MCI_STATUS_PCC) ? "PCC" : "-"), | ||
778 | ((m->status & MCI_STATUS_ADDRV) ? "AddrV" : "-")); | ||
555 | 779 | ||
556 | pr_cont("%sorrected error, other errors lost: %s, " | 780 | if (c->x86 == 0x15) |
557 | "CPU context corrupt: %s", | 781 | pr_cont("|%s|%s", |
558 | ((m->status & MCI_STATUS_UC) ? "Unc" : "C"), | 782 | ((m->status & BIT_64(44)) ? "Deferred" : "-"), |
559 | ((m->status & MCI_STATUS_OVER) ? "yes" : "no"), | 783 | ((m->status & BIT_64(43)) ? "Poison" : "-")); |
560 | ((m->status & MCI_STATUS_PCC) ? "yes" : "no")); | ||
561 | 784 | ||
562 | /* do the two bits[14:13] together */ | 785 | /* do the two bits[14:13] together */ |
563 | ecc = (m->status >> 45) & 0x3; | 786 | ecc = (m->status >> 45) & 0x3; |
564 | if (ecc) | 787 | if (ecc) |
565 | pr_cont(", %sECC Error", ((ecc == 2) ? "C" : "U")); | 788 | pr_cont("|%sECC", ((ecc == 2) ? "C" : "U")); |
789 | |||
790 | pr_cont("]: 0x%016llx\n", m->status); | ||
566 | 791 | ||
567 | pr_cont("\n"); | ||
568 | 792 | ||
569 | switch (m->bank) { | 793 | switch (m->bank) { |
570 | case 0: | 794 | case 0: |
@@ -576,7 +800,10 @@ int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data) | |||
576 | break; | 800 | break; |
577 | 801 | ||
578 | case 2: | 802 | case 2: |
579 | amd_decode_bu_mce(m); | 803 | if (c->x86 == 0x15) |
804 | amd_decode_cu_mce(m); | ||
805 | else | ||
806 | amd_decode_bu_mce(m); | ||
580 | break; | 807 | break; |
581 | 808 | ||
582 | case 3: | 809 | case 3: |
@@ -592,6 +819,10 @@ int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data) | |||
592 | amd_decode_fr_mce(m); | 819 | amd_decode_fr_mce(m); |
593 | break; | 820 | break; |
594 | 821 | ||
822 | case 6: | ||
823 | amd_decode_fp_mce(m); | ||
824 | break; | ||
825 | |||
595 | default: | 826 | default: |
596 | break; | 827 | break; |
597 | } | 828 | } |
@@ -608,18 +839,21 @@ static struct notifier_block amd_mce_dec_nb = { | |||
608 | 839 | ||
609 | static int __init mce_amd_init(void) | 840 | static int __init mce_amd_init(void) |
610 | { | 841 | { |
611 | if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) | 842 | struct cpuinfo_x86 *c = &boot_cpu_data; |
843 | |||
844 | if (c->x86_vendor != X86_VENDOR_AMD) | ||
612 | return 0; | 845 | return 0; |
613 | 846 | ||
614 | if ((boot_cpu_data.x86 < 0xf || boot_cpu_data.x86 > 0x12) && | 847 | if ((c->x86 < 0xf || c->x86 > 0x12) && |
615 | (boot_cpu_data.x86 != 0x14 || boot_cpu_data.x86_model > 0xf)) | 848 | (c->x86 != 0x14 || c->x86_model > 0xf) && |
849 | (c->x86 != 0x15 || c->x86_model > 0xf)) | ||
616 | return 0; | 850 | return 0; |
617 | 851 | ||
618 | fam_ops = kzalloc(sizeof(struct amd_decoder_ops), GFP_KERNEL); | 852 | fam_ops = kzalloc(sizeof(struct amd_decoder_ops), GFP_KERNEL); |
619 | if (!fam_ops) | 853 | if (!fam_ops) |
620 | return -ENOMEM; | 854 | return -ENOMEM; |
621 | 855 | ||
622 | switch (boot_cpu_data.x86) { | 856 | switch (c->x86) { |
623 | case 0xf: | 857 | case 0xf: |
624 | fam_ops->dc_mce = k8_dc_mce; | 858 | fam_ops->dc_mce = k8_dc_mce; |
625 | fam_ops->ic_mce = k8_ic_mce; | 859 | fam_ops->ic_mce = k8_ic_mce; |
@@ -651,9 +885,15 @@ static int __init mce_amd_init(void) | |||
651 | fam_ops->nb_mce = nb_noop_mce; | 885 | fam_ops->nb_mce = nb_noop_mce; |
652 | break; | 886 | break; |
653 | 887 | ||
888 | case 0x15: | ||
889 | xec_mask = 0x1f; | ||
890 | fam_ops->dc_mce = f15h_dc_mce; | ||
891 | fam_ops->ic_mce = f15h_ic_mce; | ||
892 | fam_ops->nb_mce = f10h_nb_mce; | ||
893 | break; | ||
894 | |||
654 | default: | 895 | default: |
655 | printk(KERN_WARNING "Huh? What family is that: %d?!\n", | 896 | printk(KERN_WARNING "Huh? What family is that: %d?!\n", c->x86); |
656 | boot_cpu_data.x86); | ||
657 | kfree(fam_ops); | 897 | kfree(fam_ops); |
658 | return -EINVAL; | 898 | return -EINVAL; |
659 | } | 899 | } |
diff --git a/drivers/edac/mce_amd.h b/drivers/edac/mce_amd.h index 35f6e0e3b297..45dda47173f2 100644 --- a/drivers/edac/mce_amd.h +++ b/drivers/edac/mce_amd.h | |||
@@ -7,8 +7,8 @@ | |||
7 | 7 | ||
8 | #define BIT_64(n) (U64_C(1) << (n)) | 8 | #define BIT_64(n) (U64_C(1) << (n)) |
9 | 9 | ||
10 | #define ERROR_CODE(x) ((x) & 0xffff) | 10 | #define EC(x) ((x) & 0xffff) |
11 | #define EXT_ERROR_CODE(x) (((x) >> 16) & 0x1f) | 11 | #define XEC(x, mask) (((x) >> 16) & mask) |
12 | 12 | ||
13 | #define LOW_SYNDROME(x) (((x) >> 15) & 0xff) | 13 | #define LOW_SYNDROME(x) (((x) >> 15) & 0xff) |
14 | #define HIGH_SYNDROME(x) (((x) >> 24) & 0xff) | 14 | #define HIGH_SYNDROME(x) (((x) >> 24) & 0xff) |
@@ -21,15 +21,15 @@ | |||
21 | #define TT_MSG(x) tt_msgs[TT(x)] | 21 | #define TT_MSG(x) tt_msgs[TT(x)] |
22 | #define II(x) (((x) >> 2) & 0x3) | 22 | #define II(x) (((x) >> 2) & 0x3) |
23 | #define II_MSG(x) ii_msgs[II(x)] | 23 | #define II_MSG(x) ii_msgs[II(x)] |
24 | #define LL(x) (((x) >> 0) & 0x3) | 24 | #define LL(x) ((x) & 0x3) |
25 | #define LL_MSG(x) ll_msgs[LL(x)] | 25 | #define LL_MSG(x) ll_msgs[LL(x)] |
26 | #define TO(x) (((x) >> 8) & 0x1) | 26 | #define TO(x) (((x) >> 8) & 0x1) |
27 | #define TO_MSG(x) to_msgs[TO(x)] | 27 | #define TO_MSG(x) to_msgs[TO(x)] |
28 | #define PP(x) (((x) >> 9) & 0x3) | 28 | #define PP(x) (((x) >> 9) & 0x3) |
29 | #define PP_MSG(x) pp_msgs[PP(x)] | 29 | #define PP_MSG(x) pp_msgs[PP(x)] |
30 | 30 | ||
31 | #define RRRR(x) (((x) >> 4) & 0xf) | 31 | #define R4(x) (((x) >> 4) & 0xf) |
32 | #define RRRR_MSG(x) ((RRRR(x) < 9) ? rrrr_msgs[RRRR(x)] : "Wrong R4!") | 32 | #define R4_MSG(x) ((R4(x) < 9) ? rrrr_msgs[R4(x)] : "Wrong R4!") |
33 | 33 | ||
34 | #define K8_NBSH 0x4C | 34 | #define K8_NBSH 0x4C |
35 | 35 | ||
@@ -100,8 +100,8 @@ struct err_regs { | |||
100 | * per-family decoder ops | 100 | * per-family decoder ops |
101 | */ | 101 | */ |
102 | struct amd_decoder_ops { | 102 | struct amd_decoder_ops { |
103 | bool (*dc_mce)(u16); | 103 | bool (*dc_mce)(u16, u8); |
104 | bool (*ic_mce)(u16); | 104 | bool (*ic_mce)(u16, u8); |
105 | bool (*nb_mce)(u16, u8); | 105 | bool (*nb_mce)(u16, u8); |
106 | }; | 106 | }; |
107 | 107 | ||
diff --git a/drivers/edac/mce_amd_inj.c b/drivers/edac/mce_amd_inj.c index 39faded3cadd..733a7e7a8d6f 100644 --- a/drivers/edac/mce_amd_inj.c +++ b/drivers/edac/mce_amd_inj.c | |||
@@ -88,10 +88,11 @@ static ssize_t edac_inject_bank_store(struct kobject *kobj, | |||
88 | return -EINVAL; | 88 | return -EINVAL; |
89 | } | 89 | } |
90 | 90 | ||
91 | if (value > 5) { | 91 | if (value > 5) |
92 | printk(KERN_ERR "Non-existant MCE bank: %lu\n", value); | 92 | if (boot_cpu_data.x86 != 0x15 || value > 6) { |
93 | return -EINVAL; | 93 | printk(KERN_ERR "Non-existant MCE bank: %lu\n", value); |
94 | } | 94 | return -EINVAL; |
95 | } | ||
95 | 96 | ||
96 | i_mce.bank = value; | 97 | i_mce.bank = value; |
97 | 98 | ||