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 /drivers/edac/amd64_edac.c | |
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
Diffstat (limited to 'drivers/edac/amd64_edac.c')
-rw-r--r-- | drivers/edac/amd64_edac.c | 823 |
1 files changed, 341 insertions, 482 deletions
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 | } |