diff options
author | Borislav Petkov <borislav.petkov@amd.com> | 2010-03-09 06:46:00 -0500 |
---|---|---|
committer | Borislav Petkov <borislav.petkov@amd.com> | 2010-08-03 10:13:31 -0400 |
commit | ad6a32e96939a0eb0eb382e7d78dbf33457aed1a (patch) | |
tree | 62824540584ff79cde370edc3730d2b592a5a0d9 /drivers/edac | |
parent | 9fe6206f400646a2322096b56c59891d530e8d51 (diff) |
amd64_edac: Sanitize syndrome extraction
Remove the two syndrome extraction macros and add a single function
which does the same thing but with proper typechecking. While at it,
make sure to cache ECC syndrome size and dump it in debug output.
Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
Diffstat (limited to 'drivers/edac')
-rw-r--r-- | drivers/edac/amd64_edac.c | 83 | ||||
-rw-r--r-- | drivers/edac/amd64_edac.h | 5 |
2 files changed, 55 insertions, 33 deletions
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index ac9f7985096d..e8d84f89dbcf 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c | |||
@@ -796,6 +796,11 @@ static int sys_addr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr) | |||
796 | 796 | ||
797 | static int get_channel_from_ecc_syndrome(struct mem_ctl_info *, u16); | 797 | static int get_channel_from_ecc_syndrome(struct mem_ctl_info *, u16); |
798 | 798 | ||
799 | static u16 extract_syndrome(struct err_regs *err) | ||
800 | { | ||
801 | return ((err->nbsh >> 15) & 0xff) | ((err->nbsl >> 16) & 0xff00); | ||
802 | } | ||
803 | |||
799 | static void amd64_cpu_display_info(struct amd64_pvt *pvt) | 804 | static void amd64_cpu_display_info(struct amd64_pvt *pvt) |
800 | { | 805 | { |
801 | if (boot_cpu_data.x86 == 0x11) | 806 | if (boot_cpu_data.x86 == 0x11) |
@@ -888,6 +893,9 @@ static void amd64_dump_misc_regs(struct amd64_pvt *pvt) | |||
888 | return; | 893 | return; |
889 | } | 894 | } |
890 | 895 | ||
896 | amd64_printk(KERN_INFO, "using %s syndromes.\n", | ||
897 | ((pvt->syn_type == 8) ? "x8" : "x4")); | ||
898 | |||
891 | /* Only if NOT ganged does dclr1 have valid info */ | 899 | /* Only if NOT ganged does dclr1 have valid info */ |
892 | if (!dct_ganging_enabled(pvt)) | 900 | if (!dct_ganging_enabled(pvt)) |
893 | amd64_dump_dramcfg_low(pvt->dclr1, 1); | 901 | amd64_dump_dramcfg_low(pvt->dclr1, 1); |
@@ -1101,20 +1109,17 @@ static void k8_read_dram_base_limit(struct amd64_pvt *pvt, int dram) | |||
1101 | } | 1109 | } |
1102 | 1110 | ||
1103 | static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, | 1111 | static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, |
1104 | struct err_regs *info, | 1112 | struct err_regs *err_info, u64 sys_addr) |
1105 | u64 sys_addr) | ||
1106 | { | 1113 | { |
1107 | struct mem_ctl_info *src_mci; | 1114 | struct mem_ctl_info *src_mci; |
1108 | unsigned short syndrome; | ||
1109 | int channel, csrow; | 1115 | int channel, csrow; |
1110 | u32 page, offset; | 1116 | u32 page, offset; |
1117 | u16 syndrome; | ||
1111 | 1118 | ||
1112 | /* Extract the syndrome parts and form a 16-bit syndrome */ | 1119 | syndrome = extract_syndrome(err_info); |
1113 | syndrome = HIGH_SYNDROME(info->nbsl) << 8; | ||
1114 | syndrome |= LOW_SYNDROME(info->nbsh); | ||
1115 | 1120 | ||
1116 | /* CHIPKILL enabled */ | 1121 | /* CHIPKILL enabled */ |
1117 | if (info->nbcfg & K8_NBCFG_CHIPKILL) { | 1122 | if (err_info->nbcfg & K8_NBCFG_CHIPKILL) { |
1118 | channel = get_channel_from_ecc_syndrome(mci, syndrome); | 1123 | channel = get_channel_from_ecc_syndrome(mci, syndrome); |
1119 | if (channel < 0) { | 1124 | if (channel < 0) { |
1120 | /* | 1125 | /* |
@@ -1123,8 +1128,8 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, | |||
1123 | * as suspect. | 1128 | * as suspect. |
1124 | */ | 1129 | */ |
1125 | amd64_mc_printk(mci, KERN_WARNING, | 1130 | amd64_mc_printk(mci, KERN_WARNING, |
1126 | "unknown syndrome 0x%x - possible error " | 1131 | "unknown syndrome 0x%04x - possible " |
1127 | "reporting race\n", syndrome); | 1132 | "error reporting race\n", syndrome); |
1128 | edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR); | 1133 | edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR); |
1129 | return; | 1134 | return; |
1130 | } | 1135 | } |
@@ -1654,13 +1659,13 @@ static int f10_translate_sysaddr_to_cs(struct amd64_pvt *pvt, u64 sys_addr, | |||
1654 | * (MCX_ADDR). | 1659 | * (MCX_ADDR). |
1655 | */ | 1660 | */ |
1656 | static void f10_map_sysaddr_to_csrow(struct mem_ctl_info *mci, | 1661 | static void f10_map_sysaddr_to_csrow(struct mem_ctl_info *mci, |
1657 | struct err_regs *info, | 1662 | struct err_regs *err_info, |
1658 | u64 sys_addr) | 1663 | u64 sys_addr) |
1659 | { | 1664 | { |
1660 | struct amd64_pvt *pvt = mci->pvt_info; | 1665 | struct amd64_pvt *pvt = mci->pvt_info; |
1661 | u32 page, offset; | 1666 | u32 page, offset; |
1662 | unsigned short syndrome; | ||
1663 | int nid, csrow, chan = 0; | 1667 | int nid, csrow, chan = 0; |
1668 | u16 syndrome; | ||
1664 | 1669 | ||
1665 | csrow = f10_translate_sysaddr_to_cs(pvt, sys_addr, &nid, &chan); | 1670 | csrow = f10_translate_sysaddr_to_cs(pvt, sys_addr, &nid, &chan); |
1666 | 1671 | ||
@@ -1671,8 +1676,7 @@ static void f10_map_sysaddr_to_csrow(struct mem_ctl_info *mci, | |||
1671 | 1676 | ||
1672 | error_address_to_page_and_offset(sys_addr, &page, &offset); | 1677 | error_address_to_page_and_offset(sys_addr, &page, &offset); |
1673 | 1678 | ||
1674 | syndrome = HIGH_SYNDROME(info->nbsl) << 8; | 1679 | syndrome = extract_syndrome(err_info); |
1675 | syndrome |= LOW_SYNDROME(info->nbsh); | ||
1676 | 1680 | ||
1677 | /* | 1681 | /* |
1678 | * We need the syndromes for channel detection only when we're | 1682 | * We need the syndromes for channel detection only when we're |
@@ -1878,7 +1882,7 @@ static u16 x8_vectors[] = { | |||
1878 | }; | 1882 | }; |
1879 | 1883 | ||
1880 | static int decode_syndrome(u16 syndrome, u16 *vectors, int num_vecs, | 1884 | static int decode_syndrome(u16 syndrome, u16 *vectors, int num_vecs, |
1881 | int v_dim) | 1885 | int v_dim) |
1882 | { | 1886 | { |
1883 | unsigned int i, err_sym; | 1887 | unsigned int i, err_sym; |
1884 | 1888 | ||
@@ -1955,23 +1959,23 @@ static int map_err_sym_to_channel(int err_sym, int sym_size) | |||
1955 | static int get_channel_from_ecc_syndrome(struct mem_ctl_info *mci, u16 syndrome) | 1959 | static int get_channel_from_ecc_syndrome(struct mem_ctl_info *mci, u16 syndrome) |
1956 | { | 1960 | { |
1957 | struct amd64_pvt *pvt = mci->pvt_info; | 1961 | struct amd64_pvt *pvt = mci->pvt_info; |
1958 | u32 value = 0; | 1962 | int err_sym = -1; |
1959 | int err_sym = 0; | 1963 | |
1960 | 1964 | if (pvt->syn_type == 8) | |
1961 | if (boot_cpu_data.x86 == 0x10) { | 1965 | err_sym = decode_syndrome(syndrome, x8_vectors, |
1962 | 1966 | ARRAY_SIZE(x8_vectors), | |
1963 | amd64_read_pci_cfg(pvt->misc_f3_ctl, 0x180, &value); | 1967 | pvt->syn_type); |
1964 | 1968 | else if (pvt->syn_type == 4) | |
1965 | /* F3x180[EccSymbolSize]=1 => x8 symbols */ | 1969 | err_sym = decode_syndrome(syndrome, x4_vectors, |
1966 | if (boot_cpu_data.x86_model > 7 && | 1970 | ARRAY_SIZE(x4_vectors), |
1967 | value & BIT(25)) { | 1971 | pvt->syn_type); |
1968 | err_sym = decode_syndrome(syndrome, x8_vectors, | 1972 | else { |
1969 | ARRAY_SIZE(x8_vectors), 8); | 1973 | amd64_printk(KERN_WARNING, "%s: Illegal syndrome type: %u\n", |
1970 | return map_err_sym_to_channel(err_sym, 8); | 1974 | __func__, pvt->syn_type); |
1971 | } | 1975 | return err_sym; |
1972 | } | 1976 | } |
1973 | err_sym = decode_syndrome(syndrome, x4_vectors, ARRAY_SIZE(x4_vectors), 4); | 1977 | |
1974 | return map_err_sym_to_channel(err_sym, 4); | 1978 | return map_err_sym_to_channel(err_sym, pvt->syn_type); |
1975 | } | 1979 | } |
1976 | 1980 | ||
1977 | /* | 1981 | /* |
@@ -2284,6 +2288,7 @@ static void amd64_free_mc_sibling_devices(struct amd64_pvt *pvt) | |||
2284 | static void amd64_read_mc_registers(struct amd64_pvt *pvt) | 2288 | static void amd64_read_mc_registers(struct amd64_pvt *pvt) |
2285 | { | 2289 | { |
2286 | u64 msr_val; | 2290 | u64 msr_val; |
2291 | u32 tmp; | ||
2287 | int dram; | 2292 | int dram; |
2288 | 2293 | ||
2289 | /* | 2294 | /* |
@@ -2349,10 +2354,22 @@ static void amd64_read_mc_registers(struct amd64_pvt *pvt) | |||
2349 | amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCLR_0, &pvt->dclr0); | 2354 | amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCLR_0, &pvt->dclr0); |
2350 | amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCHR_0, &pvt->dchr0); | 2355 | amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCHR_0, &pvt->dchr0); |
2351 | 2356 | ||
2352 | if (!dct_ganging_enabled(pvt) && boot_cpu_data.x86 >= 0x10) { | 2357 | if (boot_cpu_data.x86 >= 0x10) { |
2353 | amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCLR_1, &pvt->dclr1); | 2358 | if (!dct_ganging_enabled(pvt)) { |
2354 | amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCHR_1, &pvt->dchr1); | 2359 | amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCLR_1, &pvt->dclr1); |
2360 | amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCHR_1, &pvt->dchr1); | ||
2361 | } | ||
2362 | amd64_read_pci_cfg(pvt->misc_f3_ctl, EXT_NB_MCA_CFG, &tmp); | ||
2355 | } | 2363 | } |
2364 | |||
2365 | if (boot_cpu_data.x86 == 0x10 && | ||
2366 | boot_cpu_data.x86_model > 7 && | ||
2367 | /* F3x180[EccSymbolSize]=1 => x8 symbols */ | ||
2368 | tmp & BIT(25)) | ||
2369 | pvt->syn_type = 8; | ||
2370 | else | ||
2371 | pvt->syn_type = 4; | ||
2372 | |||
2356 | amd64_dump_misc_regs(pvt); | 2373 | amd64_dump_misc_regs(pvt); |
2357 | } | 2374 | } |
2358 | 2375 | ||
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index 0d4bf5638243..707745b36733 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h | |||
@@ -382,6 +382,8 @@ enum { | |||
382 | #define K8_NBCAP_SECDED BIT(3) | 382 | #define K8_NBCAP_SECDED BIT(3) |
383 | #define K8_NBCAP_DCT_DUAL BIT(0) | 383 | #define K8_NBCAP_DCT_DUAL BIT(0) |
384 | 384 | ||
385 | #define EXT_NB_MCA_CFG 0x180 | ||
386 | |||
385 | /* MSRs */ | 387 | /* MSRs */ |
386 | #define K8_MSR_MCGCTL_NBE BIT(4) | 388 | #define K8_MSR_MCGCTL_NBE BIT(4) |
387 | 389 | ||
@@ -471,6 +473,9 @@ struct amd64_pvt { | |||
471 | u32 dram_ctl_select_high; /* DRAM Controller Select High Reg */ | 473 | u32 dram_ctl_select_high; /* DRAM Controller Select High Reg */ |
472 | u32 online_spare; /* On-Line spare Reg */ | 474 | u32 online_spare; /* On-Line spare Reg */ |
473 | 475 | ||
476 | /* x4 or x8 syndromes in use */ | ||
477 | u8 syn_type; | ||
478 | |||
474 | /* temp storage for when input is received from sysfs */ | 479 | /* temp storage for when input is received from sysfs */ |
475 | struct err_regs ctl_error_info; | 480 | struct err_regs ctl_error_info; |
476 | 481 | ||