Pull edac updates from Mauro Carvalho Chehab: "Two EDAC fixes for Intel systems (Haswell and Ivy Bridge)" * tag 'edac/v4.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-edac: sb_edac: correctly fetch DIMM width on Ivy Bridge and Haswell sb_edac: look harder for DDRIO on Haswell systems
Unified · Split
| @@ -280,6 +280,7 @@ struct sbridge_info { · 279 unmodified lines | ||
| 280 | 280 | u8 max_interleave; |
| 281 | 281 | u8 (*get_node_id)(struct sbridge_pvt *pvt); |
| 282 | 282 | enum mem_type (*get_memory_type)(struct sbridge_pvt *pvt); |
| 283 | + enum dev_type (*get_width)(struct sbridge_pvt *pvt, u32 mtr); | |
| 283 | 284 | struct pci_dev *pci_vtd; |
| 284 | 285 | }; |
| 285 | 286 | |
| @@ -471,6 +472,9 @@ static const struct pci_id_table pci_dev_descr_ibridge_table[] = { · 185 unmodified lines | ||
| 471 | 472 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2 0x2f6c |
| 472 | 473 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3 0x2f6d |
| 473 | 474 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0 0x2fbd |
| 475 | +#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO1 0x2fbf | |
| 476 | +#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO2 0x2fb9 | |
| 477 | +#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO3 0x2fbb | |
| 474 | 478 | static const struct pci_id_descr pci_dev_descr_haswell[] = { |
| 475 | 479 | /* first item must be the HA */ |
| 476 | 480 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0, 0) }, |
| @@ -488,6 +492,9 @@ static const struct pci_id_descr pci_dev_descr_haswell[] = { · 11 unmodified lines | ||
| 488 | 492 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3, 1) }, |
| 489 | 493 | |
| 490 | 494 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0, 1) }, |
| 495 | + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO1, 1) }, | |
| 496 | + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO2, 1) }, | |
| 497 | + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO3, 1) }, | |
| 491 | 498 | |
| 492 | 499 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA, 1) }, |
| 493 | 500 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_THERMAL, 1) }, |
| @@ -762,6 +769,49 @@ out: · 268 unmodified lines | ||
| 762 | 769 | return mtype; |
| 763 | 770 | } |
| 764 | 771 | |
| 772 | +static enum dev_type sbridge_get_width(struct sbridge_pvt *pvt, u32 mtr) | |
| 773 | +{ | |
| 774 | + /* there's no way to figure out */ | |
| 775 | + return DEV_UNKNOWN; | |
| 776 | +} | |
| 777 | + | |
| 778 | +static enum dev_type __ibridge_get_width(u32 mtr) | |
| 779 | +{ | |
| 780 | + enum dev_type type; | |
| 781 | + | |
| 782 | + switch (mtr) { | |
| 783 | + case 3: | |
| 784 | + type = DEV_UNKNOWN; | |
| 785 | + break; | |
| 786 | + case 2: | |
| 787 | + type = DEV_X16; | |
| 788 | + break; | |
| 789 | + case 1: | |
| 790 | + type = DEV_X8; | |
| 791 | + break; | |
| 792 | + case 0: | |
| 793 | + type = DEV_X4; | |
| 794 | + break; | |
| 795 | + } | |
| 796 | + | |
| 797 | + return type; | |
| 798 | +} | |
| 799 | + | |
| 800 | +static enum dev_type ibridge_get_width(struct sbridge_pvt *pvt, u32 mtr) | |
| 801 | +{ | |
| 802 | + /* | |
| 803 | + * ddr3_width on the documentation but also valid for DDR4 on | |
| 804 | + * Haswell | |
| 805 | + */ | |
| 806 | + return __ibridge_get_width(GET_BITFIELD(mtr, 7, 8)); | |
| 807 | +} | |
| 808 | + | |
| 809 | +static enum dev_type broadwell_get_width(struct sbridge_pvt *pvt, u32 mtr) | |
| 810 | +{ | |
| 811 | + /* ddr3_width on the documentation but also valid for DDR4 */ | |
| 812 | + return __ibridge_get_width(GET_BITFIELD(mtr, 8, 9)); | |
| 813 | +} | |
| 814 | + | |
| 765 | 815 | static u8 get_node_id(struct sbridge_pvt *pvt) |
| 766 | 816 | { |
| 767 | 817 | u32 reg; |
| @@ -966,17 +1016,7 @@ static int get_dimm_config(struct mem_ctl_info *mci) · 198 unmodified lines | ||
| 966 | 1016 | |
| 967 | 1017 | dimm->nr_pages = npages; |
| 968 | 1018 | dimm->grain = 32; |
| 969 | − switch (banks) { | |
| 970 | − case 16: | |
| 971 | − dimm->dtype = DEV_X16; | |
| 972 | − break; | |
| 973 | − case 8: | |
| 974 | − dimm->dtype = DEV_X8; | |
| 975 | − break; | |
| 976 | − case 4: | |
| 977 | − dimm->dtype = DEV_X4; | |
| 978 | − break; | |
| 979 | − } | |
| 1019 | + dimm->dtype = pvt->info.get_width(pvt, mtr); | |
| 980 | 1020 | dimm->mtype = mtype; |
| 981 | 1021 | dimm->edac_mode = mode; |
| 982 | 1022 | snprintf(dimm->label, sizeof(dimm->label), |
| @@ -1869,7 +1909,11 @@ static int haswell_mci_bind_devs(struct mem_ctl_info *mci, · 886 unmodified lines | ||
| 1869 | 1909 | } |
| 1870 | 1910 | break; |
| 1871 | 1911 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0: |
| 1872 | − pvt->pci_ddrio = pdev; | |
| 1912 | + case PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO1: | |
| 1913 | + case PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO2: | |
| 1914 | + case PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO3: | |
| 1915 | + if (!pvt->pci_ddrio) | |
| 1916 | + pvt->pci_ddrio = pdev; | |
| 1873 | 1917 | break; |
| 1874 | 1918 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1: |
| 1875 | 1919 | pvt->pci_ha1 = pdev; |
| @@ -2361,6 +2405,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) · 485 unmodified lines | ||
| 2361 | 2405 | pvt->info.interleave_list = ibridge_interleave_list; |
| 2362 | 2406 | pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); |
| 2363 | 2407 | pvt->info.interleave_pkg = ibridge_interleave_pkg; |
| 2408 | + pvt->info.get_width = ibridge_get_width; | |
| 2364 | 2409 | mci->ctl_name = kasprintf(GFP_KERNEL, "Ivy Bridge Socket#%d", mci->mc_idx); |
| 2365 | 2410 | |
| 2366 | 2411 | /* Store pci devices at mci for faster access */ |
| @@ -2380,6 +2425,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) · 13 unmodified lines | ||
| 2380 | 2425 | pvt->info.interleave_list = sbridge_interleave_list; |
| 2381 | 2426 | pvt->info.max_interleave = ARRAY_SIZE(sbridge_interleave_list); |
| 2382 | 2427 | pvt->info.interleave_pkg = sbridge_interleave_pkg; |
| 2428 | + pvt->info.get_width = sbridge_get_width; | |
| 2383 | 2429 | mci->ctl_name = kasprintf(GFP_KERNEL, "Sandy Bridge Socket#%d", mci->mc_idx); |
| 2384 | 2430 | |
| 2385 | 2431 | /* Store pci devices at mci for faster access */ |
| @@ -2399,6 +2445,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) · 13 unmodified lines | ||
| 2399 | 2445 | pvt->info.interleave_list = ibridge_interleave_list; |
| 2400 | 2446 | pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); |
| 2401 | 2447 | pvt->info.interleave_pkg = ibridge_interleave_pkg; |
| 2448 | + pvt->info.get_width = ibridge_get_width; | |
| 2402 | 2449 | mci->ctl_name = kasprintf(GFP_KERNEL, "Haswell Socket#%d", mci->mc_idx); |
| 2403 | 2450 | |
| 2404 | 2451 | /* Store pci devices at mci for faster access */ |
| @@ -2418,6 +2465,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) · 13 unmodified lines | ||
| 2418 | 2465 | pvt->info.interleave_list = ibridge_interleave_list; |
| 2419 | 2466 | pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); |
| 2420 | 2467 | pvt->info.interleave_pkg = ibridge_interleave_pkg; |
| 2468 | + pvt->info.get_width = broadwell_get_width; | |
| 2421 | 2469 | mci->ctl_name = kasprintf(GFP_KERNEL, "Broadwell Socket#%d", mci->mc_idx); |
| 2422 | 2470 | |
| 2423 | 2471 | /* Store pci devices at mci for faster access */ |