diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 9a8bebcf6b177fa79e9635ecde71f05b2578e798..c9eee6d33e9a70cf5f851570c48ff3086b93c39a 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, return __amd64_read_pci_cfg_dword(pvt->F2, addr, val, func); } +/* + * Select DCT to which PCI cfg accesses are routed + */ +static void f15h_select_dct(struct amd64_pvt *pvt, u8 dct) +{ + u32 reg = 0; + + amd64_read_pci_cfg(pvt->F1, DCT_CFG_SEL, ®); + reg &= 0xfffffffe; + reg |= dct; + amd64_write_pci_cfg(pvt->F1, DCT_CFG_SEL, reg); +} + static int f15_read_dct_pci_cfg(struct amd64_pvt *pvt, int addr, u32 *val, const char *func) { - u32 reg = 0; u8 dct = 0; if (addr >= 0x140 && addr <= 0x1a0) { @@ -125,10 +137,7 @@ static int f15_read_dct_pci_cfg(struct amd64_pvt *pvt, int addr, u32 *val, addr -= 0x100; } - amd64_read_pci_cfg(pvt->F1, DCT_CFG_SEL, ®); - reg &= 0xfffffffe; - reg |= dct; - amd64_write_pci_cfg(pvt->F1, DCT_CFG_SEL, reg); + f15h_select_dct(pvt, dct); return __amd64_read_pci_cfg_dword(pvt->F2, addr, val, func); } @@ -198,6 +207,10 @@ static int amd64_set_scrub_rate(struct mem_ctl_info *mci, u32 bw) if (boot_cpu_data.x86 == 0xf) min_scrubrate = 0x0; + /* F15h Erratum #505 */ + if (boot_cpu_data.x86 == 0x15) + f15h_select_dct(pvt, 0); + return __amd64_set_scrub_rate(pvt->F3, bw, min_scrubrate); } @@ -207,6 +220,10 @@ static int amd64_get_scrub_rate(struct mem_ctl_info *mci) u32 scrubval = 0; int i, retval = -EINVAL; + /* F15h Erratum #505 */ + if (boot_cpu_data.x86 == 0x15) + f15h_select_dct(pvt, 0); + amd64_read_pci_cfg(pvt->F3, SCRCTRL, &scrubval); scrubval = scrubval & 0x001F; @@ -751,10 +768,10 @@ static int get_channel_from_ecc_syndrome(struct mem_ctl_info *, u16); * Determine if the DIMMs have ECC enabled. ECC is enabled ONLY if all the DIMMs * are ECC capable. */ -static enum edac_type amd64_determine_edac_cap(struct amd64_pvt *pvt) +static unsigned long amd64_determine_edac_cap(struct amd64_pvt *pvt) { u8 bit; - enum dev_type edac_cap = EDAC_FLAG_NONE; + unsigned long edac_cap = EDAC_FLAG_NONE; bit = (boot_cpu_data.x86 > 0xf || pvt->ext_model >= K8_REV_F) ? 19 @@ -1953,11 +1970,9 @@ static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci, amd64_handle_ue(mci, m); } -void amd64_decode_bus_error(int node_id, struct mce *m, u32 nbcfg) +void amd64_decode_bus_error(int node_id, struct mce *m) { - struct mem_ctl_info *mci = mcis[node_id]; - - __amd64_decode_bus_error(mci, m); + __amd64_decode_bus_error(mcis[node_id], m); } /* diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c index 795cfbc0bf50ff39b3f3911b6596d3353f90d4ef..d0864d9c38ad18b4b44026f22cd83549cd75b45c 100644 --- a/drivers/edac/mce_amd.c +++ b/drivers/edac/mce_amd.c @@ -9,7 +9,7 @@ static u8 xec_mask = 0xf; static u8 nb_err_cpumask = 0xf; static bool report_gart_errors; -static void (*nb_bus_decoder)(int node_id, struct mce *m, u32 nbcfg); +static void (*nb_bus_decoder)(int node_id, struct mce *m); void amd_report_gart_errors(bool v) { @@ -17,13 +17,13 @@ void amd_report_gart_errors(bool v) } EXPORT_SYMBOL_GPL(amd_report_gart_errors); -void amd_register_ecc_decoder(void (*f)(int, struct mce *, u32)) +void amd_register_ecc_decoder(void (*f)(int, struct mce *)) { nb_bus_decoder = f; } EXPORT_SYMBOL_GPL(amd_register_ecc_decoder); -void amd_unregister_ecc_decoder(void (*f)(int, struct mce *, u32)) +void amd_unregister_ecc_decoder(void (*f)(int, struct mce *)) { if (nb_bus_decoder) { WARN_ON(nb_bus_decoder != f); @@ -592,31 +592,14 @@ static bool nb_noop_mce(u16 ec, u8 xec) return false; } -void amd_decode_nb_mce(int node_id, struct mce *m, u32 nbcfg) +void amd_decode_nb_mce(struct mce *m) { struct cpuinfo_x86 *c = &boot_cpu_data; - u16 ec = EC(m->status); - u8 xec = XEC(m->status, 0x1f); - u32 nbsh = (u32)(m->status >> 32); - int core = -1; - - pr_emerg(HW_ERR "Northbridge Error (node %d", node_id); - - /* F10h, revD can disable ErrCpu[3:0] through ErrCpuVal */ - if (c->x86 == 0x10 && c->x86_model > 7) { - if (nbsh & NBSH_ERR_CPU_VAL) - core = nbsh & nb_err_cpumask; - } else { - u8 assoc_cpus = nbsh & nb_err_cpumask; - - if (assoc_cpus > 0) - core = fls(assoc_cpus) - 1; - } + int node_id = amd_get_nb_id(m->extcpu); + u16 ec = EC(m->status); + u8 xec = XEC(m->status, 0x1f); - if (core >= 0) - pr_cont(", core %d): ", core); - else - pr_cont("): "); + pr_emerg(HW_ERR "Northbridge Error (node %d): ", node_id); switch (xec) { case 0x2: @@ -648,7 +631,7 @@ void amd_decode_nb_mce(int node_id, struct mce *m, u32 nbcfg) if (c->x86 == 0xf || c->x86 == 0x10 || c->x86 == 0x15) if ((xec == 0x8 || xec == 0x0) && nb_bus_decoder) - nb_bus_decoder(node_id, m, nbcfg); + nb_bus_decoder(node_id, m); return; @@ -764,13 +747,13 @@ int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data) { struct mce *m = (struct mce *)data; struct cpuinfo_x86 *c = &boot_cpu_data; - int node, ecc; + int ecc; if (amd_filter_mce(m)) return NOTIFY_STOP; - pr_emerg(HW_ERR "MC%d_STATUS[%s|%s|%s|%s|%s", - m->bank, + pr_emerg(HW_ERR "CPU:%d\tMC%d_STATUS[%s|%s|%s|%s|%s", + m->extcpu, m->bank, ((m->status & MCI_STATUS_OVER) ? "Over" : "-"), ((m->status & MCI_STATUS_UC) ? "UE" : "CE"), ((m->status & MCI_STATUS_MISCV) ? "MiscV" : "-"), @@ -789,6 +772,8 @@ int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data) pr_cont("]: 0x%016llx\n", m->status); + if (m->status & MCI_STATUS_ADDRV) + pr_emerg(HW_ERR "\tMC%d_ADDR: 0x%016llx\n", m->bank, m->addr); switch (m->bank) { case 0: @@ -811,8 +796,7 @@ int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data) break; case 4: - node = amd_get_nb_id(m->extcpu); - amd_decode_nb_mce(node, m, 0); + amd_decode_nb_mce(m); break; case 5: diff --git a/drivers/edac/mce_amd.h b/drivers/edac/mce_amd.h index 795a3206acf5f83759f6c9d35e7938fc84e96aed..0106747e240c764bcc3a1507e44850f412073537 100644 --- a/drivers/edac/mce_amd.h +++ b/drivers/edac/mce_amd.h @@ -86,9 +86,9 @@ struct amd_decoder_ops { }; void amd_report_gart_errors(bool); -void amd_register_ecc_decoder(void (*f)(int, struct mce *, u32)); -void amd_unregister_ecc_decoder(void (*f)(int, struct mce *, u32)); -void amd_decode_nb_mce(int, struct mce *, u32); +void amd_register_ecc_decoder(void (*f)(int, struct mce *)); +void amd_unregister_ecc_decoder(void (*f)(int, struct mce *)); +void amd_decode_nb_mce(struct mce *); int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data); #endif /* _EDAC_MCE_AMD_H */