diff options
author | Borislav Petkov <borislav.petkov@amd.com> | 2010-10-21 12:52:53 -0400 |
---|---|---|
committer | Borislav Petkov <borislav.petkov@amd.com> | 2011-03-17 09:46:11 -0400 |
commit | 7f19bf755ced6fa16dbf118c0eff60586760496b (patch) | |
tree | 93b050e1a30efe33aaa1ffdf26473bd9ab55a585 /drivers/edac | |
parent | b2b0c605436e343a9a24f00e7fc8fb89a8316e20 (diff) |
amd64_edac: Remove DRAM base/limit subfields caching
Add a struct representing the DRAM base/limit range pairs and remove all
cached subfields. Replace them with accessor functions, which actually
saves us some space:
text data bss dec hex filename
14712 1577 336 16625 40f1 drivers/edac/amd64_edac_mod.o.after
14831 1609 336 16776 4188 drivers/edac/amd64_edac_mod.o.before
Also, it simplifies the code a lot allowing to merge the K8 and F10h
routines.
No functional change.
Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
Diffstat (limited to 'drivers/edac')
-rw-r--r-- | drivers/edac/amd64_edac.c | 230 | ||||
-rw-r--r-- | drivers/edac/amd64_edac.h | 73 |
2 files changed, 115 insertions, 188 deletions
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index ae5adac3733f..683fd3c716a0 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c | |||
@@ -296,32 +296,13 @@ static u32 amd64_get_dct_mask(struct amd64_pvt *pvt, int dct, int csrow) | |||
296 | return pvt->dcsm1[amd64_map_to_dcs_mask(pvt, csrow)]; | 296 | return pvt->dcsm1[amd64_map_to_dcs_mask(pvt, csrow)]; |
297 | } | 297 | } |
298 | 298 | ||
299 | |||
300 | /* | 299 | /* |
301 | * In *base and *limit, pass back the full 40-bit base and limit physical | 300 | * returns true if the SysAddr given by sys_addr matches the |
302 | * addresses for the node given by node_id. This information is obtained from | 301 | * DRAM base/limit associated with node_id |
303 | * DRAM Base (section 3.4.4.1) and DRAM Limit (section 3.4.4.2) registers. The | ||
304 | * base and limit addresses are of type SysAddr, as defined at the start of | ||
305 | * section 3.4.4 (p. 70). They are the lowest and highest physical addresses | ||
306 | * in the address range they represent. | ||
307 | */ | 302 | */ |
308 | static void amd64_get_base_and_limit(struct amd64_pvt *pvt, int node_id, | 303 | static bool amd64_base_limit_match(struct amd64_pvt *pvt, u64 sys_addr, int nid) |
309 | u64 *base, u64 *limit) | ||
310 | { | 304 | { |
311 | *base = pvt->dram_base[node_id]; | 305 | u64 addr; |
312 | *limit = pvt->dram_limit[node_id]; | ||
313 | } | ||
314 | |||
315 | /* | ||
316 | * Return 1 if the SysAddr given by sys_addr matches the base/limit associated | ||
317 | * with node_id | ||
318 | */ | ||
319 | static int amd64_base_limit_match(struct amd64_pvt *pvt, | ||
320 | u64 sys_addr, int node_id) | ||
321 | { | ||
322 | u64 base, limit, addr; | ||
323 | |||
324 | amd64_get_base_and_limit(pvt, node_id, &base, &limit); | ||
325 | 306 | ||
326 | /* The K8 treats this as a 40-bit value. However, bits 63-40 will be | 307 | /* The K8 treats this as a 40-bit value. However, bits 63-40 will be |
327 | * all ones if the most significant implemented address bit is 1. | 308 | * all ones if the most significant implemented address bit is 1. |
@@ -331,7 +312,8 @@ static int amd64_base_limit_match(struct amd64_pvt *pvt, | |||
331 | */ | 312 | */ |
332 | addr = sys_addr & 0x000000ffffffffffull; | 313 | addr = sys_addr & 0x000000ffffffffffull; |
333 | 314 | ||
334 | return (addr >= base) && (addr <= limit); | 315 | return ((addr >= get_dram_base(pvt, nid)) && |
316 | (addr <= get_dram_limit(pvt, nid))); | ||
335 | } | 317 | } |
336 | 318 | ||
337 | /* | 319 | /* |
@@ -358,10 +340,10 @@ static struct mem_ctl_info *find_mc_by_sys_addr(struct mem_ctl_info *mci, | |||
358 | * registers. Therefore we arbitrarily choose to read it from the | 340 | * registers. Therefore we arbitrarily choose to read it from the |
359 | * register for node 0. | 341 | * register for node 0. |
360 | */ | 342 | */ |
361 | intlv_en = pvt->dram_IntlvEn[0]; | 343 | intlv_en = dram_intlv_en(pvt, 0); |
362 | 344 | ||
363 | if (intlv_en == 0) { | 345 | if (intlv_en == 0) { |
364 | for (node_id = 0; node_id < DRAM_REG_COUNT; node_id++) { | 346 | for (node_id = 0; node_id < DRAM_RANGES; node_id++) { |
365 | if (amd64_base_limit_match(pvt, sys_addr, node_id)) | 347 | if (amd64_base_limit_match(pvt, sys_addr, node_id)) |
366 | goto found; | 348 | goto found; |
367 | } | 349 | } |
@@ -378,10 +360,10 @@ static struct mem_ctl_info *find_mc_by_sys_addr(struct mem_ctl_info *mci, | |||
378 | bits = (((u32) sys_addr) >> 12) & intlv_en; | 360 | bits = (((u32) sys_addr) >> 12) & intlv_en; |
379 | 361 | ||
380 | for (node_id = 0; ; ) { | 362 | for (node_id = 0; ; ) { |
381 | if ((pvt->dram_IntlvSel[node_id] & intlv_en) == bits) | 363 | if ((dram_intlv_sel(pvt, node_id) & intlv_en) == bits) |
382 | break; /* intlv_sel field matches */ | 364 | break; /* intlv_sel field matches */ |
383 | 365 | ||
384 | if (++node_id >= DRAM_REG_COUNT) | 366 | if (++node_id >= DRAM_RANGES) |
385 | goto err_no_match; | 367 | goto err_no_match; |
386 | } | 368 | } |
387 | 369 | ||
@@ -477,19 +459,6 @@ static int input_addr_to_csrow(struct mem_ctl_info *mci, u64 input_addr) | |||
477 | } | 459 | } |
478 | 460 | ||
479 | /* | 461 | /* |
480 | * Return the base value defined by the DRAM Base register for the node | ||
481 | * represented by mci. This function returns the full 40-bit value despite the | ||
482 | * fact that the register only stores bits 39-24 of the value. See section | ||
483 | * 3.4.4.1 (BKDG #26094, K8, revA-E) | ||
484 | */ | ||
485 | static inline u64 get_dram_base(struct mem_ctl_info *mci) | ||
486 | { | ||
487 | struct amd64_pvt *pvt = mci->pvt_info; | ||
488 | |||
489 | return pvt->dram_base[pvt->mc_node_id]; | ||
490 | } | ||
491 | |||
492 | /* | ||
493 | * Obtain info from the DRAM Hole Address Register (section 3.4.8, pub #26094) | 462 | * Obtain info from the DRAM Hole Address Register (section 3.4.8, pub #26094) |
494 | * for the node represented by mci. Info is passed back in *hole_base, | 463 | * for the node represented by mci. Info is passed back in *hole_base, |
495 | * *hole_offset, and *hole_size. Function returns 0 if info is valid or 1 if | 464 | * *hole_offset, and *hole_size. Function returns 0 if info is valid or 1 if |
@@ -598,10 +567,11 @@ EXPORT_SYMBOL_GPL(amd64_get_dram_hole_info); | |||
598 | */ | 567 | */ |
599 | static u64 sys_addr_to_dram_addr(struct mem_ctl_info *mci, u64 sys_addr) | 568 | static u64 sys_addr_to_dram_addr(struct mem_ctl_info *mci, u64 sys_addr) |
600 | { | 569 | { |
570 | struct amd64_pvt *pvt = mci->pvt_info; | ||
601 | u64 dram_base, hole_base, hole_offset, hole_size, dram_addr; | 571 | u64 dram_base, hole_base, hole_offset, hole_size, dram_addr; |
602 | int ret = 0; | 572 | int ret = 0; |
603 | 573 | ||
604 | dram_base = get_dram_base(mci); | 574 | dram_base = get_dram_base(pvt, pvt->mc_node_id); |
605 | 575 | ||
606 | ret = amd64_get_dram_hole_info(mci, &hole_base, &hole_offset, | 576 | ret = amd64_get_dram_hole_info(mci, &hole_base, &hole_offset, |
607 | &hole_size); | 577 | &hole_size); |
@@ -665,7 +635,7 @@ static u64 dram_addr_to_input_addr(struct mem_ctl_info *mci, u64 dram_addr) | |||
665 | * See the start of section 3.4.4 (p. 70, BKDG #26094, K8, revA-E) | 635 | * See the start of section 3.4.4 (p. 70, BKDG #26094, K8, revA-E) |
666 | * concerning translating a DramAddr to an InputAddr. | 636 | * concerning translating a DramAddr to an InputAddr. |
667 | */ | 637 | */ |
668 | intlv_shift = num_node_interleave_bits(pvt->dram_IntlvEn[0]); | 638 | intlv_shift = num_node_interleave_bits(dram_intlv_en(pvt, 0)); |
669 | input_addr = ((dram_addr >> intlv_shift) & 0xffffff000ull) + | 639 | input_addr = ((dram_addr >> intlv_shift) & 0xffffff000ull) + |
670 | (dram_addr & 0xfff); | 640 | (dram_addr & 0xfff); |
671 | 641 | ||
@@ -717,7 +687,7 @@ static u64 input_addr_to_dram_addr(struct mem_ctl_info *mci, u64 input_addr) | |||
717 | node_id = pvt->mc_node_id; | 687 | node_id = pvt->mc_node_id; |
718 | BUG_ON((node_id < 0) || (node_id > 7)); | 688 | BUG_ON((node_id < 0) || (node_id > 7)); |
719 | 689 | ||
720 | intlv_shift = num_node_interleave_bits(pvt->dram_IntlvEn[0]); | 690 | intlv_shift = num_node_interleave_bits(dram_intlv_en(pvt, 0)); |
721 | 691 | ||
722 | if (intlv_shift == 0) { | 692 | if (intlv_shift == 0) { |
723 | debugf1(" InputAddr 0x%lx translates to DramAddr of " | 693 | debugf1(" InputAddr 0x%lx translates to DramAddr of " |
@@ -729,7 +699,7 @@ static u64 input_addr_to_dram_addr(struct mem_ctl_info *mci, u64 input_addr) | |||
729 | bits = ((input_addr & 0xffffff000ull) << intlv_shift) + | 699 | bits = ((input_addr & 0xffffff000ull) << intlv_shift) + |
730 | (input_addr & 0xfff); | 700 | (input_addr & 0xfff); |
731 | 701 | ||
732 | intlv_sel = pvt->dram_IntlvSel[node_id] & ((1 << intlv_shift) - 1); | 702 | intlv_sel = dram_intlv_sel(pvt, node_id) & ((1 << intlv_shift) - 1); |
733 | dram_addr = bits + (intlv_sel << 12); | 703 | dram_addr = bits + (intlv_sel << 12); |
734 | 704 | ||
735 | debugf1("InputAddr 0x%lx translates to DramAddr 0x%lx " | 705 | debugf1("InputAddr 0x%lx translates to DramAddr 0x%lx " |
@@ -746,7 +716,7 @@ static u64 input_addr_to_dram_addr(struct mem_ctl_info *mci, u64 input_addr) | |||
746 | static u64 dram_addr_to_sys_addr(struct mem_ctl_info *mci, u64 dram_addr) | 716 | static u64 dram_addr_to_sys_addr(struct mem_ctl_info *mci, u64 dram_addr) |
747 | { | 717 | { |
748 | struct amd64_pvt *pvt = mci->pvt_info; | 718 | struct amd64_pvt *pvt = mci->pvt_info; |
749 | u64 hole_base, hole_offset, hole_size, base, limit, sys_addr; | 719 | u64 hole_base, hole_offset, hole_size, base, sys_addr; |
750 | int ret = 0; | 720 | int ret = 0; |
751 | 721 | ||
752 | ret = amd64_get_dram_hole_info(mci, &hole_base, &hole_offset, | 722 | ret = amd64_get_dram_hole_info(mci, &hole_base, &hole_offset, |
@@ -764,7 +734,7 @@ static u64 dram_addr_to_sys_addr(struct mem_ctl_info *mci, u64 dram_addr) | |||
764 | } | 734 | } |
765 | } | 735 | } |
766 | 736 | ||
767 | amd64_get_base_and_limit(pvt, pvt->mc_node_id, &base, &limit); | 737 | base = get_dram_base(pvt, pvt->mc_node_id); |
768 | sys_addr = dram_addr + base; | 738 | sys_addr = dram_addr + base; |
769 | 739 | ||
770 | /* | 740 | /* |
@@ -1090,33 +1060,21 @@ static u64 k8_get_error_address(struct mem_ctl_info *mci, | |||
1090 | (info->nbeal & ~0x03); | 1060 | (info->nbeal & ~0x03); |
1091 | } | 1061 | } |
1092 | 1062 | ||
1093 | /* | 1063 | static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range) |
1094 | * Read the Base and Limit registers for K8 based Memory controllers; extract | ||
1095 | * fields from the 'raw' reg into separate data fields | ||
1096 | * | ||
1097 | * Isolates: BASE, LIMIT, IntlvEn, IntlvSel, RW_EN | ||
1098 | */ | ||
1099 | static void k8_read_dram_base_limit(struct amd64_pvt *pvt, int dram) | ||
1100 | { | 1064 | { |
1101 | u32 low; | 1065 | u32 off = range << 3; |
1102 | u32 off = dram << 3; /* 8 bytes between DRAM entries */ | ||
1103 | 1066 | ||
1104 | amd64_read_pci_cfg(pvt->F1, K8_DRAM_BASE_LOW + off, &low); | 1067 | amd64_read_pci_cfg(pvt->F1, DRAM_BASE_LO + off, &pvt->ranges[range].base.lo); |
1068 | amd64_read_pci_cfg(pvt->F1, DRAM_LIMIT_LO + off, &pvt->ranges[range].lim.lo); | ||
1105 | 1069 | ||
1106 | /* Extract parts into separate data entries */ | 1070 | if (boot_cpu_data.x86 == 0xf) |
1107 | pvt->dram_base[dram] = ((u64) low & 0xFFFF0000) << 8; | 1071 | return; |
1108 | pvt->dram_IntlvEn[dram] = (low >> 8) & 0x7; | ||
1109 | pvt->dram_rw_en[dram] = (low & 0x3); | ||
1110 | 1072 | ||
1111 | amd64_read_pci_cfg(pvt->F1, K8_DRAM_LIMIT_LOW + off, &low); | 1073 | if (!dram_rw(pvt, range)) |
1074 | return; | ||
1112 | 1075 | ||
1113 | /* | 1076 | amd64_read_pci_cfg(pvt->F1, DRAM_BASE_HI + off, &pvt->ranges[range].base.hi); |
1114 | * Extract parts into separate data entries. Limit is the HIGHEST memory | 1077 | amd64_read_pci_cfg(pvt->F1, DRAM_LIMIT_HI + off, &pvt->ranges[range].lim.hi); |
1115 | * location of the region, so lower 24 bits need to be all ones | ||
1116 | */ | ||
1117 | pvt->dram_limit[dram] = (((u64) low & 0xFFFF0000) << 8) | 0x00FFFFFF; | ||
1118 | pvt->dram_IntlvSel[dram] = (low >> 8) & 0x7; | ||
1119 | pvt->dram_DstNode[dram] = (low & 0x7); | ||
1120 | } | 1078 | } |
1121 | 1079 | ||
1122 | static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, | 1080 | static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, |
@@ -1271,53 +1229,6 @@ static u64 f10_get_error_address(struct mem_ctl_info *mci, | |||
1271 | (info->nbeal & ~0x01); | 1229 | (info->nbeal & ~0x01); |
1272 | } | 1230 | } |
1273 | 1231 | ||
1274 | /* | ||
1275 | * Read the Base and Limit registers for F10 based Memory controllers. Extract | ||
1276 | * fields from the 'raw' reg into separate data fields. | ||
1277 | * | ||
1278 | * Isolates: BASE, LIMIT, IntlvEn, IntlvSel, RW_EN. | ||
1279 | */ | ||
1280 | static void f10_read_dram_base_limit(struct amd64_pvt *pvt, int dram) | ||
1281 | { | ||
1282 | u32 high_offset, low_offset, high_base, low_base, high_limit, low_limit; | ||
1283 | |||
1284 | low_offset = K8_DRAM_BASE_LOW + (dram << 3); | ||
1285 | high_offset = F10_DRAM_BASE_HIGH + (dram << 3); | ||
1286 | |||
1287 | /* read the 'raw' DRAM BASE Address register */ | ||
1288 | amd64_read_pci_cfg(pvt->F1, low_offset, &low_base); | ||
1289 | amd64_read_pci_cfg(pvt->F1, high_offset, &high_base); | ||
1290 | |||
1291 | /* Extract parts into separate data entries */ | ||
1292 | pvt->dram_rw_en[dram] = (low_base & 0x3); | ||
1293 | |||
1294 | if (pvt->dram_rw_en[dram] == 0) | ||
1295 | return; | ||
1296 | |||
1297 | pvt->dram_IntlvEn[dram] = (low_base >> 8) & 0x7; | ||
1298 | |||
1299 | pvt->dram_base[dram] = (((u64)high_base & 0x000000FF) << 40) | | ||
1300 | (((u64)low_base & 0xFFFF0000) << 8); | ||
1301 | |||
1302 | low_offset = K8_DRAM_LIMIT_LOW + (dram << 3); | ||
1303 | high_offset = F10_DRAM_LIMIT_HIGH + (dram << 3); | ||
1304 | |||
1305 | /* read the 'raw' LIMIT registers */ | ||
1306 | amd64_read_pci_cfg(pvt->F1, low_offset, &low_limit); | ||
1307 | amd64_read_pci_cfg(pvt->F1, high_offset, &high_limit); | ||
1308 | |||
1309 | pvt->dram_DstNode[dram] = (low_limit & 0x7); | ||
1310 | pvt->dram_IntlvSel[dram] = (low_limit >> 8) & 0x7; | ||
1311 | |||
1312 | /* | ||
1313 | * Extract address values and form a LIMIT address. Limit is the HIGHEST | ||
1314 | * memory location of the region, so low 24 bits need to be all ones. | ||
1315 | */ | ||
1316 | pvt->dram_limit[dram] = (((u64)high_limit & 0x000000FF) << 40) | | ||
1317 | (((u64) low_limit & 0xFFFF0000) << 8) | | ||
1318 | 0x00FFFFFF; | ||
1319 | } | ||
1320 | |||
1321 | static void f10_read_dram_ctl_register(struct amd64_pvt *pvt) | 1232 | static void f10_read_dram_ctl_register(struct amd64_pvt *pvt) |
1322 | { | 1233 | { |
1323 | 1234 | ||
@@ -1520,22 +1431,21 @@ static int f10_lookup_addr_in_dct(u32 in_addr, u32 nid, u32 cs) | |||
1520 | } | 1431 | } |
1521 | 1432 | ||
1522 | /* For a given @dram_range, check if @sys_addr falls within it. */ | 1433 | /* For a given @dram_range, check if @sys_addr falls within it. */ |
1523 | static int f10_match_to_this_node(struct amd64_pvt *pvt, int dram_range, | 1434 | static int f10_match_to_this_node(struct amd64_pvt *pvt, int range, |
1524 | u64 sys_addr, int *nid, int *chan_sel) | 1435 | u64 sys_addr, int *nid, int *chan_sel) |
1525 | { | 1436 | { |
1526 | int node_id, cs_found = -EINVAL, high_range = 0; | 1437 | int cs_found = -EINVAL, high_range = 0; |
1527 | u32 intlv_en, intlv_sel, intlv_shift, hole_off; | 1438 | u32 intlv_shift, hole_off; |
1528 | u32 hole_valid, tmp, dct_sel_base, channel; | 1439 | u32 hole_valid, tmp, dct_sel_base, channel; |
1529 | u64 dram_base, chan_addr, dct_sel_base_off; | 1440 | u64 chan_addr, dct_sel_base_off; |
1530 | |||
1531 | dram_base = pvt->dram_base[dram_range]; | ||
1532 | intlv_en = pvt->dram_IntlvEn[dram_range]; | ||
1533 | 1441 | ||
1534 | node_id = pvt->dram_DstNode[dram_range]; | 1442 | u8 node_id = dram_dst_node(pvt, range); |
1535 | intlv_sel = pvt->dram_IntlvSel[dram_range]; | 1443 | u32 intlv_en = dram_intlv_en(pvt, range); |
1444 | u32 intlv_sel = dram_intlv_sel(pvt, range); | ||
1445 | u64 dram_base = get_dram_base(pvt, range); | ||
1536 | 1446 | ||
1537 | debugf1("(dram=%d) Base=0x%llx SystemAddr= 0x%llx Limit=0x%llx\n", | 1447 | debugf1("(range %d) Base=0x%llx SystemAddr= 0x%llx Limit=0x%llx\n", |
1538 | dram_range, dram_base, sys_addr, pvt->dram_limit[dram_range]); | 1448 | range, dram_base, sys_addr, get_dram_limit(pvt, range)); |
1539 | 1449 | ||
1540 | /* | 1450 | /* |
1541 | * This assumes that one node's DHAR is the same as all the other | 1451 | * This assumes that one node's DHAR is the same as all the other |
@@ -1604,20 +1514,17 @@ static int f10_match_to_this_node(struct amd64_pvt *pvt, int dram_range, | |||
1604 | static int f10_translate_sysaddr_to_cs(struct amd64_pvt *pvt, u64 sys_addr, | 1514 | static int f10_translate_sysaddr_to_cs(struct amd64_pvt *pvt, u64 sys_addr, |
1605 | int *node, int *chan_sel) | 1515 | int *node, int *chan_sel) |
1606 | { | 1516 | { |
1607 | int dram_range, cs_found = -EINVAL; | 1517 | int range, cs_found = -EINVAL; |
1608 | u64 dram_base, dram_limit; | ||
1609 | 1518 | ||
1610 | for (dram_range = 0; dram_range < DRAM_REG_COUNT; dram_range++) { | 1519 | for (range = 0; range < DRAM_RANGES; range++) { |
1611 | 1520 | ||
1612 | if (!pvt->dram_rw_en[dram_range]) | 1521 | if (!dram_rw(pvt, range)) |
1613 | continue; | 1522 | continue; |
1614 | 1523 | ||
1615 | dram_base = pvt->dram_base[dram_range]; | 1524 | if ((get_dram_base(pvt, range) <= sys_addr) && |
1616 | dram_limit = pvt->dram_limit[dram_range]; | 1525 | (get_dram_limit(pvt, range) >= sys_addr)) { |
1617 | 1526 | ||
1618 | if ((dram_base <= sys_addr) && (sys_addr <= dram_limit)) { | 1527 | cs_found = f10_match_to_this_node(pvt, range, |
1619 | |||
1620 | cs_found = f10_match_to_this_node(pvt, dram_range, | ||
1621 | sys_addr, node, | 1528 | sys_addr, node, |
1622 | chan_sel); | 1529 | chan_sel); |
1623 | if (cs_found >= 0) | 1530 | if (cs_found >= 0) |
@@ -1727,7 +1634,6 @@ static struct amd64_family_type amd64_family_types[] = { | |||
1727 | .ops = { | 1634 | .ops = { |
1728 | .early_channel_count = k8_early_channel_count, | 1635 | .early_channel_count = k8_early_channel_count, |
1729 | .get_error_address = k8_get_error_address, | 1636 | .get_error_address = k8_get_error_address, |
1730 | .read_dram_base_limit = k8_read_dram_base_limit, | ||
1731 | .map_sysaddr_to_csrow = k8_map_sysaddr_to_csrow, | 1637 | .map_sysaddr_to_csrow = k8_map_sysaddr_to_csrow, |
1732 | .dbam_to_cs = k8_dbam_to_chip_select, | 1638 | .dbam_to_cs = k8_dbam_to_chip_select, |
1733 | .read_dct_pci_cfg = k8_read_dct_pci_cfg, | 1639 | .read_dct_pci_cfg = k8_read_dct_pci_cfg, |
@@ -1740,7 +1646,6 @@ static struct amd64_family_type amd64_family_types[] = { | |||
1740 | .ops = { | 1646 | .ops = { |
1741 | .early_channel_count = f10_early_channel_count, | 1647 | .early_channel_count = f10_early_channel_count, |
1742 | .get_error_address = f10_get_error_address, | 1648 | .get_error_address = f10_get_error_address, |
1743 | .read_dram_base_limit = f10_read_dram_base_limit, | ||
1744 | .read_dram_ctl_register = f10_read_dram_ctl_register, | 1649 | .read_dram_ctl_register = f10_read_dram_ctl_register, |
1745 | .map_sysaddr_to_csrow = f10_map_sysaddr_to_csrow, | 1650 | .map_sysaddr_to_csrow = f10_map_sysaddr_to_csrow, |
1746 | .dbam_to_cs = f10_dbam_to_chip_select, | 1651 | .dbam_to_cs = f10_dbam_to_chip_select, |
@@ -2099,7 +2004,7 @@ static void read_mc_regs(struct amd64_pvt *pvt) | |||
2099 | { | 2004 | { |
2100 | u64 msr_val; | 2005 | u64 msr_val; |
2101 | u32 tmp; | 2006 | u32 tmp; |
2102 | int dram; | 2007 | int range; |
2103 | 2008 | ||
2104 | /* | 2009 | /* |
2105 | * Retrieve TOP_MEM and TOP_MEM2; no masking off of reserved bits since | 2010 | * Retrieve TOP_MEM and TOP_MEM2; no masking off of reserved bits since |
@@ -2121,34 +2026,27 @@ static void read_mc_regs(struct amd64_pvt *pvt) | |||
2121 | if (pvt->ops->read_dram_ctl_register) | 2026 | if (pvt->ops->read_dram_ctl_register) |
2122 | pvt->ops->read_dram_ctl_register(pvt); | 2027 | pvt->ops->read_dram_ctl_register(pvt); |
2123 | 2028 | ||
2124 | for (dram = 0; dram < DRAM_REG_COUNT; dram++) { | 2029 | for (range = 0; range < DRAM_RANGES; range++) { |
2125 | /* | 2030 | u8 rw; |
2126 | * Call CPU specific READ function to get the DRAM Base and | ||
2127 | * Limit values from the DCT. | ||
2128 | */ | ||
2129 | pvt->ops->read_dram_base_limit(pvt, dram); | ||
2130 | 2031 | ||
2131 | /* | 2032 | /* read settings for this DRAM range */ |
2132 | * Only print out debug info on rows with both R and W Enabled. | 2033 | read_dram_base_limit_regs(pvt, range); |
2133 | * Normal processing, compiler should optimize this whole 'if' | 2034 | |
2134 | * debug output block away. | 2035 | rw = dram_rw(pvt, range); |
2135 | */ | 2036 | if (!rw) |
2136 | if (pvt->dram_rw_en[dram] != 0) { | 2037 | continue; |
2137 | debugf1(" DRAM-BASE[%d]: 0x%016llx " | 2038 | |
2138 | "DRAM-LIMIT: 0x%016llx\n", | 2039 | debugf1(" DRAM range[%d], base: 0x%016llx; limit: 0x%016llx\n", |
2139 | dram, | 2040 | range, |
2140 | pvt->dram_base[dram], | 2041 | get_dram_base(pvt, range), |
2141 | pvt->dram_limit[dram]); | 2042 | get_dram_limit(pvt, range)); |
2142 | 2043 | ||
2143 | debugf1(" IntlvEn=%s %s %s " | 2044 | debugf1(" IntlvEn=%s; Range access: %s%s IntlvSel=%d DstNode=%d\n", |
2144 | "IntlvSel=%d DstNode=%d\n", | 2045 | dram_intlv_en(pvt, range) ? "Enabled" : "Disabled", |
2145 | pvt->dram_IntlvEn[dram] ? | 2046 | (rw & 0x1) ? "R" : "-", |
2146 | "Enabled" : "Disabled", | 2047 | (rw & 0x2) ? "W" : "-", |
2147 | (pvt->dram_rw_en[dram] & 0x2) ? "W" : "!W", | 2048 | dram_intlv_sel(pvt, range), |
2148 | (pvt->dram_rw_en[dram] & 0x1) ? "R" : "!R", | 2049 | dram_dst_node(pvt, range)); |
2149 | pvt->dram_IntlvSel[dram], | ||
2150 | pvt->dram_DstNode[dram]); | ||
2151 | } | ||
2152 | } | 2050 | } |
2153 | 2051 | ||
2154 | read_dct_base_mask(pvt); | 2052 | read_dct_base_mask(pvt); |
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index 91c266b9f6cf..93af3575e427 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h | |||
@@ -153,8 +153,8 @@ | |||
153 | #define K8_REV_F 4 | 153 | #define K8_REV_F 4 |
154 | 154 | ||
155 | /* Hardware limit on ChipSelect rows per MC and processors per system */ | 155 | /* Hardware limit on ChipSelect rows per MC and processors per system */ |
156 | #define MAX_CS_COUNT 8 | 156 | #define NUM_CHIPSELECTS 8 |
157 | #define DRAM_REG_COUNT 8 | 157 | #define DRAM_RANGES 8 |
158 | 158 | ||
159 | #define ON true | 159 | #define ON true |
160 | #define OFF false | 160 | #define OFF false |
@@ -167,8 +167,14 @@ | |||
167 | /* | 167 | /* |
168 | * Function 1 - Address Map | 168 | * Function 1 - Address Map |
169 | */ | 169 | */ |
170 | #define K8_DRAM_BASE_LOW 0x40 | 170 | #define DRAM_BASE_LO 0x40 |
171 | #define K8_DRAM_LIMIT_LOW 0x44 | 171 | #define DRAM_LIMIT_LO 0x44 |
172 | |||
173 | #define dram_intlv_en(pvt, i) ((pvt->ranges[i].base.lo >> 8) & 0x7) | ||
174 | #define dram_rw(pvt, i) (pvt->ranges[i].base.lo & 0x3) | ||
175 | #define dram_intlv_sel(pvt, i) ((pvt->ranges[i].lim.lo >> 8) & 0x7) | ||
176 | #define dram_dst_node(pvt, i) (pvt->ranges[i].lim.lo & 0x7) | ||
177 | |||
172 | #define K8_DHAR 0xf0 | 178 | #define K8_DHAR 0xf0 |
173 | 179 | ||
174 | #define DHAR_VALID BIT(0) | 180 | #define DHAR_VALID BIT(0) |
@@ -186,9 +192,8 @@ | |||
186 | 192 | ||
187 | #define DCT_CFG_SEL 0x10C | 193 | #define DCT_CFG_SEL 0x10C |
188 | 194 | ||
189 | /* F10 High BASE/LIMIT registers */ | 195 | #define DRAM_BASE_HI 0x140 |
190 | #define F10_DRAM_BASE_HIGH 0x140 | 196 | #define DRAM_LIMIT_HI 0x144 |
191 | #define F10_DRAM_LIMIT_HIGH 0x144 | ||
192 | 197 | ||
193 | 198 | ||
194 | /* | 199 | /* |
@@ -395,6 +400,19 @@ struct error_injection { | |||
395 | u32 bit_map; | 400 | u32 bit_map; |
396 | }; | 401 | }; |
397 | 402 | ||
403 | /* low and high part of PCI config space regs */ | ||
404 | struct reg_pair { | ||
405 | u32 lo, hi; | ||
406 | }; | ||
407 | |||
408 | /* | ||
409 | * See F1x[1, 0][7C:40] DRAM Base/Limit Registers | ||
410 | */ | ||
411 | struct dram_range { | ||
412 | struct reg_pair base; | ||
413 | struct reg_pair lim; | ||
414 | }; | ||
415 | |||
398 | struct amd64_pvt { | 416 | struct amd64_pvt { |
399 | struct low_ops *ops; | 417 | struct low_ops *ops; |
400 | 418 | ||
@@ -418,23 +436,15 @@ struct amd64_pvt { | |||
418 | u32 dbam1; /* DRAM Base Address Mapping reg for DCT1 */ | 436 | u32 dbam1; /* DRAM Base Address Mapping reg for DCT1 */ |
419 | 437 | ||
420 | /* DRAM CS Base Address Registers F2x[1,0][5C:40] */ | 438 | /* DRAM CS Base Address Registers F2x[1,0][5C:40] */ |
421 | u32 dcsb0[MAX_CS_COUNT]; | 439 | u32 dcsb0[NUM_CHIPSELECTS]; |
422 | u32 dcsb1[MAX_CS_COUNT]; | 440 | u32 dcsb1[NUM_CHIPSELECTS]; |
423 | 441 | ||
424 | /* DRAM CS Mask Registers F2x[1,0][6C:60] */ | 442 | /* DRAM CS Mask Registers F2x[1,0][6C:60] */ |
425 | u32 dcsm0[MAX_CS_COUNT]; | 443 | u32 dcsm0[NUM_CHIPSELECTS]; |
426 | u32 dcsm1[MAX_CS_COUNT]; | 444 | u32 dcsm1[NUM_CHIPSELECTS]; |
427 | 445 | ||
428 | /* | 446 | /* DRAM base and limit pairs F1x[78,70,68,60,58,50,48,40] */ |
429 | * Decoded parts of DRAM BASE and LIMIT Registers | 447 | struct dram_range ranges[DRAM_RANGES]; |
430 | * F1x[78,70,68,60,58,50,48,40] | ||
431 | */ | ||
432 | u64 dram_base[DRAM_REG_COUNT]; | ||
433 | u64 dram_limit[DRAM_REG_COUNT]; | ||
434 | u8 dram_IntlvSel[DRAM_REG_COUNT]; | ||
435 | u8 dram_IntlvEn[DRAM_REG_COUNT]; | ||
436 | u8 dram_DstNode[DRAM_REG_COUNT]; | ||
437 | u8 dram_rw_en[DRAM_REG_COUNT]; | ||
438 | 448 | ||
439 | /* | 449 | /* |
440 | * The following fields are set at (load) run time, after CPU revision | 450 | * The following fields are set at (load) run time, after CPU revision |
@@ -472,6 +482,26 @@ struct amd64_pvt { | |||
472 | 482 | ||
473 | }; | 483 | }; |
474 | 484 | ||
485 | static inline u64 get_dram_base(struct amd64_pvt *pvt, unsigned i) | ||
486 | { | ||
487 | u64 addr = ((u64)pvt->ranges[i].base.lo & 0xffff0000) << 8; | ||
488 | |||
489 | if (boot_cpu_data.x86 == 0xf) | ||
490 | return addr; | ||
491 | |||
492 | return (((u64)pvt->ranges[i].base.hi & 0x000000ff) << 40) | addr; | ||
493 | } | ||
494 | |||
495 | static inline u64 get_dram_limit(struct amd64_pvt *pvt, unsigned i) | ||
496 | { | ||
497 | u64 lim = (((u64)pvt->ranges[i].lim.lo & 0xffff0000) << 8) | 0x00ffffff; | ||
498 | |||
499 | if (boot_cpu_data.x86 == 0xf) | ||
500 | return lim; | ||
501 | |||
502 | return (((u64)pvt->ranges[i].lim.hi & 0x000000ff) << 40) | lim; | ||
503 | } | ||
504 | |||
475 | /* | 505 | /* |
476 | * per-node ECC settings descriptor | 506 | * per-node ECC settings descriptor |
477 | */ | 507 | */ |
@@ -517,7 +547,6 @@ struct low_ops { | |||
517 | 547 | ||
518 | u64 (*get_error_address) (struct mem_ctl_info *mci, | 548 | u64 (*get_error_address) (struct mem_ctl_info *mci, |
519 | struct err_regs *info); | 549 | struct err_regs *info); |
520 | void (*read_dram_base_limit) (struct amd64_pvt *pvt, int dram); | ||
521 | void (*read_dram_ctl_register) (struct amd64_pvt *pvt); | 550 | void (*read_dram_ctl_register) (struct amd64_pvt *pvt); |
522 | void (*map_sysaddr_to_csrow) (struct mem_ctl_info *mci, | 551 | void (*map_sysaddr_to_csrow) (struct mem_ctl_info *mci, |
523 | struct err_regs *info, u64 SystemAddr); | 552 | struct err_regs *info, u64 SystemAddr); |