diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-08 23:17:49 -0500 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-12-08 23:17:49 -0500 |
| commit | 0160928e792eff243c84b39a46cddb2fb89da0cb (patch) | |
| tree | 0d8f0b4c0a6218c1618771bed48af1695ee2a3be /drivers/edac | |
| parent | 3a7dbed7f23cdde8394e9adf92cc222856e0fc1e (diff) | |
| parent | 50872ccd8786dc72bc5a32c17695561e031fae4c (diff) | |
Merge tag 'edac_for_3.19' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp
Pull EDAC updates from Borislav Petkov:
"EDAC updates all over the place:
- Enablement for AMD F15h models 0x60 CPUs. Most notably DDR4 RAM
support. Out of tree stuff is adding the required PCI IDs. From
Aravind Gopalakrishnan.
- Enable amd64_edac for 32-bit due to popular demand. From Tomasz
Pala.
- Convert the AMD MCE injection module to debugfs, where it belongs.
- Misc EDAC cleanups"
* tag 'edac_for_3.19' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp:
EDAC, MCE, AMD: Correct formatting of decoded text
EDAC, mce_amd_inj: Add an injector function
EDAC, mce_amd_inj: Add hw-injection attributes
EDAC, mce_amd_inj: Enable direct writes to MCE MSRs
EDAC, mce_amd_inj: Convert mce_amd_inj module to debugfs
EDAC: Delete unnecessary check before calling pci_dev_put()
EDAC, pci_sysfs: remove unneccessary ifdef around entire file
ghes_edac: Use snprintf() to silence a static checker warning
amd64_edac: Build module on x86-32
EDAC, MCE, AMD: Add decoding table for MC6 xec
amd64_edac: Add F15h M60h support
{mv64x60,ppc4xx}_edac,: Remove deprecated IRQF_DISABLED
EDAC: Sync memory types and names
EDAC: Add DDR3 LRDIMM entries to edac_mem_types
x86, amd_nb: Add device IDs to NB tables for F15h M60h
pci_ids: Add PCI device IDs for F15h M60h
Diffstat (limited to 'drivers/edac')
| -rw-r--r-- | drivers/edac/Kconfig | 16 | ||||
| -rw-r--r-- | drivers/edac/Makefile | 2 | ||||
| -rw-r--r-- | drivers/edac/amd64_edac.c | 260 | ||||
| -rw-r--r-- | drivers/edac/amd64_edac.h | 15 | ||||
| -rw-r--r-- | drivers/edac/edac_mc.c | 40 | ||||
| -rw-r--r-- | drivers/edac/edac_pci_sysfs.c | 5 | ||||
| -rw-r--r-- | drivers/edac/ghes_edac.c | 4 | ||||
| -rw-r--r-- | drivers/edac/i3000_edac.c | 3 | ||||
| -rw-r--r-- | drivers/edac/i3200_edac.c | 3 | ||||
| -rw-r--r-- | drivers/edac/i82443bxgx_edac.c | 3 | ||||
| -rw-r--r-- | drivers/edac/mce_amd.c | 47 | ||||
| -rw-r--r-- | drivers/edac/mce_amd_inj.c | 293 | ||||
| -rw-r--r-- | drivers/edac/mv64x60_edac.c | 8 | ||||
| -rw-r--r-- | drivers/edac/ppc4xx_edac.c | 4 | ||||
| -rw-r--r-- | drivers/edac/x38_edac.c | 3 |
15 files changed, 439 insertions, 267 deletions
diff --git a/drivers/edac/Kconfig b/drivers/edac/Kconfig index 7072c2892d63..49c265255a07 100644 --- a/drivers/edac/Kconfig +++ b/drivers/edac/Kconfig | |||
| @@ -61,14 +61,14 @@ config EDAC_DECODE_MCE | |||
| 61 | has been initialized. | 61 | has been initialized. |
| 62 | 62 | ||
| 63 | config EDAC_MCE_INJ | 63 | config EDAC_MCE_INJ |
| 64 | tristate "Simple MCE injection interface over /sysfs" | 64 | tristate "Simple MCE injection interface" |
| 65 | depends on EDAC_DECODE_MCE | 65 | depends on EDAC_DECODE_MCE && DEBUG_FS |
| 66 | default n | 66 | default n |
| 67 | help | 67 | help |
| 68 | This is a simple interface to inject MCEs over /sysfs and test | 68 | This is a simple debugfs interface to inject MCEs and test different |
| 69 | the MCE decoding code in EDAC. | 69 | aspects of the MCE handling code. |
| 70 | 70 | ||
| 71 | This is currently AMD-only. | 71 | WARNING: Do not even assume this interface is staying stable! |
| 72 | 72 | ||
| 73 | config EDAC_MM_EDAC | 73 | config EDAC_MM_EDAC |
| 74 | tristate "Main Memory EDAC (Error Detection And Correction) reporting" | 74 | tristate "Main Memory EDAC (Error Detection And Correction) reporting" |
| @@ -105,11 +105,11 @@ config EDAC_GHES | |||
| 105 | In doubt, say 'Y'. | 105 | In doubt, say 'Y'. |
| 106 | 106 | ||
| 107 | config EDAC_AMD64 | 107 | config EDAC_AMD64 |
| 108 | tristate "AMD64 (Opteron, Athlon64) K8, F10h" | 108 | tristate "AMD64 (Opteron, Athlon64)" |
| 109 | depends on EDAC_MM_EDAC && AMD_NB && X86_64 && EDAC_DECODE_MCE | 109 | depends on EDAC_MM_EDAC && AMD_NB && EDAC_DECODE_MCE |
| 110 | help | 110 | help |
| 111 | Support for error detection and correction of DRAM ECC errors on | 111 | Support for error detection and correction of DRAM ECC errors on |
| 112 | the AMD64 families of memory controllers (K8 and F10h) | 112 | the AMD64 families (>= K8) of memory controllers. |
| 113 | 113 | ||
| 114 | config EDAC_AMD64_ERROR_INJECTION | 114 | config EDAC_AMD64_ERROR_INJECTION |
| 115 | bool "Sysfs HW Error injection facilities" | 115 | bool "Sysfs HW Error injection facilities" |
diff --git a/drivers/edac/Makefile b/drivers/edac/Makefile index 359aa499b200..d40c69a04df7 100644 --- a/drivers/edac/Makefile +++ b/drivers/edac/Makefile | |||
| @@ -9,7 +9,7 @@ | |||
| 9 | obj-$(CONFIG_EDAC) := edac_stub.o | 9 | obj-$(CONFIG_EDAC) := edac_stub.o |
| 10 | obj-$(CONFIG_EDAC_MM_EDAC) += edac_core.o | 10 | obj-$(CONFIG_EDAC_MM_EDAC) += edac_core.o |
| 11 | 11 | ||
| 12 | edac_core-y := edac_mc.o edac_device.o edac_mc_sysfs.o edac_pci_sysfs.o | 12 | edac_core-y := edac_mc.o edac_device.o edac_mc_sysfs.o |
| 13 | edac_core-y += edac_module.o edac_device_sysfs.o | 13 | edac_core-y += edac_module.o edac_device_sysfs.o |
| 14 | 14 | ||
| 15 | ifdef CONFIG_PCI | 15 | ifdef CONFIG_PCI |
diff --git a/drivers/edac/amd64_edac.c b/drivers/edac/amd64_edac.c index bbd65149cdb2..17638d7cf5c2 100644 --- a/drivers/edac/amd64_edac.c +++ b/drivers/edac/amd64_edac.c | |||
| @@ -692,9 +692,19 @@ static void debug_dump_dramcfg_low(struct amd64_pvt *pvt, u32 dclr, int chan) | |||
| 692 | { | 692 | { |
| 693 | edac_dbg(1, "F2x%d90 (DRAM Cfg Low): 0x%08x\n", chan, dclr); | 693 | edac_dbg(1, "F2x%d90 (DRAM Cfg Low): 0x%08x\n", chan, dclr); |
| 694 | 694 | ||
| 695 | edac_dbg(1, " DIMM type: %sbuffered; all DIMMs support ECC: %s\n", | 695 | if (pvt->dram_type == MEM_LRDDR3) { |
| 696 | (dclr & BIT(16)) ? "un" : "", | 696 | u32 dcsm = pvt->csels[chan].csmasks[0]; |
| 697 | (dclr & BIT(19)) ? "yes" : "no"); | 697 | /* |
| 698 | * It's assumed all LRDIMMs in a DCT are going to be of | ||
| 699 | * same 'type' until proven otherwise. So, use a cs | ||
| 700 | * value of '0' here to get dcsm value. | ||
| 701 | */ | ||
| 702 | edac_dbg(1, " LRDIMM %dx rank multiply\n", (dcsm & 0x3)); | ||
| 703 | } | ||
| 704 | |||
| 705 | edac_dbg(1, "All DIMMs support ECC:%s\n", | ||
| 706 | (dclr & BIT(19)) ? "yes" : "no"); | ||
| 707 | |||
| 698 | 708 | ||
| 699 | edac_dbg(1, " PAR/ERR parity: %s\n", | 709 | edac_dbg(1, " PAR/ERR parity: %s\n", |
| 700 | (dclr & BIT(8)) ? "enabled" : "disabled"); | 710 | (dclr & BIT(8)) ? "enabled" : "disabled"); |
| @@ -756,7 +766,7 @@ static void prep_chip_selects(struct amd64_pvt *pvt) | |||
| 756 | if (pvt->fam == 0xf && pvt->ext_model < K8_REV_F) { | 766 | if (pvt->fam == 0xf && pvt->ext_model < K8_REV_F) { |
| 757 | pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 8; | 767 | pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 8; |
| 758 | pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 8; | 768 | pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 8; |
| 759 | } else if (pvt->fam == 0x15 && pvt->model >= 0x30) { | 769 | } else if (pvt->fam == 0x15 && pvt->model == 0x30) { |
| 760 | pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 4; | 770 | pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 4; |
| 761 | pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 2; | 771 | pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 2; |
| 762 | } else { | 772 | } else { |
| @@ -813,25 +823,63 @@ static void read_dct_base_mask(struct amd64_pvt *pvt) | |||
| 813 | } | 823 | } |
| 814 | } | 824 | } |
| 815 | 825 | ||
| 816 | static enum mem_type determine_memory_type(struct amd64_pvt *pvt, int cs) | 826 | static void determine_memory_type(struct amd64_pvt *pvt) |
| 817 | { | 827 | { |
| 818 | enum mem_type type; | 828 | u32 dram_ctrl, dcsm; |
| 819 | 829 | ||
| 820 | /* F15h supports only DDR3 */ | 830 | switch (pvt->fam) { |
| 821 | if (pvt->fam >= 0x15) | 831 | case 0xf: |
| 822 | type = (pvt->dclr0 & BIT(16)) ? MEM_DDR3 : MEM_RDDR3; | 832 | if (pvt->ext_model >= K8_REV_F) |
| 823 | else if (pvt->fam == 0x10 || pvt->ext_model >= K8_REV_F) { | 833 | goto ddr3; |
| 834 | |||
| 835 | pvt->dram_type = (pvt->dclr0 & BIT(18)) ? MEM_DDR : MEM_RDDR; | ||
| 836 | return; | ||
| 837 | |||
| 838 | case 0x10: | ||
| 824 | if (pvt->dchr0 & DDR3_MODE) | 839 | if (pvt->dchr0 & DDR3_MODE) |
| 825 | type = (pvt->dclr0 & BIT(16)) ? MEM_DDR3 : MEM_RDDR3; | 840 | goto ddr3; |
| 841 | |||
| 842 | pvt->dram_type = (pvt->dclr0 & BIT(16)) ? MEM_DDR2 : MEM_RDDR2; | ||
| 843 | return; | ||
| 844 | |||
| 845 | case 0x15: | ||
| 846 | if (pvt->model < 0x60) | ||
| 847 | goto ddr3; | ||
| 848 | |||
| 849 | /* | ||
| 850 | * Model 0x60h needs special handling: | ||
| 851 | * | ||
| 852 | * We use a Chip Select value of '0' to obtain dcsm. | ||
| 853 | * Theoretically, it is possible to populate LRDIMMs of different | ||
| 854 | * 'Rank' value on a DCT. But this is not the common case. So, | ||
| 855 | * it's reasonable to assume all DIMMs are going to be of same | ||
| 856 | * 'type' until proven otherwise. | ||
| 857 | */ | ||
| 858 | amd64_read_dct_pci_cfg(pvt, 0, DRAM_CONTROL, &dram_ctrl); | ||
| 859 | dcsm = pvt->csels[0].csmasks[0]; | ||
| 860 | |||
| 861 | if (((dram_ctrl >> 8) & 0x7) == 0x2) | ||
| 862 | pvt->dram_type = MEM_DDR4; | ||
| 863 | else if (pvt->dclr0 & BIT(16)) | ||
| 864 | pvt->dram_type = MEM_DDR3; | ||
| 865 | else if (dcsm & 0x3) | ||
| 866 | pvt->dram_type = MEM_LRDDR3; | ||
| 826 | else | 867 | else |
| 827 | type = (pvt->dclr0 & BIT(16)) ? MEM_DDR2 : MEM_RDDR2; | 868 | pvt->dram_type = MEM_RDDR3; |
| 828 | } else { | ||
| 829 | type = (pvt->dclr0 & BIT(18)) ? MEM_DDR : MEM_RDDR; | ||
| 830 | } | ||
| 831 | 869 | ||
| 832 | amd64_info("CS%d: %s\n", cs, edac_mem_types[type]); | 870 | return; |
| 833 | 871 | ||
| 834 | return type; | 872 | case 0x16: |
| 873 | goto ddr3; | ||
| 874 | |||
| 875 | default: | ||
| 876 | WARN(1, KERN_ERR "%s: Family??? 0x%x\n", __func__, pvt->fam); | ||
| 877 | pvt->dram_type = MEM_EMPTY; | ||
| 878 | } | ||
| 879 | return; | ||
| 880 | |||
| 881 | ddr3: | ||
| 882 | pvt->dram_type = (pvt->dclr0 & BIT(16)) ? MEM_DDR3 : MEM_RDDR3; | ||
| 835 | } | 883 | } |
| 836 | 884 | ||
| 837 | /* Get the number of DCT channels the memory controller is using. */ | 885 | /* Get the number of DCT channels the memory controller is using. */ |
| @@ -958,8 +1006,12 @@ static void read_dram_base_limit_regs(struct amd64_pvt *pvt, unsigned range) | |||
| 958 | if (WARN_ON(!nb)) | 1006 | if (WARN_ON(!nb)) |
| 959 | return; | 1007 | return; |
| 960 | 1008 | ||
| 961 | pci_func = (pvt->model == 0x30) ? PCI_DEVICE_ID_AMD_15H_M30H_NB_F1 | 1009 | if (pvt->model == 0x60) |
| 962 | : PCI_DEVICE_ID_AMD_15H_NB_F1; | 1010 | pci_func = PCI_DEVICE_ID_AMD_15H_M60H_NB_F1; |
| 1011 | else if (pvt->model == 0x30) | ||
| 1012 | pci_func = PCI_DEVICE_ID_AMD_15H_M30H_NB_F1; | ||
| 1013 | else | ||
| 1014 | pci_func = PCI_DEVICE_ID_AMD_15H_NB_F1; | ||
| 963 | 1015 | ||
| 964 | f1 = pci_get_related_function(nb->misc->vendor, pci_func, nb->misc); | 1016 | f1 = pci_get_related_function(nb->misc->vendor, pci_func, nb->misc); |
| 965 | if (WARN_ON(!f1)) | 1017 | if (WARN_ON(!f1)) |
| @@ -1049,7 +1101,7 @@ static int ddr2_cs_size(unsigned i, bool dct_width) | |||
| 1049 | } | 1101 | } |
| 1050 | 1102 | ||
| 1051 | static int k8_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct, | 1103 | static int k8_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct, |
| 1052 | unsigned cs_mode) | 1104 | unsigned cs_mode, int cs_mask_nr) |
| 1053 | { | 1105 | { |
| 1054 | u32 dclr = dct ? pvt->dclr1 : pvt->dclr0; | 1106 | u32 dclr = dct ? pvt->dclr1 : pvt->dclr0; |
| 1055 | 1107 | ||
| @@ -1167,8 +1219,43 @@ static int ddr3_cs_size(unsigned i, bool dct_width) | |||
| 1167 | return cs_size; | 1219 | return cs_size; |
| 1168 | } | 1220 | } |
| 1169 | 1221 | ||
| 1222 | static int ddr3_lrdimm_cs_size(unsigned i, unsigned rank_multiply) | ||
| 1223 | { | ||
| 1224 | unsigned shift = 0; | ||
| 1225 | int cs_size = 0; | ||
| 1226 | |||
| 1227 | if (i < 4 || i == 6) | ||
| 1228 | cs_size = -1; | ||
| 1229 | else if (i == 12) | ||
| 1230 | shift = 7; | ||
| 1231 | else if (!(i & 0x1)) | ||
| 1232 | shift = i >> 1; | ||
| 1233 | else | ||
| 1234 | shift = (i + 1) >> 1; | ||
| 1235 | |||
| 1236 | if (cs_size != -1) | ||
| 1237 | cs_size = rank_multiply * (128 << shift); | ||
| 1238 | |||
| 1239 | return cs_size; | ||
| 1240 | } | ||
| 1241 | |||
| 1242 | static int ddr4_cs_size(unsigned i) | ||
| 1243 | { | ||
| 1244 | int cs_size = 0; | ||
| 1245 | |||
| 1246 | if (i == 0) | ||
| 1247 | cs_size = -1; | ||
| 1248 | else if (i == 1) | ||
| 1249 | cs_size = 1024; | ||
| 1250 | else | ||
| 1251 | /* Min cs_size = 1G */ | ||
| 1252 | cs_size = 1024 * (1 << (i >> 1)); | ||
| 1253 | |||
| 1254 | return cs_size; | ||
| 1255 | } | ||
| 1256 | |||
| 1170 | static int f10_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct, | 1257 | static int f10_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct, |
| 1171 | unsigned cs_mode) | 1258 | unsigned cs_mode, int cs_mask_nr) |
| 1172 | { | 1259 | { |
| 1173 | u32 dclr = dct ? pvt->dclr1 : pvt->dclr0; | 1260 | u32 dclr = dct ? pvt->dclr1 : pvt->dclr0; |
| 1174 | 1261 | ||
| @@ -1184,18 +1271,49 @@ static int f10_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct, | |||
| 1184 | * F15h supports only 64bit DCT interfaces | 1271 | * F15h supports only 64bit DCT interfaces |
| 1185 | */ | 1272 | */ |
| 1186 | static int f15_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct, | 1273 | static int f15_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct, |
| 1187 | unsigned cs_mode) | 1274 | unsigned cs_mode, int cs_mask_nr) |
| 1188 | { | 1275 | { |
| 1189 | WARN_ON(cs_mode > 12); | 1276 | WARN_ON(cs_mode > 12); |
| 1190 | 1277 | ||
| 1191 | return ddr3_cs_size(cs_mode, false); | 1278 | return ddr3_cs_size(cs_mode, false); |
| 1192 | } | 1279 | } |
| 1193 | 1280 | ||
| 1281 | /* F15h M60h supports DDR4 mapping as well.. */ | ||
| 1282 | static int f15_m60h_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct, | ||
| 1283 | unsigned cs_mode, int cs_mask_nr) | ||
| 1284 | { | ||
| 1285 | int cs_size; | ||
| 1286 | u32 dcsm = pvt->csels[dct].csmasks[cs_mask_nr]; | ||
| 1287 | |||
| 1288 | WARN_ON(cs_mode > 12); | ||
| 1289 | |||
| 1290 | if (pvt->dram_type == MEM_DDR4) { | ||
| 1291 | if (cs_mode > 9) | ||
| 1292 | return -1; | ||
| 1293 | |||
| 1294 | cs_size = ddr4_cs_size(cs_mode); | ||
| 1295 | } else if (pvt->dram_type == MEM_LRDDR3) { | ||
| 1296 | unsigned rank_multiply = dcsm & 0xf; | ||
| 1297 | |||
| 1298 | if (rank_multiply == 3) | ||
| 1299 | rank_multiply = 4; | ||
| 1300 | cs_size = ddr3_lrdimm_cs_size(cs_mode, rank_multiply); | ||
| 1301 | } else { | ||
| 1302 | /* Minimum cs size is 512mb for F15hM60h*/ | ||
| 1303 | if (cs_mode == 0x1) | ||
| 1304 | return -1; | ||
| 1305 | |||
| 1306 | cs_size = ddr3_cs_size(cs_mode, false); | ||
| 1307 | } | ||
| 1308 | |||
| 1309 | return cs_size; | ||
| 1310 | } | ||
| 1311 | |||
| 1194 | /* | 1312 | /* |
| 1195 | * F16h and F15h model 30h have only limited cs_modes. | 1313 | * F16h and F15h model 30h have only limited cs_modes. |
| 1196 | */ | 1314 | */ |
| 1197 | static int f16_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct, | 1315 | static int f16_dbam_to_chip_select(struct amd64_pvt *pvt, u8 dct, |
| 1198 | unsigned cs_mode) | 1316 | unsigned cs_mode, int cs_mask_nr) |
| 1199 | { | 1317 | { |
| 1200 | WARN_ON(cs_mode > 12); | 1318 | WARN_ON(cs_mode > 12); |
| 1201 | 1319 | ||
| @@ -1757,13 +1875,20 @@ static void debug_display_dimm_sizes(struct amd64_pvt *pvt, u8 ctrl) | |||
| 1757 | 1875 | ||
| 1758 | size0 = 0; | 1876 | size0 = 0; |
| 1759 | if (dcsb[dimm*2] & DCSB_CS_ENABLE) | 1877 | if (dcsb[dimm*2] & DCSB_CS_ENABLE) |
| 1878 | /* For f15m60h, need multiplier for LRDIMM cs_size | ||
| 1879 | * calculation. We pass 'dimm' value to the dbam_to_cs | ||
| 1880 | * mapper so we can find the multiplier from the | ||
| 1881 | * corresponding DCSM. | ||
| 1882 | */ | ||
| 1760 | size0 = pvt->ops->dbam_to_cs(pvt, ctrl, | 1883 | size0 = pvt->ops->dbam_to_cs(pvt, ctrl, |
| 1761 | DBAM_DIMM(dimm, dbam)); | 1884 | DBAM_DIMM(dimm, dbam), |
| 1885 | dimm); | ||
| 1762 | 1886 | ||
| 1763 | size1 = 0; | 1887 | size1 = 0; |
| 1764 | if (dcsb[dimm*2 + 1] & DCSB_CS_ENABLE) | 1888 | if (dcsb[dimm*2 + 1] & DCSB_CS_ENABLE) |
| 1765 | size1 = pvt->ops->dbam_to_cs(pvt, ctrl, | 1889 | size1 = pvt->ops->dbam_to_cs(pvt, ctrl, |
| 1766 | DBAM_DIMM(dimm, dbam)); | 1890 | DBAM_DIMM(dimm, dbam), |
| 1891 | dimm); | ||
| 1767 | 1892 | ||
| 1768 | amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n", | 1893 | amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n", |
| 1769 | dimm * 2, size0, | 1894 | dimm * 2, size0, |
| @@ -1812,6 +1937,16 @@ static struct amd64_family_type family_types[] = { | |||
| 1812 | .dbam_to_cs = f16_dbam_to_chip_select, | 1937 | .dbam_to_cs = f16_dbam_to_chip_select, |
| 1813 | } | 1938 | } |
| 1814 | }, | 1939 | }, |
| 1940 | [F15_M60H_CPUS] = { | ||
| 1941 | .ctl_name = "F15h_M60h", | ||
| 1942 | .f1_id = PCI_DEVICE_ID_AMD_15H_M60H_NB_F1, | ||
| 1943 | .f3_id = PCI_DEVICE_ID_AMD_15H_M60H_NB_F3, | ||
| 1944 | .ops = { | ||
| 1945 | .early_channel_count = f1x_early_channel_count, | ||
| 1946 | .map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow, | ||
| 1947 | .dbam_to_cs = f15_m60h_dbam_to_chip_select, | ||
| 1948 | } | ||
| 1949 | }, | ||
| 1815 | [F16_CPUS] = { | 1950 | [F16_CPUS] = { |
| 1816 | .ctl_name = "F16h", | 1951 | .ctl_name = "F16h", |
| 1817 | .f1_id = PCI_DEVICE_ID_AMD_16H_NB_F1, | 1952 | .f1_id = PCI_DEVICE_ID_AMD_16H_NB_F1, |
| @@ -2175,6 +2310,8 @@ static void read_mc_regs(struct amd64_pvt *pvt) | |||
| 2175 | } | 2310 | } |
| 2176 | 2311 | ||
| 2177 | pvt->ecc_sym_sz = 4; | 2312 | pvt->ecc_sym_sz = 4; |
| 2313 | determine_memory_type(pvt); | ||
| 2314 | edac_dbg(1, " DIMM type: %s\n", edac_mem_types[pvt->dram_type]); | ||
| 2178 | 2315 | ||
| 2179 | if (pvt->fam >= 0x10) { | 2316 | if (pvt->fam >= 0x10) { |
| 2180 | amd64_read_pci_cfg(pvt->F3, EXT_NB_MCA_CFG, &tmp); | 2317 | amd64_read_pci_cfg(pvt->F3, EXT_NB_MCA_CFG, &tmp); |
| @@ -2238,7 +2375,8 @@ static u32 get_csrow_nr_pages(struct amd64_pvt *pvt, u8 dct, int csrow_nr) | |||
| 2238 | */ | 2375 | */ |
| 2239 | cs_mode = DBAM_DIMM(csrow_nr / 2, dbam); | 2376 | cs_mode = DBAM_DIMM(csrow_nr / 2, dbam); |
| 2240 | 2377 | ||
| 2241 | nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode) << (20 - PAGE_SHIFT); | 2378 | nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode, (csrow_nr / 2)) |
| 2379 | << (20 - PAGE_SHIFT); | ||
| 2242 | 2380 | ||
| 2243 | edac_dbg(0, "csrow: %d, channel: %d, DBAM idx: %d\n", | 2381 | edac_dbg(0, "csrow: %d, channel: %d, DBAM idx: %d\n", |
| 2244 | csrow_nr, dct, cs_mode); | 2382 | csrow_nr, dct, cs_mode); |
| @@ -2257,7 +2395,6 @@ static int init_csrows(struct mem_ctl_info *mci) | |||
| 2257 | struct csrow_info *csrow; | 2395 | struct csrow_info *csrow; |
| 2258 | struct dimm_info *dimm; | 2396 | struct dimm_info *dimm; |
| 2259 | enum edac_type edac_mode; | 2397 | enum edac_type edac_mode; |
| 2260 | enum mem_type mtype; | ||
| 2261 | int i, j, empty = 1; | 2398 | int i, j, empty = 1; |
| 2262 | int nr_pages = 0; | 2399 | int nr_pages = 0; |
| 2263 | u32 val; | 2400 | u32 val; |
| @@ -2302,8 +2439,6 @@ static int init_csrows(struct mem_ctl_info *mci) | |||
| 2302 | nr_pages += row_dct1_pages; | 2439 | nr_pages += row_dct1_pages; |
| 2303 | } | 2440 | } |
| 2304 | 2441 | ||
| 2305 | mtype = determine_memory_type(pvt, i); | ||
| 2306 | |||
| 2307 | edac_dbg(1, "Total csrow%d pages: %u\n", i, nr_pages); | 2442 | edac_dbg(1, "Total csrow%d pages: %u\n", i, nr_pages); |
| 2308 | 2443 | ||
| 2309 | /* | 2444 | /* |
| @@ -2317,7 +2452,7 @@ static int init_csrows(struct mem_ctl_info *mci) | |||
| 2317 | 2452 | ||
| 2318 | for (j = 0; j < pvt->channel_count; j++) { | 2453 | for (j = 0; j < pvt->channel_count; j++) { |
| 2319 | dimm = csrow->channels[j]->dimm; | 2454 | dimm = csrow->channels[j]->dimm; |
| 2320 | dimm->mtype = mtype; | 2455 | dimm->mtype = pvt->dram_type; |
| 2321 | dimm->edac_mode = edac_mode; | 2456 | dimm->edac_mode = edac_mode; |
| 2322 | } | 2457 | } |
| 2323 | } | 2458 | } |
| @@ -2604,6 +2739,10 @@ static struct amd64_family_type *per_family_init(struct amd64_pvt *pvt) | |||
| 2604 | fam_type = &family_types[F15_M30H_CPUS]; | 2739 | fam_type = &family_types[F15_M30H_CPUS]; |
| 2605 | pvt->ops = &family_types[F15_M30H_CPUS].ops; | 2740 | pvt->ops = &family_types[F15_M30H_CPUS].ops; |
| 2606 | break; | 2741 | break; |
| 2742 | } else if (pvt->model == 0x60) { | ||
| 2743 | fam_type = &family_types[F15_M60H_CPUS]; | ||
| 2744 | pvt->ops = &family_types[F15_M60H_CPUS].ops; | ||
| 2745 | break; | ||
| 2607 | } | 2746 | } |
| 2608 | 2747 | ||
| 2609 | fam_type = &family_types[F15_CPUS]; | 2748 | fam_type = &family_types[F15_CPUS]; |
| @@ -2828,55 +2967,13 @@ static void remove_one_instance(struct pci_dev *pdev) | |||
| 2828 | * inquiry this table to see if this driver is for a given device found. | 2967 | * inquiry this table to see if this driver is for a given device found. |
| 2829 | */ | 2968 | */ |
| 2830 | static const struct pci_device_id amd64_pci_table[] = { | 2969 | static const struct pci_device_id amd64_pci_table[] = { |
| 2831 | { | 2970 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_K8_NB_MEMCTL) }, |
| 2832 | .vendor = PCI_VENDOR_ID_AMD, | 2971 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_10H_NB_DRAM) }, |
| 2833 | .device = PCI_DEVICE_ID_AMD_K8_NB_MEMCTL, | 2972 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F2) }, |
| 2834 | .subvendor = PCI_ANY_ID, | 2973 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F2) }, |
| 2835 | .subdevice = PCI_ANY_ID, | 2974 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M60H_NB_F2) }, |
| 2836 | .class = 0, | 2975 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F2) }, |
| 2837 | .class_mask = 0, | 2976 | { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F2) }, |
| 2838 | }, | ||
| 2839 | { | ||
| 2840 | .vendor = PCI_VENDOR_ID_AMD, | ||
| 2841 | .device = PCI_DEVICE_ID_AMD_10H_NB_DRAM, | ||
| 2842 | .subvendor = PCI_ANY_ID, | ||
| 2843 | .subdevice = PCI_ANY_ID, | ||
| 2844 | .class = 0, | ||
| 2845 | .class_mask = 0, | ||
| 2846 | }, | ||
| 2847 | { | ||
| 2848 | .vendor = PCI_VENDOR_ID_AMD, | ||
| 2849 | .device = PCI_DEVICE_ID_AMD_15H_NB_F2, | ||
| 2850 | .subvendor = PCI_ANY_ID, | ||
| 2851 | .subdevice = PCI_ANY_ID, | ||
| 2852 | .class = 0, | ||
| 2853 | .class_mask = 0, | ||
| 2854 | }, | ||
| 2855 | { | ||
| 2856 | .vendor = PCI_VENDOR_ID_AMD, | ||
| 2857 | .device = PCI_DEVICE_ID_AMD_15H_M30H_NB_F2, | ||
| 2858 | .subvendor = PCI_ANY_ID, | ||
| 2859 | .subdevice = PCI_ANY_ID, | ||
| 2860 | .class = 0, | ||
| 2861 | .class_mask = 0, | ||
| 2862 | }, | ||
| 2863 | { | ||
| 2864 | .vendor = PCI_VENDOR_ID_AMD, | ||
| 2865 | .device = PCI_DEVICE_ID_AMD_16H_NB_F2, | ||
| 2866 | .subvendor = PCI_ANY_ID, | ||
| 2867 | .subdevice = PCI_ANY_ID, | ||
| 2868 | .class = 0, | ||
| 2869 | .class_mask = 0, | ||
| 2870 | }, | ||
| 2871 | { | ||
| 2872 | .vendor = PCI_VENDOR_ID_AMD, | ||
| 2873 | .device = PCI_DEVICE_ID_AMD_16H_M30H_NB_F2, | ||
| 2874 | .subvendor = PCI_ANY_ID, | ||
| 2875 | .subdevice = PCI_ANY_ID, | ||
| 2876 | .class = 0, | ||
| 2877 | .class_mask = 0, | ||
| 2878 | }, | ||
| 2879 | |||
| 2880 | {0, } | 2977 | {0, } |
| 2881 | }; | 2978 | }; |
| 2882 | MODULE_DEVICE_TABLE(pci, amd64_pci_table); | 2979 | MODULE_DEVICE_TABLE(pci, amd64_pci_table); |
| @@ -2938,6 +3035,11 @@ static int __init amd64_edac_init(void) | |||
| 2938 | goto err_no_instances; | 3035 | goto err_no_instances; |
| 2939 | 3036 | ||
| 2940 | setup_pci_device(); | 3037 | setup_pci_device(); |
| 3038 | |||
| 3039 | #ifdef CONFIG_X86_32 | ||
| 3040 | amd64_err("%s on 32-bit is unsupported. USE AT YOUR OWN RISK!\n", EDAC_MOD_STR); | ||
| 3041 | #endif | ||
| 3042 | |||
| 2941 | return 0; | 3043 | return 0; |
| 2942 | 3044 | ||
| 2943 | err_no_instances: | 3045 | err_no_instances: |
diff --git a/drivers/edac/amd64_edac.h b/drivers/edac/amd64_edac.h index 55fb5941c6d4..d8468c667925 100644 --- a/drivers/edac/amd64_edac.h +++ b/drivers/edac/amd64_edac.h | |||
| @@ -162,10 +162,12 @@ | |||
| 162 | /* | 162 | /* |
| 163 | * PCI-defined configuration space registers | 163 | * PCI-defined configuration space registers |
| 164 | */ | 164 | */ |
| 165 | #define PCI_DEVICE_ID_AMD_15H_M30H_NB_F1 0x141b | ||
| 166 | #define PCI_DEVICE_ID_AMD_15H_M30H_NB_F2 0x141c | ||
| 167 | #define PCI_DEVICE_ID_AMD_15H_NB_F1 0x1601 | 165 | #define PCI_DEVICE_ID_AMD_15H_NB_F1 0x1601 |
| 168 | #define PCI_DEVICE_ID_AMD_15H_NB_F2 0x1602 | 166 | #define PCI_DEVICE_ID_AMD_15H_NB_F2 0x1602 |
| 167 | #define PCI_DEVICE_ID_AMD_15H_M30H_NB_F1 0x141b | ||
| 168 | #define PCI_DEVICE_ID_AMD_15H_M30H_NB_F2 0x141c | ||
| 169 | #define PCI_DEVICE_ID_AMD_15H_M60H_NB_F1 0x1571 | ||
| 170 | #define PCI_DEVICE_ID_AMD_15H_M60H_NB_F2 0x1572 | ||
| 169 | #define PCI_DEVICE_ID_AMD_16H_NB_F1 0x1531 | 171 | #define PCI_DEVICE_ID_AMD_16H_NB_F1 0x1531 |
| 170 | #define PCI_DEVICE_ID_AMD_16H_NB_F2 0x1532 | 172 | #define PCI_DEVICE_ID_AMD_16H_NB_F2 0x1532 |
| 171 | #define PCI_DEVICE_ID_AMD_16H_M30H_NB_F1 0x1581 | 173 | #define PCI_DEVICE_ID_AMD_16H_M30H_NB_F1 0x1581 |
| @@ -221,6 +223,8 @@ | |||
| 221 | 223 | ||
| 222 | #define csrow_enabled(i, dct, pvt) ((pvt)->csels[(dct)].csbases[(i)] & DCSB_CS_ENABLE) | 224 | #define csrow_enabled(i, dct, pvt) ((pvt)->csels[(dct)].csbases[(i)] & DCSB_CS_ENABLE) |
| 223 | 225 | ||
| 226 | #define DRAM_CONTROL 0x78 | ||
| 227 | |||
| 224 | #define DBAM0 0x80 | 228 | #define DBAM0 0x80 |
| 225 | #define DBAM1 0x180 | 229 | #define DBAM1 0x180 |
| 226 | 230 | ||
| @@ -301,6 +305,7 @@ enum amd_families { | |||
| 301 | F10_CPUS, | 305 | F10_CPUS, |
| 302 | F15_CPUS, | 306 | F15_CPUS, |
| 303 | F15_M30H_CPUS, | 307 | F15_M30H_CPUS, |
| 308 | F15_M60H_CPUS, | ||
| 304 | F16_CPUS, | 309 | F16_CPUS, |
| 305 | F16_M30H_CPUS, | 310 | F16_M30H_CPUS, |
| 306 | NUM_FAMILIES, | 311 | NUM_FAMILIES, |
| @@ -379,6 +384,9 @@ struct amd64_pvt { | |||
| 379 | 384 | ||
| 380 | /* place to store error injection parameters prior to issue */ | 385 | /* place to store error injection parameters prior to issue */ |
| 381 | struct error_injection injection; | 386 | struct error_injection injection; |
| 387 | |||
| 388 | /* cache the dram_type */ | ||
| 389 | enum mem_type dram_type; | ||
| 382 | }; | 390 | }; |
| 383 | 391 | ||
| 384 | enum err_codes { | 392 | enum err_codes { |
| @@ -480,7 +488,8 @@ struct low_ops { | |||
| 480 | int (*early_channel_count) (struct amd64_pvt *pvt); | 488 | int (*early_channel_count) (struct amd64_pvt *pvt); |
| 481 | void (*map_sysaddr_to_csrow) (struct mem_ctl_info *mci, u64 sys_addr, | 489 | void (*map_sysaddr_to_csrow) (struct mem_ctl_info *mci, u64 sys_addr, |
| 482 | struct err_info *); | 490 | struct err_info *); |
| 483 | int (*dbam_to_cs) (struct amd64_pvt *pvt, u8 dct, unsigned cs_mode); | 491 | int (*dbam_to_cs) (struct amd64_pvt *pvt, u8 dct, |
| 492 | unsigned cs_mode, int cs_mask_nr); | ||
| 484 | }; | 493 | }; |
| 485 | 494 | ||
| 486 | struct amd64_family_type { | 495 | struct amd64_family_type { |
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c index c3893b0ddb18..1747906f10ce 100644 --- a/drivers/edac/edac_mc.c +++ b/drivers/edac/edac_mc.c | |||
| @@ -125,27 +125,27 @@ static void edac_mc_dump_mci(struct mem_ctl_info *mci) | |||
| 125 | 125 | ||
| 126 | #endif /* CONFIG_EDAC_DEBUG */ | 126 | #endif /* CONFIG_EDAC_DEBUG */ |
| 127 | 127 | ||
| 128 | /* | ||
| 129 | * keep those in sync with the enum mem_type | ||
| 130 | */ | ||
| 131 | const char * const edac_mem_types[] = { | 128 | const char * const edac_mem_types[] = { |
| 132 | "Empty csrow", | 129 | [MEM_EMPTY] = "Empty csrow", |
| 133 | "Reserved csrow type", | 130 | [MEM_RESERVED] = "Reserved csrow type", |
| 134 | "Unknown csrow type", | 131 | [MEM_UNKNOWN] = "Unknown csrow type", |
| 135 | "Fast page mode RAM", | 132 | [MEM_FPM] = "Fast page mode RAM", |
| 136 | "Extended data out RAM", | 133 | [MEM_EDO] = "Extended data out RAM", |
| 137 | "Burst Extended data out RAM", | 134 | [MEM_BEDO] = "Burst Extended data out RAM", |
| 138 | "Single data rate SDRAM", | 135 | [MEM_SDR] = "Single data rate SDRAM", |
| 139 | "Registered single data rate SDRAM", | 136 | [MEM_RDR] = "Registered single data rate SDRAM", |
| 140 | "Double data rate SDRAM", | 137 | [MEM_DDR] = "Double data rate SDRAM", |
| 141 | "Registered Double data rate SDRAM", | 138 | [MEM_RDDR] = "Registered Double data rate SDRAM", |
| 142 | "Rambus DRAM", | 139 | [MEM_RMBS] = "Rambus DRAM", |
| 143 | "Unbuffered DDR2 RAM", | 140 | [MEM_DDR2] = "Unbuffered DDR2 RAM", |
| 144 | "Fully buffered DDR2", | 141 | [MEM_FB_DDR2] = "Fully buffered DDR2", |
| 145 | "Registered DDR2 RAM", | 142 | [MEM_RDDR2] = "Registered DDR2 RAM", |
| 146 | "Rambus XDR", | 143 | [MEM_XDR] = "Rambus XDR", |
| 147 | "Unbuffered DDR3 RAM", | 144 | [MEM_DDR3] = "Unbuffered DDR3 RAM", |
| 148 | "Registered DDR3 RAM", | 145 | [MEM_RDDR3] = "Registered DDR3 RAM", |
| 146 | [MEM_LRDDR3] = "Load-Reduced DDR3 RAM", | ||
| 147 | [MEM_DDR4] = "Unbuffered DDR4 RAM", | ||
| 148 | [MEM_RDDR4] = "Registered DDR4 RAM", | ||
| 149 | }; | 149 | }; |
| 150 | EXPORT_SYMBOL_GPL(edac_mem_types); | 150 | EXPORT_SYMBOL_GPL(edac_mem_types); |
| 151 | 151 | ||
diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c index e8658e451762..24d877f6e577 100644 --- a/drivers/edac/edac_pci_sysfs.c +++ b/drivers/edac/edac_pci_sysfs.c | |||
| @@ -14,9 +14,6 @@ | |||
| 14 | #include "edac_core.h" | 14 | #include "edac_core.h" |
| 15 | #include "edac_module.h" | 15 | #include "edac_module.h" |
| 16 | 16 | ||
| 17 | /* Turn off this whole feature if PCI is not configured */ | ||
| 18 | #ifdef CONFIG_PCI | ||
| 19 | |||
| 20 | #define EDAC_PCI_SYMLINK "device" | 17 | #define EDAC_PCI_SYMLINK "device" |
| 21 | 18 | ||
| 22 | /* data variables exported via sysfs */ | 19 | /* data variables exported via sysfs */ |
| @@ -761,5 +758,3 @@ MODULE_PARM_DESC(check_pci_errors, | |||
| 761 | module_param(edac_pci_panic_on_pe, int, 0644); | 758 | module_param(edac_pci_panic_on_pe, int, 0644); |
| 762 | MODULE_PARM_DESC(edac_pci_panic_on_pe, | 759 | MODULE_PARM_DESC(edac_pci_panic_on_pe, |
| 763 | "Panic on PCI Bus Parity error: 0=off 1=on"); | 760 | "Panic on PCI Bus Parity error: 0=off 1=on"); |
| 764 | |||
| 765 | #endif /* CONFIG_PCI */ | ||
diff --git a/drivers/edac/ghes_edac.c b/drivers/edac/ghes_edac.c index 8399b4e16fe0..b24681998740 100644 --- a/drivers/edac/ghes_edac.c +++ b/drivers/edac/ghes_edac.c | |||
| @@ -413,8 +413,8 @@ void ghes_edac_report_mem_error(struct ghes *ghes, int sev, | |||
| 413 | 413 | ||
| 414 | /* Generate the trace event */ | 414 | /* Generate the trace event */ |
| 415 | grain_bits = fls_long(e->grain); | 415 | grain_bits = fls_long(e->grain); |
| 416 | sprintf(pvt->detail_location, "APEI location: %s %s", | 416 | snprintf(pvt->detail_location, sizeof(pvt->detail_location), |
| 417 | e->location, e->other_detail); | 417 | "APEI location: %s %s", e->location, e->other_detail); |
| 418 | trace_mc_event(type, e->msg, e->label, e->error_count, | 418 | trace_mc_event(type, e->msg, e->label, e->error_count, |
| 419 | mci->mc_idx, e->top_layer, e->mid_layer, e->low_layer, | 419 | mci->mc_idx, e->top_layer, e->mid_layer, e->low_layer, |
| 420 | PAGES_TO_MiB(e->page_frame_number) | e->offset_in_page, | 420 | PAGES_TO_MiB(e->page_frame_number) | e->offset_in_page, |
diff --git a/drivers/edac/i3000_edac.c b/drivers/edac/i3000_edac.c index cd28b968e5c7..5cb36a6022cc 100644 --- a/drivers/edac/i3000_edac.c +++ b/drivers/edac/i3000_edac.c | |||
| @@ -542,8 +542,7 @@ fail1: | |||
| 542 | pci_unregister_driver(&i3000_driver); | 542 | pci_unregister_driver(&i3000_driver); |
| 543 | 543 | ||
| 544 | fail0: | 544 | fail0: |
| 545 | if (mci_pdev) | 545 | pci_dev_put(mci_pdev); |
| 546 | pci_dev_put(mci_pdev); | ||
| 547 | 546 | ||
| 548 | return pci_rc; | 547 | return pci_rc; |
| 549 | } | 548 | } |
diff --git a/drivers/edac/i3200_edac.c b/drivers/edac/i3200_edac.c index aa98b136f5d0..4ad062b0ef26 100644 --- a/drivers/edac/i3200_edac.c +++ b/drivers/edac/i3200_edac.c | |||
| @@ -523,8 +523,7 @@ fail1: | |||
| 523 | pci_unregister_driver(&i3200_driver); | 523 | pci_unregister_driver(&i3200_driver); |
| 524 | 524 | ||
| 525 | fail0: | 525 | fail0: |
| 526 | if (mci_pdev) | 526 | pci_dev_put(mci_pdev); |
| 527 | pci_dev_put(mci_pdev); | ||
| 528 | 527 | ||
| 529 | return pci_rc; | 528 | return pci_rc; |
| 530 | } | 529 | } |
diff --git a/drivers/edac/i82443bxgx_edac.c b/drivers/edac/i82443bxgx_edac.c index d730e276d1a8..b4705d9366bf 100644 --- a/drivers/edac/i82443bxgx_edac.c +++ b/drivers/edac/i82443bxgx_edac.c | |||
| @@ -458,8 +458,7 @@ static void __exit i82443bxgx_edacmc_exit(void) | |||
| 458 | if (!i82443bxgx_registered) | 458 | if (!i82443bxgx_registered) |
| 459 | i82443bxgx_edacmc_remove_one(mci_pdev); | 459 | i82443bxgx_edacmc_remove_one(mci_pdev); |
| 460 | 460 | ||
| 461 | if (mci_pdev) | 461 | pci_dev_put(mci_pdev); |
| 462 | pci_dev_put(mci_pdev); | ||
| 463 | } | 462 | } |
| 464 | 463 | ||
| 465 | module_init(i82443bxgx_edacmc_init); | 464 | module_init(i82443bxgx_edacmc_init); |
diff --git a/drivers/edac/mce_amd.c b/drivers/edac/mce_amd.c index f78c1c54dbd5..58586d59bf8e 100644 --- a/drivers/edac/mce_amd.c +++ b/drivers/edac/mce_amd.c | |||
| @@ -138,6 +138,15 @@ static const char * const mc5_mce_desc[] = { | |||
| 138 | "Retire status queue" | 138 | "Retire status queue" |
| 139 | }; | 139 | }; |
| 140 | 140 | ||
| 141 | static const char * const mc6_mce_desc[] = { | ||
| 142 | "Hardware Assertion", | ||
| 143 | "Free List", | ||
| 144 | "Physical Register File", | ||
| 145 | "Retire Queue", | ||
| 146 | "Scheduler table", | ||
| 147 | "Status Register File", | ||
| 148 | }; | ||
| 149 | |||
| 141 | static bool f12h_mc0_mce(u16 ec, u8 xec) | 150 | static bool f12h_mc0_mce(u16 ec, u8 xec) |
| 142 | { | 151 | { |
| 143 | bool ret = false; | 152 | bool ret = false; |
| @@ -432,8 +441,8 @@ static bool k8_mc2_mce(u16 ec, u8 xec) | |||
| 432 | pr_cont(": %s error in the L2 cache tags.\n", R4_MSG(ec)); | 441 | pr_cont(": %s error in the L2 cache tags.\n", R4_MSG(ec)); |
| 433 | else if (xec == 0x0) { | 442 | else if (xec == 0x0) { |
| 434 | if (TLB_ERROR(ec)) | 443 | if (TLB_ERROR(ec)) |
| 435 | pr_cont(": %s error in a Page Descriptor Cache or " | 444 | pr_cont("%s error in a Page Descriptor Cache or Guest TLB.\n", |
| 436 | "Guest TLB.\n", TT_MSG(ec)); | 445 | TT_MSG(ec)); |
| 437 | else if (BUS_ERROR(ec)) | 446 | else if (BUS_ERROR(ec)) |
| 438 | pr_cont(": %s/ECC error in data read from NB: %s.\n", | 447 | pr_cont(": %s/ECC error in data read from NB: %s.\n", |
| 439 | R4_MSG(ec), PP_MSG(ec)); | 448 | R4_MSG(ec), PP_MSG(ec)); |
| @@ -672,38 +681,10 @@ static void decode_mc6_mce(struct mce *m) | |||
| 672 | 681 | ||
| 673 | pr_emerg(HW_ERR "MC6 Error: "); | 682 | pr_emerg(HW_ERR "MC6 Error: "); |
| 674 | 683 | ||
| 675 | switch (xec) { | 684 | if (xec > 0x5) |
| 676 | case 0x0: | ||
| 677 | pr_cont("Hardware Assertion"); | ||
| 678 | break; | ||
| 679 | |||
| 680 | case 0x1: | ||
| 681 | pr_cont("Free List"); | ||
| 682 | break; | ||
| 683 | |||
| 684 | case 0x2: | ||
| 685 | pr_cont("Physical Register File"); | ||
| 686 | break; | ||
| 687 | |||
| 688 | case 0x3: | ||
| 689 | pr_cont("Retire Queue"); | ||
| 690 | break; | ||
| 691 | |||
| 692 | case 0x4: | ||
| 693 | pr_cont("Scheduler table"); | ||
| 694 | break; | ||
| 695 | |||
| 696 | case 0x5: | ||
| 697 | pr_cont("Status Register File"); | ||
| 698 | break; | ||
| 699 | |||
| 700 | default: | ||
| 701 | goto wrong_mc6_mce; | 685 | goto wrong_mc6_mce; |
| 702 | break; | ||
| 703 | } | ||
| 704 | |||
| 705 | pr_cont(" parity error.\n"); | ||
| 706 | 686 | ||
| 687 | pr_cont("%s parity error.\n", mc6_mce_desc[xec]); | ||
| 707 | return; | 688 | return; |
| 708 | 689 | ||
| 709 | wrong_mc6_mce: | 690 | wrong_mc6_mce: |
| @@ -800,7 +781,7 @@ int amd_decode_mce(struct notifier_block *nb, unsigned long val, void *data) | |||
| 800 | pr_cont("]: 0x%016llx\n", m->status); | 781 | pr_cont("]: 0x%016llx\n", m->status); |
| 801 | 782 | ||
| 802 | if (m->status & MCI_STATUS_ADDRV) | 783 | if (m->status & MCI_STATUS_ADDRV) |
| 803 | pr_emerg(HW_ERR "MC%d_ADDR: 0x%016llx\n", m->bank, m->addr); | 784 | pr_emerg(HW_ERR "MC%d Error Address: 0x%016llx\n", m->bank, m->addr); |
| 804 | 785 | ||
| 805 | if (!fam_ops) | 786 | if (!fam_ops) |
| 806 | goto err_code; | 787 | goto err_code; |
diff --git a/drivers/edac/mce_amd_inj.c b/drivers/edac/mce_amd_inj.c index 5e46a9fea31b..0bd91a802c67 100644 --- a/drivers/edac/mce_amd_inj.c +++ b/drivers/edac/mce_amd_inj.c | |||
| @@ -1,173 +1,262 @@ | |||
| 1 | /* | 1 | /* |
| 2 | * A simple MCE injection facility for testing the MCE decoding code. This | 2 | * A simple MCE injection facility for testing different aspects of the RAS |
| 3 | * driver should be built as module so that it can be loaded on production | 3 | * code. This driver should be built as module so that it can be loaded |
| 4 | * kernels for testing purposes. | 4 | * on production kernels for testing purposes. |
| 5 | * | 5 | * |
| 6 | * This file may be distributed under the terms of the GNU General Public | 6 | * This file may be distributed under the terms of the GNU General Public |
| 7 | * License version 2. | 7 | * License version 2. |
| 8 | * | 8 | * |
| 9 | * Copyright (c) 2010: Borislav Petkov <bp@alien8.de> | 9 | * Copyright (c) 2010-14: Borislav Petkov <bp@alien8.de> |
| 10 | * Advanced Micro Devices Inc. | 10 | * Advanced Micro Devices Inc. |
| 11 | */ | 11 | */ |
| 12 | 12 | ||
| 13 | #include <linux/kobject.h> | 13 | #include <linux/kobject.h> |
| 14 | #include <linux/debugfs.h> | ||
| 14 | #include <linux/device.h> | 15 | #include <linux/device.h> |
| 15 | #include <linux/edac.h> | ||
| 16 | #include <linux/module.h> | 16 | #include <linux/module.h> |
| 17 | #include <linux/cpu.h> | ||
| 17 | #include <asm/mce.h> | 18 | #include <asm/mce.h> |
| 18 | 19 | ||
| 19 | #include "mce_amd.h" | 20 | #include "mce_amd.h" |
| 20 | 21 | ||
| 21 | struct edac_mce_attr { | ||
| 22 | struct attribute attr; | ||
| 23 | ssize_t (*show) (struct kobject *kobj, struct edac_mce_attr *attr, char *buf); | ||
| 24 | ssize_t (*store)(struct kobject *kobj, struct edac_mce_attr *attr, | ||
| 25 | const char *buf, size_t count); | ||
| 26 | }; | ||
| 27 | |||
| 28 | #define EDAC_MCE_ATTR(_name, _mode, _show, _store) \ | ||
| 29 | static struct edac_mce_attr mce_attr_##_name = __ATTR(_name, _mode, _show, _store) | ||
| 30 | |||
| 31 | static struct kobject *mce_kobj; | ||
| 32 | |||
| 33 | /* | 22 | /* |
| 34 | * Collect all the MCi_XXX settings | 23 | * Collect all the MCi_XXX settings |
| 35 | */ | 24 | */ |
| 36 | static struct mce i_mce; | 25 | static struct mce i_mce; |
| 26 | static struct dentry *dfs_inj; | ||
| 37 | 27 | ||
| 38 | #define MCE_INJECT_STORE(reg) \ | 28 | #define MCE_INJECT_SET(reg) \ |
| 39 | static ssize_t edac_inject_##reg##_store(struct kobject *kobj, \ | 29 | static int inj_##reg##_set(void *data, u64 val) \ |
| 40 | struct edac_mce_attr *attr, \ | ||
| 41 | const char *data, size_t count)\ | ||
| 42 | { \ | 30 | { \ |
| 43 | int ret = 0; \ | 31 | struct mce *m = (struct mce *)data; \ |
| 44 | unsigned long value; \ | ||
| 45 | \ | ||
| 46 | ret = kstrtoul(data, 16, &value); \ | ||
| 47 | if (ret < 0) \ | ||
| 48 | printk(KERN_ERR "Error writing MCE " #reg " field.\n"); \ | ||
| 49 | \ | 32 | \ |
| 50 | i_mce.reg = value; \ | 33 | m->reg = val; \ |
| 51 | \ | 34 | return 0; \ |
| 52 | return count; \ | ||
| 53 | } | 35 | } |
| 54 | 36 | ||
| 55 | MCE_INJECT_STORE(status); | 37 | MCE_INJECT_SET(status); |
| 56 | MCE_INJECT_STORE(misc); | 38 | MCE_INJECT_SET(misc); |
| 57 | MCE_INJECT_STORE(addr); | 39 | MCE_INJECT_SET(addr); |
| 58 | 40 | ||
| 59 | #define MCE_INJECT_SHOW(reg) \ | 41 | #define MCE_INJECT_GET(reg) \ |
| 60 | static ssize_t edac_inject_##reg##_show(struct kobject *kobj, \ | 42 | static int inj_##reg##_get(void *data, u64 *val) \ |
| 61 | struct edac_mce_attr *attr, \ | ||
| 62 | char *buf) \ | ||
| 63 | { \ | 43 | { \ |
| 64 | return sprintf(buf, "0x%016llx\n", i_mce.reg); \ | 44 | struct mce *m = (struct mce *)data; \ |
| 45 | \ | ||
| 46 | *val = m->reg; \ | ||
| 47 | return 0; \ | ||
| 65 | } | 48 | } |
| 66 | 49 | ||
| 67 | MCE_INJECT_SHOW(status); | 50 | MCE_INJECT_GET(status); |
| 68 | MCE_INJECT_SHOW(misc); | 51 | MCE_INJECT_GET(misc); |
| 69 | MCE_INJECT_SHOW(addr); | 52 | MCE_INJECT_GET(addr); |
| 70 | 53 | ||
| 71 | EDAC_MCE_ATTR(status, 0644, edac_inject_status_show, edac_inject_status_store); | 54 | DEFINE_SIMPLE_ATTRIBUTE(status_fops, inj_status_get, inj_status_set, "%llx\n"); |
| 72 | EDAC_MCE_ATTR(misc, 0644, edac_inject_misc_show, edac_inject_misc_store); | 55 | DEFINE_SIMPLE_ATTRIBUTE(misc_fops, inj_misc_get, inj_misc_set, "%llx\n"); |
| 73 | EDAC_MCE_ATTR(addr, 0644, edac_inject_addr_show, edac_inject_addr_store); | 56 | DEFINE_SIMPLE_ATTRIBUTE(addr_fops, inj_addr_get, inj_addr_set, "%llx\n"); |
| 74 | 57 | ||
| 75 | /* | 58 | /* |
| 76 | * This denotes into which bank we're injecting and triggers | 59 | * Caller needs to be make sure this cpu doesn't disappear |
| 77 | * the injection, at the same time. | 60 | * from under us, i.e.: get_cpu/put_cpu. |
| 78 | */ | 61 | */ |
| 79 | static ssize_t edac_inject_bank_store(struct kobject *kobj, | 62 | static int toggle_hw_mce_inject(unsigned int cpu, bool enable) |
| 80 | struct edac_mce_attr *attr, | ||
| 81 | const char *data, size_t count) | ||
| 82 | { | 63 | { |
| 83 | int ret = 0; | 64 | u32 l, h; |
| 84 | unsigned long value; | 65 | int err; |
| 85 | 66 | ||
| 86 | ret = kstrtoul(data, 10, &value); | 67 | err = rdmsr_on_cpu(cpu, MSR_K7_HWCR, &l, &h); |
| 87 | if (ret < 0) { | 68 | if (err) { |
| 88 | printk(KERN_ERR "Invalid bank value!\n"); | 69 | pr_err("%s: error reading HWCR\n", __func__); |
| 89 | return -EINVAL; | 70 | return err; |
| 90 | } | 71 | } |
| 91 | 72 | ||
| 92 | if (value > 5) | 73 | enable ? (l |= BIT(18)) : (l &= ~BIT(18)); |
| 93 | if (boot_cpu_data.x86 != 0x15 || value > 6) { | ||
| 94 | printk(KERN_ERR "Non-existent MCE bank: %lu\n", value); | ||
| 95 | return -EINVAL; | ||
| 96 | } | ||
| 97 | 74 | ||
| 98 | i_mce.bank = value; | 75 | err = wrmsr_on_cpu(cpu, MSR_K7_HWCR, l, h); |
| 76 | if (err) | ||
| 77 | pr_err("%s: error writing HWCR\n", __func__); | ||
| 99 | 78 | ||
| 100 | amd_decode_mce(NULL, 0, &i_mce); | 79 | return err; |
| 80 | } | ||
| 101 | 81 | ||
| 102 | return count; | 82 | static int flags_get(void *data, u64 *val) |
| 83 | { | ||
| 84 | struct mce *m = (struct mce *)data; | ||
| 85 | |||
| 86 | *val = m->inject_flags; | ||
| 87 | |||
| 88 | return 0; | ||
| 103 | } | 89 | } |
| 104 | 90 | ||
| 105 | static ssize_t edac_inject_bank_show(struct kobject *kobj, | 91 | static int flags_set(void *data, u64 val) |
| 106 | struct edac_mce_attr *attr, char *buf) | ||
| 107 | { | 92 | { |
| 108 | return sprintf(buf, "%d\n", i_mce.bank); | 93 | struct mce *m = (struct mce *)data; |
| 94 | |||
| 95 | m->inject_flags = (u8)val; | ||
| 96 | return 0; | ||
| 109 | } | 97 | } |
| 110 | 98 | ||
| 111 | EDAC_MCE_ATTR(bank, 0644, edac_inject_bank_show, edac_inject_bank_store); | 99 | DEFINE_SIMPLE_ATTRIBUTE(flags_fops, flags_get, flags_set, "%llu\n"); |
| 112 | 100 | ||
| 113 | static struct edac_mce_attr *sysfs_attrs[] = { &mce_attr_status, &mce_attr_misc, | 101 | /* |
| 114 | &mce_attr_addr, &mce_attr_bank | 102 | * On which CPU to inject? |
| 115 | }; | 103 | */ |
| 104 | MCE_INJECT_GET(extcpu); | ||
| 116 | 105 | ||
| 117 | static int __init edac_init_mce_inject(void) | 106 | static int inj_extcpu_set(void *data, u64 val) |
| 118 | { | 107 | { |
| 119 | struct bus_type *edac_subsys = NULL; | 108 | struct mce *m = (struct mce *)data; |
| 120 | int i, err = 0; | ||
| 121 | 109 | ||
| 122 | edac_subsys = edac_get_sysfs_subsys(); | 110 | if (val >= nr_cpu_ids || !cpu_online(val)) { |
| 123 | if (!edac_subsys) | 111 | pr_err("%s: Invalid CPU: %llu\n", __func__, val); |
| 124 | return -EINVAL; | 112 | return -EINVAL; |
| 113 | } | ||
| 114 | m->extcpu = val; | ||
| 115 | return 0; | ||
| 116 | } | ||
| 117 | |||
| 118 | DEFINE_SIMPLE_ATTRIBUTE(extcpu_fops, inj_extcpu_get, inj_extcpu_set, "%llu\n"); | ||
| 125 | 119 | ||
| 126 | mce_kobj = kobject_create_and_add("mce", &edac_subsys->dev_root->kobj); | 120 | static void trigger_mce(void *info) |
| 127 | if (!mce_kobj) { | 121 | { |
| 128 | printk(KERN_ERR "Error creating a mce kset.\n"); | 122 | asm volatile("int $18"); |
| 129 | err = -ENOMEM; | 123 | } |
| 130 | goto err_mce_kobj; | 124 | |
| 125 | static void do_inject(void) | ||
| 126 | { | ||
| 127 | u64 mcg_status = 0; | ||
| 128 | unsigned int cpu = i_mce.extcpu; | ||
| 129 | u8 b = i_mce.bank; | ||
| 130 | |||
| 131 | if (!(i_mce.inject_flags & MCJ_EXCEPTION)) { | ||
| 132 | amd_decode_mce(NULL, 0, &i_mce); | ||
| 133 | return; | ||
| 131 | } | 134 | } |
| 132 | 135 | ||
| 133 | for (i = 0; i < ARRAY_SIZE(sysfs_attrs); i++) { | 136 | get_online_cpus(); |
| 134 | err = sysfs_create_file(mce_kobj, &sysfs_attrs[i]->attr); | 137 | if (!cpu_online(cpu)) |
| 135 | if (err) { | 138 | goto err; |
| 136 | printk(KERN_ERR "Error creating %s in sysfs.\n", | 139 | |
| 137 | sysfs_attrs[i]->attr.name); | 140 | /* prep MCE global settings for the injection */ |
| 138 | goto err_sysfs_create; | 141 | mcg_status = MCG_STATUS_MCIP | MCG_STATUS_EIPV; |
| 142 | |||
| 143 | if (!(i_mce.status & MCI_STATUS_PCC)) | ||
| 144 | mcg_status |= MCG_STATUS_RIPV; | ||
| 145 | |||
| 146 | toggle_hw_mce_inject(cpu, true); | ||
| 147 | |||
| 148 | wrmsr_on_cpu(cpu, MSR_IA32_MCG_STATUS, | ||
| 149 | (u32)mcg_status, (u32)(mcg_status >> 32)); | ||
| 150 | |||
| 151 | wrmsr_on_cpu(cpu, MSR_IA32_MCx_STATUS(b), | ||
| 152 | (u32)i_mce.status, (u32)(i_mce.status >> 32)); | ||
| 153 | |||
| 154 | wrmsr_on_cpu(cpu, MSR_IA32_MCx_ADDR(b), | ||
| 155 | (u32)i_mce.addr, (u32)(i_mce.addr >> 32)); | ||
| 156 | |||
| 157 | wrmsr_on_cpu(cpu, MSR_IA32_MCx_MISC(b), | ||
| 158 | (u32)i_mce.misc, (u32)(i_mce.misc >> 32)); | ||
| 159 | |||
| 160 | toggle_hw_mce_inject(cpu, false); | ||
| 161 | |||
| 162 | smp_call_function_single(cpu, trigger_mce, NULL, 0); | ||
| 163 | |||
| 164 | err: | ||
| 165 | put_online_cpus(); | ||
| 166 | |||
| 167 | } | ||
| 168 | |||
| 169 | /* | ||
| 170 | * This denotes into which bank we're injecting and triggers | ||
| 171 | * the injection, at the same time. | ||
| 172 | */ | ||
| 173 | static int inj_bank_set(void *data, u64 val) | ||
| 174 | { | ||
| 175 | struct mce *m = (struct mce *)data; | ||
| 176 | |||
| 177 | if (val > 5) { | ||
| 178 | if (boot_cpu_data.x86 != 0x15 || val > 6) { | ||
| 179 | pr_err("Non-existent MCE bank: %llu\n", val); | ||
| 180 | return -EINVAL; | ||
| 139 | } | 181 | } |
| 140 | } | 182 | } |
| 141 | return 0; | ||
| 142 | 183 | ||
| 143 | err_sysfs_create: | 184 | m->bank = val; |
| 144 | while (--i >= 0) | 185 | do_inject(); |
| 145 | sysfs_remove_file(mce_kobj, &sysfs_attrs[i]->attr); | ||
| 146 | 186 | ||
| 147 | kobject_del(mce_kobj); | 187 | return 0; |
| 188 | } | ||
| 148 | 189 | ||
| 149 | err_mce_kobj: | 190 | static int inj_bank_get(void *data, u64 *val) |
| 150 | edac_put_sysfs_subsys(); | 191 | { |
| 192 | struct mce *m = (struct mce *)data; | ||
| 151 | 193 | ||
| 152 | return err; | 194 | *val = m->bank; |
| 195 | return 0; | ||
| 153 | } | 196 | } |
| 154 | 197 | ||
| 155 | static void __exit edac_exit_mce_inject(void) | 198 | DEFINE_SIMPLE_ATTRIBUTE(bank_fops, inj_bank_get, inj_bank_set, "%llu\n"); |
| 199 | |||
| 200 | struct dfs_node { | ||
| 201 | char *name; | ||
| 202 | struct dentry *d; | ||
| 203 | const struct file_operations *fops; | ||
| 204 | } dfs_fls[] = { | ||
| 205 | { .name = "status", .fops = &status_fops }, | ||
| 206 | { .name = "misc", .fops = &misc_fops }, | ||
| 207 | { .name = "addr", .fops = &addr_fops }, | ||
| 208 | { .name = "bank", .fops = &bank_fops }, | ||
| 209 | { .name = "flags", .fops = &flags_fops }, | ||
| 210 | { .name = "cpu", .fops = &extcpu_fops }, | ||
| 211 | }; | ||
| 212 | |||
| 213 | static int __init init_mce_inject(void) | ||
| 156 | { | 214 | { |
| 157 | int i; | 215 | int i; |
| 158 | 216 | ||
| 159 | for (i = 0; i < ARRAY_SIZE(sysfs_attrs); i++) | 217 | dfs_inj = debugfs_create_dir("mce-inject", NULL); |
| 160 | sysfs_remove_file(mce_kobj, &sysfs_attrs[i]->attr); | 218 | if (!dfs_inj) |
| 219 | return -EINVAL; | ||
| 220 | |||
| 221 | for (i = 0; i < ARRAY_SIZE(dfs_fls); i++) { | ||
| 222 | dfs_fls[i].d = debugfs_create_file(dfs_fls[i].name, | ||
| 223 | S_IRUSR | S_IWUSR, | ||
| 224 | dfs_inj, | ||
| 225 | &i_mce, | ||
| 226 | dfs_fls[i].fops); | ||
| 227 | |||
| 228 | if (!dfs_fls[i].d) | ||
| 229 | goto err_dfs_add; | ||
| 230 | } | ||
| 231 | |||
| 232 | return 0; | ||
| 233 | |||
| 234 | err_dfs_add: | ||
| 235 | while (--i >= 0) | ||
| 236 | debugfs_remove(dfs_fls[i].d); | ||
| 161 | 237 | ||
| 162 | kobject_del(mce_kobj); | 238 | debugfs_remove(dfs_inj); |
| 239 | dfs_inj = NULL; | ||
| 163 | 240 | ||
| 164 | edac_put_sysfs_subsys(); | 241 | return -ENOMEM; |
| 165 | } | 242 | } |
| 166 | 243 | ||
| 167 | module_init(edac_init_mce_inject); | 244 | static void __exit exit_mce_inject(void) |
| 168 | module_exit(edac_exit_mce_inject); | 245 | { |
| 246 | int i; | ||
| 247 | |||
| 248 | for (i = 0; i < ARRAY_SIZE(dfs_fls); i++) | ||
| 249 | debugfs_remove(dfs_fls[i].d); | ||
| 250 | |||
| 251 | memset(&dfs_fls, 0, sizeof(dfs_fls)); | ||
| 252 | |||
| 253 | debugfs_remove(dfs_inj); | ||
| 254 | dfs_inj = NULL; | ||
| 255 | } | ||
| 256 | module_init(init_mce_inject); | ||
| 257 | module_exit(exit_mce_inject); | ||
| 169 | 258 | ||
| 170 | MODULE_LICENSE("GPL"); | 259 | MODULE_LICENSE("GPL"); |
| 171 | MODULE_AUTHOR("Borislav Petkov <bp@alien8.de>"); | 260 | MODULE_AUTHOR("Borislav Petkov <bp@alien8.de>"); |
| 172 | MODULE_AUTHOR("AMD Inc."); | 261 | MODULE_AUTHOR("AMD Inc."); |
| 173 | MODULE_DESCRIPTION("MCE injection facility for testing MCE decoding"); | 262 | MODULE_DESCRIPTION("MCE injection facility for RAS testing"); |
diff --git a/drivers/edac/mv64x60_edac.c b/drivers/edac/mv64x60_edac.c index 542fad70e360..6366e880f978 100644 --- a/drivers/edac/mv64x60_edac.c +++ b/drivers/edac/mv64x60_edac.c | |||
| @@ -178,7 +178,7 @@ static int mv64x60_pci_err_probe(struct platform_device *pdev) | |||
| 178 | res = devm_request_irq(&pdev->dev, | 178 | res = devm_request_irq(&pdev->dev, |
| 179 | pdata->irq, | 179 | pdata->irq, |
| 180 | mv64x60_pci_isr, | 180 | mv64x60_pci_isr, |
| 181 | IRQF_DISABLED, | 181 | 0, |
| 182 | "[EDAC] PCI err", | 182 | "[EDAC] PCI err", |
| 183 | pci); | 183 | pci); |
| 184 | if (res < 0) { | 184 | if (res < 0) { |
| @@ -345,7 +345,7 @@ static int mv64x60_sram_err_probe(struct platform_device *pdev) | |||
| 345 | res = devm_request_irq(&pdev->dev, | 345 | res = devm_request_irq(&pdev->dev, |
| 346 | pdata->irq, | 346 | pdata->irq, |
| 347 | mv64x60_sram_isr, | 347 | mv64x60_sram_isr, |
| 348 | IRQF_DISABLED, | 348 | 0, |
| 349 | "[EDAC] SRAM err", | 349 | "[EDAC] SRAM err", |
| 350 | edac_dev); | 350 | edac_dev); |
| 351 | if (res < 0) { | 351 | if (res < 0) { |
| @@ -540,7 +540,7 @@ static int mv64x60_cpu_err_probe(struct platform_device *pdev) | |||
| 540 | res = devm_request_irq(&pdev->dev, | 540 | res = devm_request_irq(&pdev->dev, |
| 541 | pdata->irq, | 541 | pdata->irq, |
| 542 | mv64x60_cpu_isr, | 542 | mv64x60_cpu_isr, |
| 543 | IRQF_DISABLED, | 543 | 0, |
| 544 | "[EDAC] CPU err", | 544 | "[EDAC] CPU err", |
| 545 | edac_dev); | 545 | edac_dev); |
| 546 | if (res < 0) { | 546 | if (res < 0) { |
| @@ -800,7 +800,7 @@ static int mv64x60_mc_err_probe(struct platform_device *pdev) | |||
| 800 | res = devm_request_irq(&pdev->dev, | 800 | res = devm_request_irq(&pdev->dev, |
| 801 | pdata->irq, | 801 | pdata->irq, |
| 802 | mv64x60_mc_isr, | 802 | mv64x60_mc_isr, |
| 803 | IRQF_DISABLED, | 803 | 0, |
| 804 | "[EDAC] MC err", | 804 | "[EDAC] MC err", |
| 805 | mci); | 805 | mci); |
| 806 | if (res < 0) { | 806 | if (res < 0) { |
diff --git a/drivers/edac/ppc4xx_edac.c b/drivers/edac/ppc4xx_edac.c index 0f04d5ead521..41593539cec4 100644 --- a/drivers/edac/ppc4xx_edac.c +++ b/drivers/edac/ppc4xx_edac.c | |||
| @@ -1120,7 +1120,7 @@ static int ppc4xx_edac_register_irq(struct platform_device *op, | |||
| 1120 | 1120 | ||
| 1121 | status = request_irq(ded_irq, | 1121 | status = request_irq(ded_irq, |
| 1122 | ppc4xx_edac_isr, | 1122 | ppc4xx_edac_isr, |
| 1123 | IRQF_DISABLED, | 1123 | 0, |
| 1124 | "[EDAC] MC ECCDED", | 1124 | "[EDAC] MC ECCDED", |
| 1125 | mci); | 1125 | mci); |
| 1126 | 1126 | ||
| @@ -1134,7 +1134,7 @@ static int ppc4xx_edac_register_irq(struct platform_device *op, | |||
| 1134 | 1134 | ||
| 1135 | status = request_irq(sec_irq, | 1135 | status = request_irq(sec_irq, |
| 1136 | ppc4xx_edac_isr, | 1136 | ppc4xx_edac_isr, |
| 1137 | IRQF_DISABLED, | 1137 | 0, |
| 1138 | "[EDAC] MC ECCSEC", | 1138 | "[EDAC] MC ECCSEC", |
| 1139 | mci); | 1139 | mci); |
| 1140 | 1140 | ||
diff --git a/drivers/edac/x38_edac.c b/drivers/edac/x38_edac.c index e644b52c287c..7c5cdc62f31c 100644 --- a/drivers/edac/x38_edac.c +++ b/drivers/edac/x38_edac.c | |||
| @@ -500,8 +500,7 @@ fail1: | |||
| 500 | pci_unregister_driver(&x38_driver); | 500 | pci_unregister_driver(&x38_driver); |
| 501 | 501 | ||
| 502 | fail0: | 502 | fail0: |
| 503 | if (mci_pdev) | 503 | pci_dev_put(mci_pdev); |
| 504 | pci_dev_put(mci_pdev); | ||
| 505 | 504 | ||
| 506 | return pci_rc; | 505 | return pci_rc; |
| 507 | } | 506 | } |
