aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/edac/sb_edac.c
diff options
context:
space:
mode:
authorTony Luck <tony.luck@intel.com>2014-12-02 12:27:30 -0500
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>2014-12-02 13:46:08 -0500
commit1f39581a9a7a3387f40f379478d8827878c57530 (patch)
tree28d68867ff842a75fe73b4cf42b2edafa7375dfb /drivers/edac/sb_edac.c
parentf7cf2a22a2896d3b3595b71d7936b6d7a3316b00 (diff)
sb_edac: Add support for Broadwell-DE processor
Broadwell-DE is the microserver version of next generation Xeon processors. A whole bunch of new PCIe device ids, but otherwise pretty much the same as Haswell. Acked-by: Aristeu Rozanski <aris@redhat.com> Signed-off-by: Tony Luck <tony.luck@intel.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
Diffstat (limited to 'drivers/edac/sb_edac.c')
-rw-r--r--drivers/edac/sb_edac.c163
1 files changed, 157 insertions, 6 deletions
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index ead0bf9a5d2d..993e8b61c4b2 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -262,6 +262,7 @@ enum type {
262 SANDY_BRIDGE, 262 SANDY_BRIDGE,
263 IVY_BRIDGE, 263 IVY_BRIDGE,
264 HASWELL, 264 HASWELL,
265 BROADWELL,
265}; 266};
266 267
267struct sbridge_pvt; 268struct sbridge_pvt;
@@ -446,7 +447,7 @@ static const struct pci_id_table pci_dev_descr_ibridge_table[] = {
446 * - each SMI channel interfaces with a scalable memory buffer 447 * - each SMI channel interfaces with a scalable memory buffer
447 * - each scalable memory buffer supports 4 DDR3/DDR4 channels, 3 DPC 448 * - each scalable memory buffer supports 4 DDR3/DDR4 channels, 3 DPC
448 */ 449 */
449#define HASWELL_DDRCRCLKCONTROLS 0xa10 450#define HASWELL_DDRCRCLKCONTROLS 0xa10 /* Ditto on Broadwell */
450#define HASWELL_HASYSDEFEATURE2 0x84 451#define HASWELL_HASYSDEFEATURE2 0x84
451#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_VTD_MISC 0x2f28 452#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_VTD_MISC 0x2f28
452#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0 0x2fa0 453#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0 0x2fa0
@@ -498,12 +499,53 @@ static const struct pci_id_table pci_dev_descr_haswell_table[] = {
498}; 499};
499 500
500/* 501/*
502 * Broadwell support
503 *
504 * DE processor:
505 * - 1 IMC
506 * - 2 DDR3 channels, 2 DPC per channel
507 */
508#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_VTD_MISC 0x6f28
509#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0 0x6fa0
510#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA 0x6fa8
511#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_THERMAL 0x6f71
512#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD0 0x6ffc
513#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD1 0x6ffd
514#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0 0x6faa
515#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD1 0x6fab
516#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD2 0x6fac
517#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD3 0x6fad
518#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_DDRIO0 0x6faf
519
520static const struct pci_id_descr pci_dev_descr_broadwell[] = {
521 /* first item must be the HA */
522 { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0, 0) },
523
524 { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD0, 0) },
525 { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD1, 0) },
526
527 { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA, 0) },
528 { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_THERMAL, 0) },
529 { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0, 0) },
530 { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD1, 0) },
531 { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD2, 0) },
532 { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD3, 0) },
533 { PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_DDRIO0, 1) },
534};
535
536static const struct pci_id_table pci_dev_descr_broadwell_table[] = {
537 PCI_ID_TABLE_ENTRY(pci_dev_descr_broadwell),
538 {0,} /* 0 terminated list. */
539};
540
541/*
501 * pci_device_id table for which devices we are looking for 542 * pci_device_id table for which devices we are looking for
502 */ 543 */
503static const struct pci_device_id sbridge_pci_tbl[] = { 544static const struct pci_device_id sbridge_pci_tbl[] = {
504 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0)}, 545 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0)},
505 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA)}, 546 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA)},
506 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0)}, 547 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0)},
548 {PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0)},
507 {0,} /* 0 terminated list. */ 549 {0,} /* 0 terminated list. */
508}; 550};
509 551
@@ -768,12 +810,22 @@ static int check_if_ecc_is_active(const u8 bus, enum type type)
768 struct pci_dev *pdev = NULL; 810 struct pci_dev *pdev = NULL;
769 u32 mcmtr, id; 811 u32 mcmtr, id;
770 812
771 if (type == IVY_BRIDGE) 813 switch (type) {
814 case IVY_BRIDGE:
772 id = PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA; 815 id = PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA;
773 else if (type == HASWELL) 816 break;
817 case HASWELL:
774 id = PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA; 818 id = PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA;
775 else 819 break;
820 case SANDY_BRIDGE:
776 id = PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA; 821 id = PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA;
822 break;
823 case BROADWELL:
824 id = PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA;
825 break;
826 default:
827 return -ENODEV;
828 }
777 829
778 pdev = get_pdev_same_bus(bus, id); 830 pdev = get_pdev_same_bus(bus, id);
779 if (!pdev) { 831 if (!pdev) {
@@ -801,7 +853,7 @@ static int get_dimm_config(struct mem_ctl_info *mci)
801 enum edac_type mode; 853 enum edac_type mode;
802 enum mem_type mtype; 854 enum mem_type mtype;
803 855
804 if (pvt->info.type == HASWELL) 856 if (pvt->info.type == HASWELL || pvt->info.type == BROADWELL)
805 pci_read_config_dword(pvt->pci_sad1, SAD_TARGET, &reg); 857 pci_read_config_dword(pvt->pci_sad1, SAD_TARGET, &reg);
806 else 858 else
807 pci_read_config_dword(pvt->pci_br0, SAD_TARGET, &reg); 859 pci_read_config_dword(pvt->pci_br0, SAD_TARGET, &reg);
@@ -1182,7 +1234,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
1182 *socket = sad_interleave[idx]; 1234 *socket = sad_interleave[idx];
1183 edac_dbg(0, "SAD interleave index: %d (wayness %d) = CPU socket %d\n", 1235 edac_dbg(0, "SAD interleave index: %d (wayness %d) = CPU socket %d\n",
1184 idx, sad_way, *socket); 1236 idx, sad_way, *socket);
1185 } else if (pvt->info.type == HASWELL) { 1237 } else if (pvt->info.type == HASWELL || pvt->info.type == BROADWELL) {
1186 int bits, a7mode = A7MODE(dram_rule); 1238 int bits, a7mode = A7MODE(dram_rule);
1187 1239
1188 if (a7mode) { 1240 if (a7mode) {
@@ -1831,6 +1883,82 @@ enodev:
1831 return -ENODEV; 1883 return -ENODEV;
1832} 1884}
1833 1885
1886static int broadwell_mci_bind_devs(struct mem_ctl_info *mci,
1887 struct sbridge_dev *sbridge_dev)
1888{
1889 struct sbridge_pvt *pvt = mci->pvt_info;
1890 struct pci_dev *pdev;
1891 int i;
1892
1893 /* there's only one device per system; not tied to any bus */
1894 if (pvt->info.pci_vtd == NULL)
1895 /* result will be checked later */
1896 pvt->info.pci_vtd = pci_get_device(PCI_VENDOR_ID_INTEL,
1897 PCI_DEVICE_ID_INTEL_BROADWELL_IMC_VTD_MISC,
1898 NULL);
1899
1900 for (i = 0; i < sbridge_dev->n_devs; i++) {
1901 pdev = sbridge_dev->pdev[i];
1902 if (!pdev)
1903 continue;
1904
1905 switch (pdev->device) {
1906 case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD0:
1907 pvt->pci_sad0 = pdev;
1908 break;
1909 case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD1:
1910 pvt->pci_sad1 = pdev;
1911 break;
1912 case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0:
1913 pvt->pci_ha0 = pdev;
1914 break;
1915 case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA:
1916 pvt->pci_ta = pdev;
1917 break;
1918 case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_THERMAL:
1919 pvt->pci_ras = pdev;
1920 break;
1921 case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0:
1922 pvt->pci_tad[0] = pdev;
1923 break;
1924 case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD1:
1925 pvt->pci_tad[1] = pdev;
1926 break;
1927 case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD2:
1928 pvt->pci_tad[2] = pdev;
1929 break;
1930 case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD3:
1931 pvt->pci_tad[3] = pdev;
1932 break;
1933 case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_DDRIO0:
1934 pvt->pci_ddrio = pdev;
1935 break;
1936 default:
1937 break;
1938 }
1939
1940 edac_dbg(0, "Associated PCI %02x.%02d.%d with dev = %p\n",
1941 sbridge_dev->bus,
1942 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
1943 pdev);
1944 }
1945
1946 /* Check if everything were registered */
1947 if (!pvt->pci_sad0 || !pvt->pci_ha0 || !pvt->pci_sad1 ||
1948 !pvt->pci_ras || !pvt->pci_ta || !pvt->info.pci_vtd)
1949 goto enodev;
1950
1951 for (i = 0; i < NUM_CHANNELS; i++) {
1952 if (!pvt->pci_tad[i])
1953 goto enodev;
1954 }
1955 return 0;
1956
1957enodev:
1958 sbridge_printk(KERN_ERR, "Some needed devices are missing\n");
1959 return -ENODEV;
1960}
1961
1834/**************************************************************************** 1962/****************************************************************************
1835 Error check routines 1963 Error check routines
1836 ****************************************************************************/ 1964 ****************************************************************************/
@@ -2243,6 +2371,25 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
2243 if (unlikely(rc < 0)) 2371 if (unlikely(rc < 0))
2244 goto fail0; 2372 goto fail0;
2245 break; 2373 break;
2374 case BROADWELL:
2375 /* rankcfgr isn't used */
2376 pvt->info.get_tolm = haswell_get_tolm;
2377 pvt->info.get_tohm = haswell_get_tohm;
2378 pvt->info.dram_rule = ibridge_dram_rule;
2379 pvt->info.get_memory_type = haswell_get_memory_type;
2380 pvt->info.get_node_id = haswell_get_node_id;
2381 pvt->info.rir_limit = haswell_rir_limit;
2382 pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule);
2383 pvt->info.interleave_list = ibridge_interleave_list;
2384 pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
2385 pvt->info.interleave_pkg = ibridge_interleave_pkg;
2386 mci->ctl_name = kasprintf(GFP_KERNEL, "Broadwell Socket#%d", mci->mc_idx);
2387
2388 /* Store pci devices at mci for faster access */
2389 rc = broadwell_mci_bind_devs(mci, sbridge_dev);
2390 if (unlikely(rc < 0))
2391 goto fail0;
2392 break;
2246 } 2393 }
2247 2394
2248 /* Get dimm basic config and the memory layout */ 2395 /* Get dimm basic config and the memory layout */
@@ -2308,6 +2455,10 @@ static int sbridge_probe(struct pci_dev *pdev, const struct pci_device_id *id)
2308 rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_haswell_table); 2455 rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_haswell_table);
2309 type = HASWELL; 2456 type = HASWELL;
2310 break; 2457 break;
2458 case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0:
2459 rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_broadwell_table);
2460 type = BROADWELL;
2461 break;
2311 } 2462 }
2312 if (unlikely(rc < 0)) 2463 if (unlikely(rc < 0))
2313 goto fail0; 2464 goto fail0;