diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-30 18:43:32 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-10-30 18:43:32 -0400 |
commit | b48aeab65e9fc4b0c9757c5fbc1d722544eb8786 (patch) | |
tree | 0bfce428f067ca9cf06d971ba8795ad69ca610e2 /drivers | |
parent | 1bc87b00556e8f7ba30a1010471951c5b8f71114 (diff) | |
parent | 1f6189ed18cbd99d90bffdbc76c3adc54418b2fd (diff) |
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp:
amd64_edac: Cleanup return type of amd64_determine_edac_cap()
amd64_edac: Add a fix for Erratum 505
EDAC, MCE, AMD: Simplify NB MCE decoder interface
EDAC, MCE, AMD: Drop local coreid reporting
EDAC, MCE, AMD: Print valid addr when reporting an error
EDAC, MCE, AMD: Print CPU number when reporting the error
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/edac/amd64_edac.c | 37 | ||||
-rw-r--r-- | drivers/edac/mce_amd.c | 46 | ||||
-rw-r--r-- | drivers/edac/mce_amd.h | 6 |
3 files changed, 44 insertions, 45 deletions
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 9a8bebcf6b17..c9eee6d33e9a 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c | |||
@@ -114,10 +114,22 @@ static int f10_read_dct_pci_cfg(struct amd64_pvt *pvt, int addr, u32 *val, | |||
114 | return __amd64_read_pci_cfg_dword(pvt->F2, addr, val, func); | 114 | return __amd64_read_pci_cfg_dword(pvt->F2, addr, val, func); |
115 | } | 115 | } |
116 | 116 | ||
117 | /* | ||
118 | * Select DCT to which PCI cfg accesses are routed | ||
119 | */ | ||
120 | static void f15h_select_dct(struct amd64_pvt *pvt, u8 dct) | ||
121 | { | ||
122 | u32 reg = 0; | ||
123 | |||
124 | amd64_read_pci_cfg(pvt->F1, DCT_CFG_SEL, ®); | ||
125 | reg &= 0xfffffffe; | ||
126 | reg |= dct; | ||
127 | amd64_write_pci_cfg(pvt->F1, DCT_CFG_SEL, reg); | ||
128 | } | ||
129 | |||
117 | static int f15_read_dct_pci_cfg(struct amd64_pvt *pvt, int addr, u32 *val, | 130 | static int f15_read_dct_pci_cfg(struct amd64_pvt *pvt, int addr, u32 *val, |
118 | const char *func) | 131 | const char *func) |
119 | { | 132 | { |
120 | u32 reg = 0; | ||
121 | u8 dct = 0; | 133 | u8 dct = 0; |
122 | 134 | ||
123 | if (addr >= 0x140 && addr <= 0x1a0) { | 135 | if (addr >= 0x140 && addr <= 0x1a0) { |
@@ -125,10 +137,7 @@ static int f15_read_dct_pci_cfg(struct amd64_pvt *pvt, int addr, u32 *val, | |||
125 | addr -= 0x100; | 137 | addr -= 0x100; |
126 | } | 138 | } |
127 | 139 | ||
128 | amd64_read_pci_cfg(pvt->F1, DCT_CFG_SEL, ®); | 140 | f15h_select_dct(pvt, dct); |
129 | reg &= 0xfffffffe; | ||
130 | reg |= dct; | ||
131 | amd64_write_pci_cfg(pvt->F1, DCT_CFG_SEL, reg); | ||
132 | 141 | ||
133 | return __amd64_read_pci_cfg_dword(pvt->F2, addr, val, func); | 142 | return __amd64_read_pci_cfg_dword(pvt->F2, addr, val, func); |
134 | } | 143 | } |
@@ -198,6 +207,10 @@ static int amd64_set_scrub_rate(struct mem_ctl_info *mci, u32 bw) | |||
198 | if (boot_cpu_data.x86 == 0xf) | 207 | if (boot_cpu_data.x86 == 0xf) |
199 | min_scrubrate = 0x0; | 208 | min_scrubrate = 0x0; |
200 | 209 | ||
210 | /* F15h Erratum #505 */ | ||
211 | if (boot_cpu_data.x86 == 0x15) | ||
212 | f15h_select_dct(pvt, 0); | ||
213 | |||
201 | return __amd64_set_scrub_rate(pvt->F3, bw, min_scrubrate); | 214 | return __amd64_set_scrub_rate(pvt->F3, bw, min_scrubrate); |
202 | } | 215 | } |
203 | 216 | ||
@@ -207,6 +220,10 @@ static int amd64_get_scrub_rate(struct mem_ctl_info *mci) | |||
207 | u32 scrubval = 0; | 220 | u32 scrubval = 0; |
208 | int i, retval = -EINVAL; | 221 | int i, retval = -EINVAL; |
209 | 222 | ||
223 | /* F15h Erratum #505 */ | ||
224 | if (boot_cpu_data.x86 == 0x15) | ||
225 | f15h_select_dct(pvt, 0); | ||
226 | |||
210 | amd64_read_pci_cfg(pvt->F3, SCRCTRL, &scrubval); | 227 | amd64_read_pci_cfg(pvt->F3, SCRCTRL, &scrubval); |
211 | 228 | ||
212 | scrubval = scrubval & 0x001F; | 229 | scrubval = scrubval & 0x001F; |
@@ -751,10 +768,10 @@ static int get_channel_from_ecc_syndrome(struct mem_ctl_info *, u16); | |||
751 | * Determine if the DIMMs have ECC enabled. ECC is enabled ONLY if all the DIMMs | 768 | * Determine if the DIMMs have ECC enabled. ECC is enabled ONLY if all the DIMMs |
752 | * are ECC capable. | 769 | * are ECC capable. |
753 | */ | 770 | */ |
754 | static enum edac_type amd64_determine_edac_cap(struct amd64_pvt *pvt) | 771 | static unsigned long amd64_determine_edac_cap(struct amd64_pvt *pvt) |
755 | { | 772 | { |
756 | u8 bit; | 773 | u8 bit; |
757 | enum dev_type edac_cap = EDAC_FLAG_NONE; | 774 | unsigned long edac_cap = EDAC_FLAG_NONE; |
758 | 775 | ||
759 | bit = (boot_cpu_data.x86 > 0xf || pvt->ext_model >= K8_REV_F) | 776 | bit = (boot_cpu_data.x86 > 0xf || pvt->ext_model >= K8_REV_F) |
760 | ? 19 | 777 | ? 19 |
@@ -1953,11 +1970,9 @@ static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci, | |||
1953 | amd64_handle_ue(mci, m); | 1970 | amd64_handle_ue(mci, m); |
1954 | } | 1971 | } |
1955 | 1972 | ||
1956 | void amd64_decode_bus_error(int node_id, struct mce *m, u32 nbcfg) | 1973 | void amd64_decode_bus_error(int node_id, struct mce *m) |
1957 | { | 1974 | { |
1958 | struct mem_ctl_info *mci = mcis[node_id]; | 1975 | __amd64_decode_bus_error(mcis[node_id], m); |
1959 | |||
1960 | __amd64_decode_bus_error(mci, m); | ||
1961 | } | 1976 | } |
1962 | 1977 | ||
1963 | /* | 1978 | /* |
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c index 795cfbc0bf50..d0864d9c38ad 100644 --- a/drivers/edac/mce_amd.c +++ b/drivers/edac/mce_amd.c | |||
@@ -9,7 +9,7 @@ static u8 xec_mask = 0xf; | |||
9 | static u8 nb_err_cpumask = 0xf; | 9 | static u8 nb_err_cpumask = 0xf; |
10 | 10 | ||
11 | static bool report_gart_errors; | 11 | static bool report_gart_errors; |
12 | static void (*nb_bus_decoder)(int node_id, struct mce *m, u32 nbcfg); | 12 | static void (*nb_bus_decoder)(int node_id, struct mce *m); |
13 | 13 | ||
14 | void amd_report_gart_errors(bool v) | 14 | void amd_report_gart_errors(bool v) |
15 | { | 15 | { |
@@ -17,13 +17,13 @@ void amd_report_gart_errors(bool v) | |||
17 | } | 17 | } |
18 | EXPORT_SYMBOL_GPL(amd_report_gart_errors); | 18 | EXPORT_SYMBOL_GPL(amd_report_gart_errors); |
19 | 19 | ||
20 | void amd_register_ecc_decoder(void (*f)(int, struct mce *, u32)) | 20 | void amd_register_ecc_decoder(void (*f)(int, struct mce *)) |
21 | { | 21 | { |
22 | nb_bus_decoder = f; | 22 | nb_bus_decoder = f; |
23 | } | 23 | } |
24 | EXPORT_SYMBOL_GPL(amd_register_ecc_decoder); | 24 | EXPORT_SYMBOL_GPL(amd_register_ecc_decoder); |
25 | 25 | ||
26 | void amd_unregister_ecc_decoder(void (*f)(int, struct mce *, u32)) | 26 | void amd_unregister_ecc_decoder(void (*f)(int, struct mce *)) |
27 | { | 27 | { |
28 | if (nb_bus_decoder) { | 28 | if (nb_bus_decoder) { |
29 | WARN_ON(nb_bus_decoder != f); | 29 | WARN_ON(nb_bus_decoder != f); |
@@ -592,31 +592,14 @@ static bool nb_noop_mce(u16 ec, u8 xec) | |||
592 | return false; | 592 | return false; |
593 | } | 593 | } |
594 | 594 | ||
595 | void amd_decode_nb_mce(int node_id, struct mce *m, u32 nbcfg) | 595 | void amd_decode_nb_mce(struct mce *m) |
596 | { | 596 | { |
597 | struct cpuinfo_x86 *c = &boot_cpu_data; | 597 | struct cpuinfo_x86 *c = &boot_cpu_data; |
598 | u16 ec = EC(m->status); | 598 | int node_id = amd_get_nb_id(m->extcpu); |
599 | u8 xec = XEC(m->status, 0x1f); | 599 | u16 ec = EC(m->status); |
600 | u32 nbsh = (u32)(m->status >> 32); | 600 | u8 xec = XEC(m->status, 0x1f); |
601 | int core = -1; | ||
602 | |||
603 | pr_emerg(HW_ERR "Northbridge Error (node %d", node_id); | ||
604 | |||
605 | /* F10h, revD can disable ErrCpu[3:0] through ErrCpuVal */ | ||
606 | if (c->x86 == 0x10 && c->x86_model > 7) { | ||
607 | if (nbsh & NBSH_ERR_CPU_VAL) | ||
608 | core = nbsh & nb_err_cpumask; | ||
609 | } else { | ||
610 | u8 assoc_cpus = nbsh & nb_err_cpumask; | ||
611 | |||
612 | if (assoc_cpus > 0) | ||
613 | core = fls(assoc_cpus) - 1; | ||
614 | } | ||
615 | 601 | ||
616 | if (core >= 0) | 602 | pr_emerg(HW_ERR "Northbridge Error (node %d): ", node_id); |
617 | pr_cont(", core %d): ", core); | ||
618 | else | ||
619 | pr_cont("): "); | ||
620 | 603 | ||
621 | switch (xec) { | 604 | switch (xec) { |
622 | case 0x2: | 605 | case 0x2: |
@@ -648,7 +631,7 @@ void amd_decode_nb_mce(int node_id, struct mce *m, u32 nbcfg) | |||
648 | 631 | ||
649 | if (c->x86 == 0xf || c->x86 == 0x10 || c->x86 == 0x15) | 632 | if (c->x86 == 0xf || c->x86 == 0x10 || c->x86 == 0x15) |
650 | if ((xec == 0x8 || xec == 0x0) && nb_bus_decoder) | 633 | if ((xec == 0x8 || xec == 0x0) && nb_bus_decoder) |
651 | nb_bus_decoder(node_id, m, nbcfg); | 634 | nb_bus_decoder(node_id, m); |
652 | 635 | ||
653 | return; | 636 | return; |
654 | 637 | ||
@@ -764,13 +747,13 @@ int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data) | |||
764 | { | 747 | { |
765 | struct mce *m = (struct mce *)data; | 748 | struct mce *m = (struct mce *)data; |
766 | struct cpuinfo_x86 *c = &boot_cpu_data; | 749 | struct cpuinfo_x86 *c = &boot_cpu_data; |
767 | int node, ecc; | 750 | int ecc; |
768 | 751 | ||
769 | if (amd_filter_mce(m)) | 752 | if (amd_filter_mce(m)) |
770 | return NOTIFY_STOP; | 753 | return NOTIFY_STOP; |
771 | 754 | ||
772 | pr_emerg(HW_ERR "MC%d_STATUS[%s|%s|%s|%s|%s", | 755 | pr_emerg(HW_ERR "CPU:%d\tMC%d_STATUS[%s|%s|%s|%s|%s", |
773 | m->bank, | 756 | m->extcpu, m->bank, |
774 | ((m->status & MCI_STATUS_OVER) ? "Over" : "-"), | 757 | ((m->status & MCI_STATUS_OVER) ? "Over" : "-"), |
775 | ((m->status & MCI_STATUS_UC) ? "UE" : "CE"), | 758 | ((m->status & MCI_STATUS_UC) ? "UE" : "CE"), |
776 | ((m->status & MCI_STATUS_MISCV) ? "MiscV" : "-"), | 759 | ((m->status & MCI_STATUS_MISCV) ? "MiscV" : "-"), |
@@ -789,6 +772,8 @@ int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data) | |||
789 | 772 | ||
790 | pr_cont("]: 0x%016llx\n", m->status); | 773 | pr_cont("]: 0x%016llx\n", m->status); |
791 | 774 | ||
775 | if (m->status & MCI_STATUS_ADDRV) | ||
776 | pr_emerg(HW_ERR "\tMC%d_ADDR: 0x%016llx\n", m->bank, m->addr); | ||
792 | 777 | ||
793 | switch (m->bank) { | 778 | switch (m->bank) { |
794 | case 0: | 779 | case 0: |
@@ -811,8 +796,7 @@ int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data) | |||
811 | break; | 796 | break; |
812 | 797 | ||
813 | case 4: | 798 | case 4: |
814 | node = amd_get_nb_id(m->extcpu); | 799 | amd_decode_nb_mce(m); |
815 | amd_decode_nb_mce(node, m, 0); | ||
816 | break; | 800 | break; |
817 | 801 | ||
818 | case 5: | 802 | case 5: |
diff --git a/drivers/edac/mce_amd.h b/drivers/edac/mce_amd.h index 795a3206acf5..0106747e240c 100644 --- a/drivers/edac/mce_amd.h +++ b/drivers/edac/mce_amd.h | |||
@@ -86,9 +86,9 @@ struct amd_decoder_ops { | |||
86 | }; | 86 | }; |
87 | 87 | ||
88 | void amd_report_gart_errors(bool); | 88 | void amd_report_gart_errors(bool); |
89 | void amd_register_ecc_decoder(void (*f)(int, struct mce *, u32)); | 89 | void amd_register_ecc_decoder(void (*f)(int, struct mce *)); |
90 | void amd_unregister_ecc_decoder(void (*f)(int, struct mce *, u32)); | 90 | void amd_unregister_ecc_decoder(void (*f)(int, struct mce *)); |
91 | void amd_decode_nb_mce(int, struct mce *, u32); | 91 | void amd_decode_nb_mce(struct mce *); |
92 | int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data); | 92 | int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data); |
93 | 93 | ||
94 | #endif /* _EDAC_MCE_AMD_H */ | 94 | #endif /* _EDAC_MCE_AMD_H */ |