diff options
Diffstat (limited to 'drivers/edac')
-rw-r--r-- | drivers/edac/amd64_edac.c | 83 | ||||
-rw-r--r-- | drivers/edac/amd64_edac.h | 15 |
2 files changed, 50 insertions, 48 deletions
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index d9e951ce7167..32e323198f7c 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c | |||
@@ -460,13 +460,12 @@ int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base, | |||
460 | } | 460 | } |
461 | 461 | ||
462 | /* valid for Fam10h and above */ | 462 | /* valid for Fam10h and above */ |
463 | if (boot_cpu_data.x86 >= 0x10 && | 463 | if (boot_cpu_data.x86 >= 0x10 && !dhar_mem_hoist_valid(pvt)) { |
464 | (pvt->dhar & DRAM_MEM_HOIST_VALID) == 0) { | ||
465 | debugf1(" Dram Memory Hoisting is DISABLED on this system\n"); | 464 | debugf1(" Dram Memory Hoisting is DISABLED on this system\n"); |
466 | return 1; | 465 | return 1; |
467 | } | 466 | } |
468 | 467 | ||
469 | if ((pvt->dhar & DHAR_VALID) == 0) { | 468 | if (!dhar_valid(pvt)) { |
470 | debugf1(" Dram Memory Hoisting is DISABLED on this node %d\n", | 469 | debugf1(" Dram Memory Hoisting is DISABLED on this node %d\n", |
471 | pvt->mc_node_id); | 470 | pvt->mc_node_id); |
472 | return 1; | 471 | return 1; |
@@ -859,8 +858,7 @@ static void dump_misc_regs(struct amd64_pvt *pvt) | |||
859 | (boot_cpu_data.x86 == 0xf) ? k8_dhar_offset(pvt) | 858 | (boot_cpu_data.x86 == 0xf) ? k8_dhar_offset(pvt) |
860 | : f10_dhar_offset(pvt)); | 859 | : f10_dhar_offset(pvt)); |
861 | 860 | ||
862 | debugf1(" DramHoleValid: %s\n", | 861 | debugf1(" DramHoleValid: %s\n", dhar_valid(pvt) ? "yes" : "no"); |
863 | (pvt->dhar & DHAR_VALID) ? "yes" : "no"); | ||
864 | 862 | ||
865 | amd64_debug_display_dimm_sizes(0, pvt); | 863 | amd64_debug_display_dimm_sizes(0, pvt); |
866 | 864 | ||
@@ -1238,30 +1236,53 @@ static u8 f10_determine_channel(struct amd64_pvt *pvt, u64 sys_addr, | |||
1238 | return 0; | 1236 | return 0; |
1239 | } | 1237 | } |
1240 | 1238 | ||
1241 | /* See F10h BKDG, 2.8.10.2 DctSelBaseOffset Programming */ | 1239 | /* Convert the sys_addr to the normalized DCT address */ |
1242 | static inline u64 f10_get_base_addr_offset(u64 sys_addr, bool hi_range_sel, | 1240 | static u64 f10_get_norm_dct_addr(struct amd64_pvt *pvt, int range, |
1243 | u32 dct_sel_base_addr, | 1241 | u64 sys_addr, bool hi_rng, |
1244 | u64 dct_sel_base_off, | 1242 | u32 dct_sel_base_addr) |
1245 | u32 hole_valid, u64 hole_off, | ||
1246 | u64 dram_base) | ||
1247 | { | 1243 | { |
1248 | u64 chan_off; | 1244 | u64 chan_off; |
1245 | u64 dram_base = get_dram_base(pvt, range); | ||
1246 | u64 hole_off = f10_dhar_offset(pvt); | ||
1247 | u32 hole_valid = dhar_valid(pvt); | ||
1248 | u64 dct_sel_base_off = (pvt->dct_sel_hi & 0xFFFFFC00) << 16; | ||
1249 | 1249 | ||
1250 | if (hi_range_sel) { | 1250 | if (hi_rng) { |
1251 | if (!(dct_sel_base_addr & 0xFFFF0000) && | 1251 | /* |
1252 | hole_valid && (sys_addr >= 0x100000000ULL)) | 1252 | * if |
1253 | * base address of high range is below 4Gb | ||
1254 | * (bits [47:27] at [31:11]) | ||
1255 | * DRAM address space on this DCT is hoisted above 4Gb && | ||
1256 | * sys_addr > 4Gb | ||
1257 | * | ||
1258 | * remove hole offset from sys_addr | ||
1259 | * else | ||
1260 | * remove high range offset from sys_addr | ||
1261 | */ | ||
1262 | if ((!(dct_sel_base_addr >> 16) || | ||
1263 | dct_sel_base_addr < dhar_base(pvt)) && | ||
1264 | hole_valid && | ||
1265 | (sys_addr >= BIT_64(32))) | ||
1253 | chan_off = hole_off; | 1266 | chan_off = hole_off; |
1254 | else | 1267 | else |
1255 | chan_off = dct_sel_base_off; | 1268 | chan_off = dct_sel_base_off; |
1256 | } else { | 1269 | } else { |
1257 | if (hole_valid && (sys_addr >= 0x100000000ULL)) | 1270 | /* |
1271 | * if | ||
1272 | * we have a valid hole && | ||
1273 | * sys_addr > 4Gb | ||
1274 | * | ||
1275 | * remove hole | ||
1276 | * else | ||
1277 | * remove dram base to normalize to DCT address | ||
1278 | */ | ||
1279 | if (hole_valid && (sys_addr >= BIT_64(32))) | ||
1258 | chan_off = hole_off; | 1280 | chan_off = hole_off; |
1259 | else | 1281 | else |
1260 | chan_off = dram_base & 0xFFFFF8000000ULL; | 1282 | chan_off = dram_base; |
1261 | } | 1283 | } |
1262 | 1284 | ||
1263 | return (sys_addr & 0x0000FFFFFFFFFFC0ULL) - | 1285 | return (sys_addr & GENMASK(6,47)) - (chan_off & GENMASK(23,47)); |
1264 | (chan_off & 0x0000FFFFFF800000ULL); | ||
1265 | } | 1286 | } |
1266 | 1287 | ||
1267 | /* Hack for the time being - Can we get this from BIOS?? */ | 1288 | /* Hack for the time being - Can we get this from BIOS?? */ |
@@ -1346,30 +1367,17 @@ static int f10_match_to_this_node(struct amd64_pvt *pvt, int range, | |||
1346 | u64 sys_addr, int *nid, int *chan_sel) | 1367 | u64 sys_addr, int *nid, int *chan_sel) |
1347 | { | 1368 | { |
1348 | int cs_found = -EINVAL; | 1369 | int cs_found = -EINVAL; |
1349 | u64 chan_addr, dct_sel_base_off; | 1370 | u64 chan_addr; |
1350 | u64 hole_off; | 1371 | u32 tmp, dct_sel_base; |
1351 | u32 hole_valid, tmp, dct_sel_base; | ||
1352 | u8 channel; | 1372 | u8 channel; |
1353 | bool high_range = false; | 1373 | bool high_range = false; |
1354 | 1374 | ||
1355 | u8 node_id = dram_dst_node(pvt, range); | 1375 | u8 node_id = dram_dst_node(pvt, range); |
1356 | u8 intlv_en = dram_intlv_en(pvt, range); | 1376 | u8 intlv_en = dram_intlv_en(pvt, range); |
1357 | u32 intlv_sel = dram_intlv_sel(pvt, range); | 1377 | u32 intlv_sel = dram_intlv_sel(pvt, range); |
1358 | u64 dram_base = get_dram_base(pvt, range); | ||
1359 | |||
1360 | debugf1("(range %d) Base=0x%llx SystemAddr= 0x%llx Limit=0x%llx\n", | ||
1361 | range, dram_base, sys_addr, get_dram_limit(pvt, range)); | ||
1362 | |||
1363 | /* | ||
1364 | * This assumes that one node's DHAR is the same as all the other | ||
1365 | * nodes' DHAR. | ||
1366 | */ | ||
1367 | hole_off = f10_dhar_offset(pvt); | ||
1368 | hole_valid = (pvt->dhar & DHAR_VALID); | ||
1369 | dct_sel_base_off = (pvt->dct_sel_hi & 0xFFFFFC00) << 16; | ||
1370 | 1378 | ||
1371 | debugf1(" HoleOffset=0x%016llx HoleValid=%d IntlvSel=0x%x\n", | 1379 | debugf1("(range %d) SystemAddr= 0x%llx Limit=0x%llx\n", |
1372 | hole_off, hole_valid, intlv_sel); | 1380 | range, sys_addr, get_dram_limit(pvt, range)); |
1373 | 1381 | ||
1374 | if (intlv_en && | 1382 | if (intlv_en && |
1375 | (intlv_sel != ((sys_addr >> 12) & intlv_en))) | 1383 | (intlv_sel != ((sys_addr >> 12) & intlv_en))) |
@@ -1388,9 +1396,8 @@ static int f10_match_to_this_node(struct amd64_pvt *pvt, int range, | |||
1388 | 1396 | ||
1389 | channel = f10_determine_channel(pvt, sys_addr, high_range, intlv_en); | 1397 | channel = f10_determine_channel(pvt, sys_addr, high_range, intlv_en); |
1390 | 1398 | ||
1391 | chan_addr = f10_get_base_addr_offset(sys_addr, high_range, dct_sel_base, | 1399 | chan_addr = f10_get_norm_dct_addr(pvt, range, sys_addr, |
1392 | dct_sel_base_off, hole_valid, | 1400 | high_range, dct_sel_base); |
1393 | hole_off, dram_base); | ||
1394 | 1401 | ||
1395 | /* remove Node ID (in case of memory interleaving) */ | 1402 | /* remove Node ID (in case of memory interleaving) */ |
1396 | tmp = chan_addr & 0xFC0; | 1403 | tmp = chan_addr & 0xFC0; |
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index 1964f89a28bc..ba1818305943 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h | |||
@@ -184,18 +184,13 @@ | |||
184 | #define dram_dst_node(pvt, i) (pvt->ranges[i].lim.lo & 0x7) | 184 | #define dram_dst_node(pvt, i) (pvt->ranges[i].lim.lo & 0x7) |
185 | 185 | ||
186 | #define DHAR 0xf0 | 186 | #define DHAR 0xf0 |
187 | #define DHAR_VALID BIT(0) | 187 | #define dhar_valid(pvt) ((pvt)->dhar & BIT(0)) |
188 | #define DRAM_MEM_HOIST_VALID BIT(1) | 188 | #define dhar_mem_hoist_valid(pvt) ((pvt)->dhar & BIT(1)) |
189 | #define dhar_base(pvt) ((pvt)->dhar & 0xff000000) | ||
190 | #define k8_dhar_offset(pvt) (((pvt)->dhar & 0x0000ff00) << 16) | ||
189 | 191 | ||
190 | #define DHAR_BASE_MASK 0xff000000 | ||
191 | #define dhar_base(pvt) ((pvt)->dhar & DHAR_BASE_MASK) | ||
192 | |||
193 | #define K8_DHAR_OFFSET_MASK 0x0000ff00 | ||
194 | #define k8_dhar_offset(pvt) (((pvt)->dhar & K8_DHAR_OFFSET_MASK) << 16) | ||
195 | |||
196 | #define F10_DHAR_OFFSET_MASK 0x0000ff80 | ||
197 | /* NOTE: Extra mask bit vs K8 */ | 192 | /* NOTE: Extra mask bit vs K8 */ |
198 | #define f10_dhar_offset(pvt) (((pvt)->dhar & F10_DHAR_OFFSET_MASK) << 16) | 193 | #define f10_dhar_offset(pvt) (((pvt)->dhar & 0x0000ff80) << 16) |
199 | 194 | ||
200 | #define DCT_CFG_SEL 0x10C | 195 | #define DCT_CFG_SEL 0x10C |
201 | 196 | ||