Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

+60 -12
+60 -12
drivers/edac/sb_edac.c
··· 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 ··· 472 471 #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD2 0x2f6c 473 472 #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TAD3 0x2f6d 474 473 #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0 0x2fbd 474 + #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO1 0x2fbf 475 + #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO2 0x2fb9 476 + #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO3 0x2fbb 475 477 static const struct pci_id_descr pci_dev_descr_haswell[] = { 476 478 /* first item must be the HA */ 477 479 { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0, 0) }, ··· 492 488 { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TAD3, 1) }, 493 489 494 490 { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0, 1) }, 491 + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO1, 1) }, 492 + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO2, 1) }, 493 + { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO3, 1) }, 495 494 496 495 { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_TA, 1) }, 497 496 { PCI_DESCR(PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1_THERMAL, 1) }, ··· 769 762 return mtype; 770 763 } 771 764 765 + static enum dev_type sbridge_get_width(struct sbridge_pvt *pvt, u32 mtr) 766 + { 767 + /* there's no way to figure out */ 768 + return DEV_UNKNOWN; 769 + } 770 + 771 + static enum dev_type __ibridge_get_width(u32 mtr) 772 + { 773 + enum dev_type type; 774 + 775 + switch (mtr) { 776 + case 3: 777 + type = DEV_UNKNOWN; 778 + break; 779 + case 2: 780 + type = DEV_X16; 781 + break; 782 + case 1: 783 + type = DEV_X8; 784 + break; 785 + case 0: 786 + type = DEV_X4; 787 + break; 788 + } 789 + 790 + return type; 791 + } 792 + 793 + static enum dev_type ibridge_get_width(struct sbridge_pvt *pvt, u32 mtr) 794 + { 795 + /* 796 + * ddr3_width on the documentation but also valid for DDR4 on 797 + * Haswell 798 + */ 799 + return __ibridge_get_width(GET_BITFIELD(mtr, 7, 8)); 800 + } 801 + 802 + static enum dev_type broadwell_get_width(struct sbridge_pvt *pvt, u32 mtr) 803 + { 804 + /* ddr3_width on the documentation but also valid for DDR4 */ 805 + return __ibridge_get_width(GET_BITFIELD(mtr, 8, 9)); 806 + } 807 + 772 808 static u8 get_node_id(struct sbridge_pvt *pvt) 773 809 { 774 810 u32 reg; ··· 1016 966 1017 967 dimm->nr_pages = npages; 1018 968 dimm->grain = 32; 1019 - switch (banks) { 1020 - case 16: 1021 - dimm->dtype = DEV_X16; 1022 - break; 1023 - case 8: 1024 - dimm->dtype = DEV_X8; 1025 - break; 1026 - case 4: 1027 - dimm->dtype = DEV_X4; 1028 - break; 1029 - } 969 + dimm->dtype = pvt->info.get_width(pvt, mtr); 1030 970 dimm->mtype = mtype; 1031 971 dimm->edac_mode = mode; 1032 972 snprintf(dimm->label, sizeof(dimm->label), ··· 1909 1869 } 1910 1870 break; 1911 1871 case PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO0: 1912 - pvt->pci_ddrio = pdev; 1872 + case PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO1: 1873 + case PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO2: 1874 + case PCI_DEVICE_ID_INTEL_HASWELL_IMC_DDRIO3: 1875 + if (!pvt->pci_ddrio) 1876 + pvt->pci_ddrio = pdev; 1913 1877 break; 1914 1878 case PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA1: 1915 1879 pvt->pci_ha1 = pdev; ··· 2405 2361 pvt->info.interleave_list = ibridge_interleave_list; 2406 2362 pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); 2407 2363 pvt->info.interleave_pkg = ibridge_interleave_pkg; 2364 + pvt->info.get_width = ibridge_get_width; 2408 2365 mci->ctl_name = kasprintf(GFP_KERNEL, "Ivy Bridge Socket#%d", mci->mc_idx); 2409 2366 2410 2367 /* Store pci devices at mci for faster access */ ··· 2425 2380 pvt->info.interleave_list = sbridge_interleave_list; 2426 2381 pvt->info.max_interleave = ARRAY_SIZE(sbridge_interleave_list); 2427 2382 pvt->info.interleave_pkg = sbridge_interleave_pkg; 2383 + pvt->info.get_width = sbridge_get_width; 2428 2384 mci->ctl_name = kasprintf(GFP_KERNEL, "Sandy Bridge Socket#%d", mci->mc_idx); 2429 2385 2430 2386 /* Store pci devices at mci for faster access */ ··· 2445 2399 pvt->info.interleave_list = ibridge_interleave_list; 2446 2400 pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); 2447 2401 pvt->info.interleave_pkg = ibridge_interleave_pkg; 2402 + pvt->info.get_width = ibridge_get_width; 2448 2403 mci->ctl_name = kasprintf(GFP_KERNEL, "Haswell Socket#%d", mci->mc_idx); 2449 2404 2450 2405 /* Store pci devices at mci for faster access */ ··· 2465 2418 pvt->info.interleave_list = ibridge_interleave_list; 2466 2419 pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list); 2467 2420 pvt->info.interleave_pkg = ibridge_interleave_pkg; 2421 + pvt->info.get_width = broadwell_get_width; 2468 2422 mci->ctl_name = kasprintf(GFP_KERNEL, "Broadwell Socket#%d", mci->mc_idx); 2469 2423 2470 2424 /* Store pci devices at mci for faster access */