diff options
| -rw-r--r-- | drivers/edac/amd64_edac.c | 88 | ||||
| -rw-r--r-- | drivers/edac/amd64_edac.h | 3 | ||||
| -rw-r--r-- | drivers/edac/edac_mc_sysfs.c | 11 |
3 files changed, 86 insertions, 16 deletions
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 31e71c4fc83..9a8bebcf6b1 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c | |||
| @@ -211,8 +211,6 @@ static int amd64_get_scrub_rate(struct mem_ctl_info *mci) | |||
| 211 | 211 | ||
| 212 | scrubval = scrubval & 0x001F; | 212 | scrubval = scrubval & 0x001F; |
| 213 | 213 | ||
| 214 | amd64_debug("pci-read, sdram scrub control value: %d\n", scrubval); | ||
| 215 | |||
| 216 | for (i = 0; i < ARRAY_SIZE(scrubrates); i++) { | 214 | for (i = 0; i < ARRAY_SIZE(scrubrates); i++) { |
| 217 | if (scrubrates[i].scrubval == scrubval) { | 215 | if (scrubrates[i].scrubval == scrubval) { |
| 218 | retval = scrubrates[i].bandwidth; | 216 | retval = scrubrates[i].bandwidth; |
| @@ -933,25 +931,74 @@ static int k8_early_channel_count(struct amd64_pvt *pvt) | |||
| 933 | /* On F10h and later ErrAddr is MC4_ADDR[47:1] */ | 931 | /* On F10h and later ErrAddr is MC4_ADDR[47:1] */ |
| 934 | static u64 get_error_address(struct mce *m) | 932 | static u64 get_error_address(struct mce *m) |
| 935 | { | 933 | { |
| 934 | struct cpuinfo_x86 *c = &boot_cpu_data; | ||
| 935 | u64 addr; | ||
| 936 | u8 start_bit = 1; | 936 | u8 start_bit = 1; |
| 937 | u8 end_bit = 47; | 937 | u8 end_bit = 47; |
| 938 | 938 | ||
| 939 | if (boot_cpu_data.x86 == 0xf) { | 939 | if (c->x86 == 0xf) { |
| 940 | start_bit = 3; | 940 | start_bit = 3; |
| 941 | end_bit = 39; | 941 | end_bit = 39; |
| 942 | } | 942 | } |
| 943 | 943 | ||
| 944 | return m->addr & GENMASK(start_bit, end_bit); | 944 | addr = m->addr & GENMASK(start_bit, end_bit); |
| 945 | |||
| 946 | /* | ||
| 947 | * Erratum 637 workaround | ||
| 948 | */ | ||
| 949 | if (c->x86 == 0x15) { | ||
| 950 | struct amd64_pvt *pvt; | ||
| 951 | u64 cc6_base, tmp_addr; | ||
| 952 | u32 tmp; | ||
| 953 | u8 mce_nid, intlv_en; | ||
| 954 | |||
| 955 | if ((addr & GENMASK(24, 47)) >> 24 != 0x00fdf7) | ||
| 956 | return addr; | ||
| 957 | |||
| 958 | mce_nid = amd_get_nb_id(m->extcpu); | ||
| 959 | pvt = mcis[mce_nid]->pvt_info; | ||
| 960 | |||
| 961 | amd64_read_pci_cfg(pvt->F1, DRAM_LOCAL_NODE_LIM, &tmp); | ||
| 962 | intlv_en = tmp >> 21 & 0x7; | ||
| 963 | |||
| 964 | /* add [47:27] + 3 trailing bits */ | ||
| 965 | cc6_base = (tmp & GENMASK(0, 20)) << 3; | ||
| 966 | |||
| 967 | /* reverse and add DramIntlvEn */ | ||
| 968 | cc6_base |= intlv_en ^ 0x7; | ||
| 969 | |||
| 970 | /* pin at [47:24] */ | ||
| 971 | cc6_base <<= 24; | ||
| 972 | |||
| 973 | if (!intlv_en) | ||
| 974 | return cc6_base | (addr & GENMASK(0, 23)); | ||
| 975 | |||
| 976 | amd64_read_pci_cfg(pvt->F1, DRAM_LOCAL_NODE_BASE, &tmp); | ||
| 977 | |||
| 978 | /* faster log2 */ | ||
| 979 | tmp_addr = (addr & GENMASK(12, 23)) << __fls(intlv_en + 1); | ||
| 980 | |||
| 981 | /* OR DramIntlvSel into bits [14:12] */ | ||
| 982 | tmp_addr |= (tmp & GENMASK(21, 23)) >> 9; | ||
| 983 | |||
| 984 | /* add remaining [11:0] bits from original MC4_ADDR */ | ||
| 985 | tmp_addr |= addr & GENMASK(0, 11); | ||
| 986 | |||
| 987 | return cc6_base | tmp_addr; | ||
| 988 | } | ||
| 989 | |||
| 990 | return addr; | ||
| 945 | } | 991 | } |
| 946 | 992 | ||
| 947 | static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range) | 993 | static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range) |
| 948 | { | 994 | { |
| 995 | struct cpuinfo_x86 *c = &boot_cpu_data; | ||
| 949 | int off = range << 3; | 996 | int off = range << 3; |
| 950 | 997 | ||
| 951 | amd64_read_pci_cfg(pvt->F1, DRAM_BASE_LO + off, &pvt->ranges[range].base.lo); | 998 | amd64_read_pci_cfg(pvt->F1, DRAM_BASE_LO + off, &pvt->ranges[range].base.lo); |
| 952 | amd64_read_pci_cfg(pvt->F1, DRAM_LIMIT_LO + off, &pvt->ranges[range].lim.lo); | 999 | amd64_read_pci_cfg(pvt->F1, DRAM_LIMIT_LO + off, &pvt->ranges[range].lim.lo); |
| 953 | 1000 | ||
| 954 | if (boot_cpu_data.x86 == 0xf) | 1001 | if (c->x86 == 0xf) |
| 955 | return; | 1002 | return; |
| 956 | 1003 | ||
| 957 | if (!dram_rw(pvt, range)) | 1004 | if (!dram_rw(pvt, range)) |
| @@ -959,6 +1006,31 @@ static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range) | |||
| 959 | 1006 | ||
| 960 | amd64_read_pci_cfg(pvt->F1, DRAM_BASE_HI + off, &pvt->ranges[range].base.hi); | 1007 | amd64_read_pci_cfg(pvt->F1, DRAM_BASE_HI + off, &pvt->ranges[range].base.hi); |
| 961 | amd64_read_pci_cfg(pvt->F1, DRAM_LIMIT_HI + off, &pvt->ranges[range].lim.hi); | 1008 | amd64_read_pci_cfg(pvt->F1, DRAM_LIMIT_HI + off, &pvt->ranges[range].lim.hi); |
| 1009 | |||
| 1010 | /* Factor in CC6 save area by reading dst node's limit reg */ | ||
| 1011 | if (c->x86 == 0x15) { | ||
| 1012 | struct pci_dev *f1 = NULL; | ||
| 1013 | u8 nid = dram_dst_node(pvt, range); | ||
| 1014 | u32 llim; | ||
| 1015 | |||
| 1016 | f1 = pci_get_domain_bus_and_slot(0, 0, PCI_DEVFN(0x18 + nid, 1)); | ||
| 1017 | if (WARN_ON(!f1)) | ||
| 1018 | return; | ||
| 1019 | |||
| 1020 | amd64_read_pci_cfg(f1, DRAM_LOCAL_NODE_LIM, &llim); | ||
| 1021 | |||
| 1022 | pvt->ranges[range].lim.lo &= GENMASK(0, 15); | ||
| 1023 | |||
| 1024 | /* {[39:27],111b} */ | ||
| 1025 | pvt->ranges[range].lim.lo |= ((llim & 0x1fff) << 3 | 0x7) << 16; | ||
| 1026 | |||
| 1027 | pvt->ranges[range].lim.hi &= GENMASK(0, 7); | ||
| 1028 | |||
| 1029 | /* [47:40] */ | ||
| 1030 | pvt->ranges[range].lim.hi |= llim >> 13; | ||
| 1031 | |||
| 1032 | pci_dev_put(f1); | ||
| 1033 | } | ||
| 962 | } | 1034 | } |
| 963 | 1035 | ||
| 964 | static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, | 1036 | static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, |
| @@ -1403,12 +1475,8 @@ static int f1x_match_to_this_node(struct amd64_pvt *pvt, unsigned range, | |||
| 1403 | return -EINVAL; | 1475 | return -EINVAL; |
| 1404 | } | 1476 | } |
| 1405 | 1477 | ||
| 1406 | if (intlv_en && | 1478 | if (intlv_en && (intlv_sel != ((sys_addr >> 12) & intlv_en))) |
| 1407 | (intlv_sel != ((sys_addr >> 12) & intlv_en))) { | ||
| 1408 | amd64_warn("Botched intlv bits, en: 0x%x, sel: 0x%x\n", | ||
| 1409 | intlv_en, intlv_sel); | ||
| 1410 | return -EINVAL; | 1479 | return -EINVAL; |
| 1411 | } | ||
| 1412 | 1480 | ||
| 1413 | sys_addr = f1x_swap_interleaved_region(pvt, sys_addr); | 1481 | sys_addr = f1x_swap_interleaved_region(pvt, sys_addr); |
| 1414 | 1482 | ||
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index 11be36a311e..9a666cb985b 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h | |||
| @@ -196,6 +196,9 @@ | |||
| 196 | 196 | ||
| 197 | #define DCT_CFG_SEL 0x10C | 197 | #define DCT_CFG_SEL 0x10C |
| 198 | 198 | ||
| 199 | #define DRAM_LOCAL_NODE_BASE 0x120 | ||
| 200 | #define DRAM_LOCAL_NODE_LIM 0x124 | ||
| 201 | |||
| 199 | #define DRAM_BASE_HI 0x140 | 202 | #define DRAM_BASE_HI 0x140 |
| 200 | #define DRAM_LIMIT_HI 0x144 | 203 | #define DRAM_LIMIT_HI 0x144 |
| 201 | 204 | ||
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index 26343fd4659..29ffa350bfb 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c | |||
| @@ -458,13 +458,13 @@ static ssize_t mci_sdram_scrub_rate_store(struct mem_ctl_info *mci, | |||
| 458 | return -EINVAL; | 458 | return -EINVAL; |
| 459 | 459 | ||
| 460 | new_bw = mci->set_sdram_scrub_rate(mci, bandwidth); | 460 | new_bw = mci->set_sdram_scrub_rate(mci, bandwidth); |
| 461 | if (new_bw >= 0) { | 461 | if (new_bw < 0) { |
| 462 | edac_printk(KERN_DEBUG, EDAC_MC, "Scrub rate set to %d\n", new_bw); | 462 | edac_printk(KERN_WARNING, EDAC_MC, |
| 463 | return count; | 463 | "Error setting scrub rate to: %lu\n", bandwidth); |
| 464 | return -EINVAL; | ||
| 464 | } | 465 | } |
| 465 | 466 | ||
| 466 | edac_printk(KERN_DEBUG, EDAC_MC, "Error setting scrub rate to: %lu\n", bandwidth); | 467 | return count; |
| 467 | return -EINVAL; | ||
| 468 | } | 468 | } |
| 469 | 469 | ||
| 470 | /* | 470 | /* |
| @@ -483,7 +483,6 @@ static ssize_t mci_sdram_scrub_rate_show(struct mem_ctl_info *mci, char *data) | |||
| 483 | return bandwidth; | 483 | return bandwidth; |
| 484 | } | 484 | } |
| 485 | 485 | ||
| 486 | edac_printk(KERN_DEBUG, EDAC_MC, "Read scrub rate: %d\n", bandwidth); | ||
| 487 | return sprintf(data, "%d\n", bandwidth); | 486 | return sprintf(data, "%d\n", bandwidth); |
| 488 | } | 487 | } |
| 489 | 488 | ||
