diff options
Diffstat (limited to 'drivers/edac')
-rw-r--r-- | drivers/edac/Kconfig | 14 | ||||
-rw-r--r-- | drivers/edac/Makefile | 5 | ||||
-rw-r--r-- | drivers/edac/amd64_edac.c | 106 | ||||
-rw-r--r-- | drivers/edac/amd64_edac.h | 23 | ||||
-rw-r--r-- | drivers/edac/amd64_edac_inj.c | 49 | ||||
-rw-r--r-- | drivers/edac/edac_mce_amd.c | 32 | ||||
-rw-r--r-- | drivers/edac/i5000_edac.c | 7 | ||||
-rw-r--r-- | drivers/edac/i5400_edac.c | 89 | ||||
-rw-r--r-- | drivers/edac/mpc85xx_edac.c | 2 |
9 files changed, 180 insertions, 147 deletions
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 02127e59fe8e..55c9c59b3f71 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig | |||
@@ -47,6 +47,18 @@ config EDAC_DEBUG_VERBOSE | |||
47 | Source file name and line number where debugging message | 47 | Source file name and line number where debugging message |
48 | printed will be added to debugging message. | 48 | printed will be added to debugging message. |
49 | 49 | ||
50 | config EDAC_DECODE_MCE | ||
51 | tristate "Decode MCEs in human-readable form (only on AMD for now)" | ||
52 | depends on CPU_SUP_AMD && X86_MCE | ||
53 | default y | ||
54 | ---help--- | ||
55 | Enable this option if you want to decode Machine Check Exceptions | ||
56 | occuring on your machine in human-readable form. | ||
57 | |||
58 | You should definitely say Y here in case you want to decode MCEs | ||
59 | which occur really early upon boot, before the module infrastructure | ||
60 | has been initialized. | ||
61 | |||
50 | config EDAC_MM_EDAC | 62 | config EDAC_MM_EDAC |
51 | tristate "Main Memory EDAC (Error Detection And Correction) reporting" | 63 | tristate "Main Memory EDAC (Error Detection And Correction) reporting" |
52 | help | 64 | help |
@@ -59,7 +71,7 @@ config EDAC_MM_EDAC | |||
59 | 71 | ||
60 | config EDAC_AMD64 | 72 | config EDAC_AMD64 |
61 | tristate "AMD64 (Opteron, Athlon64) K8, F10h, F11h" | 73 | tristate "AMD64 (Opteron, Athlon64) K8, F10h, F11h" |
62 | depends on EDAC_MM_EDAC && K8_NB && X86_64 && PCI && CPU_SUP_AMD | 74 | depends on EDAC_MM_EDAC && K8_NB && X86_64 && PCI && EDAC_DECODE_MCE |
63 | help | 75 | help |
64 | Support for error detection and correction on the AMD 64 | 76 | Support for error detection and correction on the AMD 64 |
65 | Families of Memory Controllers (K8, F10h and F11h) | 77 | Families of Memory Controllers (K8, F10h and F11h) |
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile index 7a473bbe8abd..bc5dc232a0fb 100644 --- a/drivers/edac/Makefile +++ b/drivers/edac/Makefile | |||
@@ -6,7 +6,6 @@ | |||
6 | # GNU General Public License. | 6 | # GNU General Public License. |
7 | # | 7 | # |
8 | 8 | ||
9 | |||
10 | obj-$(CONFIG_EDAC) := edac_stub.o | 9 | obj-$(CONFIG_EDAC) := edac_stub.o |
11 | obj-$(CONFIG_EDAC_MM_EDAC) += edac_core.o | 10 | obj-$(CONFIG_EDAC_MM_EDAC) += edac_core.o |
12 | 11 | ||
@@ -17,9 +16,7 @@ ifdef CONFIG_PCI | |||
17 | edac_core-objs += edac_pci.o edac_pci_sysfs.o | 16 | edac_core-objs += edac_pci.o edac_pci_sysfs.o |
18 | endif | 17 | endif |
19 | 18 | ||
20 | ifdef CONFIG_CPU_SUP_AMD | 19 | obj-$(CONFIG_EDAC_DECODE_MCE) += edac_mce_amd.o |
21 | edac_core-objs += edac_mce_amd.o | ||
22 | endif | ||
23 | 20 | ||
24 | obj-$(CONFIG_EDAC_AMD76X) += amd76x_edac.o | 21 | obj-$(CONFIG_EDAC_AMD76X) += amd76x_edac.o |
25 | obj-$(CONFIG_EDAC_CPC925) += cpc925_edac.o | 22 | obj-$(CONFIG_EDAC_CPC925) += cpc925_edac.o |
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 4e551e63b6dc..a38831c82649 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c | |||
@@ -15,8 +15,8 @@ module_param(ecc_enable_override, int, 0644); | |||
15 | 15 | ||
16 | /* Lookup table for all possible MC control instances */ | 16 | /* Lookup table for all possible MC control instances */ |
17 | struct amd64_pvt; | 17 | struct amd64_pvt; |
18 | static struct mem_ctl_info *mci_lookup[MAX_NUMNODES]; | 18 | static struct mem_ctl_info *mci_lookup[EDAC_MAX_NUMNODES]; |
19 | static struct amd64_pvt *pvt_lookup[MAX_NUMNODES]; | 19 | static struct amd64_pvt *pvt_lookup[EDAC_MAX_NUMNODES]; |
20 | 20 | ||
21 | /* | 21 | /* |
22 | * See F2x80 for K8 and F2x[1,0]80 for Fam10 and later. The table below is only | 22 | * See F2x80 for K8 and F2x[1,0]80 for Fam10 and later. The table below is only |
@@ -189,7 +189,10 @@ static int amd64_get_scrub_rate(struct mem_ctl_info *mci, u32 *bw) | |||
189 | /* Map from a CSROW entry to the mask entry that operates on it */ | 189 | /* Map from a CSROW entry to the mask entry that operates on it */ |
190 | static inline u32 amd64_map_to_dcs_mask(struct amd64_pvt *pvt, int csrow) | 190 | static inline u32 amd64_map_to_dcs_mask(struct amd64_pvt *pvt, int csrow) |
191 | { | 191 | { |
192 | return csrow >> (pvt->num_dcsm >> 3); | 192 | if (boot_cpu_data.x86 == 0xf && pvt->ext_model < OPTERON_CPU_REV_F) |
193 | return csrow; | ||
194 | else | ||
195 | return csrow >> 1; | ||
193 | } | 196 | } |
194 | 197 | ||
195 | /* return the 'base' address the i'th CS entry of the 'dct' DRAM controller */ | 198 | /* return the 'base' address the i'th CS entry of the 'dct' DRAM controller */ |
@@ -279,29 +282,26 @@ static struct mem_ctl_info *find_mc_by_sys_addr(struct mem_ctl_info *mci, | |||
279 | intlv_en = pvt->dram_IntlvEn[0]; | 282 | intlv_en = pvt->dram_IntlvEn[0]; |
280 | 283 | ||
281 | if (intlv_en == 0) { | 284 | if (intlv_en == 0) { |
282 | for (node_id = 0; ; ) { | 285 | for (node_id = 0; node_id < DRAM_REG_COUNT; node_id++) { |
283 | if (amd64_base_limit_match(pvt, sys_addr, node_id)) | 286 | if (amd64_base_limit_match(pvt, sys_addr, node_id)) |
284 | break; | 287 | goto found; |
285 | |||
286 | if (++node_id >= DRAM_REG_COUNT) | ||
287 | goto err_no_match; | ||
288 | } | 288 | } |
289 | goto found; | 289 | goto err_no_match; |
290 | } | 290 | } |
291 | 291 | ||
292 | if (unlikely((intlv_en != (0x01 << 8)) && | 292 | if (unlikely((intlv_en != 0x01) && |
293 | (intlv_en != (0x03 << 8)) && | 293 | (intlv_en != 0x03) && |
294 | (intlv_en != (0x07 << 8)))) { | 294 | (intlv_en != 0x07))) { |
295 | amd64_printk(KERN_WARNING, "junk value of 0x%x extracted from " | 295 | amd64_printk(KERN_WARNING, "junk value of 0x%x extracted from " |
296 | "IntlvEn field of DRAM Base Register for node 0: " | 296 | "IntlvEn field of DRAM Base Register for node 0: " |
297 | "This probably indicates a BIOS bug.\n", intlv_en); | 297 | "this probably indicates a BIOS bug.\n", intlv_en); |
298 | return NULL; | 298 | return NULL; |
299 | } | 299 | } |
300 | 300 | ||
301 | bits = (((u32) sys_addr) >> 12) & intlv_en; | 301 | bits = (((u32) sys_addr) >> 12) & intlv_en; |
302 | 302 | ||
303 | for (node_id = 0; ; ) { | 303 | for (node_id = 0; ; ) { |
304 | if ((pvt->dram_limit[node_id] & intlv_en) == bits) | 304 | if ((pvt->dram_IntlvSel[node_id] & intlv_en) == bits) |
305 | break; /* intlv_sel field matches */ | 305 | break; /* intlv_sel field matches */ |
306 | 306 | ||
307 | if (++node_id >= DRAM_REG_COUNT) | 307 | if (++node_id >= DRAM_REG_COUNT) |
@@ -311,10 +311,10 @@ static struct mem_ctl_info *find_mc_by_sys_addr(struct mem_ctl_info *mci, | |||
311 | /* sanity test for sys_addr */ | 311 | /* sanity test for sys_addr */ |
312 | if (unlikely(!amd64_base_limit_match(pvt, sys_addr, node_id))) { | 312 | if (unlikely(!amd64_base_limit_match(pvt, sys_addr, node_id))) { |
313 | amd64_printk(KERN_WARNING, | 313 | amd64_printk(KERN_WARNING, |
314 | "%s(): sys_addr 0x%lx falls outside base/limit " | 314 | "%s(): sys_addr 0x%llx falls outside base/limit " |
315 | "address range for node %d with node interleaving " | 315 | "address range for node %d with node interleaving " |
316 | "enabled.\n", __func__, (unsigned long)sys_addr, | 316 | "enabled.\n", |
317 | node_id); | 317 | __func__, sys_addr, node_id); |
318 | return NULL; | 318 | return NULL; |
319 | } | 319 | } |
320 | 320 | ||
@@ -377,7 +377,7 @@ static int input_addr_to_csrow(struct mem_ctl_info *mci, u64 input_addr) | |||
377 | * base/mask register pair, test the condition shown near the start of | 377 | * base/mask register pair, test the condition shown near the start of |
378 | * section 3.5.4 (p. 84, BKDG #26094, K8, revA-E). | 378 | * section 3.5.4 (p. 84, BKDG #26094, K8, revA-E). |
379 | */ | 379 | */ |
380 | for (csrow = 0; csrow < CHIPSELECT_COUNT; csrow++) { | 380 | for (csrow = 0; csrow < pvt->cs_count; csrow++) { |
381 | 381 | ||
382 | /* This DRAM chip select is disabled on this node */ | 382 | /* This DRAM chip select is disabled on this node */ |
383 | if ((pvt->dcsb0[csrow] & K8_DCSB_CS_ENABLE) == 0) | 383 | if ((pvt->dcsb0[csrow] & K8_DCSB_CS_ENABLE) == 0) |
@@ -734,7 +734,7 @@ static void find_csrow_limits(struct mem_ctl_info *mci, int csrow, | |||
734 | u64 base, mask; | 734 | u64 base, mask; |
735 | 735 | ||
736 | pvt = mci->pvt_info; | 736 | pvt = mci->pvt_info; |
737 | BUG_ON((csrow < 0) || (csrow >= CHIPSELECT_COUNT)); | 737 | BUG_ON((csrow < 0) || (csrow >= pvt->cs_count)); |
738 | 738 | ||
739 | base = base_from_dct_base(pvt, csrow); | 739 | base = base_from_dct_base(pvt, csrow); |
740 | mask = mask_from_dct_mask(pvt, csrow); | 740 | mask = mask_from_dct_mask(pvt, csrow); |
@@ -962,35 +962,27 @@ err_reg: | |||
962 | */ | 962 | */ |
963 | static void amd64_set_dct_base_and_mask(struct amd64_pvt *pvt) | 963 | static void amd64_set_dct_base_and_mask(struct amd64_pvt *pvt) |
964 | { | 964 | { |
965 | if (pvt->ext_model >= OPTERON_CPU_REV_F) { | 965 | |
966 | if (boot_cpu_data.x86 == 0xf && pvt->ext_model < OPTERON_CPU_REV_F) { | ||
967 | pvt->dcsb_base = REV_E_DCSB_BASE_BITS; | ||
968 | pvt->dcsm_mask = REV_E_DCSM_MASK_BITS; | ||
969 | pvt->dcs_mask_notused = REV_E_DCS_NOTUSED_BITS; | ||
970 | pvt->dcs_shift = REV_E_DCS_SHIFT; | ||
971 | pvt->cs_count = 8; | ||
972 | pvt->num_dcsm = 8; | ||
973 | } else { | ||
966 | pvt->dcsb_base = REV_F_F1Xh_DCSB_BASE_BITS; | 974 | pvt->dcsb_base = REV_F_F1Xh_DCSB_BASE_BITS; |
967 | pvt->dcsm_mask = REV_F_F1Xh_DCSM_MASK_BITS; | 975 | pvt->dcsm_mask = REV_F_F1Xh_DCSM_MASK_BITS; |
968 | pvt->dcs_mask_notused = REV_F_F1Xh_DCS_NOTUSED_BITS; | 976 | pvt->dcs_mask_notused = REV_F_F1Xh_DCS_NOTUSED_BITS; |
969 | pvt->dcs_shift = REV_F_F1Xh_DCS_SHIFT; | 977 | pvt->dcs_shift = REV_F_F1Xh_DCS_SHIFT; |
970 | 978 | ||
971 | switch (boot_cpu_data.x86) { | 979 | if (boot_cpu_data.x86 == 0x11) { |
972 | case 0xf: | 980 | pvt->cs_count = 4; |
973 | pvt->num_dcsm = REV_F_DCSM_COUNT; | 981 | pvt->num_dcsm = 2; |
974 | break; | 982 | } else { |
975 | 983 | pvt->cs_count = 8; | |
976 | case 0x10: | 984 | pvt->num_dcsm = 4; |
977 | pvt->num_dcsm = F10_DCSM_COUNT; | ||
978 | break; | ||
979 | |||
980 | case 0x11: | ||
981 | pvt->num_dcsm = F11_DCSM_COUNT; | ||
982 | break; | ||
983 | |||
984 | default: | ||
985 | amd64_printk(KERN_ERR, "Unsupported family!\n"); | ||
986 | break; | ||
987 | } | 985 | } |
988 | } else { | ||
989 | pvt->dcsb_base = REV_E_DCSB_BASE_BITS; | ||
990 | pvt->dcsm_mask = REV_E_DCSM_MASK_BITS; | ||
991 | pvt->dcs_mask_notused = REV_E_DCS_NOTUSED_BITS; | ||
992 | pvt->dcs_shift = REV_E_DCS_SHIFT; | ||
993 | pvt->num_dcsm = REV_E_DCSM_COUNT; | ||
994 | } | 986 | } |
995 | } | 987 | } |
996 | 988 | ||
@@ -1003,7 +995,7 @@ static void amd64_read_dct_base_mask(struct amd64_pvt *pvt) | |||
1003 | 995 | ||
1004 | amd64_set_dct_base_and_mask(pvt); | 996 | amd64_set_dct_base_and_mask(pvt); |
1005 | 997 | ||
1006 | for (cs = 0; cs < CHIPSELECT_COUNT; cs++) { | 998 | for (cs = 0; cs < pvt->cs_count; cs++) { |
1007 | reg = K8_DCSB0 + (cs * 4); | 999 | reg = K8_DCSB0 + (cs * 4); |
1008 | err = pci_read_config_dword(pvt->dram_f2_ctl, reg, | 1000 | err = pci_read_config_dword(pvt->dram_f2_ctl, reg, |
1009 | &pvt->dcsb0[cs]); | 1001 | &pvt->dcsb0[cs]); |
@@ -1193,7 +1185,7 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, | |||
1193 | * different from the node that detected the error. | 1185 | * different from the node that detected the error. |
1194 | */ | 1186 | */ |
1195 | src_mci = find_mc_by_sys_addr(mci, SystemAddress); | 1187 | src_mci = find_mc_by_sys_addr(mci, SystemAddress); |
1196 | if (src_mci) { | 1188 | if (!src_mci) { |
1197 | amd64_mc_printk(mci, KERN_ERR, | 1189 | amd64_mc_printk(mci, KERN_ERR, |
1198 | "failed to map error address 0x%lx to a node\n", | 1190 | "failed to map error address 0x%lx to a node\n", |
1199 | (unsigned long)SystemAddress); | 1191 | (unsigned long)SystemAddress); |
@@ -1376,8 +1368,8 @@ static void f10_read_dram_base_limit(struct amd64_pvt *pvt, int dram) | |||
1376 | 1368 | ||
1377 | pvt->dram_IntlvEn[dram] = (low_base >> 8) & 0x7; | 1369 | pvt->dram_IntlvEn[dram] = (low_base >> 8) & 0x7; |
1378 | 1370 | ||
1379 | pvt->dram_base[dram] = (((((u64) high_base & 0x000000FF) << 32) | | 1371 | pvt->dram_base[dram] = (((u64)high_base & 0x000000FF) << 40) | |
1380 | ((u64) low_base & 0xFFFF0000))) << 8; | 1372 | (((u64)low_base & 0xFFFF0000) << 8); |
1381 | 1373 | ||
1382 | low_offset = K8_DRAM_LIMIT_LOW + (dram << 3); | 1374 | low_offset = K8_DRAM_LIMIT_LOW + (dram << 3); |
1383 | high_offset = F10_DRAM_LIMIT_HIGH + (dram << 3); | 1375 | high_offset = F10_DRAM_LIMIT_HIGH + (dram << 3); |
@@ -1398,9 +1390,9 @@ static void f10_read_dram_base_limit(struct amd64_pvt *pvt, int dram) | |||
1398 | * Extract address values and form a LIMIT address. Limit is the HIGHEST | 1390 | * Extract address values and form a LIMIT address. Limit is the HIGHEST |
1399 | * memory location of the region, so low 24 bits need to be all ones. | 1391 | * memory location of the region, so low 24 bits need to be all ones. |
1400 | */ | 1392 | */ |
1401 | low_limit |= 0x0000FFFF; | 1393 | pvt->dram_limit[dram] = (((u64)high_limit & 0x000000FF) << 40) | |
1402 | pvt->dram_limit[dram] = | 1394 | (((u64) low_limit & 0xFFFF0000) << 8) | |
1403 | ((((u64) high_limit << 32) + (u64) low_limit) << 8) | (0xFF); | 1395 | 0x00FFFFFF; |
1404 | } | 1396 | } |
1405 | 1397 | ||
1406 | static void f10_read_dram_ctl_register(struct amd64_pvt *pvt) | 1398 | static void f10_read_dram_ctl_register(struct amd64_pvt *pvt) |
@@ -1566,7 +1558,7 @@ static int f10_lookup_addr_in_dct(u32 in_addr, u32 nid, u32 cs) | |||
1566 | 1558 | ||
1567 | debugf1("InputAddr=0x%x channelselect=%d\n", in_addr, cs); | 1559 | debugf1("InputAddr=0x%x channelselect=%d\n", in_addr, cs); |
1568 | 1560 | ||
1569 | for (csrow = 0; csrow < CHIPSELECT_COUNT; csrow++) { | 1561 | for (csrow = 0; csrow < pvt->cs_count; csrow++) { |
1570 | 1562 | ||
1571 | cs_base = amd64_get_dct_base(pvt, cs, csrow); | 1563 | cs_base = amd64_get_dct_base(pvt, cs, csrow); |
1572 | if (!(cs_base & K8_DCSB_CS_ENABLE)) | 1564 | if (!(cs_base & K8_DCSB_CS_ENABLE)) |
@@ -2262,7 +2254,7 @@ static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci, | |||
2262 | { | 2254 | { |
2263 | u32 ec = ERROR_CODE(info->nbsl); | 2255 | u32 ec = ERROR_CODE(info->nbsl); |
2264 | u32 xec = EXT_ERROR_CODE(info->nbsl); | 2256 | u32 xec = EXT_ERROR_CODE(info->nbsl); |
2265 | int ecc_type = info->nbsh & (0x3 << 13); | 2257 | int ecc_type = (info->nbsh >> 13) & 0x3; |
2266 | 2258 | ||
2267 | /* Bail early out if this was an 'observed' error */ | 2259 | /* Bail early out if this was an 'observed' error */ |
2268 | if (PP(ec) == K8_NBSL_PP_OBS) | 2260 | if (PP(ec) == K8_NBSL_PP_OBS) |
@@ -2497,7 +2489,7 @@ err_reg: | |||
2497 | * NOTE: CPU Revision Dependent code | 2489 | * NOTE: CPU Revision Dependent code |
2498 | * | 2490 | * |
2499 | * Input: | 2491 | * Input: |
2500 | * @csrow_nr ChipSelect Row Number (0..CHIPSELECT_COUNT-1) | 2492 | * @csrow_nr ChipSelect Row Number (0..pvt->cs_count-1) |
2501 | * k8 private pointer to --> | 2493 | * k8 private pointer to --> |
2502 | * DRAM Bank Address mapping register | 2494 | * DRAM Bank Address mapping register |
2503 | * node_id | 2495 | * node_id |
@@ -2577,7 +2569,7 @@ static int amd64_init_csrows(struct mem_ctl_info *mci) | |||
2577 | (pvt->nbcfg & K8_NBCFG_ECC_ENABLE) ? "Enabled" : "Disabled" | 2569 | (pvt->nbcfg & K8_NBCFG_ECC_ENABLE) ? "Enabled" : "Disabled" |
2578 | ); | 2570 | ); |
2579 | 2571 | ||
2580 | for (i = 0; i < CHIPSELECT_COUNT; i++) { | 2572 | for (i = 0; i < pvt->cs_count; i++) { |
2581 | csrow = &mci->csrows[i]; | 2573 | csrow = &mci->csrows[i]; |
2582 | 2574 | ||
2583 | if ((pvt->dcsb0[i] & K8_DCSB_CS_ENABLE) == 0) { | 2575 | if ((pvt->dcsb0[i] & K8_DCSB_CS_ENABLE) == 0) { |
@@ -2988,7 +2980,7 @@ static int amd64_init_2nd_stage(struct amd64_pvt *pvt) | |||
2988 | goto err_exit; | 2980 | goto err_exit; |
2989 | 2981 | ||
2990 | ret = -ENOMEM; | 2982 | ret = -ENOMEM; |
2991 | mci = edac_mc_alloc(0, CHIPSELECT_COUNT, pvt->channel_count, node_id); | 2983 | mci = edac_mc_alloc(0, pvt->cs_count, pvt->channel_count, node_id); |
2992 | if (!mci) | 2984 | if (!mci) |
2993 | goto err_exit; | 2985 | goto err_exit; |
2994 | 2986 | ||
@@ -3171,7 +3163,7 @@ static int __init amd64_edac_init(void) | |||
3171 | opstate_init(); | 3163 | opstate_init(); |
3172 | 3164 | ||
3173 | if (cache_k8_northbridges() < 0) | 3165 | if (cache_k8_northbridges() < 0) |
3174 | goto err_exit; | 3166 | return err; |
3175 | 3167 | ||
3176 | err = pci_register_driver(&amd64_pci_driver); | 3168 | err = pci_register_driver(&amd64_pci_driver); |
3177 | if (err) | 3169 | if (err) |
@@ -3197,8 +3189,6 @@ static int __init amd64_edac_init(void) | |||
3197 | 3189 | ||
3198 | err_2nd_stage: | 3190 | err_2nd_stage: |
3199 | debugf0("2nd stage failed\n"); | 3191 | debugf0("2nd stage failed\n"); |
3200 | |||
3201 | err_exit: | ||
3202 | pci_unregister_driver(&amd64_pci_driver); | 3192 | pci_unregister_driver(&amd64_pci_driver); |
3203 | 3193 | ||
3204 | return err; | 3194 | return err; |
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index 8ea07e2715dc..c6f359a85207 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h | |||
@@ -132,6 +132,8 @@ | |||
132 | #define EDAC_AMD64_VERSION " Ver: 3.2.0 " __DATE__ | 132 | #define EDAC_AMD64_VERSION " Ver: 3.2.0 " __DATE__ |
133 | #define EDAC_MOD_STR "amd64_edac" | 133 | #define EDAC_MOD_STR "amd64_edac" |
134 | 134 | ||
135 | #define EDAC_MAX_NUMNODES 8 | ||
136 | |||
135 | /* Extended Model from CPUID, for CPU Revision numbers */ | 137 | /* Extended Model from CPUID, for CPU Revision numbers */ |
136 | #define OPTERON_CPU_LE_REV_C 0 | 138 | #define OPTERON_CPU_LE_REV_C 0 |
137 | #define OPTERON_CPU_REV_D 1 | 139 | #define OPTERON_CPU_REV_D 1 |
@@ -142,7 +144,7 @@ | |||
142 | #define OPTERON_CPU_REV_FA 5 | 144 | #define OPTERON_CPU_REV_FA 5 |
143 | 145 | ||
144 | /* Hardware limit on ChipSelect rows per MC and processors per system */ | 146 | /* Hardware limit on ChipSelect rows per MC and processors per system */ |
145 | #define CHIPSELECT_COUNT 8 | 147 | #define MAX_CS_COUNT 8 |
146 | #define DRAM_REG_COUNT 8 | 148 | #define DRAM_REG_COUNT 8 |
147 | 149 | ||
148 | 150 | ||
@@ -193,7 +195,6 @@ | |||
193 | */ | 195 | */ |
194 | #define REV_E_DCSB_BASE_BITS (0xFFE0FE00ULL) | 196 | #define REV_E_DCSB_BASE_BITS (0xFFE0FE00ULL) |
195 | #define REV_E_DCS_SHIFT 4 | 197 | #define REV_E_DCS_SHIFT 4 |
196 | #define REV_E_DCSM_COUNT 8 | ||
197 | 198 | ||
198 | #define REV_F_F1Xh_DCSB_BASE_BITS (0x1FF83FE0ULL) | 199 | #define REV_F_F1Xh_DCSB_BASE_BITS (0x1FF83FE0ULL) |
199 | #define REV_F_F1Xh_DCS_SHIFT 8 | 200 | #define REV_F_F1Xh_DCS_SHIFT 8 |
@@ -204,9 +205,6 @@ | |||
204 | */ | 205 | */ |
205 | #define REV_F_DCSB_BASE_BITS (0x1FF83FE0ULL) | 206 | #define REV_F_DCSB_BASE_BITS (0x1FF83FE0ULL) |
206 | #define REV_F_DCS_SHIFT 8 | 207 | #define REV_F_DCS_SHIFT 8 |
207 | #define REV_F_DCSM_COUNT 4 | ||
208 | #define F10_DCSM_COUNT 4 | ||
209 | #define F11_DCSM_COUNT 2 | ||
210 | 208 | ||
211 | /* DRAM CS Mask Registers */ | 209 | /* DRAM CS Mask Registers */ |
212 | #define K8_DCSM0 0x60 | 210 | #define K8_DCSM0 0x60 |
@@ -374,13 +372,11 @@ enum { | |||
374 | 372 | ||
375 | #define SET_NB_DRAM_INJECTION_WRITE(word, bits) \ | 373 | #define SET_NB_DRAM_INJECTION_WRITE(word, bits) \ |
376 | (BIT(((word) & 0xF) + 20) | \ | 374 | (BIT(((word) & 0xF) + 20) | \ |
377 | BIT(17) | \ | 375 | BIT(17) | bits) |
378 | ((bits) & 0xF)) | ||
379 | 376 | ||
380 | #define SET_NB_DRAM_INJECTION_READ(word, bits) \ | 377 | #define SET_NB_DRAM_INJECTION_READ(word, bits) \ |
381 | (BIT(((word) & 0xF) + 20) | \ | 378 | (BIT(((word) & 0xF) + 20) | \ |
382 | BIT(16) | \ | 379 | BIT(16) | bits) |
383 | ((bits) & 0xF)) | ||
384 | 380 | ||
385 | #define K8_NBCAP 0xE8 | 381 | #define K8_NBCAP 0xE8 |
386 | #define K8_NBCAP_CORES (BIT(12)|BIT(13)) | 382 | #define K8_NBCAP_CORES (BIT(12)|BIT(13)) |
@@ -445,12 +441,12 @@ struct amd64_pvt { | |||
445 | u32 dbam1; /* DRAM Base Address Mapping reg for DCT1 */ | 441 | u32 dbam1; /* DRAM Base Address Mapping reg for DCT1 */ |
446 | 442 | ||
447 | /* DRAM CS Base Address Registers F2x[1,0][5C:40] */ | 443 | /* DRAM CS Base Address Registers F2x[1,0][5C:40] */ |
448 | u32 dcsb0[CHIPSELECT_COUNT]; | 444 | u32 dcsb0[MAX_CS_COUNT]; |
449 | u32 dcsb1[CHIPSELECT_COUNT]; | 445 | u32 dcsb1[MAX_CS_COUNT]; |
450 | 446 | ||
451 | /* DRAM CS Mask Registers F2x[1,0][6C:60] */ | 447 | /* DRAM CS Mask Registers F2x[1,0][6C:60] */ |
452 | u32 dcsm0[CHIPSELECT_COUNT]; | 448 | u32 dcsm0[MAX_CS_COUNT]; |
453 | u32 dcsm1[CHIPSELECT_COUNT]; | 449 | u32 dcsm1[MAX_CS_COUNT]; |
454 | 450 | ||
455 | /* | 451 | /* |
456 | * Decoded parts of DRAM BASE and LIMIT Registers | 452 | * Decoded parts of DRAM BASE and LIMIT Registers |
@@ -470,6 +466,7 @@ struct amd64_pvt { | |||
470 | */ | 466 | */ |
471 | u32 dcsb_base; /* DCSB base bits */ | 467 | u32 dcsb_base; /* DCSB base bits */ |
472 | u32 dcsm_mask; /* DCSM mask bits */ | 468 | u32 dcsm_mask; /* DCSM mask bits */ |
469 | u32 cs_count; /* num chip selects (== num DCSB registers) */ | ||
473 | u32 num_dcsm; /* Number of DCSM registers */ | 470 | u32 num_dcsm; /* Number of DCSM registers */ |
474 | u32 dcs_mask_notused; /* DCSM notused mask bits */ | 471 | u32 dcs_mask_notused; /* DCSM notused mask bits */ |
475 | u32 dcs_shift; /* DCSB and DCSM shift value */ | 472 | u32 dcs_shift; /* DCSB and DCSM shift value */ |
diff --git a/drivers/edac/amd64_edac_inj.c b/drivers/edac/amd64_edac_inj.c index d3675b76b3a7..29f1f7a612d9 100644 --- a/drivers/edac/amd64_edac_inj.c +++ b/drivers/edac/amd64_edac_inj.c | |||
@@ -1,5 +1,11 @@ | |||
1 | #include "amd64_edac.h" | 1 | #include "amd64_edac.h" |
2 | 2 | ||
3 | static ssize_t amd64_inject_section_show(struct mem_ctl_info *mci, char *buf) | ||
4 | { | ||
5 | struct amd64_pvt *pvt = mci->pvt_info; | ||
6 | return sprintf(buf, "0x%x\n", pvt->injection.section); | ||
7 | } | ||
8 | |||
3 | /* | 9 | /* |
4 | * store error injection section value which refers to one of 4 16-byte sections | 10 | * store error injection section value which refers to one of 4 16-byte sections |
5 | * within a 64-byte cacheline | 11 | * within a 64-byte cacheline |
@@ -15,12 +21,26 @@ static ssize_t amd64_inject_section_store(struct mem_ctl_info *mci, | |||
15 | 21 | ||
16 | ret = strict_strtoul(data, 10, &value); | 22 | ret = strict_strtoul(data, 10, &value); |
17 | if (ret != -EINVAL) { | 23 | if (ret != -EINVAL) { |
24 | |||
25 | if (value > 3) { | ||
26 | amd64_printk(KERN_WARNING, | ||
27 | "%s: invalid section 0x%lx\n", | ||
28 | __func__, value); | ||
29 | return -EINVAL; | ||
30 | } | ||
31 | |||
18 | pvt->injection.section = (u32) value; | 32 | pvt->injection.section = (u32) value; |
19 | return count; | 33 | return count; |
20 | } | 34 | } |
21 | return ret; | 35 | return ret; |
22 | } | 36 | } |
23 | 37 | ||
38 | static ssize_t amd64_inject_word_show(struct mem_ctl_info *mci, char *buf) | ||
39 | { | ||
40 | struct amd64_pvt *pvt = mci->pvt_info; | ||
41 | return sprintf(buf, "0x%x\n", pvt->injection.word); | ||
42 | } | ||
43 | |||
24 | /* | 44 | /* |
25 | * store error injection word value which refers to one of 9 16-bit word of the | 45 | * store error injection word value which refers to one of 9 16-bit word of the |
26 | * 16-byte (128-bit + ECC bits) section | 46 | * 16-byte (128-bit + ECC bits) section |
@@ -37,14 +57,25 @@ static ssize_t amd64_inject_word_store(struct mem_ctl_info *mci, | |||
37 | ret = strict_strtoul(data, 10, &value); | 57 | ret = strict_strtoul(data, 10, &value); |
38 | if (ret != -EINVAL) { | 58 | if (ret != -EINVAL) { |
39 | 59 | ||
40 | value = (value <= 8) ? value : 0; | 60 | if (value > 8) { |
41 | pvt->injection.word = (u32) value; | 61 | amd64_printk(KERN_WARNING, |
62 | "%s: invalid word 0x%lx\n", | ||
63 | __func__, value); | ||
64 | return -EINVAL; | ||
65 | } | ||
42 | 66 | ||
67 | pvt->injection.word = (u32) value; | ||
43 | return count; | 68 | return count; |
44 | } | 69 | } |
45 | return ret; | 70 | return ret; |
46 | } | 71 | } |
47 | 72 | ||
73 | static ssize_t amd64_inject_ecc_vector_show(struct mem_ctl_info *mci, char *buf) | ||
74 | { | ||
75 | struct amd64_pvt *pvt = mci->pvt_info; | ||
76 | return sprintf(buf, "0x%x\n", pvt->injection.bit_map); | ||
77 | } | ||
78 | |||
48 | /* | 79 | /* |
49 | * store 16 bit error injection vector which enables injecting errors to the | 80 | * store 16 bit error injection vector which enables injecting errors to the |
50 | * corresponding bit within the error injection word above. When used during a | 81 | * corresponding bit within the error injection word above. When used during a |
@@ -60,8 +91,14 @@ static ssize_t amd64_inject_ecc_vector_store(struct mem_ctl_info *mci, | |||
60 | ret = strict_strtoul(data, 16, &value); | 91 | ret = strict_strtoul(data, 16, &value); |
61 | if (ret != -EINVAL) { | 92 | if (ret != -EINVAL) { |
62 | 93 | ||
63 | pvt->injection.bit_map = (u32) value & 0xFFFF; | 94 | if (value & 0xFFFF0000) { |
95 | amd64_printk(KERN_WARNING, | ||
96 | "%s: invalid EccVector: 0x%lx\n", | ||
97 | __func__, value); | ||
98 | return -EINVAL; | ||
99 | } | ||
64 | 100 | ||
101 | pvt->injection.bit_map = (u32) value; | ||
65 | return count; | 102 | return count; |
66 | } | 103 | } |
67 | return ret; | 104 | return ret; |
@@ -147,7 +184,7 @@ struct mcidev_sysfs_attribute amd64_inj_attrs[] = { | |||
147 | .name = "inject_section", | 184 | .name = "inject_section", |
148 | .mode = (S_IRUGO | S_IWUSR) | 185 | .mode = (S_IRUGO | S_IWUSR) |
149 | }, | 186 | }, |
150 | .show = NULL, | 187 | .show = amd64_inject_section_show, |
151 | .store = amd64_inject_section_store, | 188 | .store = amd64_inject_section_store, |
152 | }, | 189 | }, |
153 | { | 190 | { |
@@ -155,7 +192,7 @@ struct mcidev_sysfs_attribute amd64_inj_attrs[] = { | |||
155 | .name = "inject_word", | 192 | .name = "inject_word", |
156 | .mode = (S_IRUGO | S_IWUSR) | 193 | .mode = (S_IRUGO | S_IWUSR) |
157 | }, | 194 | }, |
158 | .show = NULL, | 195 | .show = amd64_inject_word_show, |
159 | .store = amd64_inject_word_store, | 196 | .store = amd64_inject_word_store, |
160 | }, | 197 | }, |
161 | { | 198 | { |
@@ -163,7 +200,7 @@ struct mcidev_sysfs_attribute amd64_inj_attrs[] = { | |||
163 | .name = "inject_ecc_vector", | 200 | .name = "inject_ecc_vector", |
164 | .mode = (S_IRUGO | S_IWUSR) | 201 | .mode = (S_IRUGO | S_IWUSR) |
165 | }, | 202 | }, |
166 | .show = NULL, | 203 | .show = amd64_inject_ecc_vector_show, |
167 | .store = amd64_inject_ecc_vector_store, | 204 | .store = amd64_inject_ecc_vector_store, |
168 | }, | 205 | }, |
169 | { | 206 | { |
diff --git a/drivers/edac/edac_mce_amd.c b/drivers/edac/edac_mce_amd.c index 0c21c370c9dd..713ed7d37247 100644 --- a/drivers/edac/edac_mce_amd.c +++ b/drivers/edac/edac_mce_amd.c | |||
@@ -3,6 +3,7 @@ | |||
3 | 3 | ||
4 | static bool report_gart_errors; | 4 | static bool report_gart_errors; |
5 | static void (*nb_bus_decoder)(int node_id, struct err_regs *regs); | 5 | static void (*nb_bus_decoder)(int node_id, struct err_regs *regs); |
6 | static void (*orig_mce_callback)(struct mce *m); | ||
6 | 7 | ||
7 | void amd_report_gart_errors(bool v) | 8 | void amd_report_gart_errors(bool v) |
8 | { | 9 | { |
@@ -362,7 +363,7 @@ static inline void amd_decode_err_code(unsigned int ec) | |||
362 | pr_warning("Huh? Unknown MCE error 0x%x\n", ec); | 363 | pr_warning("Huh? Unknown MCE error 0x%x\n", ec); |
363 | } | 364 | } |
364 | 365 | ||
365 | void decode_mce(struct mce *m) | 366 | static void amd_decode_mce(struct mce *m) |
366 | { | 367 | { |
367 | struct err_regs regs; | 368 | struct err_regs regs; |
368 | int node, ecc; | 369 | int node, ecc; |
@@ -420,3 +421,32 @@ void decode_mce(struct mce *m) | |||
420 | 421 | ||
421 | amd_decode_err_code(m->status & 0xffff); | 422 | amd_decode_err_code(m->status & 0xffff); |
422 | } | 423 | } |
424 | |||
425 | static int __init mce_amd_init(void) | ||
426 | { | ||
427 | /* | ||
428 | * We can decode MCEs for Opteron and later CPUs: | ||
429 | */ | ||
430 | if ((boot_cpu_data.x86_vendor == X86_VENDOR_AMD) && | ||
431 | (boot_cpu_data.x86 >= 0xf)) { | ||
432 | /* safe the default decode mce callback */ | ||
433 | orig_mce_callback = x86_mce_decode_callback; | ||
434 | |||
435 | x86_mce_decode_callback = amd_decode_mce; | ||
436 | } | ||
437 | |||
438 | return 0; | ||
439 | } | ||
440 | early_initcall(mce_amd_init); | ||
441 | |||
442 | #ifdef MODULE | ||
443 | static void __exit mce_amd_exit(void) | ||
444 | { | ||
445 | x86_mce_decode_callback = orig_mce_callback; | ||
446 | } | ||
447 | |||
448 | MODULE_DESCRIPTION("AMD MCE decoder"); | ||
449 | MODULE_ALIAS("edac-mce-amd"); | ||
450 | MODULE_LICENSE("GPL"); | ||
451 | module_exit(mce_amd_exit); | ||
452 | #endif | ||
diff --git a/drivers/edac/i5000_edac.c b/drivers/edac/i5000_edac.c index d335086f4a26..77a9579d7167 100644 --- a/drivers/edac/i5000_edac.c +++ b/drivers/edac/i5000_edac.c | |||
@@ -1173,7 +1173,7 @@ static void i5000_get_mc_regs(struct mem_ctl_info *mci) | |||
1173 | pci_read_config_word(pvt->branch_1, where, | 1173 | pci_read_config_word(pvt->branch_1, where, |
1174 | &pvt->b1_mtr[slot_row]); | 1174 | &pvt->b1_mtr[slot_row]); |
1175 | debugf2("MTR%d where=0x%x B1 value=0x%x\n", slot_row, | 1175 | debugf2("MTR%d where=0x%x B1 value=0x%x\n", slot_row, |
1176 | where, pvt->b0_mtr[slot_row]); | 1176 | where, pvt->b1_mtr[slot_row]); |
1177 | } else { | 1177 | } else { |
1178 | pvt->b1_mtr[slot_row] = 0; | 1178 | pvt->b1_mtr[slot_row] = 0; |
1179 | } | 1179 | } |
@@ -1232,7 +1232,7 @@ static int i5000_init_csrows(struct mem_ctl_info *mci) | |||
1232 | struct csrow_info *p_csrow; | 1232 | struct csrow_info *p_csrow; |
1233 | int empty, channel_count; | 1233 | int empty, channel_count; |
1234 | int max_csrows; | 1234 | int max_csrows; |
1235 | int mtr; | 1235 | int mtr, mtr1; |
1236 | int csrow_megs; | 1236 | int csrow_megs; |
1237 | int channel; | 1237 | int channel; |
1238 | int csrow; | 1238 | int csrow; |
@@ -1251,9 +1251,10 @@ static int i5000_init_csrows(struct mem_ctl_info *mci) | |||
1251 | 1251 | ||
1252 | /* use branch 0 for the basis */ | 1252 | /* use branch 0 for the basis */ |
1253 | mtr = pvt->b0_mtr[csrow >> 1]; | 1253 | mtr = pvt->b0_mtr[csrow >> 1]; |
1254 | mtr1 = pvt->b1_mtr[csrow >> 1]; | ||
1254 | 1255 | ||
1255 | /* if no DIMMS on this row, continue */ | 1256 | /* if no DIMMS on this row, continue */ |
1256 | if (!MTR_DIMMS_PRESENT(mtr)) | 1257 | if (!MTR_DIMMS_PRESENT(mtr) && !MTR_DIMMS_PRESENT(mtr1)) |
1257 | continue; | 1258 | continue; |
1258 | 1259 | ||
1259 | /* FAKE OUT VALUES, FIXME */ | 1260 | /* FAKE OUT VALUES, FIXME */ |
diff --git a/drivers/edac/i5400_edac.c b/drivers/edac/i5400_edac.c index b08b6d8e2dc7..f99d10655ed4 100644 --- a/drivers/edac/i5400_edac.c +++ b/drivers/edac/i5400_edac.c | |||
@@ -46,9 +46,10 @@ | |||
46 | /* Limits for i5400 */ | 46 | /* Limits for i5400 */ |
47 | #define NUM_MTRS_PER_BRANCH 4 | 47 | #define NUM_MTRS_PER_BRANCH 4 |
48 | #define CHANNELS_PER_BRANCH 2 | 48 | #define CHANNELS_PER_BRANCH 2 |
49 | #define MAX_DIMMS_PER_CHANNEL NUM_MTRS_PER_BRANCH | ||
49 | #define MAX_CHANNELS 4 | 50 | #define MAX_CHANNELS 4 |
50 | #define MAX_DIMMS (MAX_CHANNELS * 4) /* Up to 4 DIMM's per channel */ | 51 | /* max possible csrows per channel */ |
51 | #define MAX_CSROWS (MAX_DIMMS * 2) /* max possible csrows per channel */ | 52 | #define MAX_CSROWS (MAX_DIMMS_PER_CHANNEL) |
52 | 53 | ||
53 | /* Device 16, | 54 | /* Device 16, |
54 | * Function 0: System Address | 55 | * Function 0: System Address |
@@ -331,7 +332,6 @@ static const struct i5400_dev_info i5400_devs[] = { | |||
331 | 332 | ||
332 | struct i5400_dimm_info { | 333 | struct i5400_dimm_info { |
333 | int megabytes; /* size, 0 means not present */ | 334 | int megabytes; /* size, 0 means not present */ |
334 | int dual_rank; | ||
335 | }; | 335 | }; |
336 | 336 | ||
337 | /* driver private data structure */ | 337 | /* driver private data structure */ |
@@ -849,11 +849,9 @@ static int determine_mtr(struct i5400_pvt *pvt, int csrow, int channel) | |||
849 | int n; | 849 | int n; |
850 | 850 | ||
851 | /* There is one MTR for each slot pair of FB-DIMMs, | 851 | /* There is one MTR for each slot pair of FB-DIMMs, |
852 | Each slot may have one or two ranks (2 csrows), | ||
853 | Each slot pair may be at branch 0 or branch 1. | 852 | Each slot pair may be at branch 0 or branch 1. |
854 | So, csrow should be divided by eight | ||
855 | */ | 853 | */ |
856 | n = csrow >> 3; | 854 | n = csrow; |
857 | 855 | ||
858 | if (n >= NUM_MTRS_PER_BRANCH) { | 856 | if (n >= NUM_MTRS_PER_BRANCH) { |
859 | debugf0("ERROR: trying to access an invalid csrow: %d\n", | 857 | debugf0("ERROR: trying to access an invalid csrow: %d\n", |
@@ -905,25 +903,22 @@ static void handle_channel(struct i5400_pvt *pvt, int csrow, int channel, | |||
905 | amb_present_reg = determine_amb_present_reg(pvt, channel); | 903 | amb_present_reg = determine_amb_present_reg(pvt, channel); |
906 | 904 | ||
907 | /* Determine if there is a DIMM present in this DIMM slot */ | 905 | /* Determine if there is a DIMM present in this DIMM slot */ |
908 | if (amb_present_reg & (1 << (csrow >> 1))) { | 906 | if (amb_present_reg & (1 << csrow)) { |
909 | dinfo->dual_rank = MTR_DIMM_RANK(mtr); | 907 | /* Start with the number of bits for a Bank |
910 | 908 | * on the DRAM */ | |
911 | if (!((dinfo->dual_rank == 0) && | 909 | addrBits = MTR_DRAM_BANKS_ADDR_BITS(mtr); |
912 | ((csrow & 0x1) == 0x1))) { | 910 | /* Add thenumber of ROW bits */ |
913 | /* Start with the number of bits for a Bank | 911 | addrBits += MTR_DIMM_ROWS_ADDR_BITS(mtr); |
914 | * on the DRAM */ | 912 | /* add the number of COLUMN bits */ |
915 | addrBits = MTR_DRAM_BANKS_ADDR_BITS(mtr); | 913 | addrBits += MTR_DIMM_COLS_ADDR_BITS(mtr); |
916 | /* Add thenumber of ROW bits */ | 914 | /* add the number of RANK bits */ |
917 | addrBits += MTR_DIMM_ROWS_ADDR_BITS(mtr); | 915 | addrBits += MTR_DIMM_RANK(mtr); |
918 | /* add the number of COLUMN bits */ | 916 | |
919 | addrBits += MTR_DIMM_COLS_ADDR_BITS(mtr); | 917 | addrBits += 6; /* add 64 bits per DIMM */ |
920 | 918 | addrBits -= 20; /* divide by 2^^20 */ | |
921 | addrBits += 6; /* add 64 bits per DIMM */ | 919 | addrBits -= 3; /* 8 bits per bytes */ |
922 | addrBits -= 20; /* divide by 2^^20 */ | 920 | |
923 | addrBits -= 3; /* 8 bits per bytes */ | 921 | dinfo->megabytes = 1 << addrBits; |
924 | |||
925 | dinfo->megabytes = 1 << addrBits; | ||
926 | } | ||
927 | } | 922 | } |
928 | } | 923 | } |
929 | } | 924 | } |
@@ -951,12 +946,12 @@ static void calculate_dimm_size(struct i5400_pvt *pvt) | |||
951 | return; | 946 | return; |
952 | } | 947 | } |
953 | 948 | ||
954 | /* Scan all the actual CSROWS (which is # of DIMMS * 2) | 949 | /* Scan all the actual CSROWS |
955 | * and calculate the information for each DIMM | 950 | * and calculate the information for each DIMM |
956 | * Start with the highest csrow first, to display it first | 951 | * Start with the highest csrow first, to display it first |
957 | * and work toward the 0th csrow | 952 | * and work toward the 0th csrow |
958 | */ | 953 | */ |
959 | max_csrows = pvt->maxdimmperch * 2; | 954 | max_csrows = pvt->maxdimmperch; |
960 | for (csrow = max_csrows - 1; csrow >= 0; csrow--) { | 955 | for (csrow = max_csrows - 1; csrow >= 0; csrow--) { |
961 | 956 | ||
962 | /* on an odd csrow, first output a 'boundary' marker, | 957 | /* on an odd csrow, first output a 'boundary' marker, |
@@ -1064,7 +1059,7 @@ static void i5400_get_mc_regs(struct mem_ctl_info *mci) | |||
1064 | 1059 | ||
1065 | /* Get the set of MTR[0-3] regs by each branch */ | 1060 | /* Get the set of MTR[0-3] regs by each branch */ |
1066 | for (slot_row = 0; slot_row < NUM_MTRS_PER_BRANCH; slot_row++) { | 1061 | for (slot_row = 0; slot_row < NUM_MTRS_PER_BRANCH; slot_row++) { |
1067 | int where = MTR0 + (slot_row * sizeof(u32)); | 1062 | int where = MTR0 + (slot_row * sizeof(u16)); |
1068 | 1063 | ||
1069 | /* Branch 0 set of MTR registers */ | 1064 | /* Branch 0 set of MTR registers */ |
1070 | pci_read_config_word(pvt->branch_0, where, | 1065 | pci_read_config_word(pvt->branch_0, where, |
@@ -1146,7 +1141,7 @@ static int i5400_init_csrows(struct mem_ctl_info *mci) | |||
1146 | pvt = mci->pvt_info; | 1141 | pvt = mci->pvt_info; |
1147 | 1142 | ||
1148 | channel_count = pvt->maxch; | 1143 | channel_count = pvt->maxch; |
1149 | max_csrows = pvt->maxdimmperch * 2; | 1144 | max_csrows = pvt->maxdimmperch; |
1150 | 1145 | ||
1151 | empty = 1; /* Assume NO memory */ | 1146 | empty = 1; /* Assume NO memory */ |
1152 | 1147 | ||
@@ -1215,28 +1210,6 @@ static void i5400_enable_error_reporting(struct mem_ctl_info *mci) | |||
1215 | } | 1210 | } |
1216 | 1211 | ||
1217 | /* | 1212 | /* |
1218 | * i5400_get_dimm_and_channel_counts(pdev, &num_csrows, &num_channels) | ||
1219 | * | ||
1220 | * ask the device how many channels are present and how many CSROWS | ||
1221 | * as well | ||
1222 | */ | ||
1223 | static void i5400_get_dimm_and_channel_counts(struct pci_dev *pdev, | ||
1224 | int *num_dimms_per_channel, | ||
1225 | int *num_channels) | ||
1226 | { | ||
1227 | u8 value; | ||
1228 | |||
1229 | /* Need to retrieve just how many channels and dimms per channel are | ||
1230 | * supported on this memory controller | ||
1231 | */ | ||
1232 | pci_read_config_byte(pdev, MAXDIMMPERCH, &value); | ||
1233 | *num_dimms_per_channel = (int)value * 2; | ||
1234 | |||
1235 | pci_read_config_byte(pdev, MAXCH, &value); | ||
1236 | *num_channels = (int)value; | ||
1237 | } | ||
1238 | |||
1239 | /* | ||
1240 | * i5400_probe1 Probe for ONE instance of device to see if it is | 1213 | * i5400_probe1 Probe for ONE instance of device to see if it is |
1241 | * present. | 1214 | * present. |
1242 | * return: | 1215 | * return: |
@@ -1263,22 +1236,16 @@ static int i5400_probe1(struct pci_dev *pdev, int dev_idx) | |||
1263 | if (PCI_FUNC(pdev->devfn) != 0) | 1236 | if (PCI_FUNC(pdev->devfn) != 0) |
1264 | return -ENODEV; | 1237 | return -ENODEV; |
1265 | 1238 | ||
1266 | /* Ask the devices for the number of CSROWS and CHANNELS so | 1239 | /* As we don't have a motherboard identification routine to determine |
1267 | * that we can calculate the memory resources, etc | ||
1268 | * | ||
1269 | * The Chipset will report what it can handle which will be greater | ||
1270 | * or equal to what the motherboard manufacturer will implement. | ||
1271 | * | ||
1272 | * As we don't have a motherboard identification routine to determine | ||
1273 | * actual number of slots/dimms per channel, we thus utilize the | 1240 | * actual number of slots/dimms per channel, we thus utilize the |
1274 | * resource as specified by the chipset. Thus, we might have | 1241 | * resource as specified by the chipset. Thus, we might have |
1275 | * have more DIMMs per channel than actually on the mobo, but this | 1242 | * have more DIMMs per channel than actually on the mobo, but this |
1276 | * allows the driver to support upto the chipset max, without | 1243 | * allows the driver to support upto the chipset max, without |
1277 | * some fancy mobo determination. | 1244 | * some fancy mobo determination. |
1278 | */ | 1245 | */ |
1279 | i5400_get_dimm_and_channel_counts(pdev, &num_dimms_per_channel, | 1246 | num_dimms_per_channel = MAX_DIMMS_PER_CHANNEL; |
1280 | &num_channels); | 1247 | num_channels = MAX_CHANNELS; |
1281 | num_csrows = num_dimms_per_channel * 2; | 1248 | num_csrows = num_dimms_per_channel; |
1282 | 1249 | ||
1283 | debugf0("MC: %s(): Number of - Channels= %d DIMMS= %d CSROWS= %d\n", | 1250 | debugf0("MC: %s(): Number of - Channels= %d DIMMS= %d CSROWS= %d\n", |
1284 | __func__, num_channels, num_dimms_per_channel, num_csrows); | 1251 | __func__, num_channels, num_dimms_per_channel, num_csrows); |
diff --git a/drivers/edac/mpc85xx_edac.c b/drivers/edac/mpc85xx_edac.c index 157f6504f25e..cf27402af97b 100644 --- a/drivers/edac/mpc85xx_edac.c +++ b/drivers/edac/mpc85xx_edac.c | |||
@@ -26,7 +26,9 @@ | |||
26 | #include "mpc85xx_edac.h" | 26 | #include "mpc85xx_edac.h" |
27 | 27 | ||
28 | static int edac_dev_idx; | 28 | static int edac_dev_idx; |
29 | #ifdef CONFIG_PCI | ||
29 | static int edac_pci_idx; | 30 | static int edac_pci_idx; |
31 | #endif | ||
30 | static int edac_mc_idx; | 32 | static int edac_mc_idx; |
31 | 33 | ||
32 | static u32 orig_ddr_err_disable; | 34 | static u32 orig_ddr_err_disable; |