aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/edac/amd64_edac.c88
-rw-r--r--drivers/edac/amd64_edac.h3
-rw-r--r--drivers/edac/edac_mc_sysfs.c11
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] */
934static u64 get_error_address(struct mce *m) 932static 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
947static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range) 993static 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
964static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, 1036static 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