diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-11 19:21:12 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2015-09-11 19:21:12 -0400 |
| commit | d9b44fe30fb8637b23f804eab2e7afbce129d714 (patch) | |
| tree | fdf3a50bf173c4914f542be9c6ef483856af33e4 /drivers | |
| parent | 9ebd051a7d5aa7b0ce813c3c2e5b9c851e7774b9 (diff) | |
| parent | 12f0721c5a70408e86257c5c99605cf743cd44c6 (diff) | |
Merge tag 'edac/v4.3-1' of git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-edac
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
Diffstat (limited to 'drivers')
| -rw-r--r-- | drivers/edac/sb_edac.c | 72 |
1 files changed, 60 insertions, 12 deletions
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c index ca7831168298..cf1268ddef0c 100644 --- a/drivers/edac/sb_edac.c +++ b/drivers/edac/sb_edac.c | |||
| @@ -280,6 +280,7 @@ struct sbridge_info { | |||
| 280 | u8 max_interleave; | 280 | u8 max_interleave; |
| 281 | u8 (*get_node_id)(struct sbridge_pvt *pvt); | 281 | u8 (*get_node_id)(struct sbridge_pvt *pvt); |
| 282 | enum mem_type (*get_memory_type)(struct sbridge_pvt *pvt); | 282 | enum mem_type (*get_memory_type)(struct sbridge_pvt *pvt); |
| 283 | enum dev_type (*get_width)(struct sbridge_pvt *pvt, u32 mtr); | ||
| 283 | struct pci_dev *pci_vtd; | 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[] = { | |||
| 471 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2 0x2f6c | 472 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2 0x2f6c |
| 472 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3 0x2f6d | 473 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3 0x2f6d |
| 473 | #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0 0x2fbd | 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 | static const struct pci_id_descr pci_dev_descr_haswell[] = { | 478 | static const struct pci_id_descr pci_dev_descr_haswell[] = { |
| 475 | /* first item must be the HA */ | 479 | /* first item must be the HA */ |
| 476 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0, 0) }, | 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[] = { | |||
| 488 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3, 1) }, | 492 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3, 1) }, |
| 489 | 493 | ||
| 490 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0, 1) }, | 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 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA, 1) }, | 499 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA, 1) }, |
| 493 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_THERMAL, 1) }, | 500 | { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_THERMAL, 1) }, |
| @@ -762,6 +769,49 @@ out: | |||
| 762 | return mtype; | 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 | static u8 get_node_id(struct sbridge_pvt *pvt) | 815 | static u8 get_node_id(struct sbridge_pvt *pvt) |
| 766 | { | 816 | { |
| 767 | u32 reg; | 817 | u32 reg; |
| @@ -966,17 +1016,7 @@ static int get_dimm_config(struct mem_ctl_info *mci) | |||
| 966 | 1016 | ||
| 967 | dimm->nr_pages = npages; | 1017 | dimm->nr_pages = npages; |
| 968 | dimm->grain = 32; | 1018 | dimm->grain = 32; |
| 969 | switch (banks) { | 1019 | dimm->dtype = pvt->info.get_width(pvt, mtr); |
| 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 | } | ||
| 980 | dimm->mtype = mtype; | 1020 | dimm->mtype = mtype; |
| 981 | dimm->edac_mode = mode; | 1021 | dimm->edac_mode = mode; |
| 982 | snprintf(dimm->label, sizeof(dimm->label), | 1022 | snprintf(dimm->label, sizeof(dimm->label), |
| @@ -1869,7 +1909,11 @@ static int haswell_mci_bind_devs(struct mem_ctl_info *mci, | |||
| 1869 | } | 1909 | } |
| 1870 | break; | 1910 | break; |
| 1871 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0: | 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 | break; | 1917 | break; |
| 1874 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1: | 1918 | case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1: |
| 1875 | pvt->pci_ha1 = pdev; | 1919 | pvt->pci_ha1 = pdev; |
| @@ -2361,6 +2405,7 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type) | |||
| 2361 | pvt->info.interleave_list = ibridge_interleave_list; | 2405 | pvt->info.interleave_list = ibridge_interleave_list; |
| 2362 | pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); | 2406 | pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); |
| 2363 | pvt->info.interleave_pkg = ibridge_interleave_pkg; | 2407 | pvt->info.interleave_pkg = ibridge_interleave_pkg; |
| 2408 | pvt->info.get_width = ibridge_get_width; | ||
| 2364 | mci->ctl_name = kasprintf(GFP_KERNEL, "Ivy Bridge Socket#%d", mci->mc_idx); | 2409 | mci->ctl_name = kasprintf(GFP_KERNEL, "Ivy Bridge Socket#%d", mci->mc_idx); |
| 2365 | 2410 | ||
| 2366 | /* Store pci devices at mci for faster access */ | 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) | |||
| 2380 | pvt->info.interleave_list = sbridge_interleave_list; | 2425 | pvt->info.interleave_list = sbridge_interleave_list; |
| 2381 | pvt->info.max_interleave = ARRAY_SIZE(sbridge_interleave_list); | 2426 | pvt->info.max_interleave = ARRAY_SIZE(sbridge_interleave_list); |
| 2382 | pvt->info.interleave_pkg = sbridge_interleave_pkg; | 2427 | pvt->info.interleave_pkg = sbridge_interleave_pkg; |
| 2428 | pvt->info.get_width = sbridge_get_width; | ||
| 2383 | mci->ctl_name = kasprintf(GFP_KERNEL, "Sandy Bridge Socket#%d", mci->mc_idx); | 2429 | mci->ctl_name = kasprintf(GFP_KERNEL, "Sandy Bridge Socket#%d", mci->mc_idx); |
| 2384 | 2430 | ||
| 2385 | /* Store pci devices at mci for faster access */ | 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) | |||
| 2399 | pvt->info.interleave_list = ibridge_interleave_list; | 2445 | pvt->info.interleave_list = ibridge_interleave_list; |
| 2400 | pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); | 2446 | pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); |
| 2401 | pvt->info.interleave_pkg = ibridge_interleave_pkg; | 2447 | pvt->info.interleave_pkg = ibridge_interleave_pkg; |
| 2448 | pvt->info.get_width = ibridge_get_width; | ||
| 2402 | mci->ctl_name = kasprintf(GFP_KERNEL, "Haswell Socket#%d", mci->mc_idx); | 2449 | mci->ctl_name = kasprintf(GFP_KERNEL, "Haswell Socket#%d", mci->mc_idx); |
| 2403 | 2450 | ||
| 2404 | /* Store pci devices at mci for faster access */ | 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) | |||
| 2418 | pvt->info.interleave_list = ibridge_interleave_list; | 2465 | pvt->info.interleave_list = ibridge_interleave_list; |
| 2419 | pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); | 2466 | pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); |
| 2420 | pvt->info.interleave_pkg = ibridge_interleave_pkg; | 2467 | pvt->info.interleave_pkg = ibridge_interleave_pkg; |
| 2468 | pvt->info.get_width = broadwell_get_width; | ||
| 2421 | mci->ctl_name = kasprintf(GFP_KERNEL, "Broadwell Socket#%d", mci->mc_idx); | 2469 | mci->ctl_name = kasprintf(GFP_KERNEL, "Broadwell Socket#%d", mci->mc_idx); |
| 2422 | 2470 | ||
| 2423 | /* Store pci devices at mci for faster access */ | 2471 | /* Store pci devices at mci for faster access */ |
