Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

EDAC, amd64: Read MC registers on AMD Fam17h

Fam17h has a different set of registers and bitfields. Most of these
registers are read through SMN (System Management Network) rather
than PCI config space. Also, the derivation of various values is now
different.

Update amd64_edac to read the appropriate registers and extract the
correct values for Fam17h.

Signed-off-by: Yazen Ghannam <Yazen.Ghannam@amd.com>
Cc: Aravind Gopalakrishnan <aravindksg.lkml@gmail.com>
Cc: linux-edac <linux-edac@vger.kernel.org>
Cc: x86-ml <x86@kernel.org>
Link: http://lkml.kernel.org/r/1479423463-8536-12-git-send-email-Yazen.Ghannam@amd.com
[ Save us the indentation level in read_mc_regs(), add defines ]
Signed-off-by: Borislav Petkov <bp@suse.de>

authored by

Yazen Ghannam and committed by
Borislav Petkov
b64ce7cd 936fc3af

+146 -39
+133 -39
drivers/edac/amd64_edac.c
··· 789 789 */ 790 790 static void read_dct_base_mask(struct amd64_pvt *pvt) 791 791 { 792 - int cs; 792 + int base_reg0, base_reg1, mask_reg0, mask_reg1, cs; 793 793 794 794 prep_chip_selects(pvt); 795 795 796 + if (pvt->umc) { 797 + base_reg0 = get_umc_base(0) + UMCCH_BASE_ADDR; 798 + base_reg1 = get_umc_base(1) + UMCCH_BASE_ADDR; 799 + mask_reg0 = get_umc_base(0) + UMCCH_ADDR_MASK; 800 + mask_reg1 = get_umc_base(1) + UMCCH_ADDR_MASK; 801 + } else { 802 + base_reg0 = DCSB0; 803 + base_reg1 = DCSB1; 804 + mask_reg0 = DCSM0; 805 + mask_reg1 = DCSM1; 806 + } 807 + 796 808 for_each_chip_select(cs, 0, pvt) { 797 - int reg0 = DCSB0 + (cs * 4); 798 - int reg1 = DCSB1 + (cs * 4); 809 + int reg0 = base_reg0 + (cs * 4); 810 + int reg1 = base_reg1 + (cs * 4); 799 811 u32 *base0 = &pvt->csels[0].csbases[cs]; 800 812 u32 *base1 = &pvt->csels[1].csbases[cs]; 801 813 802 - if (!amd64_read_dct_pci_cfg(pvt, 0, reg0, base0)) 803 - edac_dbg(0, " DCSB0[%d]=0x%08x reg: F2x%x\n", 804 - cs, *base0, reg0); 814 + if (pvt->umc) { 815 + if (!amd_smn_read(pvt->mc_node_id, reg0, base0)) 816 + edac_dbg(0, " DCSB0[%d]=0x%08x reg: 0x%x\n", 817 + cs, *base0, reg0); 805 818 806 - if (pvt->fam == 0xf) 807 - continue; 819 + if (!amd_smn_read(pvt->mc_node_id, reg1, base1)) 820 + edac_dbg(0, " DCSB1[%d]=0x%08x reg: 0x%x\n", 821 + cs, *base1, reg1); 822 + } else { 823 + if (!amd64_read_dct_pci_cfg(pvt, 0, reg0, base0)) 824 + edac_dbg(0, " DCSB0[%d]=0x%08x reg: F2x%x\n", 825 + cs, *base0, reg0); 808 826 809 - if (!amd64_read_dct_pci_cfg(pvt, 1, reg0, base1)) 810 - edac_dbg(0, " DCSB1[%d]=0x%08x reg: F2x%x\n", 811 - cs, *base1, (pvt->fam == 0x10) ? reg1 827 + if (pvt->fam == 0xf) 828 + continue; 829 + 830 + if (!amd64_read_dct_pci_cfg(pvt, 1, reg0, base1)) 831 + edac_dbg(0, " DCSB1[%d]=0x%08x reg: F2x%x\n", 832 + cs, *base1, (pvt->fam == 0x10) ? reg1 812 833 : reg0); 834 + } 813 835 } 814 836 815 837 for_each_chip_select_mask(cs, 0, pvt) { 816 - int reg0 = DCSM0 + (cs * 4); 817 - int reg1 = DCSM1 + (cs * 4); 838 + int reg0 = mask_reg0 + (cs * 4); 839 + int reg1 = mask_reg1 + (cs * 4); 818 840 u32 *mask0 = &pvt->csels[0].csmasks[cs]; 819 841 u32 *mask1 = &pvt->csels[1].csmasks[cs]; 820 842 821 - if (!amd64_read_dct_pci_cfg(pvt, 0, reg0, mask0)) 822 - edac_dbg(0, " DCSM0[%d]=0x%08x reg: F2x%x\n", 823 - cs, *mask0, reg0); 843 + if (pvt->umc) { 844 + if (!amd_smn_read(pvt->mc_node_id, reg0, mask0)) 845 + edac_dbg(0, " DCSM0[%d]=0x%08x reg: 0x%x\n", 846 + cs, *mask0, reg0); 824 847 825 - if (pvt->fam == 0xf) 826 - continue; 848 + if (!amd_smn_read(pvt->mc_node_id, reg1, mask1)) 849 + edac_dbg(0, " DCSM1[%d]=0x%08x reg: 0x%x\n", 850 + cs, *mask1, reg1); 851 + } else { 852 + if (!amd64_read_dct_pci_cfg(pvt, 0, reg0, mask0)) 853 + edac_dbg(0, " DCSM0[%d]=0x%08x reg: F2x%x\n", 854 + cs, *mask0, reg0); 827 855 828 - if (!amd64_read_dct_pci_cfg(pvt, 1, reg0, mask1)) 829 - edac_dbg(0, " DCSM1[%d]=0x%08x reg: F2x%x\n", 830 - cs, *mask1, (pvt->fam == 0x10) ? reg1 856 + if (pvt->fam == 0xf) 857 + continue; 858 + 859 + if (!amd64_read_dct_pci_cfg(pvt, 1, reg0, mask1)) 860 + edac_dbg(0, " DCSM1[%d]=0x%08x reg: F2x%x\n", 861 + cs, *mask1, (pvt->fam == 0x10) ? reg1 831 862 : reg0); 863 + } 832 864 } 833 865 } 834 866 ··· 912 880 913 881 case 0x16: 914 882 goto ddr3; 883 + 884 + case 0x17: 885 + if ((pvt->umc[0].dimm_cfg | pvt->umc[1].dimm_cfg) & BIT(5)) 886 + pvt->dram_type = MEM_LRDDR4; 887 + else if ((pvt->umc[0].dimm_cfg | pvt->umc[1].dimm_cfg) & BIT(4)) 888 + pvt->dram_type = MEM_RDDR4; 889 + else 890 + pvt->dram_type = MEM_DDR4; 891 + return; 915 892 916 893 default: 917 894 WARN(1, KERN_ERR "%s: Family??? 0x%x\n", __func__, pvt->fam); ··· 2382 2341 } 2383 2342 } 2384 2343 2344 + static void determine_ecc_sym_sz(struct amd64_pvt *pvt) 2345 + { 2346 + pvt->ecc_sym_sz = 4; 2347 + 2348 + if (pvt->umc) { 2349 + u8 i; 2350 + 2351 + for (i = 0; i < NUM_UMCS; i++) { 2352 + /* Check enabled channels only: */ 2353 + if ((pvt->umc[i].sdp_ctrl & UMC_SDP_INIT) && 2354 + (pvt->umc[i].ecc_ctrl & BIT(7))) { 2355 + pvt->ecc_sym_sz = 8; 2356 + break; 2357 + } 2358 + } 2359 + 2360 + return; 2361 + } 2362 + 2363 + if (pvt->fam >= 0x10) { 2364 + u32 tmp; 2365 + 2366 + amd64_read_pci_cfg(pvt->F3, EXT_NB_MCA_CFG, &tmp); 2367 + /* F16h has only DCT0, so no need to read dbam1. */ 2368 + if (pvt->fam != 0x16) 2369 + amd64_read_dct_pci_cfg(pvt, 1, DBAM0, &pvt->dbam1); 2370 + 2371 + /* F10h, revD and later can do x8 ECC too. */ 2372 + if ((pvt->fam > 0x10 || pvt->model > 7) && tmp & BIT(25)) 2373 + pvt->ecc_sym_sz = 8; 2374 + } 2375 + } 2376 + 2377 + /* 2378 + * Retrieve the hardware registers of the memory controller. 2379 + */ 2380 + static void __read_mc_regs_df(struct amd64_pvt *pvt) 2381 + { 2382 + u8 nid = pvt->mc_node_id; 2383 + struct amd64_umc *umc; 2384 + u32 i, umc_base; 2385 + 2386 + /* Read registers from each UMC */ 2387 + for (i = 0; i < NUM_UMCS; i++) { 2388 + 2389 + umc_base = get_umc_base(i); 2390 + umc = &pvt->umc[i]; 2391 + 2392 + amd_smn_read(nid, umc_base + UMCCH_SDP_CTRL, &umc->sdp_ctrl); 2393 + amd_smn_read(nid, umc_base + UMCCH_ECC_CTRL, &umc->ecc_ctrl); 2394 + amd_smn_read(nid, umc_base + UMCCH_DIMM_CFG, &umc->dimm_cfg); 2395 + } 2396 + } 2397 + 2385 2398 /* 2386 2399 * Retrieve the hardware registers of the memory controller (this includes the 2387 2400 * 'Address Map' and 'Misc' device regs) 2388 2401 */ 2389 2402 static void read_mc_regs(struct amd64_pvt *pvt) 2390 2403 { 2391 - unsigned range; 2404 + unsigned int range; 2392 2405 u64 msr_val; 2393 - u32 tmp; 2394 2406 2395 2407 /* 2396 2408 * Retrieve TOP_MEM and TOP_MEM2; no masking off of reserved bits since 2397 - * those are Read-As-Zero 2409 + * those are Read-As-Zero. 2398 2410 */ 2399 2411 rdmsrl(MSR_K8_TOP_MEM1, pvt->top_mem); 2400 2412 edac_dbg(0, " TOP_MEM: 0x%016llx\n", pvt->top_mem); 2401 2413 2402 - /* check first whether TOP_MEM2 is enabled */ 2414 + /* Check first whether TOP_MEM2 is enabled: */ 2403 2415 rdmsrl(MSR_K8_SYSCFG, msr_val); 2404 - if (msr_val & (1U << 21)) { 2416 + if (msr_val & BIT(21)) { 2405 2417 rdmsrl(MSR_K8_TOP_MEM2, pvt->top_mem2); 2406 2418 edac_dbg(0, " TOP_MEM2: 0x%016llx\n", pvt->top_mem2); 2407 - } else 2419 + } else { 2408 2420 edac_dbg(0, " TOP_MEM2 disabled\n"); 2421 + } 2422 + 2423 + if (pvt->umc) { 2424 + __read_mc_regs_df(pvt); 2425 + amd64_read_pci_cfg(pvt->F0, DF_DHAR, &pvt->dhar); 2426 + 2427 + goto skip; 2428 + } 2409 2429 2410 2430 amd64_read_pci_cfg(pvt->F3, NBCAP, &pvt->nbcap); 2411 2431 ··· 2495 2393 dram_dst_node(pvt, range)); 2496 2394 } 2497 2395 2498 - read_dct_base_mask(pvt); 2499 - 2500 2396 amd64_read_pci_cfg(pvt->F1, DHAR, &pvt->dhar); 2501 2397 amd64_read_dct_pci_cfg(pvt, 0, DBAM0, &pvt->dbam0); 2502 2398 ··· 2508 2408 amd64_read_dct_pci_cfg(pvt, 1, DCHR0, &pvt->dchr1); 2509 2409 } 2510 2410 2511 - pvt->ecc_sym_sz = 4; 2411 + skip: 2412 + read_dct_base_mask(pvt); 2413 + 2512 2414 determine_memory_type(pvt); 2513 2415 edac_dbg(1, " DIMM type: %s\n", edac_mem_types[pvt->dram_type]); 2514 2416 2515 - if (pvt->fam >= 0x10) { 2516 - amd64_read_pci_cfg(pvt->F3, EXT_NB_MCA_CFG, &tmp); 2517 - /* F16h has only DCT0, so no need to read dbam1 */ 2518 - if (pvt->fam != 0x16) 2519 - amd64_read_dct_pci_cfg(pvt, 1, DBAM0, &pvt->dbam1); 2417 + determine_ecc_sym_sz(pvt); 2520 2418 2521 - /* F10h, revD and later can do x8 ECC too */ 2522 - if ((pvt->fam > 0x10 || pvt->model > 7) && tmp & BIT(25)) 2523 - pvt->ecc_sym_sz = 8; 2524 - } 2525 2419 dump_misc_regs(pvt); 2526 2420 } 2527 2421
+13
drivers/edac/amd64_edac.h
··· 250 250 /* MSRs */ 251 251 #define MSR_MCGCTL_NBE BIT(4) 252 252 253 + /* F17h */ 254 + 255 + /* F0: */ 256 + #define DF_DHAR 0x104 257 + 253 258 /* UMC CH register offsets */ 259 + #define UMCCH_BASE_ADDR 0x0 260 + #define UMCCH_ADDR_MASK 0x20 261 + #define UMCCH_DIMM_CFG 0x80 254 262 #define UMCCH_SDP_CTRL 0x104 263 + #define UMCCH_ECC_CTRL 0x14C 255 264 #define UMCCH_UMC_CAP_HI 0xDF4 256 265 257 266 /* UMC CH bitfields */ 267 + #define UMC_ECC_CHIPKILL_CAP BIT(31) 258 268 #define UMC_ECC_ENABLED BIT(30) 269 + 259 270 #define UMC_SDP_INIT BIT(31) 260 271 261 272 #define NUM_UMCS 2 ··· 313 302 }; 314 303 315 304 struct amd64_umc { 305 + u32 dimm_cfg; /* DIMM Configuration reg */ 316 306 u32 sdp_ctrl; /* SDP Control reg */ 307 + u32 ecc_ctrl; /* DRAM ECC Control reg */ 317 308 }; 318 309 319 310 struct amd64_pvt {