diff options
author | Borislav Petkov <borislav.petkov@amd.com> | 2011-01-10 08:24:32 -0500 |
---|---|---|
committer | Borislav Petkov <borislav.petkov@amd.com> | 2011-03-17 09:46:19 -0400 |
commit | f192c7b16c98839c1945733f1013f75daec5f380 (patch) | |
tree | 5b1559606678b417dc4331c00f94aa1b3e6f16be /drivers/edac | |
parent | 7d20d14da1bf24199add02cf4293871c277a4bda (diff) |
amd64_edac: Simplify decoding path
Use the struct mce directly instead of copying from it into a custom
struct err_regs.
No functionality change.
Signed-off-by: Borislav Petkov <borislav.petkov@amd.com>
Diffstat (limited to 'drivers/edac')
-rw-r--r-- | drivers/edac/amd64_edac.c | 76 | ||||
-rw-r--r-- | drivers/edac/amd64_edac.h | 12 | ||||
-rw-r--r-- | drivers/edac/mce_amd.h | 12 |
3 files changed, 35 insertions, 65 deletions
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index 1ec014534e18..c91733013b48 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c | |||
@@ -788,11 +788,6 @@ static int sys_addr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr) | |||
788 | 788 | ||
789 | static int get_channel_from_ecc_syndrome(struct mem_ctl_info *, u16); | 789 | static int get_channel_from_ecc_syndrome(struct mem_ctl_info *, u16); |
790 | 790 | ||
791 | static u16 extract_syndrome(struct err_regs *err) | ||
792 | { | ||
793 | return ((err->nbsh >> 15) & 0xff) | ((err->nbsl >> 16) & 0xff00); | ||
794 | } | ||
795 | |||
796 | /* | 791 | /* |
797 | * Determine if the DIMMs have ECC enabled. ECC is enabled ONLY if all the DIMMs | 792 | * Determine if the DIMMs have ECC enabled. ECC is enabled ONLY if all the DIMMs |
798 | * are ECC capable. | 793 | * are ECC capable. |
@@ -975,12 +970,10 @@ static int k8_early_channel_count(struct amd64_pvt *pvt) | |||
975 | return (flag) ? 2 : 1; | 970 | return (flag) ? 2 : 1; |
976 | } | 971 | } |
977 | 972 | ||
978 | /* Extract the ERROR ADDRESS for the K8 CPUs */ | 973 | static u64 k8_get_error_address(struct mem_ctl_info *mci, struct mce *m) |
979 | static u64 k8_get_error_address(struct mem_ctl_info *mci, | ||
980 | struct err_regs *info) | ||
981 | { | 974 | { |
982 | return (((u64) (info->nbeah & 0xff)) << 32) + | 975 | /* ErrAddr[39:3] */ |
983 | (info->nbeal & ~0x03); | 976 | return m->addr & GENMASK(3, 39); |
984 | } | 977 | } |
985 | 978 | ||
986 | static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range) | 979 | static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range) |
@@ -1000,18 +993,16 @@ static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range) | |||
1000 | amd64_read_pci_cfg(pvt->F1, DRAM_LIMIT_HI + off, &pvt->ranges[range].lim.hi); | 993 | amd64_read_pci_cfg(pvt->F1, DRAM_LIMIT_HI + off, &pvt->ranges[range].lim.hi); |
1001 | } | 994 | } |
1002 | 995 | ||
1003 | static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, | 996 | static void k8_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, |
1004 | struct err_regs *err_info, u64 sys_addr) | 997 | u16 syndrome) |
1005 | { | 998 | { |
1006 | struct mem_ctl_info *src_mci; | 999 | struct mem_ctl_info *src_mci; |
1000 | struct amd64_pvt *pvt = mci->pvt_info; | ||
1007 | int channel, csrow; | 1001 | int channel, csrow; |
1008 | u32 page, offset; | 1002 | u32 page, offset; |
1009 | u16 syndrome; | ||
1010 | |||
1011 | syndrome = extract_syndrome(err_info); | ||
1012 | 1003 | ||
1013 | /* CHIPKILL enabled */ | 1004 | /* CHIPKILL enabled */ |
1014 | if (err_info->nbcfg & NBCFG_CHIPKILL) { | 1005 | if (pvt->nbcfg & NBCFG_CHIPKILL) { |
1015 | channel = get_channel_from_ecc_syndrome(mci, syndrome); | 1006 | channel = get_channel_from_ecc_syndrome(mci, syndrome); |
1016 | if (channel < 0) { | 1007 | if (channel < 0) { |
1017 | /* | 1008 | /* |
@@ -1136,11 +1127,9 @@ static int f10_dbam_to_chip_select(struct amd64_pvt *pvt, int cs_mode) | |||
1136 | return dbam_map[cs_mode]; | 1127 | return dbam_map[cs_mode]; |
1137 | } | 1128 | } |
1138 | 1129 | ||
1139 | static u64 f10_get_error_address(struct mem_ctl_info *mci, | 1130 | static u64 f10_get_error_address(struct mem_ctl_info *mci, struct mce *m) |
1140 | struct err_regs *info) | ||
1141 | { | 1131 | { |
1142 | return (((u64) (info->nbeah & 0xffff)) << 32) + | 1132 | return m->addr & GENMASK(1, 47); |
1143 | (info->nbeal & ~0x01); | ||
1144 | } | 1133 | } |
1145 | 1134 | ||
1146 | static void f10_read_dram_ctl_register(struct amd64_pvt *pvt) | 1135 | static void f10_read_dram_ctl_register(struct amd64_pvt *pvt) |
@@ -1434,14 +1423,12 @@ static int f10_translate_sysaddr_to_cs(struct amd64_pvt *pvt, u64 sys_addr, | |||
1434 | * The @sys_addr is usually an error address received from the hardware | 1423 | * The @sys_addr is usually an error address received from the hardware |
1435 | * (MCX_ADDR). | 1424 | * (MCX_ADDR). |
1436 | */ | 1425 | */ |
1437 | static void f10_map_sysaddr_to_csrow(struct mem_ctl_info *mci, | 1426 | static void f10_map_sysaddr_to_csrow(struct mem_ctl_info *mci, u64 sys_addr, |
1438 | struct err_regs *err_info, | 1427 | u16 syndrome) |
1439 | u64 sys_addr) | ||
1440 | { | 1428 | { |
1441 | struct amd64_pvt *pvt = mci->pvt_info; | 1429 | struct amd64_pvt *pvt = mci->pvt_info; |
1442 | u32 page, offset; | 1430 | u32 page, offset; |
1443 | int nid, csrow, chan = 0; | 1431 | int nid, csrow, chan = 0; |
1444 | u16 syndrome; | ||
1445 | 1432 | ||
1446 | csrow = f10_translate_sysaddr_to_cs(pvt, sys_addr, &nid, &chan); | 1433 | csrow = f10_translate_sysaddr_to_cs(pvt, sys_addr, &nid, &chan); |
1447 | 1434 | ||
@@ -1452,8 +1439,6 @@ static void f10_map_sysaddr_to_csrow(struct mem_ctl_info *mci, | |||
1452 | 1439 | ||
1453 | error_address_to_page_and_offset(sys_addr, &page, &offset); | 1440 | error_address_to_page_and_offset(sys_addr, &page, &offset); |
1454 | 1441 | ||
1455 | syndrome = extract_syndrome(err_info); | ||
1456 | |||
1457 | /* | 1442 | /* |
1458 | * We need the syndromes for channel detection only when we're | 1443 | * We need the syndromes for channel detection only when we're |
1459 | * ganged. Otherwise @chan should already contain the channel at | 1444 | * ganged. Otherwise @chan should already contain the channel at |
@@ -1740,29 +1725,29 @@ static int get_channel_from_ecc_syndrome(struct mem_ctl_info *mci, u16 syndrome) | |||
1740 | * Handle any Correctable Errors (CEs) that have occurred. Check for valid ERROR | 1725 | * Handle any Correctable Errors (CEs) that have occurred. Check for valid ERROR |
1741 | * ADDRESS and process. | 1726 | * ADDRESS and process. |
1742 | */ | 1727 | */ |
1743 | static void amd64_handle_ce(struct mem_ctl_info *mci, | 1728 | static void amd64_handle_ce(struct mem_ctl_info *mci, struct mce *m) |
1744 | struct err_regs *info) | ||
1745 | { | 1729 | { |
1746 | struct amd64_pvt *pvt = mci->pvt_info; | 1730 | struct amd64_pvt *pvt = mci->pvt_info; |
1747 | u64 sys_addr; | 1731 | u64 sys_addr; |
1732 | u16 syndrome; | ||
1748 | 1733 | ||
1749 | /* Ensure that the Error Address is VALID */ | 1734 | /* Ensure that the Error Address is VALID */ |
1750 | if (!(info->nbsh & NBSH_VALID_ERROR_ADDR)) { | 1735 | if (!(m->status & MCI_STATUS_ADDRV)) { |
1751 | amd64_mc_err(mci, "HW has no ERROR_ADDRESS available\n"); | 1736 | amd64_mc_err(mci, "HW has no ERROR_ADDRESS available\n"); |
1752 | edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR); | 1737 | edac_mc_handle_ce_no_info(mci, EDAC_MOD_STR); |
1753 | return; | 1738 | return; |
1754 | } | 1739 | } |
1755 | 1740 | ||
1756 | sys_addr = pvt->ops->get_error_address(mci, info); | 1741 | sys_addr = pvt->ops->get_error_address(mci, m); |
1742 | syndrome = extract_syndrome(m->status); | ||
1757 | 1743 | ||
1758 | amd64_mc_err(mci, "CE ERROR_ADDRESS= 0x%llx\n", sys_addr); | 1744 | amd64_mc_err(mci, "CE ERROR_ADDRESS= 0x%llx\n", sys_addr); |
1759 | 1745 | ||
1760 | pvt->ops->map_sysaddr_to_csrow(mci, info, sys_addr); | 1746 | pvt->ops->map_sysaddr_to_csrow(mci, sys_addr, syndrome); |
1761 | } | 1747 | } |
1762 | 1748 | ||
1763 | /* Handle any Un-correctable Errors (UEs) */ | 1749 | /* Handle any Un-correctable Errors (UEs) */ |
1764 | static void amd64_handle_ue(struct mem_ctl_info *mci, | 1750 | static void amd64_handle_ue(struct mem_ctl_info *mci, struct mce *m) |
1765 | struct err_regs *info) | ||
1766 | { | 1751 | { |
1767 | struct amd64_pvt *pvt = mci->pvt_info; | 1752 | struct amd64_pvt *pvt = mci->pvt_info; |
1768 | struct mem_ctl_info *log_mci, *src_mci = NULL; | 1753 | struct mem_ctl_info *log_mci, *src_mci = NULL; |
@@ -1772,13 +1757,13 @@ static void amd64_handle_ue(struct mem_ctl_info *mci, | |||
1772 | 1757 | ||
1773 | log_mci = mci; | 1758 | log_mci = mci; |
1774 | 1759 | ||
1775 | if (!(info->nbsh & NBSH_VALID_ERROR_ADDR)) { | 1760 | if (!(m->status & MCI_STATUS_ADDRV)) { |
1776 | amd64_mc_err(mci, "HW has no ERROR_ADDRESS available\n"); | 1761 | amd64_mc_err(mci, "HW has no ERROR_ADDRESS available\n"); |
1777 | edac_mc_handle_ue_no_info(log_mci, EDAC_MOD_STR); | 1762 | edac_mc_handle_ue_no_info(log_mci, EDAC_MOD_STR); |
1778 | return; | 1763 | return; |
1779 | } | 1764 | } |
1780 | 1765 | ||
1781 | sys_addr = pvt->ops->get_error_address(mci, info); | 1766 | sys_addr = pvt->ops->get_error_address(mci, m); |
1782 | 1767 | ||
1783 | /* | 1768 | /* |
1784 | * Find out which node the error address belongs to. This may be | 1769 | * Find out which node the error address belongs to. This may be |
@@ -1806,11 +1791,11 @@ static void amd64_handle_ue(struct mem_ctl_info *mci, | |||
1806 | } | 1791 | } |
1807 | 1792 | ||
1808 | static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci, | 1793 | static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci, |
1809 | struct err_regs *info) | 1794 | struct mce *m) |
1810 | { | 1795 | { |
1811 | u16 ec = EC(info->nbsl); | 1796 | u16 ec = EC(m->status); |
1812 | u8 xec = XEC(info->nbsl, 0x1f); | 1797 | u8 xec = XEC(m->status, 0x1f); |
1813 | int ecc_type = (info->nbsh >> 13) & 0x3; | 1798 | u8 ecc_type = (m->status >> 45) & 0x3; |
1814 | 1799 | ||
1815 | /* Bail early out if this was an 'observed' error */ | 1800 | /* Bail early out if this was an 'observed' error */ |
1816 | if (PP(ec) == NBSL_PP_OBS) | 1801 | if (PP(ec) == NBSL_PP_OBS) |
@@ -1821,23 +1806,16 @@ static inline void __amd64_decode_bus_error(struct mem_ctl_info *mci, | |||
1821 | return; | 1806 | return; |
1822 | 1807 | ||
1823 | if (ecc_type == 2) | 1808 | if (ecc_type == 2) |
1824 | amd64_handle_ce(mci, info); | 1809 | amd64_handle_ce(mci, m); |
1825 | else if (ecc_type == 1) | 1810 | else if (ecc_type == 1) |
1826 | amd64_handle_ue(mci, info); | 1811 | amd64_handle_ue(mci, m); |
1827 | } | 1812 | } |
1828 | 1813 | ||
1829 | void amd64_decode_bus_error(int node_id, struct mce *m, u32 nbcfg) | 1814 | void amd64_decode_bus_error(int node_id, struct mce *m, u32 nbcfg) |
1830 | { | 1815 | { |
1831 | struct mem_ctl_info *mci = mcis[node_id]; | 1816 | struct mem_ctl_info *mci = mcis[node_id]; |
1832 | struct err_regs regs; | ||
1833 | |||
1834 | regs.nbsl = (u32) m->status; | ||
1835 | regs.nbsh = (u32)(m->status >> 32); | ||
1836 | regs.nbeal = (u32) m->addr; | ||
1837 | regs.nbeah = (u32)(m->addr >> 32); | ||
1838 | regs.nbcfg = nbcfg; | ||
1839 | 1817 | ||
1840 | __amd64_decode_bus_error(mci, ®s); | 1818 | __amd64_decode_bus_error(mci, m); |
1841 | } | 1819 | } |
1842 | 1820 | ||
1843 | /* | 1821 | /* |
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index 04293306bedc..ba16535842ba 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h | |||
@@ -397,6 +397,11 @@ static inline u64 get_dram_limit(struct amd64_pvt *pvt, unsigned i) | |||
397 | return (((u64)pvt->ranges[i].lim.hi & 0x000000ff) << 40) | lim; | 397 | return (((u64)pvt->ranges[i].lim.hi & 0x000000ff) << 40) | lim; |
398 | } | 398 | } |
399 | 399 | ||
400 | static inline u16 extract_syndrome(u64 status) | ||
401 | { | ||
402 | return ((status >> 47) & 0xff) | ((status >> 16) & 0xff00); | ||
403 | } | ||
404 | |||
400 | /* | 405 | /* |
401 | * per-node ECC settings descriptor | 406 | * per-node ECC settings descriptor |
402 | */ | 407 | */ |
@@ -440,11 +445,10 @@ extern struct mcidev_sysfs_attribute amd64_dbg_attrs[NUM_DBG_ATTRS], | |||
440 | struct low_ops { | 445 | struct low_ops { |
441 | int (*early_channel_count) (struct amd64_pvt *pvt); | 446 | int (*early_channel_count) (struct amd64_pvt *pvt); |
442 | 447 | ||
443 | u64 (*get_error_address) (struct mem_ctl_info *mci, | 448 | u64 (*get_error_address) (struct mem_ctl_info *mci, struct mce *m); |
444 | struct err_regs *info); | ||
445 | void (*read_dram_ctl_register) (struct amd64_pvt *pvt); | 449 | void (*read_dram_ctl_register) (struct amd64_pvt *pvt); |
446 | void (*map_sysaddr_to_csrow) (struct mem_ctl_info *mci, | 450 | void (*map_sysaddr_to_csrow) (struct mem_ctl_info *mci, u64 sys_addr, |
447 | struct err_regs *info, u64 SystemAddr); | 451 | u16 syndrome); |
448 | int (*dbam_to_cs) (struct amd64_pvt *pvt, int cs_mode); | 452 | int (*dbam_to_cs) (struct amd64_pvt *pvt, int cs_mode); |
449 | int (*read_dct_pci_cfg) (struct amd64_pvt *pvt, int offset, | 453 | int (*read_dct_pci_cfg) (struct amd64_pvt *pvt, int offset, |
450 | u32 *val, const char *func); | 454 | u32 *val, const char *func); |
diff --git a/drivers/edac/mce_amd.h b/drivers/edac/mce_amd.h index 70a0bb2c13c5..795a3206acf5 100644 --- a/drivers/edac/mce_amd.h +++ b/drivers/edac/mce_amd.h | |||
@@ -34,7 +34,6 @@ | |||
34 | /* | 34 | /* |
35 | * F3x4C bits (MCi_STATUS' high half) | 35 | * F3x4C bits (MCi_STATUS' high half) |
36 | */ | 36 | */ |
37 | #define NBSH_VALID_ERROR_ADDR BIT(26) | ||
38 | #define NBSH_ERR_CPU_VAL BIT(24) | 37 | #define NBSH_ERR_CPU_VAL BIT(24) |
39 | 38 | ||
40 | enum tt_ids { | 39 | enum tt_ids { |
@@ -78,17 +77,6 @@ extern const char *to_msgs[]; | |||
78 | extern const char *ii_msgs[]; | 77 | extern const char *ii_msgs[]; |
79 | 78 | ||
80 | /* | 79 | /* |
81 | * relevant NB regs | ||
82 | */ | ||
83 | struct err_regs { | ||
84 | u32 nbcfg; | ||
85 | u32 nbsh; | ||
86 | u32 nbsl; | ||
87 | u32 nbeah; | ||
88 | u32 nbeal; | ||
89 | }; | ||
90 | |||
91 | /* | ||
92 | * per-family decoder ops | 80 | * per-family decoder ops |
93 | */ | 81 | */ |
94 | struct amd_decoder_ops { | 82 | struct amd_decoder_ops { |