diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-07 17:53:42 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-01-07 17:53:42 -0500 |
| commit | 442d1ba237c81304ccfa33887094e843183645f7 (patch) | |
| tree | 55d516e121f3bc558e808d05ae6407f845456db3 | |
| parent | fb5131e1880ea1ba3ba7197cd5cc66c9c288f715 (diff) | |
| parent | a135cef79a2927ecff800492a26cd314e9cba996 (diff) | |
Merge branch 'edac-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp
* 'edac-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp:
amd64_edac: Disable DRAM ECC injection on K8
EDAC: Fixup scrubrate manipulation
amd64_edac: Remove two-stage initialization
amd64_edac: Check ECC capabilities initially
amd64_edac: Carve out ECC-related hw settings
amd64_edac: Remove PCI ECS enabling functions
amd64_edac: Remove explicit Kconfig PCI dependency
amd64_edac: Allocate driver instances dynamically
amd64_edac: Rework printk macros
amd64_edac: Rename CPU PCI devices
amd64_edac: Concentrate per-family init even more
amd64_edac: Cleanup the CPU PCI device reservation
amd64_edac: Simplify CPU family detection
amd64_edac: Add per-family init function
amd64_edac: Use cached extended CPU model
amd64_edac: Remove F11h support
| -rw-r--r-- | drivers/edac/Kconfig | 8 | ||||
| -rw-r--r-- | drivers/edac/amd64_edac.c | 823 | ||||
| -rw-r--r-- | drivers/edac/amd64_edac.h | 86 | ||||
| -rw-r--r-- | drivers/edac/amd64_edac_inj.c | 25 | ||||
| -rw-r--r-- | drivers/edac/cpc925_edac.c | 9 | ||||
| -rw-r--r-- | drivers/edac/e752x_edac.c | 8 | ||||
| -rw-r--r-- | drivers/edac/edac_core.h | 5 | ||||
| -rw-r--r-- | drivers/edac/edac_mc.c | 4 | ||||
| -rw-r--r-- | drivers/edac/edac_mc_sysfs.c | 57 | ||||
| -rw-r--r-- | drivers/edac/i5100_edac.c | 9 |
10 files changed, 436 insertions, 598 deletions
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index f436a2fa9f38..fe70a341bd8b 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig | |||
| @@ -75,11 +75,11 @@ config EDAC_MCE | |||
| 75 | bool | 75 | bool |
| 76 | 76 | ||
| 77 | config EDAC_AMD64 | 77 | config EDAC_AMD64 |
| 78 | tristate "AMD64 (Opteron, Athlon64) K8, F10h, F11h" | 78 | tristate "AMD64 (Opteron, Athlon64) K8, F10h" |
| 79 | depends on EDAC_MM_EDAC && AMD_NB && X86_64 && PCI && EDAC_DECODE_MCE | 79 | depends on EDAC_MM_EDAC && AMD_NB && X86_64 && EDAC_DECODE_MCE |
| 80 | help | 80 | help |
| 81 | Support for error detection and correction on the AMD 64 | 81 | Support for error detection and correction of DRAM ECC errors on |
| 82 | Families of Memory Controllers (K8, F10h and F11h) | 82 | the AMD64 families of memory controllers (K8 and F10h) |
| 83 | 83 | ||
| 84 | config EDAC_AMD64_ERROR_INJECTION | 84 | config EDAC_AMD64_ERROR_INJECTION |
| 85 | bool "Sysfs HW Error injection facilities" | 85 | bool "Sysfs HW Error injection facilities" |
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index df211181fca4..6bf7e248e758 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c | |||
| @@ -15,10 +15,14 @@ module_param(ecc_enable_override, int, 0644); | |||
| 15 | 15 | ||
| 16 | static struct msr __percpu *msrs; | 16 | static struct msr __percpu *msrs; |
| 17 | 17 | ||
| 18 | /* Lookup table for all possible MC control instances */ | 18 | /* |
| 19 | struct amd64_pvt; | 19 | * count successfully initialized driver instances for setup_pci_device() |
| 20 | static struct mem_ctl_info *mci_lookup[EDAC_MAX_NUMNODES]; | 20 | */ |
| 21 | static struct amd64_pvt *pvt_lookup[EDAC_MAX_NUMNODES]; | 21 | static atomic_t drv_instances = ATOMIC_INIT(0); |
| 22 | |||
| 23 | /* Per-node driver instances */ | ||
| 24 | static struct mem_ctl_info **mcis; | ||
| 25 | static struct ecc_settings **ecc_stngs; | ||
| 22 | 26 | ||
| 23 | /* | 27 | /* |
| 24 | * Address to DRAM bank mapping: see F2x80 for K8 and F2x[1,0]80 for Fam10 and | 28 | * Address to DRAM bank mapping: see F2x80 for K8 and F2x[1,0]80 for Fam10 and |
| @@ -62,7 +66,7 @@ static int ddr3_dbam[] = { [0] = -1, | |||
| 62 | [5 ... 6] = 1024, | 66 | [5 ... 6] = 1024, |
| 63 | [7 ... 8] = 2048, | 67 | [7 ... 8] = 2048, |
| 64 | [9 ... 10] = 4096, | 68 | [9 ... 10] = 4096, |
| 65 | [11] = 8192, | 69 | [11] = 8192, |
| 66 | }; | 70 | }; |
| 67 | 71 | ||
| 68 | /* | 72 | /* |
| @@ -73,7 +77,11 @@ static int ddr3_dbam[] = { [0] = -1, | |||
| 73 | *FIXME: Produce a better mapping/linearisation. | 77 | *FIXME: Produce a better mapping/linearisation. |
| 74 | */ | 78 | */ |
| 75 | 79 | ||
| 76 | struct scrubrate scrubrates[] = { | 80 | |
| 81 | struct scrubrate { | ||
| 82 | u32 scrubval; /* bit pattern for scrub rate */ | ||
| 83 | u32 bandwidth; /* bandwidth consumed (bytes/sec) */ | ||
| 84 | } scrubrates[] = { | ||
| 77 | { 0x01, 1600000000UL}, | 85 | { 0x01, 1600000000UL}, |
| 78 | { 0x02, 800000000UL}, | 86 | { 0x02, 800000000UL}, |
| 79 | { 0x03, 400000000UL}, | 87 | { 0x03, 400000000UL}, |
| @@ -117,8 +125,7 @@ struct scrubrate scrubrates[] = { | |||
| 117 | * scan the scrub rate mapping table for a close or matching bandwidth value to | 125 | * scan the scrub rate mapping table for a close or matching bandwidth value to |
| 118 | * issue. If requested is too big, then use last maximum value found. | 126 | * issue. If requested is too big, then use last maximum value found. |
| 119 | */ | 127 | */ |
| 120 | static int amd64_search_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, | 128 | static int __amd64_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, u32 min_rate) |
| 121 | u32 min_scrubrate) | ||
| 122 | { | 129 | { |
| 123 | u32 scrubval; | 130 | u32 scrubval; |
| 124 | int i; | 131 | int i; |
| @@ -134,7 +141,7 @@ static int amd64_search_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, | |||
| 134 | * skip scrub rates which aren't recommended | 141 | * skip scrub rates which aren't recommended |
| 135 | * (see F10 BKDG, F3x58) | 142 | * (see F10 BKDG, F3x58) |
| 136 | */ | 143 | */ |
| 137 | if (scrubrates[i].scrubval < min_scrubrate) | 144 | if (scrubrates[i].scrubval < min_rate) |
| 138 | continue; | 145 | continue; |
| 139 | 146 | ||
| 140 | if (scrubrates[i].bandwidth <= new_bw) | 147 | if (scrubrates[i].bandwidth <= new_bw) |
| @@ -148,64 +155,41 @@ static int amd64_search_set_scrub_rate(struct pci_dev *ctl, u32 new_bw, | |||
| 148 | } | 155 | } |
| 149 | 156 | ||
| 150 | scrubval = scrubrates[i].scrubval; | 157 | scrubval = scrubrates[i].scrubval; |
| 151 | if (scrubval) | ||
| 152 | edac_printk(KERN_DEBUG, EDAC_MC, | ||
| 153 | "Setting scrub rate bandwidth: %u\n", | ||
| 154 | scrubrates[i].bandwidth); | ||
| 155 | else | ||
| 156 | edac_printk(KERN_DEBUG, EDAC_MC, "Turning scrubbing off.\n"); | ||
| 157 | 158 | ||
| 158 | pci_write_bits32(ctl, K8_SCRCTRL, scrubval, 0x001F); | 159 | pci_write_bits32(ctl, K8_SCRCTRL, scrubval, 0x001F); |
| 159 | 160 | ||
| 161 | if (scrubval) | ||
| 162 | return scrubrates[i].bandwidth; | ||
| 163 | |||
| 160 | return 0; | 164 | return 0; |
| 161 | } | 165 | } |
| 162 | 166 | ||
| 163 | static int amd64_set_scrub_rate(struct mem_ctl_info *mci, u32 bandwidth) | 167 | static int amd64_set_scrub_rate(struct mem_ctl_info *mci, u32 bw) |
| 164 | { | 168 | { |
| 165 | struct amd64_pvt *pvt = mci->pvt_info; | 169 | struct amd64_pvt *pvt = mci->pvt_info; |
| 166 | u32 min_scrubrate = 0x0; | ||
| 167 | |||
| 168 | switch (boot_cpu_data.x86) { | ||
| 169 | case 0xf: | ||
| 170 | min_scrubrate = K8_MIN_SCRUB_RATE_BITS; | ||
| 171 | break; | ||
| 172 | case 0x10: | ||
| 173 | min_scrubrate = F10_MIN_SCRUB_RATE_BITS; | ||
| 174 | break; | ||
| 175 | case 0x11: | ||
| 176 | min_scrubrate = F11_MIN_SCRUB_RATE_BITS; | ||
| 177 | break; | ||
| 178 | 170 | ||
| 179 | default: | 171 | return __amd64_set_scrub_rate(pvt->F3, bw, pvt->min_scrubrate); |
| 180 | amd64_printk(KERN_ERR, "Unsupported family!\n"); | ||
| 181 | return -EINVAL; | ||
| 182 | } | ||
| 183 | return amd64_search_set_scrub_rate(pvt->misc_f3_ctl, bandwidth, | ||
| 184 | min_scrubrate); | ||
| 185 | } | 172 | } |
| 186 | 173 | ||
| 187 | static int amd64_get_scrub_rate(struct mem_ctl_info *mci, u32 *bw) | 174 | static int amd64_get_scrub_rate(struct mem_ctl_info *mci) |
| 188 | { | 175 | { |
| 189 | struct amd64_pvt *pvt = mci->pvt_info; | 176 | struct amd64_pvt *pvt = mci->pvt_info; |
| 190 | u32 scrubval = 0; | 177 | u32 scrubval = 0; |
| 191 | int status = -1, i; | 178 | int i, retval = -EINVAL; |
| 192 | 179 | ||
| 193 | amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_SCRCTRL, &scrubval); | 180 | amd64_read_pci_cfg(pvt->F3, K8_SCRCTRL, &scrubval); |
| 194 | 181 | ||
| 195 | scrubval = scrubval & 0x001F; | 182 | scrubval = scrubval & 0x001F; |
| 196 | 183 | ||
| 197 | edac_printk(KERN_DEBUG, EDAC_MC, | 184 | amd64_debug("pci-read, sdram scrub control value: %d\n", scrubval); |
| 198 | "pci-read, sdram scrub control value: %d \n", scrubval); | ||
| 199 | 185 | ||
| 200 | for (i = 0; i < ARRAY_SIZE(scrubrates); i++) { | 186 | for (i = 0; i < ARRAY_SIZE(scrubrates); i++) { |
| 201 | if (scrubrates[i].scrubval == scrubval) { | 187 | if (scrubrates[i].scrubval == scrubval) { |
| 202 | *bw = scrubrates[i].bandwidth; | 188 | retval = scrubrates[i].bandwidth; |
| 203 | status = 0; | ||
| 204 | break; | 189 | break; |
| 205 | } | 190 | } |
| 206 | } | 191 | } |
| 207 | 192 | return retval; | |
| 208 | return status; | ||
| 209 | } | 193 | } |
| 210 | 194 | ||
| 211 | /* Map from a CSROW entry to the mask entry that operates on it */ | 195 | /* Map from a CSROW entry to the mask entry that operates on it */ |
| @@ -314,9 +298,7 @@ static struct mem_ctl_info *find_mc_by_sys_addr(struct mem_ctl_info *mci, | |||
| 314 | if (unlikely((intlv_en != 0x01) && | 298 | if (unlikely((intlv_en != 0x01) && |
| 315 | (intlv_en != 0x03) && | 299 | (intlv_en != 0x03) && |
| 316 | (intlv_en != 0x07))) { | 300 | (intlv_en != 0x07))) { |
| 317 | amd64_printk(KERN_WARNING, "junk value of 0x%x extracted from " | 301 | amd64_warn("DRAM Base[IntlvEn] junk value: 0x%x, BIOS bug?\n", intlv_en); |
| 318 | "IntlvEn field of DRAM Base Register for node 0: " | ||
| 319 | "this probably indicates a BIOS bug.\n", intlv_en); | ||
| 320 | return NULL; | 302 | return NULL; |
| 321 | } | 303 | } |
| 322 | 304 | ||
| @@ -332,11 +314,9 @@ static struct mem_ctl_info *find_mc_by_sys_addr(struct mem_ctl_info *mci, | |||
| 332 | 314 | ||
| 333 | /* sanity test for sys_addr */ | 315 | /* sanity test for sys_addr */ |
| 334 | if (unlikely(!amd64_base_limit_match(pvt, sys_addr, node_id))) { | 316 | if (unlikely(!amd64_base_limit_match(pvt, sys_addr, node_id))) { |
| 335 | amd64_printk(KERN_WARNING, | 317 | amd64_warn("%s: sys_addr 0x%llx falls outside base/limit address" |
| 336 | "%s(): sys_addr 0x%llx falls outside base/limit " | 318 | "range for node %d with node interleaving enabled.\n", |
| 337 | "address range for node %d with node interleaving " | 319 | __func__, sys_addr, node_id); |
| 338 | "enabled.\n", | ||
| 339 | __func__, sys_addr, node_id); | ||
| 340 | return NULL; | 320 | return NULL; |
| 341 | } | 321 | } |
| 342 | 322 | ||
| @@ -788,9 +768,8 @@ static int sys_addr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr) | |||
| 788 | csrow = input_addr_to_csrow(mci, sys_addr_to_input_addr(mci, sys_addr)); | 768 | csrow = input_addr_to_csrow(mci, sys_addr_to_input_addr(mci, sys_addr)); |
| 789 | 769 | ||
| 790 | if (csrow == -1) | 770 | if (csrow == -1) |
| 791 | amd64_mc_printk(mci, KERN_ERR, | 771 | amd64_mc_err(mci, "Failed to translate InputAddr to csrow for " |
| 792 | "Failed to translate InputAddr to csrow for " | 772 | "address 0x%lx\n", (unsigned long)sys_addr); |
| 793 | "address 0x%lx\n", (unsigned long)sys_addr); | ||
| 794 | return csrow; | 773 | return csrow; |
| 795 | } | 774 | } |
| 796 | 775 | ||
| @@ -801,21 +780,6 @@ static u16 extract_syndrome(struct err_regs *err) | |||
| 801 | return ((err->nbsh >> 15) & 0xff) | ((err->nbsl >> 16) & 0xff00); | 780 | return ((err->nbsh >> 15) & 0xff) | ((err->nbsl >> 16) & 0xff00); |
| 802 | } | 781 | } |
| 803 | 782 | ||
| 804 | static void amd64_cpu_display_info(struct amd64_pvt *pvt) | ||
| 805 | { | ||
| 806 | if (boot_cpu_data.x86 == 0x11) | ||
| 807 | edac_printk(KERN_DEBUG, EDAC_MC, "F11h CPU detected\n"); | ||
| 808 | else if (boot_cpu_data.x86 == 0x10) | ||
| 809 | edac_printk(KERN_DEBUG, EDAC_MC, "F10h CPU detected\n"); | ||
| 810 | else if (boot_cpu_data.x86 == 0xf) | ||
| 811 | edac_printk(KERN_DEBUG, EDAC_MC, "%s detected\n", | ||
| 812 | (pvt->ext_model >= K8_REV_F) ? | ||
| 813 | "Rev F or later" : "Rev E or earlier"); | ||
| 814 | else | ||
| 815 | /* we'll hardly ever ever get here */ | ||
| 816 | edac_printk(KERN_ERR, EDAC_MC, "Unknown cpu!\n"); | ||
| 817 | } | ||
| 818 | |||
| 819 | /* | 783 | /* |
| 820 | * Determine if the DIMMs have ECC enabled. ECC is enabled ONLY if all the DIMMs | 784 | * Determine if the DIMMs have ECC enabled. ECC is enabled ONLY if all the DIMMs |
| 821 | * are ECC capable. | 785 | * are ECC capable. |
| @@ -893,8 +857,7 @@ static void amd64_dump_misc_regs(struct amd64_pvt *pvt) | |||
| 893 | return; | 857 | return; |
| 894 | } | 858 | } |
| 895 | 859 | ||
| 896 | amd64_printk(KERN_INFO, "using %s syndromes.\n", | 860 | amd64_info("using %s syndromes.\n", ((pvt->syn_type == 8) ? "x8" : "x4")); |
| 897 | ((pvt->syn_type == 8) ? "x8" : "x4")); | ||
| 898 | 861 | ||
| 899 | /* Only if NOT ganged does dclr1 have valid info */ | 862 | /* Only if NOT ganged does dclr1 have valid info */ |
| 900 | if (!dct_ganging_enabled(pvt)) | 863 | if (!dct_ganging_enabled(pvt)) |
| @@ -915,10 +878,10 @@ static void amd64_dump_misc_regs(struct amd64_pvt *pvt) | |||
| 915 | /* Read in both of DBAM registers */ | 878 | /* Read in both of DBAM registers */ |
| 916 | static void amd64_read_dbam_reg(struct amd64_pvt *pvt) | 879 | static void amd64_read_dbam_reg(struct amd64_pvt *pvt) |
| 917 | { | 880 | { |
| 918 | amd64_read_pci_cfg(pvt->dram_f2_ctl, DBAM0, &pvt->dbam0); | 881 | amd64_read_pci_cfg(pvt->F2, DBAM0, &pvt->dbam0); |
| 919 | 882 | ||
| 920 | if (boot_cpu_data.x86 >= 0x10) | 883 | if (boot_cpu_data.x86 >= 0x10) |
| 921 | amd64_read_pci_cfg(pvt->dram_f2_ctl, DBAM1, &pvt->dbam1); | 884 | amd64_read_pci_cfg(pvt->F2, DBAM1, &pvt->dbam1); |
| 922 | } | 885 | } |
| 923 | 886 | ||
| 924 | /* | 887 | /* |
| @@ -965,14 +928,8 @@ static void amd64_set_dct_base_and_mask(struct amd64_pvt *pvt) | |||
| 965 | pvt->dcsm_mask = REV_F_F1Xh_DCSM_MASK_BITS; | 928 | pvt->dcsm_mask = REV_F_F1Xh_DCSM_MASK_BITS; |
| 966 | pvt->dcs_mask_notused = REV_F_F1Xh_DCS_NOTUSED_BITS; | 929 | pvt->dcs_mask_notused = REV_F_F1Xh_DCS_NOTUSED_BITS; |
| 967 | pvt->dcs_shift = REV_F_F1Xh_DCS_SHIFT; | 930 | pvt->dcs_shift = REV_F_F1Xh_DCS_SHIFT; |
| 968 | 931 | pvt->cs_count = 8; | |
| 969 | if (boot_cpu_data.x86 == 0x11) { | 932 | pvt->num_dcsm = 4; |
| 970 | pvt->cs_count = 4; | ||
| 971 | pvt->num_dcsm = 2; | ||
| 972 | } else { | ||
| 973 | pvt->cs_count = 8; | ||
| 974 | pvt->num_dcsm = 4; | ||
| 975 | } | ||
| 976 | } | 933 | } |
| 977 | } | 934 | } |
| 978 | 935 | ||
| @@ -987,14 +944,14 @@ static void amd64_read_dct_base_mask(struct amd64_pvt *pvt) | |||
| 987 | 944 | ||
| 988 | for (cs = 0; cs < pvt->cs_count; cs++) { | 945 | for (cs = 0; cs < pvt->cs_count; cs++) { |
| 989 | reg = K8_DCSB0 + (cs * 4); | 946 | reg = K8_DCSB0 + (cs * 4); |
| 990 | if (!amd64_read_pci_cfg(pvt->dram_f2_ctl, reg, &pvt->dcsb0[cs])) | 947 | if (!amd64_read_pci_cfg(pvt->F2, reg, &pvt->dcsb0[cs])) |
| 991 | debugf0(" DCSB0[%d]=0x%08x reg: F2x%x\n", | 948 | debugf0(" DCSB0[%d]=0x%08x reg: F2x%x\n", |
| 992 | cs, pvt->dcsb0[cs], reg); | 949 | cs, pvt->dcsb0[cs], reg); |
| 993 | 950 | ||
| 994 | /* If DCT are NOT ganged, then read in DCT1's base */ | 951 | /* If DCT are NOT ganged, then read in DCT1's base */ |
| 995 | if (boot_cpu_data.x86 >= 0x10 && !dct_ganging_enabled(pvt)) { | 952 | if (boot_cpu_data.x86 >= 0x10 && !dct_ganging_enabled(pvt)) { |
| 996 | reg = F10_DCSB1 + (cs * 4); | 953 | reg = F10_DCSB1 + (cs * 4); |
| 997 | if (!amd64_read_pci_cfg(pvt->dram_f2_ctl, reg, | 954 | if (!amd64_read_pci_cfg(pvt->F2, reg, |
| 998 | &pvt->dcsb1[cs])) | 955 | &pvt->dcsb1[cs])) |
| 999 | debugf0(" DCSB1[%d]=0x%08x reg: F2x%x\n", | 956 | debugf0(" DCSB1[%d]=0x%08x reg: F2x%x\n", |
| 1000 | cs, pvt->dcsb1[cs], reg); | 957 | cs, pvt->dcsb1[cs], reg); |
| @@ -1005,14 +962,14 @@ static void amd64_read_dct_base_mask(struct amd64_pvt *pvt) | |||
| 1005 | 962 | ||
| 1006 | for (cs = 0; cs < pvt->num_dcsm; cs++) { | 963 | for (cs = 0; cs < pvt->num_dcsm; cs++) { |
| 1007 | reg = K8_DCSM0 + (cs * 4); | 964 | reg = K8_DCSM0 + (cs * 4); |
| 1008 | if (!amd64_read_pci_cfg(pvt->dram_f2_ctl, reg, &pvt->dcsm0[cs])) | 965 | if (!amd64_read_pci_cfg(pvt->F2, reg, &pvt->dcsm0[cs])) |
| 1009 | debugf0(" DCSM0[%d]=0x%08x reg: F2x%x\n", | 966 | debugf0(" DCSM0[%d]=0x%08x reg: F2x%x\n", |
| 1010 | cs, pvt->dcsm0[cs], reg); | 967 | cs, pvt->dcsm0[cs], reg); |
| 1011 | 968 | ||
| 1012 | /* If DCT are NOT ganged, then read in DCT1's mask */ | 969 | /* If DCT are NOT ganged, then read in DCT1's mask */ |
| 1013 | if (boot_cpu_data.x86 >= 0x10 && !dct_ganging_enabled(pvt)) { | 970 | if (boot_cpu_data.x86 >= 0x10 && !dct_ganging_enabled(pvt)) { |
| 1014 | reg = F10_DCSM1 + (cs * 4); | 971 | reg = F10_DCSM1 + (cs * 4); |
| 1015 | if (!amd64_read_pci_cfg(pvt->dram_f2_ctl, reg, | 972 | if (!amd64_read_pci_cfg(pvt->F2, reg, |
| 1016 | &pvt->dcsm1[cs])) | 973 | &pvt->dcsm1[cs])) |
| 1017 | debugf0(" DCSM1[%d]=0x%08x reg: F2x%x\n", | 974 | debugf0(" DCSM1[%d]=0x%08x reg: F2x%x\n", |
| 1018 | cs, pvt->dcsm1[cs], reg); | 975 | cs, pvt->dcsm1[cs], reg); |
| @@ -1022,7 +979,7 @@ static void amd64_read_dct_base_mask(struct amd64_pvt *pvt) | |||
| 1022 | } | 979 | } |
| 1023 | } | 980 | } |
| 1024 | 981 | ||
| 1025 | static enum mem_type amd64_determine_memory_type(struct amd64_pvt *pvt) | 982 | static enum mem_type amd64_determine_memory_type(struct amd64_pvt *pvt, int cs) |
| 1026 | { | 983 | { |
| 1027 | enum mem_type type; | 984 | enum mem_type type; |
| 1028 | 985 | ||
| @@ -1035,7 +992,7 @@ static enum mem_type amd64_determine_memory_type(struct amd64_pvt *pvt) | |||
| 1035 | type = (pvt->dclr0 & BIT(18)) ? MEM_DDR : MEM_RDDR; | 992 | type = (pvt->dclr0 & BIT(18)) ? MEM_DDR : MEM_RDDR; |
| 1036 | } | 993 | } |
| 1037 | 994 | ||
| 1038 | debugf1(" Memory type is: %s\n", edac_mem_types[type]); | 995 | amd64_info("CS%d: %s\n", cs, edac_mem_types[type]); |
| 1039 | 996 | ||
| 1040 | return type; | 997 | return type; |
| 1041 | } | 998 | } |
| @@ -1053,17 +1010,16 @@ static int k8_early_channel_count(struct amd64_pvt *pvt) | |||
| 1053 | { | 1010 | { |
| 1054 | int flag, err = 0; | 1011 | int flag, err = 0; |
| 1055 | 1012 | ||
| 1056 | err = amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCLR_0, &pvt->dclr0); | 1013 | err = amd64_read_pci_cfg(pvt->F2, F10_DCLR_0, &pvt->dclr0); |
| 1057 | if (err) | 1014 | if (err) |
| 1058 | return err; | 1015 | return err; |
| 1059 | 1016 | ||
| 1060 | if ((boot_cpu_data.x86_model >> 4) >= K8_REV_F) { | 1017 | if (pvt->ext_model >= K8_REV_F) |
| 1061 | /* RevF (NPT) and later */ | 1018 | /* RevF (NPT) and later */ |
| 1062 | flag = pvt->dclr0 & F10_WIDTH_128; | 1019 | flag = pvt->dclr0 & F10_WIDTH_128; |
| 1063 | } else { | 1020 | else |
| 1064 | /* RevE and earlier */ | 1021 | /* RevE and earlier */ |
| 1065 | flag = pvt->dclr0 & REVE_WIDTH_128; | 1022 | flag = pvt->dclr0 & REVE_WIDTH_128; |
| 1066 | } | ||
| 1067 | 1023 | ||
| 1068 | /* not used */ | 1024 | /* not used */ |
| 1069 | pvt->dclr1 = 0; | 1025 | pvt->dclr1 = 0; |
| @@ -1090,14 +1046,14 @@ static void k8_read_dram_base_limit(struct amd64_pvt *pvt, int dram) | |||
| 1090 | u32 low; | 1046 | u32 low; |
| 1091 | u32 off = dram << 3; /* 8 bytes between DRAM entries */ | 1047 | u32 off = dram << 3; /* 8 bytes between DRAM entries */ |
| 1092 | 1048 | ||
| 1093 | amd64_read_pci_cfg(pvt->addr_f1_ctl, K8_DRAM_BASE_LOW + off, &low); | 1049 | amd64_read_pci_cfg(pvt->F1, K8_DRAM_BASE_LOW + off, &low); |
| 1094 | 1050 | ||
| 1095 | /* Extract parts into separate data entries */ | 1051 | /* Extract parts into separate data entries */ |
| 1096 | pvt->dram_base[dram] = ((u64) low & 0xFFFF0000) << 8; | 1052 | pvt->dram_base[dram] = ((u64) low & 0xFFFF0000) << 8; |
| 1097 | pvt->dram_IntlvEn[dram] = (low >> 8) & 0x7; | 1053 | pvt->dram_IntlvEn[dram] = (low >> 8) & 0x7; |
| 1098 | pvt->dram_rw_en[dram] = (low & 0x3); | 1054 | pvt->dram_rw_en[dram] = (low & 0x3); |
| 1099 | 1055 | ||
| 1100 | amd64_read_pci_cfg(pvt->addr_f1_ctl, K8_DRAM_LIMIT_LOW + off, &low); | 1056 | amd64_read_pci_cfg(pvt->F1, K8_DRAM_LIMIT_LOW + off, &low); |
| 1101 | 1057 | ||
| 1102 | /* | 1058 | /* |
| 1103 | * Extract parts into separate data entries. Limit is the HIGHEST memory | 1059 | * Extract parts into separate data entries. Limit is the HIGHEST memory |
| @@ -1127,9 +1083,8 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, | |||
| 1127 | * 2 DIMMs is in error. So we need to ID 'both' of them | 1083 | * 2 DIMMs is in error. So we need to ID 'both' of them |
| 1128 | * as suspect. | 1084 | * as suspect. |
| 1129 | */ | 1085 | */ |
| 1130 | amd64_mc_printk(mci, KERN_WARNING, | 1086 | amd64_mc_warn(mci, "unknown syndrome 0x%04x - possible " |
| 1131 | "unknown syndrome 0x%04x - possible " | 1087 | "error reporting race\n", syndrome); |
| 1132 | "error reporting race\n", syndrome); | ||
| 1133 | edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR); | 1088 | edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR); |
| 1134 | return; | 1089 | return; |
| 1135 | } | 1090 | } |
| @@ -1151,8 +1106,7 @@ static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, | |||
| 1151 | */ | 1106 | */ |
| 1152 | src_mci = find_mc_by_sys_addr(mci, sys_addr); | 1107 | src_mci = find_mc_by_sys_addr(mci, sys_addr); |
| 1153 | if (!src_mci) { | 1108 | if (!src_mci) { |
| 1154 | amd64_mc_printk(mci, KERN_ERR, | 1109 | amd64_mc_err(mci, "failed to map error addr 0x%lx to a node\n", |
| 1155 | "failed to map error address 0x%lx to a node\n", | ||
| 1156 | (unsigned long)sys_addr); | 1110 | (unsigned long)sys_addr); |
| 1157 | edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR); | 1111 | edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR); |
| 1158 | return; | 1112 | return; |
| @@ -1220,7 +1174,7 @@ static int f10_early_channel_count(struct amd64_pvt *pvt) | |||
| 1220 | * both controllers since DIMMs can be placed in either one. | 1174 | * both controllers since DIMMs can be placed in either one. |
| 1221 | */ | 1175 | */ |
| 1222 | for (i = 0; i < ARRAY_SIZE(dbams); i++) { | 1176 | for (i = 0; i < ARRAY_SIZE(dbams); i++) { |
| 1223 | if (amd64_read_pci_cfg(pvt->dram_f2_ctl, dbams[i], &dbam)) | 1177 | if (amd64_read_pci_cfg(pvt->F2, dbams[i], &dbam)) |
| 1224 | goto err_reg; | 1178 | goto err_reg; |
| 1225 | 1179 | ||
| 1226 | for (j = 0; j < 4; j++) { | 1180 | for (j = 0; j < 4; j++) { |
| @@ -1234,7 +1188,7 @@ static int f10_early_channel_count(struct amd64_pvt *pvt) | |||
| 1234 | if (channels > 2) | 1188 | if (channels > 2) |
| 1235 | channels = 2; | 1189 | channels = 2; |
| 1236 | 1190 | ||
| 1237 | debugf0("MCT channel count: %d\n", channels); | 1191 | amd64_info("MCT channel count: %d\n", channels); |
| 1238 | 1192 | ||
| 1239 | return channels; | 1193 | return channels; |
| 1240 | 1194 | ||
| @@ -1255,31 +1209,6 @@ static int f10_dbam_to_chip_select(struct amd64_pvt *pvt, int cs_mode) | |||
| 1255 | return dbam_map[cs_mode]; | 1209 | return dbam_map[cs_mode]; |
| 1256 | } | 1210 | } |
| 1257 | 1211 | ||
| 1258 | /* Enable extended configuration access via 0xCF8 feature */ | ||
| 1259 | static void amd64_setup(struct amd64_pvt *pvt) | ||
| 1260 | { | ||
| 1261 | u32 reg; | ||
| 1262 | |||
| 1263 | amd64_read_pci_cfg(pvt->misc_f3_ctl, F10_NB_CFG_HIGH, ®); | ||
| 1264 | |||
| 1265 | pvt->flags.cf8_extcfg = !!(reg & F10_NB_CFG_LOW_ENABLE_EXT_CFG); | ||
| 1266 | reg |= F10_NB_CFG_LOW_ENABLE_EXT_CFG; | ||
| 1267 | pci_write_config_dword(pvt->misc_f3_ctl, F10_NB_CFG_HIGH, reg); | ||
| 1268 | } | ||
| 1269 | |||
| 1270 | /* Restore the extended configuration access via 0xCF8 feature */ | ||
| 1271 | static void amd64_teardown(struct amd64_pvt *pvt) | ||
| 1272 | { | ||
| 1273 | u32 reg; | ||
| 1274 | |||
| 1275 | amd64_read_pci_cfg(pvt->misc_f3_ctl, F10_NB_CFG_HIGH, ®); | ||
| 1276 | |||
| 1277 | reg &= ~F10_NB_CFG_LOW_ENABLE_EXT_CFG; | ||
| 1278 | if (pvt->flags.cf8_extcfg) | ||
| 1279 | reg |= F10_NB_CFG_LOW_ENABLE_EXT_CFG; | ||
| 1280 | pci_write_config_dword(pvt->misc_f3_ctl, F10_NB_CFG_HIGH, reg); | ||
| 1281 | } | ||
| 1282 | |||
| 1283 | static u64 f10_get_error_address(struct mem_ctl_info *mci, | 1212 | static u64 f10_get_error_address(struct mem_ctl_info *mci, |
| 1284 | struct err_regs *info) | 1213 | struct err_regs *info) |
| 1285 | { | 1214 | { |
| @@ -1301,10 +1230,8 @@ static void f10_read_dram_base_limit(struct amd64_pvt *pvt, int dram) | |||
| 1301 | high_offset = F10_DRAM_BASE_HIGH + (dram << 3); | 1230 | high_offset = F10_DRAM_BASE_HIGH + (dram << 3); |
| 1302 | 1231 | ||
| 1303 | /* read the 'raw' DRAM BASE Address register */ | 1232 | /* read the 'raw' DRAM BASE Address register */ |
| 1304 | amd64_read_pci_cfg(pvt->addr_f1_ctl, low_offset, &low_base); | 1233 | amd64_read_pci_cfg(pvt->F1, low_offset, &low_base); |
| 1305 | 1234 | amd64_read_pci_cfg(pvt->F1, high_offset, &high_base); | |
| 1306 | /* Read from the ECS data register */ | ||
| 1307 | amd64_read_pci_cfg(pvt->addr_f1_ctl, high_offset, &high_base); | ||
| 1308 | 1235 | ||
| 1309 | /* Extract parts into separate data entries */ | 1236 | /* Extract parts into separate data entries */ |
| 1310 | pvt->dram_rw_en[dram] = (low_base & 0x3); | 1237 | pvt->dram_rw_en[dram] = (low_base & 0x3); |
| @@ -1321,10 +1248,8 @@ static void f10_read_dram_base_limit(struct amd64_pvt *pvt, int dram) | |||
| 1321 | high_offset = F10_DRAM_LIMIT_HIGH + (dram << 3); | 1248 | high_offset = F10_DRAM_LIMIT_HIGH + (dram << 3); |
| 1322 | 1249 | ||
| 1323 | /* read the 'raw' LIMIT registers */ | 1250 | /* read the 'raw' LIMIT registers */ |
| 1324 | amd64_read_pci_cfg(pvt->addr_f1_ctl, low_offset, &low_limit); | 1251 | amd64_read_pci_cfg(pvt->F1, low_offset, &low_limit); |
| 1325 | 1252 | amd64_read_pci_cfg(pvt->F1, high_offset, &high_limit); | |
| 1326 | /* Read from the ECS data register for the HIGH portion */ | ||
| 1327 | amd64_read_pci_cfg(pvt->addr_f1_ctl, high_offset, &high_limit); | ||
| 1328 | 1253 | ||
| 1329 | pvt->dram_DstNode[dram] = (low_limit & 0x7); | 1254 | pvt->dram_DstNode[dram] = (low_limit & 0x7); |
| 1330 | pvt->dram_IntlvSel[dram] = (low_limit >> 8) & 0x7; | 1255 | pvt->dram_IntlvSel[dram] = (low_limit >> 8) & 0x7; |
| @@ -1341,7 +1266,7 @@ static void f10_read_dram_base_limit(struct amd64_pvt *pvt, int dram) | |||
| 1341 | static void f10_read_dram_ctl_register(struct amd64_pvt *pvt) | 1266 | static void f10_read_dram_ctl_register(struct amd64_pvt *pvt) |
| 1342 | { | 1267 | { |
| 1343 | 1268 | ||
| 1344 | if (!amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCTL_SEL_LOW, | 1269 | if (!amd64_read_pci_cfg(pvt->F2, F10_DCTL_SEL_LOW, |
| 1345 | &pvt->dram_ctl_select_low)) { | 1270 | &pvt->dram_ctl_select_low)) { |
| 1346 | debugf0("F2x110 (DCTL Sel. Low): 0x%08x, " | 1271 | debugf0("F2x110 (DCTL Sel. Low): 0x%08x, " |
| 1347 | "High range addresses at: 0x%x\n", | 1272 | "High range addresses at: 0x%x\n", |
| @@ -1367,7 +1292,7 @@ static void f10_read_dram_ctl_register(struct amd64_pvt *pvt) | |||
| 1367 | dct_sel_interleave_addr(pvt)); | 1292 | dct_sel_interleave_addr(pvt)); |
| 1368 | } | 1293 | } |
| 1369 | 1294 | ||
| 1370 | amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCTL_SEL_HIGH, | 1295 | amd64_read_pci_cfg(pvt->F2, F10_DCTL_SEL_HIGH, |
| 1371 | &pvt->dram_ctl_select_high); | 1296 | &pvt->dram_ctl_select_high); |
| 1372 | } | 1297 | } |
| 1373 | 1298 | ||
| @@ -1496,7 +1421,7 @@ static int f10_lookup_addr_in_dct(u32 in_addr, u32 nid, u32 cs) | |||
| 1496 | int cs_found = -EINVAL; | 1421 | int cs_found = -EINVAL; |
| 1497 | int csrow; | 1422 | int csrow; |
| 1498 | 1423 | ||
| 1499 | mci = mci_lookup[nid]; | 1424 | mci = mcis[nid]; |
| 1500 | if (!mci) | 1425 | if (!mci) |
| 1501 | return cs_found; | 1426 | return cs_found; |
| 1502 | 1427 | ||
| @@ -1738,28 +1663,17 @@ static void amd64_debug_display_dimm_sizes(int ctrl, struct amd64_pvt *pvt) | |||
| 1738 | if (dcsb[dimm*2 + 1] & K8_DCSB_CS_ENABLE) | 1663 | if (dcsb[dimm*2 + 1] & K8_DCSB_CS_ENABLE) |
| 1739 | size1 = pvt->ops->dbam_to_cs(pvt, DBAM_DIMM(dimm, dbam)); | 1664 | size1 = pvt->ops->dbam_to_cs(pvt, DBAM_DIMM(dimm, dbam)); |
| 1740 | 1665 | ||
| 1741 | edac_printk(KERN_DEBUG, EDAC_MC, " %d: %5dMB %d: %5dMB\n", | 1666 | amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n", |
| 1742 | dimm * 2, size0 << factor, | 1667 | dimm * 2, size0 << factor, |
| 1743 | dimm * 2 + 1, size1 << factor); | 1668 | dimm * 2 + 1, size1 << factor); |
| 1744 | } | 1669 | } |
| 1745 | } | 1670 | } |
| 1746 | 1671 | ||
| 1747 | /* | ||
| 1748 | * There currently are 3 types type of MC devices for AMD Athlon/Opterons | ||
| 1749 | * (as per PCI DEVICE_IDs): | ||
| 1750 | * | ||
| 1751 | * Family K8: That is the Athlon64 and Opteron CPUs. They all have the same PCI | ||
| 1752 | * DEVICE ID, even though there is differences between the different Revisions | ||
| 1753 | * (CG,D,E,F). | ||
| 1754 | * | ||
| 1755 | * Family F10h and F11h. | ||
| 1756 | * | ||
| 1757 | */ | ||
| 1758 | static struct amd64_family_type amd64_family_types[] = { | 1672 | static struct amd64_family_type amd64_family_types[] = { |
| 1759 | [K8_CPUS] = { | 1673 | [K8_CPUS] = { |
| 1760 | .ctl_name = "RevF", | 1674 | .ctl_name = "K8", |
| 1761 | .addr_f1_ctl = PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP, | 1675 | .f1_id = PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP, |
| 1762 | .misc_f3_ctl = PCI_DEVICE_ID_AMD_K8_NB_MISC, | 1676 | .f3_id = PCI_DEVICE_ID_AMD_K8_NB_MISC, |
| 1763 | .ops = { | 1677 | .ops = { |
| 1764 | .early_channel_count = k8_early_channel_count, | 1678 | .early_channel_count = k8_early_channel_count, |
| 1765 | .get_error_address = k8_get_error_address, | 1679 | .get_error_address = k8_get_error_address, |
| @@ -1769,22 +1683,9 @@ static struct amd64_family_type amd64_family_types[] = { | |||
| 1769 | } | 1683 | } |
| 1770 | }, | 1684 | }, |
| 1771 | [F10_CPUS] = { | 1685 | [F10_CPUS] = { |
| 1772 | .ctl_name = "Family 10h", | 1686 | .ctl_name = "F10h", |
| 1773 | .addr_f1_ctl = PCI_DEVICE_ID_AMD_10H_NB_MAP, | 1687 | .f1_id = PCI_DEVICE_ID_AMD_10H_NB_MAP, |
| 1774 | .misc_f3_ctl = PCI_DEVICE_ID_AMD_10H_NB_MISC, | 1688 | .f3_id = PCI_DEVICE_ID_AMD_10H_NB_MISC, |
| 1775 | .ops = { | ||
| 1776 | .early_channel_count = f10_early_channel_count, | ||
| 1777 | .get_error_address = f10_get_error_address, | ||
| 1778 | .read_dram_base_limit = f10_read_dram_base_limit, | ||
| 1779 | .read_dram_ctl_register = f10_read_dram_ctl_register, | ||
| 1780 | .map_sysaddr_to_csrow = f10_map_sysaddr_to_csrow, | ||
| 1781 | .dbam_to_cs = f10_dbam_to_chip_select, | ||
| 1782 | } | ||
| 1783 | }, | ||
| 1784 | [F11_CPUS] = { | ||
| 1785 | .ctl_name = "Family 11h", | ||
| 1786 | .addr_f1_ctl = PCI_DEVICE_ID_AMD_11H_NB_MAP, | ||
| 1787 | .misc_f3_ctl = PCI_DEVICE_ID_AMD_11H_NB_MISC, | ||
| 1788 | .ops = { | 1689 | .ops = { |
| 1789 | .early_channel_count = f10_early_channel_count, | 1690 | .early_channel_count = f10_early_channel_count, |
| 1790 | .get_error_address = f10_get_error_address, | 1691 | .get_error_address = f10_get_error_address, |
| @@ -1970,8 +1871,7 @@ static int get_channel_from_ecc_syndrome(struct mem_ctl_info *mci, u16 syndrome) | |||
| 1970 | ARRAY_SIZE(x4_vectors), | 1871 | ARRAY_SIZE(x4_vectors), |
| 1971 | pvt->syn_type); | 1872 | pvt->syn_type); |
| 1972 | else { | 1873 | else { |
| 1973 | amd64_printk(KERN_WARNING, "%s: Illegal syndrome type: %u\n", | 1874 | amd64_warn("Illegal syndrome type: %u\n", pvt->syn_type); |
| 1974 | __func__, pvt->syn_type); | ||
| 1975 | return err_sym; | 1875 | return err_sym; |
| 1976 | } | 1876 | } |
| 1977 | 1877 | ||
| @@ -1989,17 +1889,15 @@ static void amd64_handle_ce(struct mem_ctl_info *mci, | |||
| 1989 | u64 sys_addr; | 1889 | u64 sys_addr; |
| 1990 | 1890 | ||
| 1991 | /* Ensure that the Error Address is VALID */ | 1891 | /* Ensure that the Error Address is VALID */ |
| 1992 | if ((info->nbsh & K8_NBSH_VALID_ERROR_ADDR) == 0) { | 1892 | if (!(info->nbsh & K8_NBSH_VALID_ERROR_ADDR)) { |
| 1993 | amd64_mc_printk(mci, KERN_ERR, | 1893 | amd64_mc_err(mci, "HW has no ERROR_ADDRESS available\n"); |
| 1994 | "HW has no ERROR_ADDRESS available\n"); | ||
| 1995 | edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR); | 1894 | edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR); |
| 1996 | return; | 1895 | return; |
| 1997 | } | 1896 | } |
| 1998 | 1897 | ||
| 1999 | sys_addr = pvt->ops->get_error_address(mci, info); | 1898 | sys_addr = pvt->ops->get_error_address(mci, info); |
| 2000 | 1899 | ||
| 2001 | amd64_mc_printk(mci, KERN_ERR, | 1900 | amd64_mc_err(mci, "CE ERROR_ADDRESS= 0x%llx\n", sys_addr); |
| 2002 | "CE ERROR_ADDRESS= 0x%llx\n", sys_addr); | ||
| 2003 | 1901 | ||
| 2004 | pvt->ops->map_sysaddr_to_csrow(mci, info, sys_addr); | 1902 | pvt->ops->map_sysaddr_to_csrow(mci, info, sys_addr); |
| 2005 | } | 1903 | } |
| @@ -2016,9 +1914,8 @@ static void amd64_handle_ue(struct mem_ctl_info *mci, | |||
| 2016 | 1914 | ||
| 2017 | log_mci = mci; | 1915 | log_mci = mci; |
| 2018 | 1916 | ||
| 2019 | if ((info->nbsh & K8_NBSH_VALID_ERROR_ADDR) == 0) { | 1917 | if (!(info->nbsh & K8_NBSH_VALID_ERROR_ADDR)) { |
| 2020 | amd64_mc_printk(mci, KERN_CRIT, | 1918 | amd64_mc_err(mci, "HW has no ERROR_ADDRESS available\n"); |
| 2021 | "HW has no ERROR_ADDRESS available\n"); | ||
| 2022 | edac_mc_handle_ue_no_info(log_mci, EDAC_MOD_STR); | 1919 | edac_mc_handle_ue_no_info(log_mci, EDAC_MOD_STR); |
| 2023 | return; | 1920 | return; |
| 2024 | } | 1921 | } |
| @@ -2031,9 +1928,8 @@ static void amd64_handle_ue(struct mem_ctl_info *mci, | |||
| 2031 | */ | 1928 | */ |
| 2032 | src_mci = find_mc_by_sys_addr(mci, sys_addr); | 1929 | src_mci = find_mc_by_sys_addr(mci, sys_addr); |
| 2033 | if (!src_mci) { | 1930 | if (!src_mci) { |
| 2034 | amd64_mc_printk(mci, KERN_CRIT, | 1931 | amd64_mc_err(mci, "ERROR ADDRESS (0x%lx) NOT mapped to a MC\n", |
| 2035 | "ERROR ADDRESS (0x%lx) value NOT mapped to a MC\n", | 1932 | (unsigned long)sys_addr); |
| 2036 | (unsigned long)sys_addr); | ||
| 2037 | edac_mc_handle_ue_no_info(log_mci, EDAC_MOD_STR); | 1933 | edac_mc_handle_ue_no_info(log_mci, EDAC_MOD_STR); |
| 2038 | return; | 1934 | return; |
| 2039 | } | 1935 | } |
| @@ -2042,9 +1938,8 @@ static void amd64_handle_ue(struct mem_ctl_info *mci, | |||
| 2042 | 1938 | ||
| 2043 | csrow = sys_addr_to_csrow(log_mci, sys_addr); | 1939 | csrow = sys_addr_to_csrow(log_mci, sys_addr); |
| 2044 | if (csrow < 0) { | 1940 | if (csrow < 0) { |
| 2045 | amd64_mc_printk(mci, KERN_CRIT, | 1941 | amd64_mc_err(mci, "ERROR_ADDRESS (0x%lx) NOT mapped to CS\n", |
| 2046 | "ERROR_ADDRESS (0x%lx) value NOT mapped to 'csrow'\n", | 1942 | (unsigned long)sys_addr); |
| 2047 | (unsigned long)sys_addr); | ||
| 2048 | edac_mc_handle_ue_no_info(log_mci, EDAC_MOD_STR); | 1943 | edac_mc_handle_ue_no_info(log_mci, EDAC_MOD_STR); |
| 2049 | } else { | 1944 | } else { |
| 2050 | error_address_to_page_and_offset(sys_addr, &page, &offset); | 1945 | error_address_to_page_and_offset(sys_addr, &page, &offset); |
| @@ -2075,7 +1970,7 @@ static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci, | |||
| 2075 | 1970 | ||
| 2076 | void amd64_decode_bus_error(int node_id, struct mce *m, u32 nbcfg) | 1971 | void amd64_decode_bus_error(int node_id, struct mce *m, u32 nbcfg) |
| 2077 | { | 1972 | { |
| 2078 | struct mem_ctl_info *mci = mci_lookup[node_id]; | 1973 | struct mem_ctl_info *mci = mcis[node_id]; |
| 2079 | struct err_regs regs; | 1974 | struct err_regs regs; |
| 2080 | 1975 | ||
| 2081 | regs.nbsl = (u32) m->status; | 1976 | regs.nbsl = (u32) m->status; |
| @@ -2099,75 +1994,50 @@ void amd64_decode_bus_error(int node_id, struct mce *m, u32 nbcfg) | |||
| 2099 | } | 1994 | } |
| 2100 | 1995 | ||
| 2101 | /* | 1996 | /* |
| 2102 | * Input: | 1997 | * Use pvt->F2 which contains the F2 CPU PCI device to get the related |
| 2103 | * 1) struct amd64_pvt which contains pvt->dram_f2_ctl pointer | 1998 | * F1 (AddrMap) and F3 (Misc) devices. Return negative value on error. |
| 2104 | * 2) AMD Family index value | ||
| 2105 | * | ||
| 2106 | * Ouput: | ||
| 2107 | * Upon return of 0, the following filled in: | ||
| 2108 | * | ||
| 2109 | * struct pvt->addr_f1_ctl | ||
| 2110 | * struct pvt->misc_f3_ctl | ||
| 2111 | * | ||
| 2112 | * Filled in with related device funcitions of 'dram_f2_ctl' | ||
| 2113 | * These devices are "reserved" via the pci_get_device() | ||
| 2114 | * | ||
| 2115 | * Upon return of 1 (error status): | ||
| 2116 | * | ||
| 2117 | * Nothing reserved | ||
| 2118 | */ | 1999 | */ |
| 2119 | static int amd64_reserve_mc_sibling_devices(struct amd64_pvt *pvt, int mc_idx) | 2000 | static int reserve_mc_sibling_devs(struct amd64_pvt *pvt, u16 f1_id, u16 f3_id) |
| 2120 | { | 2001 | { |
| 2121 | const struct amd64_family_type *amd64_dev = &amd64_family_types[mc_idx]; | ||
| 2122 | |||
| 2123 | /* Reserve the ADDRESS MAP Device */ | 2002 | /* Reserve the ADDRESS MAP Device */ |
| 2124 | pvt->addr_f1_ctl = pci_get_related_function(pvt->dram_f2_ctl->vendor, | 2003 | pvt->F1 = pci_get_related_function(pvt->F2->vendor, f1_id, pvt->F2); |
| 2125 | amd64_dev->addr_f1_ctl, | 2004 | if (!pvt->F1) { |
| 2126 | pvt->dram_f2_ctl); | 2005 | amd64_err("error address map device not found: " |
| 2127 | 2006 | "vendor %x device 0x%x (broken BIOS?)\n", | |
| 2128 | if (!pvt->addr_f1_ctl) { | 2007 | PCI_VENDOR_ID_AMD, f1_id); |
| 2129 | amd64_printk(KERN_ERR, "error address map device not found: " | 2008 | return -ENODEV; |
| 2130 | "vendor %x device 0x%x (broken BIOS?)\n", | ||
| 2131 | PCI_VENDOR_ID_AMD, amd64_dev->addr_f1_ctl); | ||
| 2132 | return 1; | ||
| 2133 | } | 2009 | } |
| 2134 | 2010 | ||
| 2135 | /* Reserve the MISC Device */ | 2011 | /* Reserve the MISC Device */ |
| 2136 | pvt->misc_f3_ctl = pci_get_related_function(pvt->dram_f2_ctl->vendor, | 2012 | pvt->F3 = pci_get_related_function(pvt->F2->vendor, f3_id, pvt->F2); |
| 2137 | amd64_dev->misc_f3_ctl, | 2013 | if (!pvt->F3) { |
| 2138 | pvt->dram_f2_ctl); | 2014 | pci_dev_put(pvt->F1); |
| 2015 | pvt->F1 = NULL; | ||
| 2139 | 2016 | ||
| 2140 | if (!pvt->misc_f3_ctl) { | 2017 | amd64_err("error F3 device not found: " |
| 2141 | pci_dev_put(pvt->addr_f1_ctl); | 2018 | "vendor %x device 0x%x (broken BIOS?)\n", |
| 2142 | pvt->addr_f1_ctl = NULL; | 2019 | PCI_VENDOR_ID_AMD, f3_id); |
| 2143 | 2020 | ||
| 2144 | amd64_printk(KERN_ERR, "error miscellaneous device not found: " | 2021 | return -ENODEV; |
| 2145 | "vendor %x device 0x%x (broken BIOS?)\n", | ||
| 2146 | PCI_VENDOR_ID_AMD, amd64_dev->misc_f3_ctl); | ||
| 2147 | return 1; | ||
| 2148 | } | 2022 | } |
| 2149 | 2023 | debugf1("F1: %s\n", pci_name(pvt->F1)); | |
| 2150 | debugf1(" Addr Map device PCI Bus ID:\t%s\n", | 2024 | debugf1("F2: %s\n", pci_name(pvt->F2)); |
| 2151 | pci_name(pvt->addr_f1_ctl)); | 2025 | debugf1("F3: %s\n", pci_name(pvt->F3)); |
| 2152 | debugf1(" DRAM MEM-CTL PCI Bus ID:\t%s\n", | ||
| 2153 | pci_name(pvt->dram_f2_ctl)); | ||
| 2154 | debugf1(" Misc device PCI Bus ID:\t%s\n", | ||
| 2155 | pci_name(pvt->misc_f3_ctl)); | ||
| 2156 | 2026 | ||
| 2157 | return 0; | 2027 | return 0; |
| 2158 | } | 2028 | } |
| 2159 | 2029 | ||
| 2160 | static void amd64_free_mc_sibling_devices(struct amd64_pvt *pvt) | 2030 | static void free_mc_sibling_devs(struct amd64_pvt *pvt) |
| 2161 | { | 2031 | { |
| 2162 | pci_dev_put(pvt->addr_f1_ctl); | 2032 | pci_dev_put(pvt->F1); |
| 2163 | pci_dev_put(pvt->misc_f3_ctl); | 2033 | pci_dev_put(pvt->F3); |
| 2164 | } | 2034 | } |
| 2165 | 2035 | ||
| 2166 | /* | 2036 | /* |
| 2167 | * Retrieve the hardware registers of the memory controller (this includes the | 2037 | * Retrieve the hardware registers of the memory controller (this includes the |
| 2168 | * 'Address Map' and 'Misc' device regs) | 2038 | * 'Address Map' and 'Misc' device regs) |
| 2169 | */ | 2039 | */ |
| 2170 | static void amd64_read_mc_registers(struct amd64_pvt *pvt) | 2040 | static void read_mc_regs(struct amd64_pvt *pvt) |
| 2171 | { | 2041 | { |
| 2172 | u64 msr_val; | 2042 | u64 msr_val; |
| 2173 | u32 tmp; | 2043 | u32 tmp; |
| @@ -2188,9 +2058,7 @@ static void amd64_read_mc_registers(struct amd64_pvt *pvt) | |||
| 2188 | } else | 2058 | } else |
| 2189 | debugf0(" TOP_MEM2 disabled.\n"); | 2059 | debugf0(" TOP_MEM2 disabled.\n"); |
| 2190 | 2060 | ||
| 2191 | amd64_cpu_display_info(pvt); | 2061 | amd64_read_pci_cfg(pvt->F3, K8_NBCAP, &pvt->nbcap); |
| 2192 | |||
| 2193 | amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCAP, &pvt->nbcap); | ||
| 2194 | 2062 | ||
| 2195 | if (pvt->ops->read_dram_ctl_register) | 2063 | if (pvt->ops->read_dram_ctl_register) |
| 2196 | pvt->ops->read_dram_ctl_register(pvt); | 2064 | pvt->ops->read_dram_ctl_register(pvt); |
| @@ -2227,21 +2095,20 @@ static void amd64_read_mc_registers(struct amd64_pvt *pvt) | |||
| 2227 | 2095 | ||
| 2228 | amd64_read_dct_base_mask(pvt); | 2096 | amd64_read_dct_base_mask(pvt); |
| 2229 | 2097 | ||
| 2230 | amd64_read_pci_cfg(pvt->addr_f1_ctl, K8_DHAR, &pvt->dhar); | 2098 | amd64_read_pci_cfg(pvt->F1, K8_DHAR, &pvt->dhar); |
| 2231 | amd64_read_dbam_reg(pvt); | 2099 | amd64_read_dbam_reg(pvt); |
| 2232 | 2100 | ||
| 2233 | amd64_read_pci_cfg(pvt->misc_f3_ctl, | 2101 | amd64_read_pci_cfg(pvt->F3, F10_ONLINE_SPARE, &pvt->online_spare); |
| 2234 | F10_ONLINE_SPARE, &pvt->online_spare); | ||
| 2235 | 2102 | ||
| 2236 | amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCLR_0, &pvt->dclr0); | 2103 | amd64_read_pci_cfg(pvt->F2, F10_DCLR_0, &pvt->dclr0); |
| 2237 | amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCHR_0, &pvt->dchr0); | 2104 | amd64_read_pci_cfg(pvt->F2, F10_DCHR_0, &pvt->dchr0); |
| 2238 | 2105 | ||
| 2239 | if (boot_cpu_data.x86 >= 0x10) { | 2106 | if (boot_cpu_data.x86 >= 0x10) { |
| 2240 | if (!dct_ganging_enabled(pvt)) { | 2107 | if (!dct_ganging_enabled(pvt)) { |
| 2241 | amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCLR_1, &pvt->dclr1); | 2108 | amd64_read_pci_cfg(pvt->F2, F10_DCLR_1, &pvt->dclr1); |
| 2242 | amd64_read_pci_cfg(pvt->dram_f2_ctl, F10_DCHR_1, &pvt->dchr1); | 2109 | amd64_read_pci_cfg(pvt->F2, F10_DCHR_1, &pvt->dchr1); |
| 2243 | } | 2110 | } |
| 2244 | amd64_read_pci_cfg(pvt->misc_f3_ctl, EXT_NB_MCA_CFG, &tmp); | 2111 | amd64_read_pci_cfg(pvt->F3, EXT_NB_MCA_CFG, &tmp); |
| 2245 | } | 2112 | } |
| 2246 | 2113 | ||
| 2247 | if (boot_cpu_data.x86 == 0x10 && | 2114 | if (boot_cpu_data.x86 == 0x10 && |
| @@ -2321,21 +2188,22 @@ static u32 amd64_csrow_nr_pages(int csrow_nr, struct amd64_pvt *pvt) | |||
| 2321 | * Initialize the array of csrow attribute instances, based on the values | 2188 | * Initialize the array of csrow attribute instances, based on the values |
| 2322 | * from pci config hardware registers. | 2189 | * from pci config hardware registers. |
| 2323 | */ | 2190 | */ |
| 2324 | static int amd64_init_csrows(struct mem_ctl_info *mci) | 2191 | static int init_csrows(struct mem_ctl_info *mci) |
| 2325 | { | 2192 | { |
| 2326 | struct csrow_info *csrow; | 2193 | struct csrow_info *csrow; |
| 2327 | struct amd64_pvt *pvt; | 2194 | struct amd64_pvt *pvt = mci->pvt_info; |
| 2328 | u64 input_addr_min, input_addr_max, sys_addr; | 2195 | u64 input_addr_min, input_addr_max, sys_addr; |
| 2196 | u32 val; | ||
| 2329 | int i, empty = 1; | 2197 | int i, empty = 1; |
| 2330 | 2198 | ||
| 2331 | pvt = mci->pvt_info; | 2199 | amd64_read_pci_cfg(pvt->F3, K8_NBCFG, &val); |
| 2332 | 2200 | ||
| 2333 | amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCFG, &pvt->nbcfg); | 2201 | pvt->nbcfg = val; |
| 2202 | pvt->ctl_error_info.nbcfg = val; | ||
| 2334 | 2203 | ||
| 2335 | debugf0("NBCFG= 0x%x CHIPKILL= %s DRAM ECC= %s\n", pvt->nbcfg, | 2204 | debugf0("node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n", |
| 2336 | (pvt->nbcfg & K8_NBCFG_CHIPKILL) ? "Enabled" : "Disabled", | 2205 | pvt->mc_node_id, val, |
| 2337 | (pvt->nbcfg & K8_NBCFG_ECC_ENABLE) ? "Enabled" : "Disabled" | 2206 | !!(val & K8_NBCFG_CHIPKILL), !!(val & K8_NBCFG_ECC_ENABLE)); |
| 2338 | ); | ||
| 2339 | 2207 | ||
| 2340 | for (i = 0; i < pvt->cs_count; i++) { | 2208 | for (i = 0; i < pvt->cs_count; i++) { |
| 2341 | csrow = &mci->csrows[i]; | 2209 | csrow = &mci->csrows[i]; |
| @@ -2359,7 +2227,7 @@ static int amd64_init_csrows(struct mem_ctl_info *mci) | |||
| 2359 | csrow->page_mask = ~mask_from_dct_mask(pvt, i); | 2227 | csrow->page_mask = ~mask_from_dct_mask(pvt, i); |
| 2360 | /* 8 bytes of resolution */ | 2228 | /* 8 bytes of resolution */ |
| 2361 | 2229 | ||
| 2362 | csrow->mtype = amd64_determine_memory_type(pvt); | 2230 | csrow->mtype = amd64_determine_memory_type(pvt, i); |
| 2363 | 2231 | ||
| 2364 | debugf1(" for MC node %d csrow %d:\n", pvt->mc_node_id, i); | 2232 | debugf1(" for MC node %d csrow %d:\n", pvt->mc_node_id, i); |
| 2365 | debugf1(" input_addr_min: 0x%lx input_addr_max: 0x%lx\n", | 2233 | debugf1(" input_addr_min: 0x%lx input_addr_max: 0x%lx\n", |
| @@ -2404,8 +2272,7 @@ static bool amd64_nb_mce_bank_enabled_on_node(int nid) | |||
| 2404 | bool ret = false; | 2272 | bool ret = false; |
| 2405 | 2273 | ||
| 2406 | if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) { | 2274 | if (!zalloc_cpumask_var(&mask, GFP_KERNEL)) { |
| 2407 | amd64_printk(KERN_WARNING, "%s: error allocating mask\n", | 2275 | amd64_warn("%s: Error allocating mask\n", __func__); |
| 2408 | __func__); | ||
| 2409 | return false; | 2276 | return false; |
| 2410 | } | 2277 | } |
| 2411 | 2278 | ||
| @@ -2431,18 +2298,17 @@ out: | |||
| 2431 | return ret; | 2298 | return ret; |
| 2432 | } | 2299 | } |
| 2433 | 2300 | ||
| 2434 | static int amd64_toggle_ecc_err_reporting(struct amd64_pvt *pvt, bool on) | 2301 | static int toggle_ecc_err_reporting(struct ecc_settings *s, u8 nid, bool on) |
| 2435 | { | 2302 | { |
| 2436 | cpumask_var_t cmask; | 2303 | cpumask_var_t cmask; |
| 2437 | int cpu; | 2304 | int cpu; |
| 2438 | 2305 | ||
| 2439 | if (!zalloc_cpumask_var(&cmask, GFP_KERNEL)) { | 2306 | if (!zalloc_cpumask_var(&cmask, GFP_KERNEL)) { |
| 2440 | amd64_printk(KERN_WARNING, "%s: error allocating mask\n", | 2307 | amd64_warn("%s: error allocating mask\n", __func__); |
| 2441 | __func__); | ||
| 2442 | return false; | 2308 | return false; |
| 2443 | } | 2309 | } |
| 2444 | 2310 | ||
| 2445 | get_cpus_on_this_dct_cpumask(cmask, pvt->mc_node_id); | 2311 | get_cpus_on_this_dct_cpumask(cmask, nid); |
| 2446 | 2312 | ||
| 2447 | rdmsr_on_cpus(cmask, MSR_IA32_MCG_CTL, msrs); | 2313 | rdmsr_on_cpus(cmask, MSR_IA32_MCG_CTL, msrs); |
| 2448 | 2314 | ||
| @@ -2452,14 +2318,14 @@ static int amd64_toggle_ecc_err_reporting(struct amd64_pvt *pvt, bool on) | |||
| 2452 | 2318 | ||
| 2453 | if (on) { | 2319 | if (on) { |
| 2454 | if (reg->l & K8_MSR_MCGCTL_NBE) | 2320 | if (reg->l & K8_MSR_MCGCTL_NBE) |
| 2455 | pvt->flags.nb_mce_enable = 1; | 2321 | s->flags.nb_mce_enable = 1; |
| 2456 | 2322 | ||
| 2457 | reg->l |= K8_MSR_MCGCTL_NBE; | 2323 | reg->l |= K8_MSR_MCGCTL_NBE; |
| 2458 | } else { | 2324 | } else { |
| 2459 | /* | 2325 | /* |
| 2460 | * Turn off NB MCE reporting only when it was off before | 2326 | * Turn off NB MCE reporting only when it was off before |
| 2461 | */ | 2327 | */ |
| 2462 | if (!pvt->flags.nb_mce_enable) | 2328 | if (!s->flags.nb_mce_enable) |
| 2463 | reg->l &= ~K8_MSR_MCGCTL_NBE; | 2329 | reg->l &= ~K8_MSR_MCGCTL_NBE; |
| 2464 | } | 2330 | } |
| 2465 | } | 2331 | } |
| @@ -2470,92 +2336,92 @@ static int amd64_toggle_ecc_err_reporting(struct amd64_pvt *pvt, bool on) | |||
| 2470 | return 0; | 2336 | return 0; |
| 2471 | } | 2337 | } |
| 2472 | 2338 | ||
| 2473 | static void amd64_enable_ecc_error_reporting(struct mem_ctl_info *mci) | 2339 | static bool enable_ecc_error_reporting(struct ecc_settings *s, u8 nid, |
| 2340 | struct pci_dev *F3) | ||
| 2474 | { | 2341 | { |
| 2475 | struct amd64_pvt *pvt = mci->pvt_info; | 2342 | bool ret = true; |
| 2476 | u32 value, mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn; | 2343 | u32 value, mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn; |
| 2477 | 2344 | ||
| 2478 | amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCTL, &value); | 2345 | if (toggle_ecc_err_reporting(s, nid, ON)) { |
| 2346 | amd64_warn("Error enabling ECC reporting over MCGCTL!\n"); | ||
| 2347 | return false; | ||
| 2348 | } | ||
| 2349 | |||
| 2350 | amd64_read_pci_cfg(F3, K8_NBCTL, &value); | ||
| 2479 | 2351 | ||
| 2480 | /* turn on UECCn and CECCEn bits */ | 2352 | /* turn on UECCEn and CECCEn bits */ |
| 2481 | pvt->old_nbctl = value & mask; | 2353 | s->old_nbctl = value & mask; |
| 2482 | pvt->nbctl_mcgctl_saved = 1; | 2354 | s->nbctl_valid = true; |
| 2483 | 2355 | ||
| 2484 | value |= mask; | 2356 | value |= mask; |
| 2485 | pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCTL, value); | 2357 | pci_write_config_dword(F3, K8_NBCTL, value); |
| 2486 | |||
| 2487 | if (amd64_toggle_ecc_err_reporting(pvt, ON)) | ||
| 2488 | amd64_printk(KERN_WARNING, "Error enabling ECC reporting over " | ||
| 2489 | "MCGCTL!\n"); | ||
| 2490 | 2358 | ||
| 2491 | amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCFG, &value); | 2359 | amd64_read_pci_cfg(F3, K8_NBCFG, &value); |
| 2492 | 2360 | ||
| 2493 | debugf0("NBCFG(1)= 0x%x CHIPKILL= %s ECC_ENABLE= %s\n", value, | 2361 | debugf0("1: node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n", |
| 2494 | (value & K8_NBCFG_CHIPKILL) ? "Enabled" : "Disabled", | 2362 | nid, value, |
| 2495 | (value & K8_NBCFG_ECC_ENABLE) ? "Enabled" : "Disabled"); | 2363 | !!(value & K8_NBCFG_CHIPKILL), !!(value & K8_NBCFG_ECC_ENABLE)); |
| 2496 | 2364 | ||
| 2497 | if (!(value & K8_NBCFG_ECC_ENABLE)) { | 2365 | if (!(value & K8_NBCFG_ECC_ENABLE)) { |
| 2498 | amd64_printk(KERN_WARNING, | 2366 | amd64_warn("DRAM ECC disabled on this node, enabling...\n"); |
| 2499 | "This node reports that DRAM ECC is " | ||
| 2500 | "currently Disabled; ENABLING now\n"); | ||
| 2501 | 2367 | ||
| 2502 | pvt->flags.nb_ecc_prev = 0; | 2368 | s->flags.nb_ecc_prev = 0; |
| 2503 | 2369 | ||
| 2504 | /* Attempt to turn on DRAM ECC Enable */ | 2370 | /* Attempt to turn on DRAM ECC Enable */ |
| 2505 | value |= K8_NBCFG_ECC_ENABLE; | 2371 | value |= K8_NBCFG_ECC_ENABLE; |
| 2506 | pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCFG, value); | 2372 | pci_write_config_dword(F3, K8_NBCFG, value); |
| 2507 | 2373 | ||
| 2508 | amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCFG, &value); | 2374 | amd64_read_pci_cfg(F3, K8_NBCFG, &value); |
| 2509 | 2375 | ||
| 2510 | if (!(value & K8_NBCFG_ECC_ENABLE)) { | 2376 | if (!(value & K8_NBCFG_ECC_ENABLE)) { |
| 2511 | amd64_printk(KERN_WARNING, | 2377 | amd64_warn("Hardware rejected DRAM ECC enable," |
| 2512 | "Hardware rejects Enabling DRAM ECC checking\n" | 2378 | "check memory DIMM configuration.\n"); |
| 2513 | "Check memory DIMM configuration\n"); | 2379 | ret = false; |
| 2514 | } else { | 2380 | } else { |
| 2515 | amd64_printk(KERN_DEBUG, | 2381 | amd64_info("Hardware accepted DRAM ECC Enable\n"); |
| 2516 | "Hardware accepted DRAM ECC Enable\n"); | ||
| 2517 | } | 2382 | } |
| 2518 | } else { | 2383 | } else { |
| 2519 | pvt->flags.nb_ecc_prev = 1; | 2384 | s->flags.nb_ecc_prev = 1; |
| 2520 | } | 2385 | } |
| 2521 | 2386 | ||
| 2522 | debugf0("NBCFG(2)= 0x%x CHIPKILL= %s ECC_ENABLE= %s\n", value, | 2387 | debugf0("2: node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n", |
| 2523 | (value & K8_NBCFG_CHIPKILL) ? "Enabled" : "Disabled", | 2388 | nid, value, |
| 2524 | (value & K8_NBCFG_ECC_ENABLE) ? "Enabled" : "Disabled"); | 2389 | !!(value & K8_NBCFG_CHIPKILL), !!(value & K8_NBCFG_ECC_ENABLE)); |
| 2525 | 2390 | ||
| 2526 | pvt->ctl_error_info.nbcfg = value; | 2391 | return ret; |
| 2527 | } | 2392 | } |
| 2528 | 2393 | ||
| 2529 | static void amd64_restore_ecc_error_reporting(struct amd64_pvt *pvt) | 2394 | static void restore_ecc_error_reporting(struct ecc_settings *s, u8 nid, |
| 2395 | struct pci_dev *F3) | ||
| 2530 | { | 2396 | { |
| 2531 | u32 value, mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn; | 2397 | u32 value, mask = K8_NBCTL_CECCEn | K8_NBCTL_UECCEn; |
| 2532 | 2398 | ||
| 2533 | if (!pvt->nbctl_mcgctl_saved) | 2399 | if (!s->nbctl_valid) |
| 2534 | return; | 2400 | return; |
| 2535 | 2401 | ||
| 2536 | amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCTL, &value); | 2402 | amd64_read_pci_cfg(F3, K8_NBCTL, &value); |
| 2537 | value &= ~mask; | 2403 | value &= ~mask; |
| 2538 | value |= pvt->old_nbctl; | 2404 | value |= s->old_nbctl; |
| 2539 | 2405 | ||
| 2540 | pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCTL, value); | 2406 | pci_write_config_dword(F3, K8_NBCTL, value); |
| 2541 | 2407 | ||
| 2542 | /* restore previous BIOS DRAM ECC "off" setting which we force-enabled */ | 2408 | /* restore previous BIOS DRAM ECC "off" setting we force-enabled */ |
| 2543 | if (!pvt->flags.nb_ecc_prev) { | 2409 | if (!s->flags.nb_ecc_prev) { |
| 2544 | amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCFG, &value); | 2410 | amd64_read_pci_cfg(F3, K8_NBCFG, &value); |
| 2545 | value &= ~K8_NBCFG_ECC_ENABLE; | 2411 | value &= ~K8_NBCFG_ECC_ENABLE; |
| 2546 | pci_write_config_dword(pvt->misc_f3_ctl, K8_NBCFG, value); | 2412 | pci_write_config_dword(F3, K8_NBCFG, value); |
| 2547 | } | 2413 | } |
| 2548 | 2414 | ||
| 2549 | /* restore the NB Enable MCGCTL bit */ | 2415 | /* restore the NB Enable MCGCTL bit */ |
| 2550 | if (amd64_toggle_ecc_err_reporting(pvt, OFF)) | 2416 | if (toggle_ecc_err_reporting(s, nid, OFF)) |
| 2551 | amd64_printk(KERN_WARNING, "Error restoring NB MCGCTL settings!\n"); | 2417 | amd64_warn("Error restoring NB MCGCTL settings!\n"); |
| 2552 | } | 2418 | } |
| 2553 | 2419 | ||
| 2554 | /* | 2420 | /* |
| 2555 | * EDAC requires that the BIOS have ECC enabled before taking over the | 2421 | * EDAC requires that the BIOS have ECC enabled before |
| 2556 | * processing of ECC errors. This is because the BIOS can properly initialize | 2422 | * taking over the processing of ECC errors. A command line |
| 2557 | * the memory system completely. A command line option allows to force-enable | 2423 | * option allows to force-enable hardware ECC later in |
| 2558 | * hardware ECC later in amd64_enable_ecc_error_reporting(). | 2424 | * enable_ecc_error_reporting(). |
| 2559 | */ | 2425 | */ |
| 2560 | static const char *ecc_msg = | 2426 | static const char *ecc_msg = |
| 2561 | "ECC disabled in the BIOS or no ECC capability, module will not load.\n" | 2427 | "ECC disabled in the BIOS or no ECC capability, module will not load.\n" |
| @@ -2563,38 +2429,28 @@ static const char *ecc_msg = | |||
| 2563 | "'ecc_enable_override'.\n" | 2429 | "'ecc_enable_override'.\n" |
| 2564 | " (Note that use of the override may cause unknown side effects.)\n"; | 2430 | " (Note that use of the override may cause unknown side effects.)\n"; |
| 2565 | 2431 | ||
| 2566 | static int amd64_check_ecc_enabled(struct amd64_pvt *pvt) | 2432 | static bool ecc_enabled(struct pci_dev *F3, u8 nid) |
| 2567 | { | 2433 | { |
| 2568 | u32 value; | 2434 | u32 value; |
| 2569 | u8 ecc_enabled = 0; | 2435 | u8 ecc_en = 0; |
| 2570 | bool nb_mce_en = false; | 2436 | bool nb_mce_en = false; |
| 2571 | 2437 | ||
| 2572 | amd64_read_pci_cfg(pvt->misc_f3_ctl, K8_NBCFG, &value); | 2438 | amd64_read_pci_cfg(F3, K8_NBCFG, &value); |
| 2573 | 2439 | ||
| 2574 | ecc_enabled = !!(value & K8_NBCFG_ECC_ENABLE); | 2440 | ecc_en = !!(value & K8_NBCFG_ECC_ENABLE); |
| 2575 | if (!ecc_enabled) | 2441 | amd64_info("DRAM ECC %s.\n", (ecc_en ? "enabled" : "disabled")); |
| 2576 | amd64_printk(KERN_NOTICE, "This node reports that Memory ECC " | ||
| 2577 | "is currently disabled, set F3x%x[22] (%s).\n", | ||
| 2578 | K8_NBCFG, pci_name(pvt->misc_f3_ctl)); | ||
| 2579 | else | ||
| 2580 | amd64_printk(KERN_INFO, "ECC is enabled by BIOS.\n"); | ||
| 2581 | 2442 | ||
| 2582 | nb_mce_en = amd64_nb_mce_bank_enabled_on_node(pvt->mc_node_id); | 2443 | nb_mce_en = amd64_nb_mce_bank_enabled_on_node(nid); |
| 2583 | if (!nb_mce_en) | 2444 | if (!nb_mce_en) |
| 2584 | amd64_printk(KERN_NOTICE, "NB MCE bank disabled, set MSR " | 2445 | amd64_notice("NB MCE bank disabled, set MSR " |
| 2585 | "0x%08x[4] on node %d to enable.\n", | 2446 | "0x%08x[4] on node %d to enable.\n", |
| 2586 | MSR_IA32_MCG_CTL, pvt->mc_node_id); | 2447 | MSR_IA32_MCG_CTL, nid); |
| 2587 | 2448 | ||
| 2588 | if (!ecc_enabled || !nb_mce_en) { | 2449 | if (!ecc_en || !nb_mce_en) { |
| 2589 | if (!ecc_enable_override) { | 2450 | amd64_notice("%s", ecc_msg); |
| 2590 | amd64_printk(KERN_NOTICE, "%s", ecc_msg); | 2451 | return false; |
| 2591 | return -ENODEV; | ||
| 2592 | } else { | ||
| 2593 | amd64_printk(KERN_WARNING, "Forcing ECC checking on!\n"); | ||
| 2594 | } | ||
| 2595 | } | 2452 | } |
| 2596 | 2453 | return true; | |
| 2597 | return 0; | ||
| 2598 | } | 2454 | } |
| 2599 | 2455 | ||
| 2600 | struct mcidev_sysfs_attribute sysfs_attrs[ARRAY_SIZE(amd64_dbg_attrs) + | 2456 | struct mcidev_sysfs_attribute sysfs_attrs[ARRAY_SIZE(amd64_dbg_attrs) + |
| @@ -2603,22 +2459,23 @@ struct mcidev_sysfs_attribute sysfs_attrs[ARRAY_SIZE(amd64_dbg_attrs) + | |||
| 2603 | 2459 | ||
| 2604 | struct mcidev_sysfs_attribute terminator = { .attr = { .name = NULL } }; | 2460 | struct mcidev_sysfs_attribute terminator = { .attr = { .name = NULL } }; |
| 2605 | 2461 | ||
| 2606 | static void amd64_set_mc_sysfs_attributes(struct mem_ctl_info *mci) | 2462 | static void set_mc_sysfs_attrs(struct mem_ctl_info *mci) |
| 2607 | { | 2463 | { |
| 2608 | unsigned int i = 0, j = 0; | 2464 | unsigned int i = 0, j = 0; |
| 2609 | 2465 | ||
| 2610 | for (; i < ARRAY_SIZE(amd64_dbg_attrs); i++) | 2466 | for (; i < ARRAY_SIZE(amd64_dbg_attrs); i++) |
| 2611 | sysfs_attrs[i] = amd64_dbg_attrs[i]; | 2467 | sysfs_attrs[i] = amd64_dbg_attrs[i]; |
| 2612 | 2468 | ||
| 2613 | for (j = 0; j < ARRAY_SIZE(amd64_inj_attrs); j++, i++) | 2469 | if (boot_cpu_data.x86 >= 0x10) |
| 2614 | sysfs_attrs[i] = amd64_inj_attrs[j]; | 2470 | for (j = 0; j < ARRAY_SIZE(amd64_inj_attrs); j++, i++) |
| 2471 | sysfs_attrs[i] = amd64_inj_attrs[j]; | ||
| 2615 | 2472 | ||
| 2616 | sysfs_attrs[i] = terminator; | 2473 | sysfs_attrs[i] = terminator; |
| 2617 | 2474 | ||
| 2618 | mci->mc_driver_sysfs_attributes = sysfs_attrs; | 2475 | mci->mc_driver_sysfs_attributes = sysfs_attrs; |
| 2619 | } | 2476 | } |
| 2620 | 2477 | ||
| 2621 | static void amd64_setup_mci_misc_attributes(struct mem_ctl_info *mci) | 2478 | static void setup_mci_misc_attrs(struct mem_ctl_info *mci) |
| 2622 | { | 2479 | { |
| 2623 | struct amd64_pvt *pvt = mci->pvt_info; | 2480 | struct amd64_pvt *pvt = mci->pvt_info; |
| 2624 | 2481 | ||
| @@ -2634,8 +2491,8 @@ static void amd64_setup_mci_misc_attributes(struct mem_ctl_info *mci) | |||
| 2634 | mci->edac_cap = amd64_determine_edac_cap(pvt); | 2491 | mci->edac_cap = amd64_determine_edac_cap(pvt); |
| 2635 | mci->mod_name = EDAC_MOD_STR; | 2492 | mci->mod_name = EDAC_MOD_STR; |
| 2636 | mci->mod_ver = EDAC_AMD64_VERSION; | 2493 | mci->mod_ver = EDAC_AMD64_VERSION; |
| 2637 | mci->ctl_name = get_amd_family_name(pvt->mc_type_index); | 2494 | mci->ctl_name = pvt->ctl_name; |
| 2638 | mci->dev_name = pci_name(pvt->dram_f2_ctl); | 2495 | mci->dev_name = pci_name(pvt->F2); |
| 2639 | mci->ctl_page_to_phys = NULL; | 2496 | mci->ctl_page_to_phys = NULL; |
| 2640 | 2497 | ||
| 2641 | /* memory scrubber interface */ | 2498 | /* memory scrubber interface */ |
| @@ -2644,111 +2501,94 @@ static void amd64_setup_mci_misc_attributes(struct mem_ctl_info *mci) | |||
| 2644 | } | 2501 | } |
| 2645 | 2502 | ||
| 2646 | /* | 2503 | /* |
| 2647 | * Init stuff for this DRAM Controller device. | 2504 | * returns a pointer to the family descriptor on success, NULL otherwise. |
| 2648 | * | ||
| 2649 | * Due to a hardware feature on Fam10h CPUs, the Enable Extended Configuration | ||
| 2650 | * Space feature MUST be enabled on ALL Processors prior to actually reading | ||
| 2651 | * from the ECS registers. Since the loading of the module can occur on any | ||
| 2652 | * 'core', and cores don't 'see' all the other processors ECS data when the | ||
| 2653 | * others are NOT enabled. Our solution is to first enable ECS access in this | ||
| 2654 | * routine on all processors, gather some data in a amd64_pvt structure and | ||
| 2655 | * later come back in a finish-setup function to perform that final | ||
| 2656 | * initialization. See also amd64_init_2nd_stage() for that. | ||
| 2657 | */ | 2505 | */ |
| 2658 | static int amd64_probe_one_instance(struct pci_dev *dram_f2_ctl, | 2506 | static struct amd64_family_type *amd64_per_family_init(struct amd64_pvt *pvt) |
| 2659 | int mc_type_index) | 2507 | { |
| 2508 | u8 fam = boot_cpu_data.x86; | ||
| 2509 | struct amd64_family_type *fam_type = NULL; | ||
| 2510 | |||
| 2511 | switch (fam) { | ||
| 2512 | case 0xf: | ||
| 2513 | fam_type = &amd64_family_types[K8_CPUS]; | ||
| 2514 | pvt->ops = &amd64_family_types[K8_CPUS].ops; | ||
| 2515 | pvt->ctl_name = fam_type->ctl_name; | ||
| 2516 | pvt->min_scrubrate = K8_MIN_SCRUB_RATE_BITS; | ||
| 2517 | break; | ||
| 2518 | case 0x10: | ||
| 2519 | fam_type = &amd64_family_types[F10_CPUS]; | ||
| 2520 | pvt->ops = &amd64_family_types[F10_CPUS].ops; | ||
| 2521 | pvt->ctl_name = fam_type->ctl_name; | ||
| 2522 | pvt->min_scrubrate = F10_MIN_SCRUB_RATE_BITS; | ||
| 2523 | break; | ||
| 2524 | |||
| 2525 | default: | ||
| 2526 | amd64_err("Unsupported family!\n"); | ||
| 2527 | return NULL; | ||
| 2528 | } | ||
| 2529 | |||
| 2530 | pvt->ext_model = boot_cpu_data.x86_model >> 4; | ||
| 2531 | |||
| 2532 | amd64_info("%s %sdetected (node %d).\n", pvt->ctl_name, | ||
| 2533 | (fam == 0xf ? | ||
| 2534 | (pvt->ext_model >= K8_REV_F ? "revF or later " | ||
| 2535 | : "revE or earlier ") | ||
| 2536 | : ""), pvt->mc_node_id); | ||
| 2537 | return fam_type; | ||
| 2538 | } | ||
| 2539 | |||
| 2540 | static int amd64_init_one_instance(struct pci_dev *F2) | ||
| 2660 | { | 2541 | { |
| 2661 | struct amd64_pvt *pvt = NULL; | 2542 | struct amd64_pvt *pvt = NULL; |
| 2543 | struct amd64_family_type *fam_type = NULL; | ||
| 2544 | struct mem_ctl_info *mci = NULL; | ||
| 2662 | int err = 0, ret; | 2545 | int err = 0, ret; |
| 2546 | u8 nid = get_node_id(F2); | ||
| 2663 | 2547 | ||
| 2664 | ret = -ENOMEM; | 2548 | ret = -ENOMEM; |
| 2665 | pvt = kzalloc(sizeof(struct amd64_pvt), GFP_KERNEL); | 2549 | pvt = kzalloc(sizeof(struct amd64_pvt), GFP_KERNEL); |
| 2666 | if (!pvt) | 2550 | if (!pvt) |
| 2667 | goto err_exit; | 2551 | goto err_ret; |
| 2668 | 2552 | ||
| 2669 | pvt->mc_node_id = get_node_id(dram_f2_ctl); | 2553 | pvt->mc_node_id = nid; |
| 2554 | pvt->F2 = F2; | ||
| 2670 | 2555 | ||
| 2671 | pvt->dram_f2_ctl = dram_f2_ctl; | 2556 | ret = -EINVAL; |
| 2672 | pvt->ext_model = boot_cpu_data.x86_model >> 4; | 2557 | fam_type = amd64_per_family_init(pvt); |
| 2673 | pvt->mc_type_index = mc_type_index; | 2558 | if (!fam_type) |
| 2674 | pvt->ops = family_ops(mc_type_index); | 2559 | goto err_free; |
| 2675 | 2560 | ||
| 2676 | /* | ||
| 2677 | * We have the dram_f2_ctl device as an argument, now go reserve its | ||
| 2678 | * sibling devices from the PCI system. | ||
| 2679 | */ | ||
| 2680 | ret = -ENODEV; | 2561 | ret = -ENODEV; |
| 2681 | err = amd64_reserve_mc_sibling_devices(pvt, mc_type_index); | 2562 | err = reserve_mc_sibling_devs(pvt, fam_type->f1_id, fam_type->f3_id); |
| 2682 | if (err) | 2563 | if (err) |
| 2683 | goto err_free; | 2564 | goto err_free; |
| 2684 | 2565 | ||
| 2685 | ret = -EINVAL; | 2566 | read_mc_regs(pvt); |
| 2686 | err = amd64_check_ecc_enabled(pvt); | ||
| 2687 | if (err) | ||
| 2688 | goto err_put; | ||
| 2689 | |||
| 2690 | /* | ||
| 2691 | * Key operation here: setup of HW prior to performing ops on it. Some | ||
| 2692 | * setup is required to access ECS data. After this is performed, the | ||
| 2693 | * 'teardown' function must be called upon error and normal exit paths. | ||
| 2694 | */ | ||
| 2695 | if (boot_cpu_data.x86 >= 0x10) | ||
| 2696 | amd64_setup(pvt); | ||
| 2697 | |||
| 2698 | /* | ||
| 2699 | * Save the pointer to the private data for use in 2nd initialization | ||
| 2700 | * stage | ||
| 2701 | */ | ||
| 2702 | pvt_lookup[pvt->mc_node_id] = pvt; | ||
| 2703 | |||
| 2704 | return 0; | ||
| 2705 | |||
| 2706 | err_put: | ||
| 2707 | amd64_free_mc_sibling_devices(pvt); | ||
| 2708 | |||
| 2709 | err_free: | ||
| 2710 | kfree(pvt); | ||
| 2711 | |||
| 2712 | err_exit: | ||
| 2713 | return ret; | ||
| 2714 | } | ||
| 2715 | |||
| 2716 | /* | ||
| 2717 | * This is the finishing stage of the init code. Needs to be performed after all | ||
| 2718 | * MCs' hardware have been prepped for accessing extended config space. | ||
| 2719 | */ | ||
| 2720 | static int amd64_init_2nd_stage(struct amd64_pvt *pvt) | ||
| 2721 | { | ||
| 2722 | int node_id = pvt->mc_node_id; | ||
| 2723 | struct mem_ctl_info *mci; | ||
| 2724 | int ret = -ENODEV; | ||
| 2725 | |||
| 2726 | amd64_read_mc_registers(pvt); | ||
| 2727 | 2567 | ||
| 2728 | /* | 2568 | /* |
| 2729 | * We need to determine how many memory channels there are. Then use | 2569 | * We need to determine how many memory channels there are. Then use |
| 2730 | * that information for calculating the size of the dynamic instance | 2570 | * that information for calculating the size of the dynamic instance |
| 2731 | * tables in the 'mci' structure | 2571 | * tables in the 'mci' structure. |
| 2732 | */ | 2572 | */ |
| 2573 | ret = -EINVAL; | ||
| 2733 | pvt->channel_count = pvt->ops->early_channel_count(pvt); | 2574 | pvt->channel_count = pvt->ops->early_channel_count(pvt); |
| 2734 | if (pvt->channel_count < 0) | 2575 | if (pvt->channel_count < 0) |
| 2735 | goto err_exit; | 2576 | goto err_siblings; |
| 2736 | 2577 | ||
| 2737 | ret = -ENOMEM; | 2578 | ret = -ENOMEM; |
| 2738 | mci = edac_mc_alloc(0, pvt->cs_count, pvt->channel_count, node_id); | 2579 | mci = edac_mc_alloc(0, pvt->cs_count, pvt->channel_count, nid); |
| 2739 | if (!mci) | 2580 | if (!mci) |
| 2740 | goto err_exit; | 2581 | goto err_siblings; |
| 2741 | 2582 | ||
| 2742 | mci->pvt_info = pvt; | 2583 | mci->pvt_info = pvt; |
| 2584 | mci->dev = &pvt->F2->dev; | ||
| 2743 | 2585 | ||
| 2744 | mci->dev = &pvt->dram_f2_ctl->dev; | 2586 | setup_mci_misc_attrs(mci); |
| 2745 | amd64_setup_mci_misc_attributes(mci); | ||
| 2746 | 2587 | ||
| 2747 | if (amd64_init_csrows(mci)) | 2588 | if (init_csrows(mci)) |
| 2748 | mci->edac_cap = EDAC_FLAG_NONE; | 2589 | mci->edac_cap = EDAC_FLAG_NONE; |
| 2749 | 2590 | ||
| 2750 | amd64_enable_ecc_error_reporting(mci); | 2591 | set_mc_sysfs_attrs(mci); |
| 2751 | amd64_set_mc_sysfs_attributes(mci); | ||
| 2752 | 2592 | ||
| 2753 | ret = -ENODEV; | 2593 | ret = -ENODEV; |
| 2754 | if (edac_mc_add_mc(mci)) { | 2594 | if (edac_mc_add_mc(mci)) { |
| @@ -2756,54 +2596,77 @@ static int amd64_init_2nd_stage(struct amd64_pvt *pvt) | |||
| 2756 | goto err_add_mc; | 2596 | goto err_add_mc; |
| 2757 | } | 2597 | } |
| 2758 | 2598 | ||
| 2759 | mci_lookup[node_id] = mci; | ||
| 2760 | pvt_lookup[node_id] = NULL; | ||
| 2761 | |||
| 2762 | /* register stuff with EDAC MCE */ | 2599 | /* register stuff with EDAC MCE */ |
| 2763 | if (report_gart_errors) | 2600 | if (report_gart_errors) |
| 2764 | amd_report_gart_errors(true); | 2601 | amd_report_gart_errors(true); |
| 2765 | 2602 | ||
| 2766 | amd_register_ecc_decoder(amd64_decode_bus_error); | 2603 | amd_register_ecc_decoder(amd64_decode_bus_error); |
| 2767 | 2604 | ||
| 2605 | mcis[nid] = mci; | ||
| 2606 | |||
| 2607 | atomic_inc(&drv_instances); | ||
| 2608 | |||
| 2768 | return 0; | 2609 | return 0; |
| 2769 | 2610 | ||
| 2770 | err_add_mc: | 2611 | err_add_mc: |
| 2771 | edac_mc_free(mci); | 2612 | edac_mc_free(mci); |
| 2772 | 2613 | ||
| 2773 | err_exit: | 2614 | err_siblings: |
| 2774 | debugf0("failure to init 2nd stage: ret=%d\n", ret); | 2615 | free_mc_sibling_devs(pvt); |
| 2775 | |||
| 2776 | amd64_restore_ecc_error_reporting(pvt); | ||
| 2777 | |||
| 2778 | if (boot_cpu_data.x86 > 0xf) | ||
| 2779 | amd64_teardown(pvt); | ||
| 2780 | 2616 | ||
| 2781 | amd64_free_mc_sibling_devices(pvt); | 2617 | err_free: |
| 2782 | 2618 | kfree(pvt); | |
| 2783 | kfree(pvt_lookup[pvt->mc_node_id]); | ||
| 2784 | pvt_lookup[node_id] = NULL; | ||
| 2785 | 2619 | ||
| 2620 | err_ret: | ||
| 2786 | return ret; | 2621 | return ret; |
| 2787 | } | 2622 | } |
| 2788 | 2623 | ||
| 2789 | 2624 | static int __devinit amd64_probe_one_instance(struct pci_dev *pdev, | |
| 2790 | static int __devinit amd64_init_one_instance(struct pci_dev *pdev, | 2625 | const struct pci_device_id *mc_type) |
| 2791 | const struct pci_device_id *mc_type) | ||
| 2792 | { | 2626 | { |
| 2627 | u8 nid = get_node_id(pdev); | ||
| 2628 | struct pci_dev *F3 = node_to_amd_nb(nid)->misc; | ||
| 2629 | struct ecc_settings *s; | ||
| 2793 | int ret = 0; | 2630 | int ret = 0; |
| 2794 | 2631 | ||
| 2795 | debugf0("(MC node=%d,mc_type='%s')\n", get_node_id(pdev), | ||
| 2796 | get_amd_family_name(mc_type->driver_data)); | ||
| 2797 | |||
| 2798 | ret = pci_enable_device(pdev); | 2632 | ret = pci_enable_device(pdev); |
| 2799 | if (ret < 0) | 2633 | if (ret < 0) { |
| 2800 | ret = -EIO; | ||
| 2801 | else | ||
| 2802 | ret = amd64_probe_one_instance(pdev, mc_type->driver_data); | ||
| 2803 | |||
| 2804 | if (ret < 0) | ||
| 2805 | debugf0("ret=%d\n", ret); | 2634 | debugf0("ret=%d\n", ret); |
| 2635 | return -EIO; | ||
| 2636 | } | ||
| 2637 | |||
| 2638 | ret = -ENOMEM; | ||
| 2639 | s = kzalloc(sizeof(struct ecc_settings), GFP_KERNEL); | ||
| 2640 | if (!s) | ||
| 2641 | goto err_out; | ||
| 2642 | |||
| 2643 | ecc_stngs[nid] = s; | ||
| 2644 | |||
| 2645 | if (!ecc_enabled(F3, nid)) { | ||
| 2646 | ret = -ENODEV; | ||
| 2647 | |||
| 2648 | if (!ecc_enable_override) | ||
| 2649 | goto err_enable; | ||
| 2650 | |||
| 2651 | amd64_warn("Forcing ECC on!\n"); | ||
| 2652 | |||
| 2653 | if (!enable_ecc_error_reporting(s, nid, F3)) | ||
| 2654 | goto err_enable; | ||
| 2655 | } | ||
| 2806 | 2656 | ||
| 2657 | ret = amd64_init_one_instance(pdev); | ||
| 2658 | if (ret < 0) { | ||
| 2659 | amd64_err("Error probing instance: %d\n", nid); | ||
| 2660 | restore_ecc_error_reporting(s, nid, F3); | ||
| 2661 | } | ||
| 2662 | |||
| 2663 | return ret; | ||
| 2664 | |||
| 2665 | err_enable: | ||
| 2666 | kfree(s); | ||
| 2667 | ecc_stngs[nid] = NULL; | ||
| 2668 | |||
| 2669 | err_out: | ||
| 2807 | return ret; | 2670 | return ret; |
| 2808 | } | 2671 | } |
| 2809 | 2672 | ||
| @@ -2811,6 +2674,9 @@ static void __devexit amd64_remove_one_instance(struct pci_dev *pdev) | |||
| 2811 | { | 2674 | { |
| 2812 | struct mem_ctl_info *mci; | 2675 | struct mem_ctl_info *mci; |
| 2813 | struct amd64_pvt *pvt; | 2676 | struct amd64_pvt *pvt; |
| 2677 | u8 nid = get_node_id(pdev); | ||
| 2678 | struct pci_dev *F3 = node_to_amd_nb(nid)->misc; | ||
| 2679 | struct ecc_settings *s = ecc_stngs[nid]; | ||
| 2814 | 2680 | ||
| 2815 | /* Remove from EDAC CORE tracking list */ | 2681 | /* Remove from EDAC CORE tracking list */ |
| 2816 | mci = edac_mc_del_mc(&pdev->dev); | 2682 | mci = edac_mc_del_mc(&pdev->dev); |
| @@ -2819,20 +2685,20 @@ static void __devexit amd64_remove_one_instance(struct pci_dev *pdev) | |||
| 2819 | 2685 | ||
| 2820 | pvt = mci->pvt_info; | 2686 | pvt = mci->pvt_info; |
| 2821 | 2687 | ||
| 2822 | amd64_restore_ecc_error_reporting(pvt); | 2688 | restore_ecc_error_reporting(s, nid, F3); |
| 2823 | 2689 | ||
| 2824 | if (boot_cpu_data.x86 > 0xf) | 2690 | free_mc_sibling_devs(pvt); |
| 2825 | amd64_teardown(pvt); | ||
| 2826 | |||
| 2827 | amd64_free_mc_sibling_devices(pvt); | ||
| 2828 | 2691 | ||
| 2829 | /* unregister from EDAC MCE */ | 2692 | /* unregister from EDAC MCE */ |
| 2830 | amd_report_gart_errors(false); | 2693 | amd_report_gart_errors(false); |
| 2831 | amd_unregister_ecc_decoder(amd64_decode_bus_error); | 2694 | amd_unregister_ecc_decoder(amd64_decode_bus_error); |
| 2832 | 2695 | ||
| 2696 | kfree(ecc_stngs[nid]); | ||
| 2697 | ecc_stngs[nid] = NULL; | ||
| 2698 | |||
| 2833 | /* Free the EDAC CORE resources */ | 2699 | /* Free the EDAC CORE resources */ |
| 2834 | mci->pvt_info = NULL; | 2700 | mci->pvt_info = NULL; |
| 2835 | mci_lookup[pvt->mc_node_id] = NULL; | 2701 | mcis[nid] = NULL; |
| 2836 | 2702 | ||
| 2837 | kfree(pvt); | 2703 | kfree(pvt); |
| 2838 | edac_mc_free(mci); | 2704 | edac_mc_free(mci); |
| @@ -2851,7 +2717,6 @@ static const struct pci_device_id amd64_pci_table[] __devinitdata = { | |||
| 2851 | .subdevice = PCI_ANY_ID, | 2717 | .subdevice = PCI_ANY_ID, |
| 2852 | .class = 0, | 2718 | .class = 0, |
| 2853 | .class_mask = 0, | 2719 | .class_mask = 0, |
| 2854 | .driver_data = K8_CPUS | ||
| 2855 | }, | 2720 | }, |
| 2856 | { | 2721 | { |
| 2857 | .vendor = PCI_VENDOR_ID_AMD, | 2722 | .vendor = PCI_VENDOR_ID_AMD, |
| @@ -2860,16 +2725,6 @@ static const struct pci_device_id amd64_pci_table[] __devinitdata = { | |||
| 2860 | .subdevice = PCI_ANY_ID, | 2725 | .subdevice = PCI_ANY_ID, |
| 2861 | .class = 0, | 2726 | .class = 0, |
| 2862 | .class_mask = 0, | 2727 | .class_mask = 0, |
| 2863 | .driver_data = F10_CPUS | ||
| 2864 | }, | ||
| 2865 | { | ||
| 2866 | .vendor = PCI_VENDOR_ID_AMD, | ||
| 2867 | .device = PCI_DEVICE_ID_AMD_11H_NB_DRAM, | ||
| 2868 | .subvendor = PCI_ANY_ID, | ||
| 2869 | .subdevice = PCI_ANY_ID, | ||
| 2870 | .class = 0, | ||
| 2871 | .class_mask = 0, | ||
| 2872 | .driver_data = F11_CPUS | ||
| 2873 | }, | 2728 | }, |
| 2874 | {0, } | 2729 | {0, } |
| 2875 | }; | 2730 | }; |
| @@ -2877,12 +2732,12 @@ MODULE_DEVICE_TABLE(pci, amd64_pci_table); | |||
| 2877 | 2732 | ||
| 2878 | static struct pci_driver amd64_pci_driver = { | 2733 | static struct pci_driver amd64_pci_driver = { |
| 2879 | .name = EDAC_MOD_STR, | 2734 | .name = EDAC_MOD_STR, |
| 2880 | .probe = amd64_init_one_instance, | 2735 | .probe = amd64_probe_one_instance, |
| 2881 | .remove = __devexit_p(amd64_remove_one_instance), | 2736 | .remove = __devexit_p(amd64_remove_one_instance), |
| 2882 | .id_table = amd64_pci_table, | 2737 | .id_table = amd64_pci_table, |
| 2883 | }; | 2738 | }; |
| 2884 | 2739 | ||
| 2885 | static void amd64_setup_pci_device(void) | 2740 | static void setup_pci_device(void) |
| 2886 | { | 2741 | { |
| 2887 | struct mem_ctl_info *mci; | 2742 | struct mem_ctl_info *mci; |
| 2888 | struct amd64_pvt *pvt; | 2743 | struct amd64_pvt *pvt; |
| @@ -2890,13 +2745,12 @@ static void amd64_setup_pci_device(void) | |||
| 2890 | if (amd64_ctl_pci) | 2745 | if (amd64_ctl_pci) |
| 2891 | return; | 2746 | return; |
| 2892 | 2747 | ||
| 2893 | mci = mci_lookup[0]; | 2748 | mci = mcis[0]; |
| 2894 | if (mci) { | 2749 | if (mci) { |
| 2895 | 2750 | ||
| 2896 | pvt = mci->pvt_info; | 2751 | pvt = mci->pvt_info; |
| 2897 | amd64_ctl_pci = | 2752 | amd64_ctl_pci = |
| 2898 | edac_pci_create_generic_ctl(&pvt->dram_f2_ctl->dev, | 2753 | edac_pci_create_generic_ctl(&pvt->F2->dev, EDAC_MOD_STR); |
| 2899 | EDAC_MOD_STR); | ||
| 2900 | 2754 | ||
| 2901 | if (!amd64_ctl_pci) { | 2755 | if (!amd64_ctl_pci) { |
| 2902 | pr_warning("%s(): Unable to create PCI control\n", | 2756 | pr_warning("%s(): Unable to create PCI control\n", |
| @@ -2910,8 +2764,7 @@ static void amd64_setup_pci_device(void) | |||
| 2910 | 2764 | ||
| 2911 | static int __init amd64_edac_init(void) | 2765 | static int __init amd64_edac_init(void) |
| 2912 | { | 2766 | { |
| 2913 | int nb, err = -ENODEV; | 2767 | int err = -ENODEV; |
| 2914 | bool load_ok = false; | ||
| 2915 | 2768 | ||
| 2916 | edac_printk(KERN_INFO, EDAC_MOD_STR, EDAC_AMD64_VERSION "\n"); | 2769 | edac_printk(KERN_INFO, EDAC_MOD_STR, EDAC_AMD64_VERSION "\n"); |
| 2917 | 2770 | ||
| @@ -2920,41 +2773,41 @@ static int __init amd64_edac_init(void) | |||
| 2920 | if (amd_cache_northbridges() < 0) | 2773 | if (amd_cache_northbridges() < 0) |
| 2921 | goto err_ret; | 2774 | goto err_ret; |
| 2922 | 2775 | ||
| 2776 | err = -ENOMEM; | ||
| 2777 | mcis = kzalloc(amd_nb_num() * sizeof(mcis[0]), GFP_KERNEL); | ||
| 2778 | ecc_stngs = kzalloc(amd_nb_num() * sizeof(ecc_stngs[0]), GFP_KERNEL); | ||
| 2779 | if (!(mcis && ecc_stngs)) | ||
| 2780 | goto err_ret; | ||
| 2781 | |||
| 2923 | msrs = msrs_alloc(); | 2782 | msrs = msrs_alloc(); |
| 2924 | if (!msrs) | 2783 | if (!msrs) |
| 2925 | goto err_ret; | 2784 | goto err_free; |
| 2926 | 2785 | ||
| 2927 | err = pci_register_driver(&amd64_pci_driver); | 2786 | err = pci_register_driver(&amd64_pci_driver); |
| 2928 | if (err) | 2787 | if (err) |
| 2929 | goto err_pci; | 2788 | goto err_pci; |
| 2930 | 2789 | ||
| 2931 | /* | ||
| 2932 | * At this point, the array 'pvt_lookup[]' contains pointers to alloc'd | ||
| 2933 | * amd64_pvt structs. These will be used in the 2nd stage init function | ||
| 2934 | * to finish initialization of the MC instances. | ||
| 2935 | */ | ||
| 2936 | err = -ENODEV; | 2790 | err = -ENODEV; |
| 2937 | for (nb = 0; nb < amd_nb_num(); nb++) { | 2791 | if (!atomic_read(&drv_instances)) |
| 2938 | if (!pvt_lookup[nb]) | 2792 | goto err_no_instances; |
| 2939 | continue; | ||
| 2940 | |||
| 2941 | err = amd64_init_2nd_stage(pvt_lookup[nb]); | ||
| 2942 | if (err) | ||
| 2943 | goto err_2nd_stage; | ||
| 2944 | 2793 | ||
| 2945 | load_ok = true; | 2794 | setup_pci_device(); |
| 2946 | } | 2795 | return 0; |
| 2947 | |||
| 2948 | if (load_ok) { | ||
| 2949 | amd64_setup_pci_device(); | ||
| 2950 | return 0; | ||
| 2951 | } | ||
| 2952 | 2796 | ||
| 2953 | err_2nd_stage: | 2797 | err_no_instances: |
| 2954 | pci_unregister_driver(&amd64_pci_driver); | 2798 | pci_unregister_driver(&amd64_pci_driver); |
| 2799 | |||
| 2955 | err_pci: | 2800 | err_pci: |
| 2956 | msrs_free(msrs); | 2801 | msrs_free(msrs); |
| 2957 | msrs = NULL; | 2802 | msrs = NULL; |
| 2803 | |||
| 2804 | err_free: | ||
| 2805 | kfree(mcis); | ||
| 2806 | mcis = NULL; | ||
| 2807 | |||
| 2808 | kfree(ecc_stngs); | ||
| 2809 | ecc_stngs = NULL; | ||
| 2810 | |||
| 2958 | err_ret: | 2811 | err_ret: |
| 2959 | return err; | 2812 | return err; |
| 2960 | } | 2813 | } |
| @@ -2966,6 +2819,12 @@ static void __exit amd64_edac_exit(void) | |||
| 2966 | 2819 | ||
| 2967 | pci_unregister_driver(&amd64_pci_driver); | 2820 | pci_unregister_driver(&amd64_pci_driver); |
| 2968 | 2821 | ||
| 2822 | kfree(ecc_stngs); | ||
| 2823 | ecc_stngs = NULL; | ||
| 2824 | |||
| 2825 | kfree(mcis); | ||
| 2826 | mcis = NULL; | ||
| 2827 | |||
| 2969 | msrs_free(msrs); | 2828 | msrs_free(msrs); |
| 2970 | msrs = NULL; | 2829 | msrs = NULL; |
| 2971 | } | 2830 | } |
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index 044aee4f944d..613ec72b0f65 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h | |||
| @@ -74,11 +74,26 @@ | |||
| 74 | #include "edac_core.h" | 74 | #include "edac_core.h" |
| 75 | #include "mce_amd.h" | 75 | #include "mce_amd.h" |
| 76 | 76 | ||
| 77 | #define amd64_printk(level, fmt, arg...) \ | 77 | #define amd64_debug(fmt, arg...) \ |
| 78 | edac_printk(level, "amd64", fmt, ##arg) | 78 | edac_printk(KERN_DEBUG, "amd64", fmt, ##arg) |
| 79 | 79 | ||
| 80 | #define amd64_mc_printk(mci, level, fmt, arg...) \ | 80 | #define amd64_info(fmt, arg...) \ |
| 81 | edac_mc_chipset_printk(mci, level, "amd64", fmt, ##arg) | 81 | edac_printk(KERN_INFO, "amd64", fmt, ##arg) |
| 82 | |||
| 83 | #define amd64_notice(fmt, arg...) \ | ||
| 84 | edac_printk(KERN_NOTICE, "amd64", fmt, ##arg) | ||
| 85 | |||
| 86 | #define amd64_warn(fmt, arg...) \ | ||
| 87 | edac_printk(KERN_WARNING, "amd64", fmt, ##arg) | ||
| 88 | |||
| 89 | #define amd64_err(fmt, arg...) \ | ||
| 90 | edac_printk(KERN_ERR, "amd64", fmt, ##arg) | ||
| 91 | |||
| 92 | #define amd64_mc_warn(mci, fmt, arg...) \ | ||
| 93 | edac_mc_chipset_printk(mci, KERN_WARNING, "amd64", fmt, ##arg) | ||
| 94 | |||
| 95 | #define amd64_mc_err(mci, fmt, arg...) \ | ||
| 96 | edac_mc_chipset_printk(mci, KERN_ERR, "amd64", fmt, ##arg) | ||
| 82 | 97 | ||
| 83 | /* | 98 | /* |
| 84 | * Throughout the comments in this code, the following terms are used: | 99 | * Throughout the comments in this code, the following terms are used: |
| @@ -129,11 +144,9 @@ | |||
| 129 | * sections 3.5.4 and 3.5.5 for more information. | 144 | * sections 3.5.4 and 3.5.5 for more information. |
| 130 | */ | 145 | */ |
| 131 | 146 | ||
| 132 | #define EDAC_AMD64_VERSION " Ver: 3.3.0 " __DATE__ | 147 | #define EDAC_AMD64_VERSION "v3.3.0" |
| 133 | #define EDAC_MOD_STR "amd64_edac" | 148 | #define EDAC_MOD_STR "amd64_edac" |
| 134 | 149 | ||
| 135 | #define EDAC_MAX_NUMNODES 8 | ||
| 136 | |||
| 137 | /* Extended Model from CPUID, for CPU Revision numbers */ | 150 | /* Extended Model from CPUID, for CPU Revision numbers */ |
| 138 | #define K8_REV_D 1 | 151 | #define K8_REV_D 1 |
| 139 | #define K8_REV_E 2 | 152 | #define K8_REV_E 2 |
| @@ -322,9 +335,6 @@ | |||
| 322 | #define K8_SCRCTRL 0x58 | 335 | #define K8_SCRCTRL 0x58 |
| 323 | 336 | ||
| 324 | #define F10_NB_CFG_LOW 0x88 | 337 | #define F10_NB_CFG_LOW 0x88 |
| 325 | #define F10_NB_CFG_LOW_ENABLE_EXT_CFG BIT(14) | ||
| 326 | |||
| 327 | #define F10_NB_CFG_HIGH 0x8C | ||
| 328 | 338 | ||
| 329 | #define F10_ONLINE_SPARE 0xB0 | 339 | #define F10_ONLINE_SPARE 0xB0 |
| 330 | #define F10_ONLINE_SPARE_SWAPDONE0(x) ((x) & BIT(1)) | 340 | #define F10_ONLINE_SPARE_SWAPDONE0(x) ((x) & BIT(1)) |
| @@ -373,7 +383,6 @@ static inline int get_node_id(struct pci_dev *pdev) | |||
| 373 | enum amd64_chipset_families { | 383 | enum amd64_chipset_families { |
| 374 | K8_CPUS = 0, | 384 | K8_CPUS = 0, |
| 375 | F10_CPUS, | 385 | F10_CPUS, |
| 376 | F11_CPUS, | ||
| 377 | }; | 386 | }; |
| 378 | 387 | ||
| 379 | /* Error injection control structure */ | 388 | /* Error injection control structure */ |
| @@ -384,16 +393,13 @@ struct error_injection { | |||
| 384 | }; | 393 | }; |
| 385 | 394 | ||
| 386 | struct amd64_pvt { | 395 | struct amd64_pvt { |
| 396 | struct low_ops *ops; | ||
| 397 | |||
| 387 | /* pci_device handles which we utilize */ | 398 | /* pci_device handles which we utilize */ |
| 388 | struct pci_dev *addr_f1_ctl; | 399 | struct pci_dev *F1, *F2, *F3; |
| 389 | struct pci_dev *dram_f2_ctl; | ||
| 390 | struct pci_dev *misc_f3_ctl; | ||
| 391 | 400 | ||
| 392 | int mc_node_id; /* MC index of this MC node */ | 401 | int mc_node_id; /* MC index of this MC node */ |
| 393 | int ext_model; /* extended model value of this node */ | 402 | int ext_model; /* extended model value of this node */ |
| 394 | |||
| 395 | struct low_ops *ops; /* pointer to per PCI Device ID func table */ | ||
| 396 | |||
| 397 | int channel_count; | 403 | int channel_count; |
| 398 | 404 | ||
| 399 | /* Raw registers */ | 405 | /* Raw registers */ |
| @@ -455,27 +461,27 @@ struct amd64_pvt { | |||
| 455 | /* place to store error injection parameters prior to issue */ | 461 | /* place to store error injection parameters prior to issue */ |
| 456 | struct error_injection injection; | 462 | struct error_injection injection; |
| 457 | 463 | ||
| 458 | /* Save old hw registers' values before we modified them */ | 464 | /* DCT per-family scrubrate setting */ |
| 459 | u32 nbctl_mcgctl_saved; /* When true, following 2 are valid */ | 465 | u32 min_scrubrate; |
| 460 | u32 old_nbctl; | ||
| 461 | 466 | ||
| 462 | /* MC Type Index value: socket F vs Family 10h */ | 467 | /* family name this instance is running on */ |
| 463 | u32 mc_type_index; | 468 | const char *ctl_name; |
| 469 | |||
| 470 | }; | ||
| 471 | |||
| 472 | /* | ||
| 473 | * per-node ECC settings descriptor | ||
| 474 | */ | ||
| 475 | struct ecc_settings { | ||
| 476 | u32 old_nbctl; | ||
| 477 | bool nbctl_valid; | ||
| 464 | 478 | ||
| 465 | /* misc settings */ | ||
| 466 | struct flags { | 479 | struct flags { |
| 467 | unsigned long cf8_extcfg:1; | ||
| 468 | unsigned long nb_mce_enable:1; | 480 | unsigned long nb_mce_enable:1; |
| 469 | unsigned long nb_ecc_prev:1; | 481 | unsigned long nb_ecc_prev:1; |
| 470 | } flags; | 482 | } flags; |
| 471 | }; | 483 | }; |
| 472 | 484 | ||
| 473 | struct scrubrate { | ||
| 474 | u32 scrubval; /* bit pattern for scrub rate */ | ||
| 475 | u32 bandwidth; /* bandwidth consumed (bytes/sec) */ | ||
| 476 | }; | ||
| 477 | |||
| 478 | extern struct scrubrate scrubrates[23]; | ||
| 479 | extern const char *tt_msgs[4]; | 485 | extern const char *tt_msgs[4]; |
| 480 | extern const char *ll_msgs[4]; | 486 | extern const char *ll_msgs[4]; |
| 481 | extern const char *rrrr_msgs[16]; | 487 | extern const char *rrrr_msgs[16]; |
| @@ -517,23 +523,10 @@ struct low_ops { | |||
| 517 | 523 | ||
| 518 | struct amd64_family_type { | 524 | struct amd64_family_type { |
| 519 | const char *ctl_name; | 525 | const char *ctl_name; |
| 520 | u16 addr_f1_ctl; | 526 | u16 f1_id, f3_id; |
| 521 | u16 misc_f3_ctl; | ||
| 522 | struct low_ops ops; | 527 | struct low_ops ops; |
| 523 | }; | 528 | }; |
| 524 | 529 | ||
| 525 | static struct amd64_family_type amd64_family_types[]; | ||
| 526 | |||
| 527 | static inline const char *get_amd_family_name(int index) | ||
| 528 | { | ||
| 529 | return amd64_family_types[index].ctl_name; | ||
| 530 | } | ||
| 531 | |||
| 532 | static inline struct low_ops *family_ops(int index) | ||
| 533 | { | ||
| 534 | return &amd64_family_types[index].ops; | ||
| 535 | } | ||
| 536 | |||
| 537 | static inline int amd64_read_pci_cfg_dword(struct pci_dev *pdev, int offset, | 530 | static inline int amd64_read_pci_cfg_dword(struct pci_dev *pdev, int offset, |
| 538 | u32 *val, const char *func) | 531 | u32 *val, const char *func) |
| 539 | { | 532 | { |
| @@ -541,8 +534,8 @@ static inline int amd64_read_pci_cfg_dword(struct pci_dev *pdev, int offset, | |||
| 541 | 534 | ||
| 542 | err = pci_read_config_dword(pdev, offset, val); | 535 | err = pci_read_config_dword(pdev, offset, val); |
| 543 | if (err) | 536 | if (err) |
| 544 | amd64_printk(KERN_WARNING, "%s: error reading F%dx%x.\n", | 537 | amd64_warn("%s: error reading F%dx%x.\n", |
| 545 | func, PCI_FUNC(pdev->devfn), offset); | 538 | func, PCI_FUNC(pdev->devfn), offset); |
| 546 | 539 | ||
| 547 | return err; | 540 | return err; |
| 548 | } | 541 | } |
| @@ -556,7 +549,6 @@ static inline int amd64_read_pci_cfg_dword(struct pci_dev *pdev, int offset, | |||
| 556 | */ | 549 | */ |
| 557 | #define K8_MIN_SCRUB_RATE_BITS 0x0 | 550 | #define K8_MIN_SCRUB_RATE_BITS 0x0 |
| 558 | #define F10_MIN_SCRUB_RATE_BITS 0x5 | 551 | #define F10_MIN_SCRUB_RATE_BITS 0x5 |
| 559 | #define F11_MIN_SCRUB_RATE_BITS 0x6 | ||
| 560 | 552 | ||
| 561 | int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base, | 553 | int amd64_get_dram_hole_info(struct mem_ctl_info *mci, u64 *hole_base, |
| 562 | u64 *hole_offset, u64 *hole_size); | 554 | u64 *hole_offset, u64 *hole_size); |
diff --git a/drivers/edac/amd64_edac_inj.c b/drivers/edac/amd64_edac_inj.c index 29f1f7a612d9..688478de1cbd 100644 --- a/drivers/edac/amd64_edac_inj.c +++ b/drivers/edac/amd64_edac_inj.c | |||
| @@ -23,9 +23,7 @@ static ssize_t amd64_inject_section_store(struct mem_ctl_info *mci, | |||
| 23 | if (ret != -EINVAL) { | 23 | if (ret != -EINVAL) { |
| 24 | 24 | ||
| 25 | if (value > 3) { | 25 | if (value > 3) { |
| 26 | amd64_printk(KERN_WARNING, | 26 | amd64_warn("%s: invalid section 0x%lx\n", __func__, value); |
| 27 | "%s: invalid section 0x%lx\n", | ||
| 28 | __func__, value); | ||
| 29 | return -EINVAL; | 27 | return -EINVAL; |
| 30 | } | 28 | } |
| 31 | 29 | ||
| @@ -58,9 +56,7 @@ static ssize_t amd64_inject_word_store(struct mem_ctl_info *mci, | |||
| 58 | if (ret != -EINVAL) { | 56 | if (ret != -EINVAL) { |
| 59 | 57 | ||
| 60 | if (value > 8) { | 58 | if (value > 8) { |
| 61 | amd64_printk(KERN_WARNING, | 59 | amd64_warn("%s: invalid word 0x%lx\n", __func__, value); |
| 62 | "%s: invalid word 0x%lx\n", | ||
| 63 | __func__, value); | ||
| 64 | return -EINVAL; | 60 | return -EINVAL; |
| 65 | } | 61 | } |
| 66 | 62 | ||
| @@ -92,9 +88,8 @@ static ssize_t amd64_inject_ecc_vector_store(struct mem_ctl_info *mci, | |||
| 92 | if (ret != -EINVAL) { | 88 | if (ret != -EINVAL) { |
| 93 | 89 | ||
| 94 | if (value & 0xFFFF0000) { | 90 | if (value & 0xFFFF0000) { |
| 95 | amd64_printk(KERN_WARNING, | 91 | amd64_warn("%s: invalid EccVector: 0x%lx\n", |
| 96 | "%s: invalid EccVector: 0x%lx\n", | 92 | __func__, value); |
| 97 | __func__, value); | ||
| 98 | return -EINVAL; | 93 | return -EINVAL; |
| 99 | } | 94 | } |
| 100 | 95 | ||
| @@ -122,15 +117,13 @@ static ssize_t amd64_inject_read_store(struct mem_ctl_info *mci, | |||
| 122 | /* Form value to choose 16-byte section of cacheline */ | 117 | /* Form value to choose 16-byte section of cacheline */ |
| 123 | section = F10_NB_ARRAY_DRAM_ECC | | 118 | section = F10_NB_ARRAY_DRAM_ECC | |
| 124 | SET_NB_ARRAY_ADDRESS(pvt->injection.section); | 119 | SET_NB_ARRAY_ADDRESS(pvt->injection.section); |
| 125 | pci_write_config_dword(pvt->misc_f3_ctl, | 120 | pci_write_config_dword(pvt->F3, F10_NB_ARRAY_ADDR, section); |
| 126 | F10_NB_ARRAY_ADDR, section); | ||
| 127 | 121 | ||
| 128 | word_bits = SET_NB_DRAM_INJECTION_READ(pvt->injection.word, | 122 | word_bits = SET_NB_DRAM_INJECTION_READ(pvt->injection.word, |
| 129 | pvt->injection.bit_map); | 123 | pvt->injection.bit_map); |
| 130 | 124 | ||
| 131 | /* Issue 'word' and 'bit' along with the READ request */ | 125 | /* Issue 'word' and 'bit' along with the READ request */ |
| 132 | pci_write_config_dword(pvt->misc_f3_ctl, | 126 | pci_write_config_dword(pvt->F3, F10_NB_ARRAY_DATA, word_bits); |
| 133 | F10_NB_ARRAY_DATA, word_bits); | ||
| 134 | 127 | ||
| 135 | debugf0("section=0x%x word_bits=0x%x\n", section, word_bits); | 128 | debugf0("section=0x%x word_bits=0x%x\n", section, word_bits); |
| 136 | 129 | ||
| @@ -157,15 +150,13 @@ static ssize_t amd64_inject_write_store(struct mem_ctl_info *mci, | |||
| 157 | /* Form value to choose 16-byte section of cacheline */ | 150 | /* Form value to choose 16-byte section of cacheline */ |
| 158 | section = F10_NB_ARRAY_DRAM_ECC | | 151 | section = F10_NB_ARRAY_DRAM_ECC | |
| 159 | SET_NB_ARRAY_ADDRESS(pvt->injection.section); | 152 | SET_NB_ARRAY_ADDRESS(pvt->injection.section); |
| 160 | pci_write_config_dword(pvt->misc_f3_ctl, | 153 | pci_write_config_dword(pvt->F3, F10_NB_ARRAY_ADDR, section); |
| 161 | F10_NB_ARRAY_ADDR, section); | ||
| 162 | 154 | ||
| 163 | word_bits = SET_NB_DRAM_INJECTION_WRITE(pvt->injection.word, | 155 | word_bits = SET_NB_DRAM_INJECTION_WRITE(pvt->injection.word, |
| 164 | pvt->injection.bit_map); | 156 | pvt->injection.bit_map); |
| 165 | 157 | ||
| 166 | /* Issue 'word' and 'bit' along with the READ request */ | 158 | /* Issue 'word' and 'bit' along with the READ request */ |
| 167 | pci_write_config_dword(pvt->misc_f3_ctl, | 159 | pci_write_config_dword(pvt->F3, F10_NB_ARRAY_DATA, word_bits); |
| 168 | F10_NB_ARRAY_DATA, word_bits); | ||
| 169 | 160 | ||
| 170 | debugf0("section=0x%x word_bits=0x%x\n", section, word_bits); | 161 | debugf0("section=0x%x word_bits=0x%x\n", section, word_bits); |
| 171 | 162 | ||
diff --git a/drivers/edac/cpc925_edac.c b/drivers/edac/cpc925_edac.c index 1609a19df495..b9a781c47e3c 100644 --- a/drivers/edac/cpc925_edac.c +++ b/drivers/edac/cpc925_edac.c | |||
| @@ -818,9 +818,10 @@ static void cpc925_del_edac_devices(void) | |||
| 818 | } | 818 | } |
| 819 | 819 | ||
| 820 | /* Convert current back-ground scrub rate into byte/sec bandwith */ | 820 | /* Convert current back-ground scrub rate into byte/sec bandwith */ |
| 821 | static int cpc925_get_sdram_scrub_rate(struct mem_ctl_info *mci, u32 *bw) | 821 | static int cpc925_get_sdram_scrub_rate(struct mem_ctl_info *mci) |
| 822 | { | 822 | { |
| 823 | struct cpc925_mc_pdata *pdata = mci->pvt_info; | 823 | struct cpc925_mc_pdata *pdata = mci->pvt_info; |
| 824 | int bw; | ||
| 824 | u32 mscr; | 825 | u32 mscr; |
| 825 | u8 si; | 826 | u8 si; |
| 826 | 827 | ||
| @@ -832,11 +833,11 @@ static int cpc925_get_sdram_scrub_rate(struct mem_ctl_info *mci, u32 *bw) | |||
| 832 | if (((mscr & MSCR_SCRUB_MOD_MASK) != MSCR_BACKGR_SCRUB) || | 833 | if (((mscr & MSCR_SCRUB_MOD_MASK) != MSCR_BACKGR_SCRUB) || |
| 833 | (si == 0)) { | 834 | (si == 0)) { |
| 834 | cpc925_mc_printk(mci, KERN_INFO, "Scrub mode not enabled\n"); | 835 | cpc925_mc_printk(mci, KERN_INFO, "Scrub mode not enabled\n"); |
| 835 | *bw = 0; | 836 | bw = 0; |
| 836 | } else | 837 | } else |
| 837 | *bw = CPC925_SCRUB_BLOCK_SIZE * 0xFA67 / si; | 838 | bw = CPC925_SCRUB_BLOCK_SIZE * 0xFA67 / si; |
| 838 | 839 | ||
| 839 | return 0; | 840 | return bw; |
| 840 | } | 841 | } |
| 841 | 842 | ||
| 842 | /* Return 0 for single channel; 1 for dual channel */ | 843 | /* Return 0 for single channel; 1 for dual channel */ |
diff --git a/drivers/edac/e752x_edac.c b/drivers/edac/e752x_edac.c index 073f5a06d238..ec302d426589 100644 --- a/drivers/edac/e752x_edac.c +++ b/drivers/edac/e752x_edac.c | |||
| @@ -983,11 +983,11 @@ static int set_sdram_scrub_rate(struct mem_ctl_info *mci, u32 new_bw) | |||
| 983 | 983 | ||
| 984 | pci_write_config_word(pdev, E752X_MCHSCRB, scrubrates[i].scrubval); | 984 | pci_write_config_word(pdev, E752X_MCHSCRB, scrubrates[i].scrubval); |
| 985 | 985 | ||
| 986 | return 0; | 986 | return scrubrates[i].bandwidth; |
| 987 | } | 987 | } |
| 988 | 988 | ||
| 989 | /* Convert current scrub rate value into byte/sec bandwidth */ | 989 | /* Convert current scrub rate value into byte/sec bandwidth */ |
| 990 | static int get_sdram_scrub_rate(struct mem_ctl_info *mci, u32 *bw) | 990 | static int get_sdram_scrub_rate(struct mem_ctl_info *mci) |
| 991 | { | 991 | { |
| 992 | const struct scrubrate *scrubrates; | 992 | const struct scrubrate *scrubrates; |
| 993 | struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info; | 993 | struct e752x_pvt *pvt = (struct e752x_pvt *) mci->pvt_info; |
| @@ -1013,10 +1013,8 @@ static int get_sdram_scrub_rate(struct mem_ctl_info *mci, u32 *bw) | |||
| 1013 | "Invalid sdram scrub control value: 0x%x\n", scrubval); | 1013 | "Invalid sdram scrub control value: 0x%x\n", scrubval); |
| 1014 | return -1; | 1014 | return -1; |
| 1015 | } | 1015 | } |
| 1016 | return scrubrates[i].bandwidth; | ||
| 1016 | 1017 | ||
| 1017 | *bw = scrubrates[i].bandwidth; | ||
| 1018 | |||
| 1019 | return 0; | ||
| 1020 | } | 1018 | } |
| 1021 | 1019 | ||
| 1022 | /* Return 1 if dual channel mode is active. Else return 0. */ | 1020 | /* Return 1 if dual channel mode is active. Else return 0. */ |
diff --git a/drivers/edac/edac_core.h b/drivers/edac/edac_core.h index 251440cd50a3..ff1eb7bb26c6 100644 --- a/drivers/edac/edac_core.h +++ b/drivers/edac/edac_core.h | |||
| @@ -68,9 +68,10 @@ | |||
| 68 | #define EDAC_PCI "PCI" | 68 | #define EDAC_PCI "PCI" |
| 69 | #define EDAC_DEBUG "DEBUG" | 69 | #define EDAC_DEBUG "DEBUG" |
| 70 | 70 | ||
| 71 | extern const char *edac_mem_types[]; | ||
| 72 | |||
| 71 | #ifdef CONFIG_EDAC_DEBUG | 73 | #ifdef CONFIG_EDAC_DEBUG |
| 72 | extern int edac_debug_level; | 74 | extern int edac_debug_level; |
| 73 | extern const char *edac_mem_types[]; | ||
| 74 | 75 | ||
| 75 | #define edac_debug_printk(level, fmt, arg...) \ | 76 | #define edac_debug_printk(level, fmt, arg...) \ |
| 76 | do { \ | 77 | do { \ |
| @@ -386,7 +387,7 @@ struct mem_ctl_info { | |||
| 386 | representation and converts it to the closest matching | 387 | representation and converts it to the closest matching |
| 387 | bandwith in bytes/sec. | 388 | bandwith in bytes/sec. |
| 388 | */ | 389 | */ |
| 389 | int (*get_sdram_scrub_rate) (struct mem_ctl_info * mci, u32 * bw); | 390 | int (*get_sdram_scrub_rate) (struct mem_ctl_info * mci); |
| 390 | 391 | ||
| 391 | 392 | ||
| 392 | /* pointer to edac checking routine */ | 393 | /* pointer to edac checking routine */ |
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index 795ea69c4d8f..a4e9db2d6524 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c | |||
| @@ -76,6 +76,8 @@ static void edac_mc_dump_mci(struct mem_ctl_info *mci) | |||
| 76 | debugf3("\tpvt_info = %p\n\n", mci->pvt_info); | 76 | debugf3("\tpvt_info = %p\n\n", mci->pvt_info); |
| 77 | } | 77 | } |
| 78 | 78 | ||
| 79 | #endif /* CONFIG_EDAC_DEBUG */ | ||
| 80 | |||
| 79 | /* | 81 | /* |
| 80 | * keep those in sync with the enum mem_type | 82 | * keep those in sync with the enum mem_type |
| 81 | */ | 83 | */ |
| @@ -100,8 +102,6 @@ const char *edac_mem_types[] = { | |||
| 100 | }; | 102 | }; |
| 101 | EXPORT_SYMBOL_GPL(edac_mem_types); | 103 | EXPORT_SYMBOL_GPL(edac_mem_types); |
| 102 | 104 | ||
| 103 | #endif /* CONFIG_EDAC_DEBUG */ | ||
| 104 | |||
| 105 | /* 'ptr' points to a possibly unaligned item X such that sizeof(X) is 'size'. | 105 | /* 'ptr' points to a possibly unaligned item X such that sizeof(X) is 'size'. |
| 106 | * Adjust 'ptr' so that its alignment is at least as stringent as what the | 106 | * Adjust 'ptr' so that its alignment is at least as stringent as what the |
| 107 | * compiler would provide for X and return the aligned result. | 107 | * compiler would provide for X and return the aligned result. |
diff --git a/drivers/edac/edac_mc_sysfs.c b/drivers/edac/edac_mc_sysfs.c index dce61f7ba38b..39d97cfdf58c 100644 --- a/drivers/edac/edac_mc_sysfs.c +++ b/drivers/edac/edac_mc_sysfs.c | |||
| @@ -436,56 +436,55 @@ static ssize_t mci_reset_counters_store(struct mem_ctl_info *mci, | |||
| 436 | return count; | 436 | return count; |
| 437 | } | 437 | } |
| 438 | 438 | ||
| 439 | /* memory scrubbing */ | 439 | /* Memory scrubbing interface: |
| 440 | * | ||
| 441 | * A MC driver can limit the scrubbing bandwidth based on the CPU type. | ||
| 442 | * Therefore, ->set_sdram_scrub_rate should be made to return the actual | ||
| 443 | * bandwidth that is accepted or 0 when scrubbing is to be disabled. | ||
| 444 | * | ||
| 445 | * Negative value still means that an error has occurred while setting | ||
| 446 | * the scrub rate. | ||
| 447 | */ | ||
| 440 | static ssize_t mci_sdram_scrub_rate_store(struct mem_ctl_info *mci, | 448 | static ssize_t mci_sdram_scrub_rate_store(struct mem_ctl_info *mci, |
| 441 | const char *data, size_t count) | 449 | const char *data, size_t count) |
| 442 | { | 450 | { |
| 443 | unsigned long bandwidth = 0; | 451 | unsigned long bandwidth = 0; |
| 444 | int err; | 452 | int new_bw = 0; |
| 445 | 453 | ||
| 446 | if (!mci->set_sdram_scrub_rate) { | 454 | if (!mci->set_sdram_scrub_rate) |
| 447 | edac_printk(KERN_WARNING, EDAC_MC, | ||
| 448 | "Memory scrub rate setting not implemented!\n"); | ||
| 449 | return -EINVAL; | 455 | return -EINVAL; |
| 450 | } | ||
| 451 | 456 | ||
| 452 | if (strict_strtoul(data, 10, &bandwidth) < 0) | 457 | if (strict_strtoul(data, 10, &bandwidth) < 0) |
| 453 | return -EINVAL; | 458 | return -EINVAL; |
| 454 | 459 | ||
| 455 | err = mci->set_sdram_scrub_rate(mci, (u32)bandwidth); | 460 | new_bw = mci->set_sdram_scrub_rate(mci, bandwidth); |
| 456 | if (err) { | 461 | if (new_bw >= 0) { |
| 457 | edac_printk(KERN_DEBUG, EDAC_MC, | 462 | edac_printk(KERN_DEBUG, EDAC_MC, "Scrub rate set to %d\n", new_bw); |
| 458 | "Failed setting scrub rate to %lu\n", bandwidth); | ||
| 459 | return -EINVAL; | ||
| 460 | } | ||
| 461 | else { | ||
| 462 | edac_printk(KERN_DEBUG, EDAC_MC, | ||
| 463 | "Scrub rate set to: %lu\n", bandwidth); | ||
| 464 | return count; | 463 | return count; |
| 465 | } | 464 | } |
| 465 | |||
| 466 | edac_printk(KERN_DEBUG, EDAC_MC, "Error setting scrub rate to: %lu\n", bandwidth); | ||
| 467 | return -EINVAL; | ||
| 466 | } | 468 | } |
| 467 | 469 | ||
| 470 | /* | ||
| 471 | * ->get_sdram_scrub_rate() return value semantics same as above. | ||
| 472 | */ | ||
| 468 | static ssize_t mci_sdram_scrub_rate_show(struct mem_ctl_info *mci, char *data) | 473 | static ssize_t mci_sdram_scrub_rate_show(struct mem_ctl_info *mci, char *data) |
| 469 | { | 474 | { |
| 470 | u32 bandwidth = 0; | 475 | int bandwidth = 0; |
| 471 | int err; | ||
| 472 | 476 | ||
| 473 | if (!mci->get_sdram_scrub_rate) { | 477 | if (!mci->get_sdram_scrub_rate) |
| 474 | edac_printk(KERN_WARNING, EDAC_MC, | ||
| 475 | "Memory scrub rate reading not implemented\n"); | ||
| 476 | return -EINVAL; | 478 | return -EINVAL; |
| 477 | } | ||
| 478 | 479 | ||
| 479 | err = mci->get_sdram_scrub_rate(mci, &bandwidth); | 480 | bandwidth = mci->get_sdram_scrub_rate(mci); |
| 480 | if (err) { | 481 | if (bandwidth < 0) { |
| 481 | edac_printk(KERN_DEBUG, EDAC_MC, "Error reading scrub rate\n"); | 482 | edac_printk(KERN_DEBUG, EDAC_MC, "Error reading scrub rate\n"); |
| 482 | return err; | 483 | return bandwidth; |
| 483 | } | ||
| 484 | else { | ||
| 485 | edac_printk(KERN_DEBUG, EDAC_MC, | ||
| 486 | "Read scrub rate: %d\n", bandwidth); | ||
| 487 | return sprintf(data, "%d\n", bandwidth); | ||
| 488 | } | 484 | } |
| 485 | |||
| 486 | edac_printk(KERN_DEBUG, EDAC_MC, "Read scrub rate: %d\n", bandwidth); | ||
| 487 | return sprintf(data, "%d\n", bandwidth); | ||
| 489 | } | 488 | } |
| 490 | 489 | ||
| 491 | /* default attribute files for the MCI object */ | 490 | /* default attribute files for the MCI object */ |
diff --git a/drivers/edac/i5100_edac.c b/drivers/edac/i5100_edac.c index f459a6c0886b..0448da0af75d 100644 --- a/drivers/edac/i5100_edac.c +++ b/drivers/edac/i5100_edac.c | |||
| @@ -611,20 +611,17 @@ static int i5100_set_scrub_rate(struct mem_ctl_info *mci, u32 bandwidth) | |||
| 611 | 611 | ||
| 612 | bandwidth = 5900000 * i5100_mc_scrben(dw); | 612 | bandwidth = 5900000 * i5100_mc_scrben(dw); |
| 613 | 613 | ||
| 614 | return 0; | 614 | return bandwidth; |
| 615 | } | 615 | } |
| 616 | 616 | ||
| 617 | static int i5100_get_scrub_rate(struct mem_ctl_info *mci, | 617 | static int i5100_get_scrub_rate(struct mem_ctl_info *mci) |
| 618 | u32 *bandwidth) | ||
| 619 | { | 618 | { |
| 620 | struct i5100_priv *priv = mci->pvt_info; | 619 | struct i5100_priv *priv = mci->pvt_info; |
| 621 | u32 dw; | 620 | u32 dw; |
| 622 | 621 | ||
| 623 | pci_read_config_dword(priv->mc, I5100_MC, &dw); | 622 | pci_read_config_dword(priv->mc, I5100_MC, &dw); |
| 624 | 623 | ||
| 625 | *bandwidth = 5900000 * i5100_mc_scrben(dw); | 624 | return 5900000 * i5100_mc_scrben(dw); |
| 626 | |||
| 627 | return 0; | ||
| 628 | } | 625 | } |
| 629 | 626 | ||
| 630 | static struct pci_dev *pci_get_device_func(unsigned vendor, | 627 | static struct pci_dev *pci_get_device_func(unsigned vendor, |
