.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | #include "amd64_edac.h" |
---|
2 | 3 | #include <asm/amd_nb.h> |
---|
3 | 4 | |
---|
4 | 5 | static struct edac_pci_ctl_info *pci_ctl; |
---|
5 | | - |
---|
6 | | -static int report_gart_errors; |
---|
7 | | -module_param(report_gart_errors, int, 0644); |
---|
8 | 6 | |
---|
9 | 7 | /* |
---|
10 | 8 | * Set by command line parameter. If BIOS has enabled the ECC, this override is |
---|
.. | .. |
---|
14 | 12 | module_param(ecc_enable_override, int, 0644); |
---|
15 | 13 | |
---|
16 | 14 | static struct msr __percpu *msrs; |
---|
| 15 | + |
---|
| 16 | +static struct amd64_family_type *fam_type; |
---|
17 | 17 | |
---|
18 | 18 | /* Per-node stuff */ |
---|
19 | 19 | static struct ecc_settings **ecc_stngs; |
---|
.. | .. |
---|
214 | 214 | |
---|
215 | 215 | scrubval = scrubrates[i].scrubval; |
---|
216 | 216 | |
---|
217 | | - if (pvt->fam == 0x17) { |
---|
| 217 | + if (pvt->umc) { |
---|
218 | 218 | __f17h_set_scrubval(pvt, scrubval); |
---|
219 | 219 | } else if (pvt->fam == 0x15 && pvt->model == 0x60) { |
---|
220 | 220 | f15h_select_dct(pvt, 0); |
---|
.. | .. |
---|
256 | 256 | int i, retval = -EINVAL; |
---|
257 | 257 | u32 scrubval = 0; |
---|
258 | 258 | |
---|
259 | | - switch (pvt->fam) { |
---|
260 | | - case 0x15: |
---|
261 | | - /* Erratum #505 */ |
---|
262 | | - if (pvt->model < 0x10) |
---|
263 | | - f15h_select_dct(pvt, 0); |
---|
264 | | - |
---|
265 | | - if (pvt->model == 0x60) |
---|
266 | | - amd64_read_pci_cfg(pvt->F2, F15H_M60H_SCRCTRL, &scrubval); |
---|
267 | | - else |
---|
268 | | - amd64_read_pci_cfg(pvt->F3, SCRCTRL, &scrubval); |
---|
269 | | - break; |
---|
270 | | - |
---|
271 | | - case 0x17: |
---|
| 259 | + if (pvt->umc) { |
---|
272 | 260 | amd64_read_pci_cfg(pvt->F6, F17H_SCR_BASE_ADDR, &scrubval); |
---|
273 | 261 | if (scrubval & BIT(0)) { |
---|
274 | 262 | amd64_read_pci_cfg(pvt->F6, F17H_SCR_LIMIT_ADDR, &scrubval); |
---|
.. | .. |
---|
277 | 265 | } else { |
---|
278 | 266 | scrubval = 0; |
---|
279 | 267 | } |
---|
280 | | - break; |
---|
| 268 | + } else if (pvt->fam == 0x15) { |
---|
| 269 | + /* Erratum #505 */ |
---|
| 270 | + if (pvt->model < 0x10) |
---|
| 271 | + f15h_select_dct(pvt, 0); |
---|
281 | 272 | |
---|
282 | | - default: |
---|
| 273 | + if (pvt->model == 0x60) |
---|
| 274 | + amd64_read_pci_cfg(pvt->F2, F15H_M60H_SCRCTRL, &scrubval); |
---|
| 275 | + else |
---|
| 276 | + amd64_read_pci_cfg(pvt->F3, SCRCTRL, &scrubval); |
---|
| 277 | + } else { |
---|
283 | 278 | amd64_read_pci_cfg(pvt->F3, SCRCTRL, &scrubval); |
---|
284 | | - break; |
---|
285 | 279 | } |
---|
286 | 280 | |
---|
287 | 281 | scrubval = scrubval & 0x001F; |
---|
.. | .. |
---|
452 | 446 | |
---|
453 | 447 | #define for_each_chip_select_mask(i, dct, pvt) \ |
---|
454 | 448 | for (i = 0; i < pvt->csels[dct].m_cnt; i++) |
---|
| 449 | + |
---|
| 450 | +#define for_each_umc(i) \ |
---|
| 451 | + for (i = 0; i < fam_type->max_mcs; i++) |
---|
455 | 452 | |
---|
456 | 453 | /* |
---|
457 | 454 | * @input_addr is an InputAddr associated with the node given by mci. Return the |
---|
.. | .. |
---|
726 | 723 | if (pvt->umc) { |
---|
727 | 724 | u8 i, umc_en_mask = 0, dimm_ecc_en_mask = 0; |
---|
728 | 725 | |
---|
729 | | - for (i = 0; i < NUM_UMCS; i++) { |
---|
| 726 | + for_each_umc(i) { |
---|
730 | 727 | if (!(pvt->umc[i].sdp_ctrl & UMC_SDP_INIT)) |
---|
731 | 728 | continue; |
---|
732 | 729 | |
---|
.. | .. |
---|
785 | 782 | (dclr & BIT(15)) ? "yes" : "no"); |
---|
786 | 783 | } |
---|
787 | 784 | |
---|
| 785 | +#define CS_EVEN_PRIMARY BIT(0) |
---|
| 786 | +#define CS_ODD_PRIMARY BIT(1) |
---|
| 787 | +#define CS_EVEN_SECONDARY BIT(2) |
---|
| 788 | +#define CS_ODD_SECONDARY BIT(3) |
---|
| 789 | +#define CS_3R_INTERLEAVE BIT(4) |
---|
| 790 | + |
---|
| 791 | +#define CS_EVEN (CS_EVEN_PRIMARY | CS_EVEN_SECONDARY) |
---|
| 792 | +#define CS_ODD (CS_ODD_PRIMARY | CS_ODD_SECONDARY) |
---|
| 793 | + |
---|
| 794 | +static int f17_get_cs_mode(int dimm, u8 ctrl, struct amd64_pvt *pvt) |
---|
| 795 | +{ |
---|
| 796 | + u8 base, count = 0; |
---|
| 797 | + int cs_mode = 0; |
---|
| 798 | + |
---|
| 799 | + if (csrow_enabled(2 * dimm, ctrl, pvt)) |
---|
| 800 | + cs_mode |= CS_EVEN_PRIMARY; |
---|
| 801 | + |
---|
| 802 | + if (csrow_enabled(2 * dimm + 1, ctrl, pvt)) |
---|
| 803 | + cs_mode |= CS_ODD_PRIMARY; |
---|
| 804 | + |
---|
| 805 | + /* Asymmetric dual-rank DIMM support. */ |
---|
| 806 | + if (csrow_sec_enabled(2 * dimm + 1, ctrl, pvt)) |
---|
| 807 | + cs_mode |= CS_ODD_SECONDARY; |
---|
| 808 | + |
---|
| 809 | + /* |
---|
| 810 | + * 3 Rank inteleaving support. |
---|
| 811 | + * There should be only three bases enabled and their two masks should |
---|
| 812 | + * be equal. |
---|
| 813 | + */ |
---|
| 814 | + for_each_chip_select(base, ctrl, pvt) |
---|
| 815 | + count += csrow_enabled(base, ctrl, pvt); |
---|
| 816 | + |
---|
| 817 | + if (count == 3 && |
---|
| 818 | + pvt->csels[ctrl].csmasks[0] == pvt->csels[ctrl].csmasks[1]) { |
---|
| 819 | + edac_dbg(1, "3R interleaving in use.\n"); |
---|
| 820 | + cs_mode |= CS_3R_INTERLEAVE; |
---|
| 821 | + } |
---|
| 822 | + |
---|
| 823 | + return cs_mode; |
---|
| 824 | +} |
---|
| 825 | + |
---|
788 | 826 | static void debug_display_dimm_sizes_df(struct amd64_pvt *pvt, u8 ctrl) |
---|
789 | 827 | { |
---|
790 | | - int dimm, size0, size1, cs0, cs1; |
---|
| 828 | + int dimm, size0, size1, cs0, cs1, cs_mode; |
---|
791 | 829 | |
---|
792 | 830 | edac_printk(KERN_DEBUG, EDAC_MC, "UMC%d chip selects:\n", ctrl); |
---|
793 | 831 | |
---|
794 | | - for (dimm = 0; dimm < 4; dimm++) { |
---|
795 | | - size0 = 0; |
---|
| 832 | + for (dimm = 0; dimm < 2; dimm++) { |
---|
796 | 833 | cs0 = dimm * 2; |
---|
797 | | - |
---|
798 | | - if (csrow_enabled(cs0, ctrl, pvt)) |
---|
799 | | - size0 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, cs0); |
---|
800 | | - |
---|
801 | | - size1 = 0; |
---|
802 | 834 | cs1 = dimm * 2 + 1; |
---|
803 | 835 | |
---|
804 | | - if (csrow_enabled(cs1, ctrl, pvt)) |
---|
805 | | - size1 = pvt->ops->dbam_to_cs(pvt, ctrl, 0, cs1); |
---|
| 836 | + cs_mode = f17_get_cs_mode(dimm, ctrl, pvt); |
---|
| 837 | + |
---|
| 838 | + size0 = pvt->ops->dbam_to_cs(pvt, ctrl, cs_mode, cs0); |
---|
| 839 | + size1 = pvt->ops->dbam_to_cs(pvt, ctrl, cs_mode, cs1); |
---|
806 | 840 | |
---|
807 | 841 | amd64_info(EDAC_MC ": %d: %5dMB %d: %5dMB\n", |
---|
808 | 842 | cs0, size0, |
---|
.. | .. |
---|
815 | 849 | struct amd64_umc *umc; |
---|
816 | 850 | u32 i, tmp, umc_base; |
---|
817 | 851 | |
---|
818 | | - for (i = 0; i < NUM_UMCS; i++) { |
---|
| 852 | + for_each_umc(i) { |
---|
819 | 853 | umc_base = get_umc_base(i); |
---|
820 | 854 | umc = &pvt->umc[i]; |
---|
821 | 855 | |
---|
.. | .. |
---|
898 | 932 | |
---|
899 | 933 | edac_dbg(1, " DramHoleValid: %s\n", dhar_valid(pvt) ? "yes" : "no"); |
---|
900 | 934 | |
---|
901 | | - amd64_info("using %s syndromes.\n", |
---|
902 | | - ((pvt->ecc_sym_sz == 8) ? "x8" : "x4")); |
---|
| 935 | + amd64_info("using x%u syndromes.\n", pvt->ecc_sym_sz); |
---|
903 | 936 | } |
---|
904 | 937 | |
---|
905 | 938 | /* |
---|
.. | .. |
---|
913 | 946 | } else if (pvt->fam == 0x15 && pvt->model == 0x30) { |
---|
914 | 947 | pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 4; |
---|
915 | 948 | pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 2; |
---|
| 949 | + } else if (pvt->fam >= 0x17) { |
---|
| 950 | + int umc; |
---|
| 951 | + |
---|
| 952 | + for_each_umc(umc) { |
---|
| 953 | + pvt->csels[umc].b_cnt = 4; |
---|
| 954 | + pvt->csels[umc].m_cnt = 2; |
---|
| 955 | + } |
---|
| 956 | + |
---|
916 | 957 | } else { |
---|
917 | 958 | pvt->csels[0].b_cnt = pvt->csels[1].b_cnt = 8; |
---|
918 | 959 | pvt->csels[0].m_cnt = pvt->csels[1].m_cnt = 4; |
---|
| 960 | + } |
---|
| 961 | +} |
---|
| 962 | + |
---|
| 963 | +static void read_umc_base_mask(struct amd64_pvt *pvt) |
---|
| 964 | +{ |
---|
| 965 | + u32 umc_base_reg, umc_base_reg_sec; |
---|
| 966 | + u32 umc_mask_reg, umc_mask_reg_sec; |
---|
| 967 | + u32 base_reg, base_reg_sec; |
---|
| 968 | + u32 mask_reg, mask_reg_sec; |
---|
| 969 | + u32 *base, *base_sec; |
---|
| 970 | + u32 *mask, *mask_sec; |
---|
| 971 | + int cs, umc; |
---|
| 972 | + |
---|
| 973 | + for_each_umc(umc) { |
---|
| 974 | + umc_base_reg = get_umc_base(umc) + UMCCH_BASE_ADDR; |
---|
| 975 | + umc_base_reg_sec = get_umc_base(umc) + UMCCH_BASE_ADDR_SEC; |
---|
| 976 | + |
---|
| 977 | + for_each_chip_select(cs, umc, pvt) { |
---|
| 978 | + base = &pvt->csels[umc].csbases[cs]; |
---|
| 979 | + base_sec = &pvt->csels[umc].csbases_sec[cs]; |
---|
| 980 | + |
---|
| 981 | + base_reg = umc_base_reg + (cs * 4); |
---|
| 982 | + base_reg_sec = umc_base_reg_sec + (cs * 4); |
---|
| 983 | + |
---|
| 984 | + if (!amd_smn_read(pvt->mc_node_id, base_reg, base)) |
---|
| 985 | + edac_dbg(0, " DCSB%d[%d]=0x%08x reg: 0x%x\n", |
---|
| 986 | + umc, cs, *base, base_reg); |
---|
| 987 | + |
---|
| 988 | + if (!amd_smn_read(pvt->mc_node_id, base_reg_sec, base_sec)) |
---|
| 989 | + edac_dbg(0, " DCSB_SEC%d[%d]=0x%08x reg: 0x%x\n", |
---|
| 990 | + umc, cs, *base_sec, base_reg_sec); |
---|
| 991 | + } |
---|
| 992 | + |
---|
| 993 | + umc_mask_reg = get_umc_base(umc) + UMCCH_ADDR_MASK; |
---|
| 994 | + umc_mask_reg_sec = get_umc_base(umc) + UMCCH_ADDR_MASK_SEC; |
---|
| 995 | + |
---|
| 996 | + for_each_chip_select_mask(cs, umc, pvt) { |
---|
| 997 | + mask = &pvt->csels[umc].csmasks[cs]; |
---|
| 998 | + mask_sec = &pvt->csels[umc].csmasks_sec[cs]; |
---|
| 999 | + |
---|
| 1000 | + mask_reg = umc_mask_reg + (cs * 4); |
---|
| 1001 | + mask_reg_sec = umc_mask_reg_sec + (cs * 4); |
---|
| 1002 | + |
---|
| 1003 | + if (!amd_smn_read(pvt->mc_node_id, mask_reg, mask)) |
---|
| 1004 | + edac_dbg(0, " DCSM%d[%d]=0x%08x reg: 0x%x\n", |
---|
| 1005 | + umc, cs, *mask, mask_reg); |
---|
| 1006 | + |
---|
| 1007 | + if (!amd_smn_read(pvt->mc_node_id, mask_reg_sec, mask_sec)) |
---|
| 1008 | + edac_dbg(0, " DCSM_SEC%d[%d]=0x%08x reg: 0x%x\n", |
---|
| 1009 | + umc, cs, *mask_sec, mask_reg_sec); |
---|
| 1010 | + } |
---|
919 | 1011 | } |
---|
920 | 1012 | } |
---|
921 | 1013 | |
---|
.. | .. |
---|
924 | 1016 | */ |
---|
925 | 1017 | static void read_dct_base_mask(struct amd64_pvt *pvt) |
---|
926 | 1018 | { |
---|
927 | | - int base_reg0, base_reg1, mask_reg0, mask_reg1, cs; |
---|
| 1019 | + int cs; |
---|
928 | 1020 | |
---|
929 | 1021 | prep_chip_selects(pvt); |
---|
930 | 1022 | |
---|
931 | | - if (pvt->umc) { |
---|
932 | | - base_reg0 = get_umc_base(0) + UMCCH_BASE_ADDR; |
---|
933 | | - base_reg1 = get_umc_base(1) + UMCCH_BASE_ADDR; |
---|
934 | | - mask_reg0 = get_umc_base(0) + UMCCH_ADDR_MASK; |
---|
935 | | - mask_reg1 = get_umc_base(1) + UMCCH_ADDR_MASK; |
---|
936 | | - } else { |
---|
937 | | - base_reg0 = DCSB0; |
---|
938 | | - base_reg1 = DCSB1; |
---|
939 | | - mask_reg0 = DCSM0; |
---|
940 | | - mask_reg1 = DCSM1; |
---|
941 | | - } |
---|
| 1023 | + if (pvt->umc) |
---|
| 1024 | + return read_umc_base_mask(pvt); |
---|
942 | 1025 | |
---|
943 | 1026 | for_each_chip_select(cs, 0, pvt) { |
---|
944 | | - int reg0 = base_reg0 + (cs * 4); |
---|
945 | | - int reg1 = base_reg1 + (cs * 4); |
---|
| 1027 | + int reg0 = DCSB0 + (cs * 4); |
---|
| 1028 | + int reg1 = DCSB1 + (cs * 4); |
---|
946 | 1029 | u32 *base0 = &pvt->csels[0].csbases[cs]; |
---|
947 | 1030 | u32 *base1 = &pvt->csels[1].csbases[cs]; |
---|
948 | 1031 | |
---|
949 | | - if (pvt->umc) { |
---|
950 | | - if (!amd_smn_read(pvt->mc_node_id, reg0, base0)) |
---|
951 | | - edac_dbg(0, " DCSB0[%d]=0x%08x reg: 0x%x\n", |
---|
952 | | - cs, *base0, reg0); |
---|
| 1032 | + if (!amd64_read_dct_pci_cfg(pvt, 0, reg0, base0)) |
---|
| 1033 | + edac_dbg(0, " DCSB0[%d]=0x%08x reg: F2x%x\n", |
---|
| 1034 | + cs, *base0, reg0); |
---|
953 | 1035 | |
---|
954 | | - if (!amd_smn_read(pvt->mc_node_id, reg1, base1)) |
---|
955 | | - edac_dbg(0, " DCSB1[%d]=0x%08x reg: 0x%x\n", |
---|
956 | | - cs, *base1, reg1); |
---|
957 | | - } else { |
---|
958 | | - if (!amd64_read_dct_pci_cfg(pvt, 0, reg0, base0)) |
---|
959 | | - edac_dbg(0, " DCSB0[%d]=0x%08x reg: F2x%x\n", |
---|
960 | | - cs, *base0, reg0); |
---|
| 1036 | + if (pvt->fam == 0xf) |
---|
| 1037 | + continue; |
---|
961 | 1038 | |
---|
962 | | - if (pvt->fam == 0xf) |
---|
963 | | - continue; |
---|
964 | | - |
---|
965 | | - if (!amd64_read_dct_pci_cfg(pvt, 1, reg0, base1)) |
---|
966 | | - edac_dbg(0, " DCSB1[%d]=0x%08x reg: F2x%x\n", |
---|
967 | | - cs, *base1, (pvt->fam == 0x10) ? reg1 |
---|
968 | | - : reg0); |
---|
969 | | - } |
---|
| 1039 | + if (!amd64_read_dct_pci_cfg(pvt, 1, reg0, base1)) |
---|
| 1040 | + edac_dbg(0, " DCSB1[%d]=0x%08x reg: F2x%x\n", |
---|
| 1041 | + cs, *base1, (pvt->fam == 0x10) ? reg1 |
---|
| 1042 | + : reg0); |
---|
970 | 1043 | } |
---|
971 | 1044 | |
---|
972 | 1045 | for_each_chip_select_mask(cs, 0, pvt) { |
---|
973 | | - int reg0 = mask_reg0 + (cs * 4); |
---|
974 | | - int reg1 = mask_reg1 + (cs * 4); |
---|
| 1046 | + int reg0 = DCSM0 + (cs * 4); |
---|
| 1047 | + int reg1 = DCSM1 + (cs * 4); |
---|
975 | 1048 | u32 *mask0 = &pvt->csels[0].csmasks[cs]; |
---|
976 | 1049 | u32 *mask1 = &pvt->csels[1].csmasks[cs]; |
---|
977 | 1050 | |
---|
978 | | - if (pvt->umc) { |
---|
979 | | - if (!amd_smn_read(pvt->mc_node_id, reg0, mask0)) |
---|
980 | | - edac_dbg(0, " DCSM0[%d]=0x%08x reg: 0x%x\n", |
---|
981 | | - cs, *mask0, reg0); |
---|
| 1051 | + if (!amd64_read_dct_pci_cfg(pvt, 0, reg0, mask0)) |
---|
| 1052 | + edac_dbg(0, " DCSM0[%d]=0x%08x reg: F2x%x\n", |
---|
| 1053 | + cs, *mask0, reg0); |
---|
982 | 1054 | |
---|
983 | | - if (!amd_smn_read(pvt->mc_node_id, reg1, mask1)) |
---|
984 | | - edac_dbg(0, " DCSM1[%d]=0x%08x reg: 0x%x\n", |
---|
985 | | - cs, *mask1, reg1); |
---|
986 | | - } else { |
---|
987 | | - if (!amd64_read_dct_pci_cfg(pvt, 0, reg0, mask0)) |
---|
988 | | - edac_dbg(0, " DCSM0[%d]=0x%08x reg: F2x%x\n", |
---|
989 | | - cs, *mask0, reg0); |
---|
| 1055 | + if (pvt->fam == 0xf) |
---|
| 1056 | + continue; |
---|
990 | 1057 | |
---|
991 | | - if (pvt->fam == 0xf) |
---|
992 | | - continue; |
---|
993 | | - |
---|
994 | | - if (!amd64_read_dct_pci_cfg(pvt, 1, reg0, mask1)) |
---|
995 | | - edac_dbg(0, " DCSM1[%d]=0x%08x reg: F2x%x\n", |
---|
996 | | - cs, *mask1, (pvt->fam == 0x10) ? reg1 |
---|
997 | | - : reg0); |
---|
998 | | - } |
---|
| 1058 | + if (!amd64_read_dct_pci_cfg(pvt, 1, reg0, mask1)) |
---|
| 1059 | + edac_dbg(0, " DCSM1[%d]=0x%08x reg: F2x%x\n", |
---|
| 1060 | + cs, *mask1, (pvt->fam == 0x10) ? reg1 |
---|
| 1061 | + : reg0); |
---|
999 | 1062 | } |
---|
1000 | 1063 | } |
---|
1001 | 1064 | |
---|
1002 | 1065 | static void determine_memory_type(struct amd64_pvt *pvt) |
---|
1003 | 1066 | { |
---|
1004 | 1067 | u32 dram_ctrl, dcsm; |
---|
| 1068 | + |
---|
| 1069 | + if (pvt->umc) { |
---|
| 1070 | + if ((pvt->umc[0].dimm_cfg | pvt->umc[1].dimm_cfg) & BIT(5)) |
---|
| 1071 | + pvt->dram_type = MEM_LRDDR4; |
---|
| 1072 | + else if ((pvt->umc[0].dimm_cfg | pvt->umc[1].dimm_cfg) & BIT(4)) |
---|
| 1073 | + pvt->dram_type = MEM_RDDR4; |
---|
| 1074 | + else |
---|
| 1075 | + pvt->dram_type = MEM_DDR4; |
---|
| 1076 | + return; |
---|
| 1077 | + } |
---|
1005 | 1078 | |
---|
1006 | 1079 | switch (pvt->fam) { |
---|
1007 | 1080 | case 0xf: |
---|
.. | .. |
---|
1047 | 1120 | |
---|
1048 | 1121 | case 0x16: |
---|
1049 | 1122 | goto ddr3; |
---|
1050 | | - |
---|
1051 | | - case 0x17: |
---|
1052 | | - if ((pvt->umc[0].dimm_cfg | pvt->umc[1].dimm_cfg) & BIT(5)) |
---|
1053 | | - pvt->dram_type = MEM_LRDDR4; |
---|
1054 | | - else if ((pvt->umc[0].dimm_cfg | pvt->umc[1].dimm_cfg) & BIT(4)) |
---|
1055 | | - pvt->dram_type = MEM_RDDR4; |
---|
1056 | | - else |
---|
1057 | | - pvt->dram_type = MEM_DDR4; |
---|
1058 | | - return; |
---|
1059 | 1123 | |
---|
1060 | 1124 | default: |
---|
1061 | 1125 | WARN(1, KERN_ERR "%s: Family??? 0x%x\n", __func__, pvt->fam); |
---|
.. | .. |
---|
1391 | 1455 | int i, channels = 0; |
---|
1392 | 1456 | |
---|
1393 | 1457 | /* SDP Control bit 31 (SdpInit) is clear for unused UMC channels */ |
---|
1394 | | - for (i = 0; i < NUM_UMCS; i++) |
---|
| 1458 | + for_each_umc(i) |
---|
1395 | 1459 | channels += !!(pvt->umc[i].sdp_ctrl & UMC_SDP_INIT); |
---|
1396 | 1460 | |
---|
1397 | 1461 | amd64_info("MCT channel count: %d\n", channels); |
---|
.. | .. |
---|
1526 | 1590 | return ddr3_cs_size(cs_mode, false); |
---|
1527 | 1591 | } |
---|
1528 | 1592 | |
---|
1529 | | -static int f17_base_addr_to_cs_size(struct amd64_pvt *pvt, u8 umc, |
---|
| 1593 | +static int f17_addr_mask_to_cs_size(struct amd64_pvt *pvt, u8 umc, |
---|
1530 | 1594 | unsigned int cs_mode, int csrow_nr) |
---|
1531 | 1595 | { |
---|
1532 | | - u32 base_addr = pvt->csels[umc].csbases[csrow_nr]; |
---|
| 1596 | + u32 addr_mask_orig, addr_mask_deinterleaved; |
---|
| 1597 | + u32 msb, weight, num_zero_bits; |
---|
| 1598 | + int dimm, size = 0; |
---|
1533 | 1599 | |
---|
1534 | | - /* Each mask is used for every two base addresses. */ |
---|
1535 | | - u32 addr_mask = pvt->csels[umc].csmasks[csrow_nr >> 1]; |
---|
| 1600 | + /* No Chip Selects are enabled. */ |
---|
| 1601 | + if (!cs_mode) |
---|
| 1602 | + return size; |
---|
1536 | 1603 | |
---|
1537 | | - /* Register [31:1] = Address [39:9]. Size is in kBs here. */ |
---|
1538 | | - u32 size = ((addr_mask >> 1) - (base_addr >> 1) + 1) >> 1; |
---|
| 1604 | + /* Requested size of an even CS but none are enabled. */ |
---|
| 1605 | + if (!(cs_mode & CS_EVEN) && !(csrow_nr & 1)) |
---|
| 1606 | + return size; |
---|
1539 | 1607 | |
---|
1540 | | - edac_dbg(1, "BaseAddr: 0x%x, AddrMask: 0x%x\n", base_addr, addr_mask); |
---|
| 1608 | + /* Requested size of an odd CS but none are enabled. */ |
---|
| 1609 | + if (!(cs_mode & CS_ODD) && (csrow_nr & 1)) |
---|
| 1610 | + return size; |
---|
| 1611 | + |
---|
| 1612 | + /* |
---|
| 1613 | + * There is one mask per DIMM, and two Chip Selects per DIMM. |
---|
| 1614 | + * CS0 and CS1 -> DIMM0 |
---|
| 1615 | + * CS2 and CS3 -> DIMM1 |
---|
| 1616 | + */ |
---|
| 1617 | + dimm = csrow_nr >> 1; |
---|
| 1618 | + |
---|
| 1619 | + /* Asymmetric dual-rank DIMM support. */ |
---|
| 1620 | + if ((csrow_nr & 1) && (cs_mode & CS_ODD_SECONDARY)) |
---|
| 1621 | + addr_mask_orig = pvt->csels[umc].csmasks_sec[dimm]; |
---|
| 1622 | + else |
---|
| 1623 | + addr_mask_orig = pvt->csels[umc].csmasks[dimm]; |
---|
| 1624 | + |
---|
| 1625 | + /* |
---|
| 1626 | + * The number of zero bits in the mask is equal to the number of bits |
---|
| 1627 | + * in a full mask minus the number of bits in the current mask. |
---|
| 1628 | + * |
---|
| 1629 | + * The MSB is the number of bits in the full mask because BIT[0] is |
---|
| 1630 | + * always 0. |
---|
| 1631 | + * |
---|
| 1632 | + * In the special 3 Rank interleaving case, a single bit is flipped |
---|
| 1633 | + * without swapping with the most significant bit. This can be handled |
---|
| 1634 | + * by keeping the MSB where it is and ignoring the single zero bit. |
---|
| 1635 | + */ |
---|
| 1636 | + msb = fls(addr_mask_orig) - 1; |
---|
| 1637 | + weight = hweight_long(addr_mask_orig); |
---|
| 1638 | + num_zero_bits = msb - weight - !!(cs_mode & CS_3R_INTERLEAVE); |
---|
| 1639 | + |
---|
| 1640 | + /* Take the number of zero bits off from the top of the mask. */ |
---|
| 1641 | + addr_mask_deinterleaved = GENMASK_ULL(msb - num_zero_bits, 1); |
---|
| 1642 | + |
---|
| 1643 | + edac_dbg(1, "CS%d DIMM%d AddrMasks:\n", csrow_nr, dimm); |
---|
| 1644 | + edac_dbg(1, " Original AddrMask: 0x%x\n", addr_mask_orig); |
---|
| 1645 | + edac_dbg(1, " Deinterleaved AddrMask: 0x%x\n", addr_mask_deinterleaved); |
---|
| 1646 | + |
---|
| 1647 | + /* Register [31:1] = Address [39:9]. Size is in kBs here. */ |
---|
| 1648 | + size = (addr_mask_deinterleaved >> 2) + 1; |
---|
1541 | 1649 | |
---|
1542 | 1650 | /* Return size in MBs. */ |
---|
1543 | 1651 | return size >> 10; |
---|
.. | .. |
---|
2130 | 2238 | .ctl_name = "K8", |
---|
2131 | 2239 | .f1_id = PCI_DEVICE_ID_AMD_K8_NB_ADDRMAP, |
---|
2132 | 2240 | .f2_id = PCI_DEVICE_ID_AMD_K8_NB_MEMCTL, |
---|
| 2241 | + .max_mcs = 2, |
---|
2133 | 2242 | .ops = { |
---|
2134 | 2243 | .early_channel_count = k8_early_channel_count, |
---|
2135 | 2244 | .map_sysaddr_to_csrow = k8_map_sysaddr_to_csrow, |
---|
.. | .. |
---|
2140 | 2249 | .ctl_name = "F10h", |
---|
2141 | 2250 | .f1_id = PCI_DEVICE_ID_AMD_10H_NB_MAP, |
---|
2142 | 2251 | .f2_id = PCI_DEVICE_ID_AMD_10H_NB_DRAM, |
---|
| 2252 | + .max_mcs = 2, |
---|
2143 | 2253 | .ops = { |
---|
2144 | 2254 | .early_channel_count = f1x_early_channel_count, |
---|
2145 | 2255 | .map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow, |
---|
.. | .. |
---|
2150 | 2260 | .ctl_name = "F15h", |
---|
2151 | 2261 | .f1_id = PCI_DEVICE_ID_AMD_15H_NB_F1, |
---|
2152 | 2262 | .f2_id = PCI_DEVICE_ID_AMD_15H_NB_F2, |
---|
| 2263 | + .max_mcs = 2, |
---|
2153 | 2264 | .ops = { |
---|
2154 | 2265 | .early_channel_count = f1x_early_channel_count, |
---|
2155 | 2266 | .map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow, |
---|
.. | .. |
---|
2160 | 2271 | .ctl_name = "F15h_M30h", |
---|
2161 | 2272 | .f1_id = PCI_DEVICE_ID_AMD_15H_M30H_NB_F1, |
---|
2162 | 2273 | .f2_id = PCI_DEVICE_ID_AMD_15H_M30H_NB_F2, |
---|
| 2274 | + .max_mcs = 2, |
---|
2163 | 2275 | .ops = { |
---|
2164 | 2276 | .early_channel_count = f1x_early_channel_count, |
---|
2165 | 2277 | .map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow, |
---|
.. | .. |
---|
2170 | 2282 | .ctl_name = "F15h_M60h", |
---|
2171 | 2283 | .f1_id = PCI_DEVICE_ID_AMD_15H_M60H_NB_F1, |
---|
2172 | 2284 | .f2_id = PCI_DEVICE_ID_AMD_15H_M60H_NB_F2, |
---|
| 2285 | + .max_mcs = 2, |
---|
2173 | 2286 | .ops = { |
---|
2174 | 2287 | .early_channel_count = f1x_early_channel_count, |
---|
2175 | 2288 | .map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow, |
---|
.. | .. |
---|
2180 | 2293 | .ctl_name = "F16h", |
---|
2181 | 2294 | .f1_id = PCI_DEVICE_ID_AMD_16H_NB_F1, |
---|
2182 | 2295 | .f2_id = PCI_DEVICE_ID_AMD_16H_NB_F2, |
---|
| 2296 | + .max_mcs = 2, |
---|
2183 | 2297 | .ops = { |
---|
2184 | 2298 | .early_channel_count = f1x_early_channel_count, |
---|
2185 | 2299 | .map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow, |
---|
.. | .. |
---|
2190 | 2304 | .ctl_name = "F16h_M30h", |
---|
2191 | 2305 | .f1_id = PCI_DEVICE_ID_AMD_16H_M30H_NB_F1, |
---|
2192 | 2306 | .f2_id = PCI_DEVICE_ID_AMD_16H_M30H_NB_F2, |
---|
| 2307 | + .max_mcs = 2, |
---|
2193 | 2308 | .ops = { |
---|
2194 | 2309 | .early_channel_count = f1x_early_channel_count, |
---|
2195 | 2310 | .map_sysaddr_to_csrow = f1x_map_sysaddr_to_csrow, |
---|
.. | .. |
---|
2200 | 2315 | .ctl_name = "F17h", |
---|
2201 | 2316 | .f0_id = PCI_DEVICE_ID_AMD_17H_DF_F0, |
---|
2202 | 2317 | .f6_id = PCI_DEVICE_ID_AMD_17H_DF_F6, |
---|
| 2318 | + .max_mcs = 2, |
---|
2203 | 2319 | .ops = { |
---|
2204 | 2320 | .early_channel_count = f17_early_channel_count, |
---|
2205 | | - .dbam_to_cs = f17_base_addr_to_cs_size, |
---|
| 2321 | + .dbam_to_cs = f17_addr_mask_to_cs_size, |
---|
2206 | 2322 | } |
---|
2207 | 2323 | }, |
---|
2208 | 2324 | [F17_M10H_CPUS] = { |
---|
2209 | 2325 | .ctl_name = "F17h_M10h", |
---|
2210 | 2326 | .f0_id = PCI_DEVICE_ID_AMD_17H_M10H_DF_F0, |
---|
2211 | 2327 | .f6_id = PCI_DEVICE_ID_AMD_17H_M10H_DF_F6, |
---|
| 2328 | + .max_mcs = 2, |
---|
2212 | 2329 | .ops = { |
---|
2213 | 2330 | .early_channel_count = f17_early_channel_count, |
---|
2214 | | - .dbam_to_cs = f17_base_addr_to_cs_size, |
---|
| 2331 | + .dbam_to_cs = f17_addr_mask_to_cs_size, |
---|
2215 | 2332 | } |
---|
2216 | 2333 | }, |
---|
2217 | 2334 | [F17_M30H_CPUS] = { |
---|
2218 | 2335 | .ctl_name = "F17h_M30h", |
---|
2219 | 2336 | .f0_id = PCI_DEVICE_ID_AMD_17H_M30H_DF_F0, |
---|
2220 | 2337 | .f6_id = PCI_DEVICE_ID_AMD_17H_M30H_DF_F6, |
---|
| 2338 | + .max_mcs = 8, |
---|
2221 | 2339 | .ops = { |
---|
2222 | 2340 | .early_channel_count = f17_early_channel_count, |
---|
2223 | | - .dbam_to_cs = f17_base_addr_to_cs_size, |
---|
| 2341 | + .dbam_to_cs = f17_addr_mask_to_cs_size, |
---|
| 2342 | + } |
---|
| 2343 | + }, |
---|
| 2344 | + [F17_M60H_CPUS] = { |
---|
| 2345 | + .ctl_name = "F17h_M60h", |
---|
| 2346 | + .f0_id = PCI_DEVICE_ID_AMD_17H_M60H_DF_F0, |
---|
| 2347 | + .f6_id = PCI_DEVICE_ID_AMD_17H_M60H_DF_F6, |
---|
| 2348 | + .max_mcs = 2, |
---|
| 2349 | + .ops = { |
---|
| 2350 | + .early_channel_count = f17_early_channel_count, |
---|
| 2351 | + .dbam_to_cs = f17_addr_mask_to_cs_size, |
---|
| 2352 | + } |
---|
| 2353 | + }, |
---|
| 2354 | + [F17_M70H_CPUS] = { |
---|
| 2355 | + .ctl_name = "F17h_M70h", |
---|
| 2356 | + .f0_id = PCI_DEVICE_ID_AMD_17H_M70H_DF_F0, |
---|
| 2357 | + .f6_id = PCI_DEVICE_ID_AMD_17H_M70H_DF_F6, |
---|
| 2358 | + .max_mcs = 2, |
---|
| 2359 | + .ops = { |
---|
| 2360 | + .early_channel_count = f17_early_channel_count, |
---|
| 2361 | + .dbam_to_cs = f17_addr_mask_to_cs_size, |
---|
| 2362 | + } |
---|
| 2363 | + }, |
---|
| 2364 | + [F19_CPUS] = { |
---|
| 2365 | + .ctl_name = "F19h", |
---|
| 2366 | + .f0_id = PCI_DEVICE_ID_AMD_19H_DF_F0, |
---|
| 2367 | + .f6_id = PCI_DEVICE_ID_AMD_19H_DF_F6, |
---|
| 2368 | + .max_mcs = 8, |
---|
| 2369 | + .ops = { |
---|
| 2370 | + .early_channel_count = f17_early_channel_count, |
---|
| 2371 | + .dbam_to_cs = f17_addr_mask_to_cs_size, |
---|
2224 | 2372 | } |
---|
2225 | 2373 | }, |
---|
2226 | 2374 | }; |
---|
.. | .. |
---|
2476 | 2624 | * To find the UMC channel represented by this bank we need to match on its |
---|
2477 | 2625 | * instance_id. The instance_id of a bank is held in the lower 32 bits of its |
---|
2478 | 2626 | * IPID. |
---|
| 2627 | + * |
---|
| 2628 | + * Currently, we can derive the channel number by looking at the 6th nibble in |
---|
| 2629 | + * the instance_id. For example, instance_id=0xYXXXXX where Y is the channel |
---|
| 2630 | + * number. |
---|
2479 | 2631 | */ |
---|
2480 | | -static int find_umc_channel(struct amd64_pvt *pvt, struct mce *m) |
---|
| 2632 | +static int find_umc_channel(struct mce *m) |
---|
2481 | 2633 | { |
---|
2482 | | - u32 umc_instance_id[] = {0x50f00, 0x150f00}; |
---|
2483 | | - u32 instance_id = m->ipid & GENMASK(31, 0); |
---|
2484 | | - int i, channel = -1; |
---|
2485 | | - |
---|
2486 | | - for (i = 0; i < ARRAY_SIZE(umc_instance_id); i++) |
---|
2487 | | - if (umc_instance_id[i] == instance_id) |
---|
2488 | | - channel = i; |
---|
2489 | | - |
---|
2490 | | - return channel; |
---|
| 2634 | + return (m->ipid & GENMASK(31, 0)) >> 20; |
---|
2491 | 2635 | } |
---|
2492 | 2636 | |
---|
2493 | 2637 | static void decode_umc_error(int node_id, struct mce *m) |
---|
.. | .. |
---|
2509 | 2653 | if (m->status & MCI_STATUS_DEFERRED) |
---|
2510 | 2654 | ecc_type = 3; |
---|
2511 | 2655 | |
---|
2512 | | - err.channel = find_umc_channel(pvt, m); |
---|
2513 | | - if (err.channel < 0) { |
---|
2514 | | - err.err_code = ERR_CHANNEL; |
---|
2515 | | - goto log_error; |
---|
2516 | | - } |
---|
| 2656 | + err.channel = find_umc_channel(m); |
---|
2517 | 2657 | |
---|
2518 | 2658 | if (!(m->status & MCI_STATUS_SYNDV)) { |
---|
2519 | 2659 | err.err_code = ERR_SYND; |
---|
.. | .. |
---|
2621 | 2761 | if (pvt->umc) { |
---|
2622 | 2762 | u8 i; |
---|
2623 | 2763 | |
---|
2624 | | - for (i = 0; i < NUM_UMCS; i++) { |
---|
| 2764 | + for_each_umc(i) { |
---|
2625 | 2765 | /* Check enabled channels only: */ |
---|
2626 | | - if ((pvt->umc[i].sdp_ctrl & UMC_SDP_INIT) && |
---|
2627 | | - (pvt->umc[i].ecc_ctrl & BIT(7))) { |
---|
2628 | | - pvt->ecc_sym_sz = 8; |
---|
2629 | | - break; |
---|
| 2766 | + if (pvt->umc[i].sdp_ctrl & UMC_SDP_INIT) { |
---|
| 2767 | + if (pvt->umc[i].ecc_ctrl & BIT(9)) { |
---|
| 2768 | + pvt->ecc_sym_sz = 16; |
---|
| 2769 | + return; |
---|
| 2770 | + } else if (pvt->umc[i].ecc_ctrl & BIT(7)) { |
---|
| 2771 | + pvt->ecc_sym_sz = 8; |
---|
| 2772 | + return; |
---|
| 2773 | + } |
---|
2630 | 2774 | } |
---|
2631 | 2775 | } |
---|
2632 | | - |
---|
2633 | | - return; |
---|
2634 | | - } |
---|
2635 | | - |
---|
2636 | | - if (pvt->fam >= 0x10) { |
---|
| 2776 | + } else if (pvt->fam >= 0x10) { |
---|
2637 | 2777 | u32 tmp; |
---|
2638 | 2778 | |
---|
2639 | 2779 | amd64_read_pci_cfg(pvt->F3, EXT_NB_MCA_CFG, &tmp); |
---|
.. | .. |
---|
2657 | 2797 | u32 i, umc_base; |
---|
2658 | 2798 | |
---|
2659 | 2799 | /* Read registers from each UMC */ |
---|
2660 | | - for (i = 0; i < NUM_UMCS; i++) { |
---|
| 2800 | + for_each_umc(i) { |
---|
2661 | 2801 | |
---|
2662 | 2802 | umc_base = get_umc_base(i); |
---|
2663 | 2803 | umc = &pvt->umc[i]; |
---|
.. | .. |
---|
2749 | 2889 | edac_dbg(1, " DIMM type: %s\n", edac_mem_types[pvt->dram_type]); |
---|
2750 | 2890 | |
---|
2751 | 2891 | determine_ecc_sym_sz(pvt); |
---|
2752 | | - |
---|
2753 | | - dump_misc_regs(pvt); |
---|
2754 | 2892 | } |
---|
2755 | 2893 | |
---|
2756 | 2894 | /* |
---|
.. | .. |
---|
2793 | 2931 | int csrow_nr = csrow_nr_orig; |
---|
2794 | 2932 | u32 cs_mode, nr_pages; |
---|
2795 | 2933 | |
---|
2796 | | - if (!pvt->umc) |
---|
| 2934 | + if (!pvt->umc) { |
---|
2797 | 2935 | csrow_nr >>= 1; |
---|
2798 | | - |
---|
2799 | | - cs_mode = DBAM_DIMM(csrow_nr, dbam); |
---|
| 2936 | + cs_mode = DBAM_DIMM(csrow_nr, dbam); |
---|
| 2937 | + } else { |
---|
| 2938 | + cs_mode = f17_get_cs_mode(csrow_nr >> 1, dct, pvt); |
---|
| 2939 | + } |
---|
2800 | 2940 | |
---|
2801 | 2941 | nr_pages = pvt->ops->dbam_to_cs(pvt, dct, cs_mode, csrow_nr); |
---|
2802 | 2942 | nr_pages <<= 20 - PAGE_SHIFT; |
---|
.. | .. |
---|
2806 | 2946 | edac_dbg(0, "nr_pages/channel: %u\n", nr_pages); |
---|
2807 | 2947 | |
---|
2808 | 2948 | return nr_pages; |
---|
| 2949 | +} |
---|
| 2950 | + |
---|
| 2951 | +static int init_csrows_df(struct mem_ctl_info *mci) |
---|
| 2952 | +{ |
---|
| 2953 | + struct amd64_pvt *pvt = mci->pvt_info; |
---|
| 2954 | + enum edac_type edac_mode = EDAC_NONE; |
---|
| 2955 | + enum dev_type dev_type = DEV_UNKNOWN; |
---|
| 2956 | + struct dimm_info *dimm; |
---|
| 2957 | + int empty = 1; |
---|
| 2958 | + u8 umc, cs; |
---|
| 2959 | + |
---|
| 2960 | + if (mci->edac_ctl_cap & EDAC_FLAG_S16ECD16ED) { |
---|
| 2961 | + edac_mode = EDAC_S16ECD16ED; |
---|
| 2962 | + dev_type = DEV_X16; |
---|
| 2963 | + } else if (mci->edac_ctl_cap & EDAC_FLAG_S8ECD8ED) { |
---|
| 2964 | + edac_mode = EDAC_S8ECD8ED; |
---|
| 2965 | + dev_type = DEV_X8; |
---|
| 2966 | + } else if (mci->edac_ctl_cap & EDAC_FLAG_S4ECD4ED) { |
---|
| 2967 | + edac_mode = EDAC_S4ECD4ED; |
---|
| 2968 | + dev_type = DEV_X4; |
---|
| 2969 | + } else if (mci->edac_ctl_cap & EDAC_FLAG_SECDED) { |
---|
| 2970 | + edac_mode = EDAC_SECDED; |
---|
| 2971 | + } |
---|
| 2972 | + |
---|
| 2973 | + for_each_umc(umc) { |
---|
| 2974 | + for_each_chip_select(cs, umc, pvt) { |
---|
| 2975 | + if (!csrow_enabled(cs, umc, pvt)) |
---|
| 2976 | + continue; |
---|
| 2977 | + |
---|
| 2978 | + empty = 0; |
---|
| 2979 | + dimm = mci->csrows[cs]->channels[umc]->dimm; |
---|
| 2980 | + |
---|
| 2981 | + edac_dbg(1, "MC node: %d, csrow: %d\n", |
---|
| 2982 | + pvt->mc_node_id, cs); |
---|
| 2983 | + |
---|
| 2984 | + dimm->nr_pages = get_csrow_nr_pages(pvt, umc, cs); |
---|
| 2985 | + dimm->mtype = pvt->dram_type; |
---|
| 2986 | + dimm->edac_mode = edac_mode; |
---|
| 2987 | + dimm->dtype = dev_type; |
---|
| 2988 | + dimm->grain = 64; |
---|
| 2989 | + } |
---|
| 2990 | + } |
---|
| 2991 | + |
---|
| 2992 | + return empty; |
---|
2809 | 2993 | } |
---|
2810 | 2994 | |
---|
2811 | 2995 | /* |
---|
.. | .. |
---|
2822 | 3006 | int nr_pages = 0; |
---|
2823 | 3007 | u32 val; |
---|
2824 | 3008 | |
---|
2825 | | - if (!pvt->umc) { |
---|
2826 | | - amd64_read_pci_cfg(pvt->F3, NBCFG, &val); |
---|
| 3009 | + if (pvt->umc) |
---|
| 3010 | + return init_csrows_df(mci); |
---|
2827 | 3011 | |
---|
2828 | | - pvt->nbcfg = val; |
---|
| 3012 | + amd64_read_pci_cfg(pvt->F3, NBCFG, &val); |
---|
2829 | 3013 | |
---|
2830 | | - edac_dbg(0, "node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n", |
---|
2831 | | - pvt->mc_node_id, val, |
---|
2832 | | - !!(val & NBCFG_CHIPKILL), !!(val & NBCFG_ECC_ENABLE)); |
---|
2833 | | - } |
---|
| 3014 | + pvt->nbcfg = val; |
---|
| 3015 | + |
---|
| 3016 | + edac_dbg(0, "node %d, NBCFG=0x%08x[ChipKillEccCap: %d|DramEccEn: %d]\n", |
---|
| 3017 | + pvt->mc_node_id, val, |
---|
| 3018 | + !!(val & NBCFG_CHIPKILL), !!(val & NBCFG_ECC_ENABLE)); |
---|
2834 | 3019 | |
---|
2835 | 3020 | /* |
---|
2836 | 3021 | * We iterate over DCT0 here but we look at DCT1 in parallel, if needed. |
---|
.. | .. |
---|
2867 | 3052 | edac_dbg(1, "Total csrow%d pages: %u\n", i, nr_pages); |
---|
2868 | 3053 | |
---|
2869 | 3054 | /* Determine DIMM ECC mode: */ |
---|
2870 | | - if (pvt->umc) { |
---|
2871 | | - if (mci->edac_ctl_cap & EDAC_FLAG_S4ECD4ED) |
---|
2872 | | - edac_mode = EDAC_S4ECD4ED; |
---|
2873 | | - else if (mci->edac_ctl_cap & EDAC_FLAG_SECDED) |
---|
2874 | | - edac_mode = EDAC_SECDED; |
---|
2875 | | - |
---|
2876 | | - } else if (pvt->nbcfg & NBCFG_ECC_ENABLE) { |
---|
| 3055 | + if (pvt->nbcfg & NBCFG_ECC_ENABLE) { |
---|
2877 | 3056 | edac_mode = (pvt->nbcfg & NBCFG_CHIPKILL) |
---|
2878 | 3057 | ? EDAC_S4ECD4ED |
---|
2879 | 3058 | : EDAC_SECDED; |
---|
.. | .. |
---|
3050 | 3229 | amd64_warn("Error restoring NB MCGCTL settings!\n"); |
---|
3051 | 3230 | } |
---|
3052 | 3231 | |
---|
3053 | | -/* |
---|
3054 | | - * EDAC requires that the BIOS have ECC enabled before |
---|
3055 | | - * taking over the processing of ECC errors. A command line |
---|
3056 | | - * option allows to force-enable hardware ECC later in |
---|
3057 | | - * enable_ecc_error_reporting(). |
---|
3058 | | - */ |
---|
3059 | | -static const char *ecc_msg = |
---|
3060 | | - "ECC disabled in the BIOS or no ECC capability, module will not load.\n" |
---|
3061 | | - " Either enable ECC checking or force module loading by setting " |
---|
3062 | | - "'ecc_enable_override'.\n" |
---|
3063 | | - " (Note that use of the override may cause unknown side effects.)\n"; |
---|
3064 | | - |
---|
3065 | | -static bool ecc_enabled(struct pci_dev *F3, u16 nid) |
---|
| 3232 | +static bool ecc_enabled(struct amd64_pvt *pvt) |
---|
3066 | 3233 | { |
---|
| 3234 | + u16 nid = pvt->mc_node_id; |
---|
3067 | 3235 | bool nb_mce_en = false; |
---|
3068 | 3236 | u8 ecc_en = 0, i; |
---|
3069 | 3237 | u32 value; |
---|
3070 | 3238 | |
---|
3071 | 3239 | if (boot_cpu_data.x86 >= 0x17) { |
---|
3072 | 3240 | u8 umc_en_mask = 0, ecc_en_mask = 0; |
---|
| 3241 | + struct amd64_umc *umc; |
---|
3073 | 3242 | |
---|
3074 | | - for (i = 0; i < NUM_UMCS; i++) { |
---|
3075 | | - u32 base = get_umc_base(i); |
---|
| 3243 | + for_each_umc(i) { |
---|
| 3244 | + umc = &pvt->umc[i]; |
---|
3076 | 3245 | |
---|
3077 | 3246 | /* Only check enabled UMCs. */ |
---|
3078 | | - if (amd_smn_read(nid, base + UMCCH_SDP_CTRL, &value)) |
---|
3079 | | - continue; |
---|
3080 | | - |
---|
3081 | | - if (!(value & UMC_SDP_INIT)) |
---|
| 3247 | + if (!(umc->sdp_ctrl & UMC_SDP_INIT)) |
---|
3082 | 3248 | continue; |
---|
3083 | 3249 | |
---|
3084 | 3250 | umc_en_mask |= BIT(i); |
---|
3085 | 3251 | |
---|
3086 | | - if (amd_smn_read(nid, base + UMCCH_UMC_CAP_HI, &value)) |
---|
3087 | | - continue; |
---|
3088 | | - |
---|
3089 | | - if (value & UMC_ECC_ENABLED) |
---|
| 3252 | + if (umc->umc_cap_hi & UMC_ECC_ENABLED) |
---|
3090 | 3253 | ecc_en_mask |= BIT(i); |
---|
3091 | 3254 | } |
---|
3092 | 3255 | |
---|
.. | .. |
---|
3099 | 3262 | /* Assume UMC MCA banks are enabled. */ |
---|
3100 | 3263 | nb_mce_en = true; |
---|
3101 | 3264 | } else { |
---|
3102 | | - amd64_read_pci_cfg(F3, NBCFG, &value); |
---|
| 3265 | + amd64_read_pci_cfg(pvt->F3, NBCFG, &value); |
---|
3103 | 3266 | |
---|
3104 | 3267 | ecc_en = !!(value & NBCFG_ECC_ENABLE); |
---|
3105 | 3268 | |
---|
.. | .. |
---|
3112 | 3275 | amd64_info("Node %d: DRAM ECC %s.\n", |
---|
3113 | 3276 | nid, (ecc_en ? "enabled" : "disabled")); |
---|
3114 | 3277 | |
---|
3115 | | - if (!ecc_en || !nb_mce_en) { |
---|
3116 | | - amd64_info("%s", ecc_msg); |
---|
| 3278 | + if (!ecc_en || !nb_mce_en) |
---|
3117 | 3279 | return false; |
---|
3118 | | - } |
---|
3119 | | - return true; |
---|
| 3280 | + else |
---|
| 3281 | + return true; |
---|
3120 | 3282 | } |
---|
3121 | 3283 | |
---|
3122 | 3284 | static inline void |
---|
.. | .. |
---|
3124 | 3286 | { |
---|
3125 | 3287 | u8 i, ecc_en = 1, cpk_en = 1, dev_x4 = 1, dev_x16 = 1; |
---|
3126 | 3288 | |
---|
3127 | | - for (i = 0; i < NUM_UMCS; i++) { |
---|
| 3289 | + for_each_umc(i) { |
---|
3128 | 3290 | if (pvt->umc[i].sdp_ctrl & UMC_SDP_INIT) { |
---|
3129 | 3291 | ecc_en &= !!(pvt->umc[i].umc_cap_hi & UMC_ECC_ENABLED); |
---|
3130 | 3292 | cpk_en &= !!(pvt->umc[i].umc_cap_hi & UMC_ECC_CHIPKILL_CAP); |
---|
.. | .. |
---|
3150 | 3312 | } |
---|
3151 | 3313 | } |
---|
3152 | 3314 | |
---|
3153 | | -static void setup_mci_misc_attrs(struct mem_ctl_info *mci, |
---|
3154 | | - struct amd64_family_type *fam) |
---|
| 3315 | +static void setup_mci_misc_attrs(struct mem_ctl_info *mci) |
---|
3155 | 3316 | { |
---|
3156 | 3317 | struct amd64_pvt *pvt = mci->pvt_info; |
---|
3157 | 3318 | |
---|
.. | .. |
---|
3170 | 3331 | |
---|
3171 | 3332 | mci->edac_cap = determine_edac_cap(pvt); |
---|
3172 | 3333 | mci->mod_name = EDAC_MOD_STR; |
---|
3173 | | - mci->ctl_name = fam->ctl_name; |
---|
| 3334 | + mci->ctl_name = fam_type->ctl_name; |
---|
3174 | 3335 | mci->dev_name = pci_name(pvt->F3); |
---|
3175 | 3336 | mci->ctl_page_to_phys = NULL; |
---|
3176 | 3337 | |
---|
.. | .. |
---|
3184 | 3345 | */ |
---|
3185 | 3346 | static struct amd64_family_type *per_family_init(struct amd64_pvt *pvt) |
---|
3186 | 3347 | { |
---|
3187 | | - struct amd64_family_type *fam_type = NULL; |
---|
3188 | | - |
---|
3189 | 3348 | pvt->ext_model = boot_cpu_data.x86_model >> 4; |
---|
3190 | 3349 | pvt->stepping = boot_cpu_data.x86_stepping; |
---|
3191 | 3350 | pvt->model = boot_cpu_data.x86_model; |
---|
.. | .. |
---|
3211 | 3370 | fam_type = &family_types[F15_M60H_CPUS]; |
---|
3212 | 3371 | pvt->ops = &family_types[F15_M60H_CPUS].ops; |
---|
3213 | 3372 | break; |
---|
| 3373 | + /* Richland is only client */ |
---|
| 3374 | + } else if (pvt->model == 0x13) { |
---|
| 3375 | + return NULL; |
---|
| 3376 | + } else { |
---|
| 3377 | + fam_type = &family_types[F15_CPUS]; |
---|
| 3378 | + pvt->ops = &family_types[F15_CPUS].ops; |
---|
3214 | 3379 | } |
---|
3215 | | - |
---|
3216 | | - fam_type = &family_types[F15_CPUS]; |
---|
3217 | | - pvt->ops = &family_types[F15_CPUS].ops; |
---|
3218 | 3380 | break; |
---|
3219 | 3381 | |
---|
3220 | 3382 | case 0x16: |
---|
.. | .. |
---|
3236 | 3398 | fam_type = &family_types[F17_M30H_CPUS]; |
---|
3237 | 3399 | pvt->ops = &family_types[F17_M30H_CPUS].ops; |
---|
3238 | 3400 | break; |
---|
| 3401 | + } else if (pvt->model >= 0x60 && pvt->model <= 0x6f) { |
---|
| 3402 | + fam_type = &family_types[F17_M60H_CPUS]; |
---|
| 3403 | + pvt->ops = &family_types[F17_M60H_CPUS].ops; |
---|
| 3404 | + break; |
---|
| 3405 | + } else if (pvt->model >= 0x70 && pvt->model <= 0x7f) { |
---|
| 3406 | + fam_type = &family_types[F17_M70H_CPUS]; |
---|
| 3407 | + pvt->ops = &family_types[F17_M70H_CPUS].ops; |
---|
| 3408 | + break; |
---|
3239 | 3409 | } |
---|
| 3410 | + fallthrough; |
---|
| 3411 | + case 0x18: |
---|
3240 | 3412 | fam_type = &family_types[F17_CPUS]; |
---|
3241 | 3413 | pvt->ops = &family_types[F17_CPUS].ops; |
---|
| 3414 | + |
---|
| 3415 | + if (pvt->fam == 0x18) |
---|
| 3416 | + family_types[F17_CPUS].ctl_name = "F18h"; |
---|
| 3417 | + break; |
---|
| 3418 | + |
---|
| 3419 | + case 0x19: |
---|
| 3420 | + if (pvt->model >= 0x20 && pvt->model <= 0x2f) { |
---|
| 3421 | + fam_type = &family_types[F17_M70H_CPUS]; |
---|
| 3422 | + pvt->ops = &family_types[F17_M70H_CPUS].ops; |
---|
| 3423 | + fam_type->ctl_name = "F19h_M20h"; |
---|
| 3424 | + break; |
---|
| 3425 | + } |
---|
| 3426 | + fam_type = &family_types[F19_CPUS]; |
---|
| 3427 | + pvt->ops = &family_types[F19_CPUS].ops; |
---|
| 3428 | + family_types[F19_CPUS].ctl_name = "F19h"; |
---|
3242 | 3429 | break; |
---|
3243 | 3430 | |
---|
3244 | 3431 | default: |
---|
.. | .. |
---|
3264 | 3451 | NULL |
---|
3265 | 3452 | }; |
---|
3266 | 3453 | |
---|
3267 | | -static int init_one_instance(unsigned int nid) |
---|
| 3454 | +static int hw_info_get(struct amd64_pvt *pvt) |
---|
3268 | 3455 | { |
---|
3269 | | - struct pci_dev *F3 = node_to_amd_nb(nid)->misc; |
---|
3270 | | - struct amd64_family_type *fam_type = NULL; |
---|
3271 | | - struct mem_ctl_info *mci = NULL; |
---|
3272 | | - struct edac_mc_layer layers[2]; |
---|
3273 | | - struct amd64_pvt *pvt = NULL; |
---|
3274 | 3456 | u16 pci_id1, pci_id2; |
---|
3275 | | - int err = 0, ret; |
---|
3276 | | - |
---|
3277 | | - ret = -ENOMEM; |
---|
3278 | | - pvt = kzalloc(sizeof(struct amd64_pvt), GFP_KERNEL); |
---|
3279 | | - if (!pvt) |
---|
3280 | | - goto err_ret; |
---|
3281 | | - |
---|
3282 | | - pvt->mc_node_id = nid; |
---|
3283 | | - pvt->F3 = F3; |
---|
3284 | | - |
---|
3285 | | - ret = -EINVAL; |
---|
3286 | | - fam_type = per_family_init(pvt); |
---|
3287 | | - if (!fam_type) |
---|
3288 | | - goto err_free; |
---|
| 3457 | + int ret; |
---|
3289 | 3458 | |
---|
3290 | 3459 | if (pvt->fam >= 0x17) { |
---|
3291 | | - pvt->umc = kcalloc(NUM_UMCS, sizeof(struct amd64_umc), GFP_KERNEL); |
---|
3292 | | - if (!pvt->umc) { |
---|
3293 | | - ret = -ENOMEM; |
---|
3294 | | - goto err_free; |
---|
3295 | | - } |
---|
| 3460 | + pvt->umc = kcalloc(fam_type->max_mcs, sizeof(struct amd64_umc), GFP_KERNEL); |
---|
| 3461 | + if (!pvt->umc) |
---|
| 3462 | + return -ENOMEM; |
---|
3296 | 3463 | |
---|
3297 | 3464 | pci_id1 = fam_type->f0_id; |
---|
3298 | 3465 | pci_id2 = fam_type->f6_id; |
---|
.. | .. |
---|
3301 | 3468 | pci_id2 = fam_type->f2_id; |
---|
3302 | 3469 | } |
---|
3303 | 3470 | |
---|
3304 | | - err = reserve_mc_sibling_devs(pvt, pci_id1, pci_id2); |
---|
3305 | | - if (err) |
---|
3306 | | - goto err_post_init; |
---|
| 3471 | + ret = reserve_mc_sibling_devs(pvt, pci_id1, pci_id2); |
---|
| 3472 | + if (ret) |
---|
| 3473 | + return ret; |
---|
3307 | 3474 | |
---|
3308 | 3475 | read_mc_regs(pvt); |
---|
| 3476 | + |
---|
| 3477 | + return 0; |
---|
| 3478 | +} |
---|
| 3479 | + |
---|
| 3480 | +static void hw_info_put(struct amd64_pvt *pvt) |
---|
| 3481 | +{ |
---|
| 3482 | + if (pvt->F0 || pvt->F1) |
---|
| 3483 | + free_mc_sibling_devs(pvt); |
---|
| 3484 | + |
---|
| 3485 | + kfree(pvt->umc); |
---|
| 3486 | +} |
---|
| 3487 | + |
---|
| 3488 | +static int init_one_instance(struct amd64_pvt *pvt) |
---|
| 3489 | +{ |
---|
| 3490 | + struct mem_ctl_info *mci = NULL; |
---|
| 3491 | + struct edac_mc_layer layers[2]; |
---|
| 3492 | + int ret = -EINVAL; |
---|
3309 | 3493 | |
---|
3310 | 3494 | /* |
---|
3311 | 3495 | * We need to determine how many memory channels there are. Then use |
---|
3312 | 3496 | * that information for calculating the size of the dynamic instance |
---|
3313 | 3497 | * tables in the 'mci' structure. |
---|
3314 | 3498 | */ |
---|
3315 | | - ret = -EINVAL; |
---|
3316 | 3499 | pvt->channel_count = pvt->ops->early_channel_count(pvt); |
---|
3317 | 3500 | if (pvt->channel_count < 0) |
---|
3318 | | - goto err_siblings; |
---|
| 3501 | + return ret; |
---|
3319 | 3502 | |
---|
3320 | 3503 | ret = -ENOMEM; |
---|
3321 | 3504 | layers[0].type = EDAC_MC_LAYER_CHIP_SELECT; |
---|
.. | .. |
---|
3328 | 3511 | * only one channel. Also, this simplifies handling later for the price |
---|
3329 | 3512 | * of a couple of KBs tops. |
---|
3330 | 3513 | */ |
---|
3331 | | - layers[1].size = 2; |
---|
| 3514 | + layers[1].size = fam_type->max_mcs; |
---|
3332 | 3515 | layers[1].is_virt_csrow = false; |
---|
3333 | 3516 | |
---|
3334 | | - mci = edac_mc_alloc(nid, ARRAY_SIZE(layers), layers, 0); |
---|
| 3517 | + mci = edac_mc_alloc(pvt->mc_node_id, ARRAY_SIZE(layers), layers, 0); |
---|
3335 | 3518 | if (!mci) |
---|
3336 | | - goto err_siblings; |
---|
| 3519 | + return ret; |
---|
3337 | 3520 | |
---|
3338 | 3521 | mci->pvt_info = pvt; |
---|
3339 | 3522 | mci->pdev = &pvt->F3->dev; |
---|
3340 | 3523 | |
---|
3341 | | - setup_mci_misc_attrs(mci, fam_type); |
---|
| 3524 | + setup_mci_misc_attrs(mci); |
---|
3342 | 3525 | |
---|
3343 | 3526 | if (init_csrows(mci)) |
---|
3344 | 3527 | mci->edac_cap = EDAC_FLAG_NONE; |
---|
.. | .. |
---|
3346 | 3529 | ret = -ENODEV; |
---|
3347 | 3530 | if (edac_mc_add_mc_with_groups(mci, amd64_edac_attr_groups)) { |
---|
3348 | 3531 | edac_dbg(1, "failed edac_mc_add_mc()\n"); |
---|
3349 | | - goto err_add_mc; |
---|
| 3532 | + edac_mc_free(mci); |
---|
| 3533 | + return ret; |
---|
3350 | 3534 | } |
---|
3351 | 3535 | |
---|
3352 | 3536 | return 0; |
---|
| 3537 | +} |
---|
3353 | 3538 | |
---|
3354 | | -err_add_mc: |
---|
3355 | | - edac_mc_free(mci); |
---|
| 3539 | +static bool instance_has_memory(struct amd64_pvt *pvt) |
---|
| 3540 | +{ |
---|
| 3541 | + bool cs_enabled = false; |
---|
| 3542 | + int cs = 0, dct = 0; |
---|
3356 | 3543 | |
---|
3357 | | -err_siblings: |
---|
3358 | | - free_mc_sibling_devs(pvt); |
---|
| 3544 | + for (dct = 0; dct < fam_type->max_mcs; dct++) { |
---|
| 3545 | + for_each_chip_select(cs, dct, pvt) |
---|
| 3546 | + cs_enabled |= csrow_enabled(cs, dct, pvt); |
---|
| 3547 | + } |
---|
3359 | 3548 | |
---|
3360 | | -err_post_init: |
---|
3361 | | - if (pvt->fam >= 0x17) |
---|
3362 | | - kfree(pvt->umc); |
---|
3363 | | - |
---|
3364 | | -err_free: |
---|
3365 | | - kfree(pvt); |
---|
3366 | | - |
---|
3367 | | -err_ret: |
---|
3368 | | - return ret; |
---|
| 3549 | + return cs_enabled; |
---|
3369 | 3550 | } |
---|
3370 | 3551 | |
---|
3371 | 3552 | static int probe_one_instance(unsigned int nid) |
---|
3372 | 3553 | { |
---|
3373 | 3554 | struct pci_dev *F3 = node_to_amd_nb(nid)->misc; |
---|
| 3555 | + struct amd64_pvt *pvt = NULL; |
---|
3374 | 3556 | struct ecc_settings *s; |
---|
3375 | 3557 | int ret; |
---|
3376 | 3558 | |
---|
.. | .. |
---|
3381 | 3563 | |
---|
3382 | 3564 | ecc_stngs[nid] = s; |
---|
3383 | 3565 | |
---|
3384 | | - if (!ecc_enabled(F3, nid)) { |
---|
3385 | | - ret = 0; |
---|
| 3566 | + pvt = kzalloc(sizeof(struct amd64_pvt), GFP_KERNEL); |
---|
| 3567 | + if (!pvt) |
---|
| 3568 | + goto err_settings; |
---|
| 3569 | + |
---|
| 3570 | + pvt->mc_node_id = nid; |
---|
| 3571 | + pvt->F3 = F3; |
---|
| 3572 | + |
---|
| 3573 | + ret = -ENODEV; |
---|
| 3574 | + fam_type = per_family_init(pvt); |
---|
| 3575 | + if (!fam_type) |
---|
| 3576 | + goto err_enable; |
---|
| 3577 | + |
---|
| 3578 | + ret = hw_info_get(pvt); |
---|
| 3579 | + if (ret < 0) |
---|
| 3580 | + goto err_enable; |
---|
| 3581 | + |
---|
| 3582 | + ret = 0; |
---|
| 3583 | + if (!instance_has_memory(pvt)) { |
---|
| 3584 | + amd64_info("Node %d: No DIMMs detected.\n", nid); |
---|
| 3585 | + goto err_enable; |
---|
| 3586 | + } |
---|
| 3587 | + |
---|
| 3588 | + if (!ecc_enabled(pvt)) { |
---|
| 3589 | + ret = -ENODEV; |
---|
3386 | 3590 | |
---|
3387 | 3591 | if (!ecc_enable_override) |
---|
3388 | 3592 | goto err_enable; |
---|
.. | .. |
---|
3397 | 3601 | goto err_enable; |
---|
3398 | 3602 | } |
---|
3399 | 3603 | |
---|
3400 | | - ret = init_one_instance(nid); |
---|
| 3604 | + ret = init_one_instance(pvt); |
---|
3401 | 3605 | if (ret < 0) { |
---|
3402 | 3606 | amd64_err("Error probing instance: %d\n", nid); |
---|
3403 | 3607 | |
---|
.. | .. |
---|
3407 | 3611 | goto err_enable; |
---|
3408 | 3612 | } |
---|
3409 | 3613 | |
---|
| 3614 | + dump_misc_regs(pvt); |
---|
| 3615 | + |
---|
3410 | 3616 | return ret; |
---|
3411 | 3617 | |
---|
3412 | 3618 | err_enable: |
---|
| 3619 | + hw_info_put(pvt); |
---|
| 3620 | + kfree(pvt); |
---|
| 3621 | + |
---|
| 3622 | +err_settings: |
---|
3413 | 3623 | kfree(s); |
---|
3414 | 3624 | ecc_stngs[nid] = NULL; |
---|
3415 | 3625 | |
---|
.. | .. |
---|
3424 | 3634 | struct mem_ctl_info *mci; |
---|
3425 | 3635 | struct amd64_pvt *pvt; |
---|
3426 | 3636 | |
---|
3427 | | - mci = find_mci_by_dev(&F3->dev); |
---|
3428 | | - WARN_ON(!mci); |
---|
3429 | | - |
---|
3430 | 3637 | /* Remove from EDAC CORE tracking list */ |
---|
3431 | 3638 | mci = edac_mc_del_mc(&F3->dev); |
---|
3432 | 3639 | if (!mci) |
---|
.. | .. |
---|
3436 | 3643 | |
---|
3437 | 3644 | restore_ecc_error_reporting(s, nid, F3); |
---|
3438 | 3645 | |
---|
3439 | | - free_mc_sibling_devs(pvt); |
---|
3440 | | - |
---|
3441 | 3646 | kfree(ecc_stngs[nid]); |
---|
3442 | 3647 | ecc_stngs[nid] = NULL; |
---|
3443 | 3648 | |
---|
3444 | 3649 | /* Free the EDAC CORE resources */ |
---|
3445 | 3650 | mci->pvt_info = NULL; |
---|
3446 | 3651 | |
---|
| 3652 | + hw_info_put(pvt); |
---|
3447 | 3653 | kfree(pvt); |
---|
3448 | 3654 | edac_mc_free(mci); |
---|
3449 | 3655 | } |
---|
.. | .. |
---|
3461 | 3667 | } |
---|
3462 | 3668 | |
---|
3463 | 3669 | static const struct x86_cpu_id amd64_cpuids[] = { |
---|
3464 | | - { X86_VENDOR_AMD, 0xF, X86_MODEL_ANY, X86_FEATURE_ANY, 0 }, |
---|
3465 | | - { X86_VENDOR_AMD, 0x10, X86_MODEL_ANY, X86_FEATURE_ANY, 0 }, |
---|
3466 | | - { X86_VENDOR_AMD, 0x15, X86_MODEL_ANY, X86_FEATURE_ANY, 0 }, |
---|
3467 | | - { X86_VENDOR_AMD, 0x16, X86_MODEL_ANY, X86_FEATURE_ANY, 0 }, |
---|
3468 | | - { X86_VENDOR_AMD, 0x17, X86_MODEL_ANY, X86_FEATURE_ANY, 0 }, |
---|
| 3670 | + X86_MATCH_VENDOR_FAM(AMD, 0x0F, NULL), |
---|
| 3671 | + X86_MATCH_VENDOR_FAM(AMD, 0x10, NULL), |
---|
| 3672 | + X86_MATCH_VENDOR_FAM(AMD, 0x15, NULL), |
---|
| 3673 | + X86_MATCH_VENDOR_FAM(AMD, 0x16, NULL), |
---|
| 3674 | + X86_MATCH_VENDOR_FAM(AMD, 0x17, NULL), |
---|
| 3675 | + X86_MATCH_VENDOR_FAM(HYGON, 0x18, NULL), |
---|
| 3676 | + X86_MATCH_VENDOR_FAM(AMD, 0x19, NULL), |
---|
3469 | 3677 | { } |
---|
3470 | 3678 | }; |
---|
3471 | 3679 | MODULE_DEVICE_TABLE(x86cpu, amd64_cpuids); |
---|
.. | .. |
---|
3514 | 3722 | } |
---|
3515 | 3723 | |
---|
3516 | 3724 | /* register stuff with EDAC MCE */ |
---|
3517 | | - if (report_gart_errors) |
---|
3518 | | - amd_report_gart_errors(true); |
---|
3519 | | - |
---|
3520 | 3725 | if (boot_cpu_data.x86 >= 0x17) |
---|
3521 | 3726 | amd_register_ecc_decoder(decode_umc_error); |
---|
3522 | 3727 | else |
---|
.. | .. |
---|
3553 | 3758 | edac_pci_release_generic_ctl(pci_ctl); |
---|
3554 | 3759 | |
---|
3555 | 3760 | /* unregister from EDAC MCE */ |
---|
3556 | | - amd_report_gart_errors(false); |
---|
3557 | | - |
---|
3558 | 3761 | if (boot_cpu_data.x86 >= 0x17) |
---|
3559 | 3762 | amd_unregister_ecc_decoder(decode_umc_error); |
---|
3560 | 3763 | else |
---|