mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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>
This commit is contained in:
		
							parent
							
								
									f7cf2a22a2
								
							
						
					
					
						commit
						1f39581a9a
					
				
					 1 changed files with 157 additions and 6 deletions
				
			
		| 
						 | 
					@ -262,6 +262,7 @@ enum type {
 | 
				
			||||||
	SANDY_BRIDGE,
 | 
						SANDY_BRIDGE,
 | 
				
			||||||
	IVY_BRIDGE,
 | 
						IVY_BRIDGE,
 | 
				
			||||||
	HASWELL,
 | 
						HASWELL,
 | 
				
			||||||
 | 
						BROADWELL,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct sbridge_pvt;
 | 
					struct sbridge_pvt;
 | 
				
			||||||
| 
						 | 
					@ -446,7 +447,7 @@ static const struct pci_id_table pci_dev_descr_ibridge_table[] = {
 | 
				
			||||||
 *	- each SMI channel interfaces with a scalable memory buffer
 | 
					 *	- each SMI channel interfaces with a scalable memory buffer
 | 
				
			||||||
 *	- each scalable memory buffer supports 4 DDR3/DDR4 channels, 3 DPC
 | 
					 *	- each scalable memory buffer supports 4 DDR3/DDR4 channels, 3 DPC
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
#define HASWELL_DDRCRCLKCONTROLS 0xa10
 | 
					#define HASWELL_DDRCRCLKCONTROLS 0xa10 /* Ditto on Broadwell */
 | 
				
			||||||
#define HASWELL_HASYSDEFEATURE2 0x84
 | 
					#define HASWELL_HASYSDEFEATURE2 0x84
 | 
				
			||||||
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_VTD_MISC 0x2f28
 | 
					#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_VTD_MISC 0x2f28
 | 
				
			||||||
#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0	0x2fa0
 | 
					#define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0	0x2fa0
 | 
				
			||||||
| 
						 | 
					@ -497,6 +498,46 @@ static const struct pci_id_table pci_dev_descr_haswell_table[] = {
 | 
				
			||||||
	{0,}			/* 0 terminated list. */
 | 
						{0,}			/* 0 terminated list. */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					 * Broadwell support
 | 
				
			||||||
 | 
					 *
 | 
				
			||||||
 | 
					 * DE processor:
 | 
				
			||||||
 | 
					 *	- 1 IMC
 | 
				
			||||||
 | 
					 *	- 2 DDR3 channels, 2 DPC per channel
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_VTD_MISC 0x6f28
 | 
				
			||||||
 | 
					#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0	0x6fa0
 | 
				
			||||||
 | 
					#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA	0x6fa8
 | 
				
			||||||
 | 
					#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_THERMAL 0x6f71
 | 
				
			||||||
 | 
					#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD0 0x6ffc
 | 
				
			||||||
 | 
					#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD1 0x6ffd
 | 
				
			||||||
 | 
					#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0 0x6faa
 | 
				
			||||||
 | 
					#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD1 0x6fab
 | 
				
			||||||
 | 
					#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD2 0x6fac
 | 
				
			||||||
 | 
					#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD3 0x6fad
 | 
				
			||||||
 | 
					#define PCI_DEVICE_ID_INTEL_BROADWELL_IMC_DDRIO0 0x6faf
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct pci_id_descr pci_dev_descr_broadwell[] = {
 | 
				
			||||||
 | 
						/* first item must be the HA */
 | 
				
			||||||
 | 
						{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0, 0)		},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD0, 0)	},
 | 
				
			||||||
 | 
						{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD1, 0)	},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA, 0)	},
 | 
				
			||||||
 | 
						{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_THERMAL, 0)	},
 | 
				
			||||||
 | 
						{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0, 0)	},
 | 
				
			||||||
 | 
						{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD1, 0)	},
 | 
				
			||||||
 | 
						{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD2, 0)	},
 | 
				
			||||||
 | 
						{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD3, 0)	},
 | 
				
			||||||
 | 
						{ PCI_DESCR(PCI_DEVICE_ID_INTEL_BROADWELL_IMC_DDRIO0, 1)	},
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static const struct pci_id_table pci_dev_descr_broadwell_table[] = {
 | 
				
			||||||
 | 
						PCI_ID_TABLE_ENTRY(pci_dev_descr_broadwell),
 | 
				
			||||||
 | 
						{0,}			/* 0 terminated list. */
 | 
				
			||||||
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/*
 | 
					/*
 | 
				
			||||||
 *	pci_device_id	table for which devices we are looking for
 | 
					 *	pci_device_id	table for which devices we are looking for
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -504,6 +545,7 @@ static const struct pci_device_id sbridge_pci_tbl[] = {
 | 
				
			||||||
	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0)},
 | 
						{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_HA0)},
 | 
				
			||||||
	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA)},
 | 
						{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA)},
 | 
				
			||||||
	{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0)},
 | 
						{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0)},
 | 
				
			||||||
 | 
						{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0)},
 | 
				
			||||||
	{0,}			/* 0 terminated list. */
 | 
						{0,}			/* 0 terminated list. */
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -768,12 +810,22 @@ static int check_if_ecc_is_active(const u8 bus, enum type type)
 | 
				
			||||||
	struct pci_dev *pdev = NULL;
 | 
						struct pci_dev *pdev = NULL;
 | 
				
			||||||
	u32 mcmtr, id;
 | 
						u32 mcmtr, id;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (type == IVY_BRIDGE)
 | 
						switch (type) {
 | 
				
			||||||
 | 
						case IVY_BRIDGE:
 | 
				
			||||||
		id = PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA;
 | 
							id = PCI_DEVICE_ID_INTEL_IBRIDGE_IMC_HA0_TA;
 | 
				
			||||||
	else if (type == HASWELL)
 | 
							break;
 | 
				
			||||||
 | 
						case HASWELL:
 | 
				
			||||||
		id = PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA;
 | 
							id = PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0_TA;
 | 
				
			||||||
	else
 | 
							break;
 | 
				
			||||||
 | 
						case SANDY_BRIDGE:
 | 
				
			||||||
		id = PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA;
 | 
							id = PCI_DEVICE_ID_INTEL_SBRIDGE_IMC_TA;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						case BROADWELL:
 | 
				
			||||||
 | 
							id = PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
 | 
						default:
 | 
				
			||||||
 | 
							return -ENODEV;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pdev = get_pdev_same_bus(bus, id);
 | 
						pdev = get_pdev_same_bus(bus, id);
 | 
				
			||||||
	if (!pdev) {
 | 
						if (!pdev) {
 | 
				
			||||||
| 
						 | 
					@ -801,7 +853,7 @@ static int get_dimm_config(struct mem_ctl_info *mci)
 | 
				
			||||||
	enum edac_type mode;
 | 
						enum edac_type mode;
 | 
				
			||||||
	enum mem_type mtype;
 | 
						enum mem_type mtype;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (pvt->info.type == HASWELL)
 | 
						if (pvt->info.type == HASWELL || pvt->info.type == BROADWELL)
 | 
				
			||||||
		pci_read_config_dword(pvt->pci_sad1, SAD_TARGET, ®);
 | 
							pci_read_config_dword(pvt->pci_sad1, SAD_TARGET, ®);
 | 
				
			||||||
	else
 | 
						else
 | 
				
			||||||
		pci_read_config_dword(pvt->pci_br0, SAD_TARGET, ®);
 | 
							pci_read_config_dword(pvt->pci_br0, SAD_TARGET, ®);
 | 
				
			||||||
| 
						 | 
					@ -1182,7 +1234,7 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
 | 
				
			||||||
		*socket = sad_interleave[idx];
 | 
							*socket = sad_interleave[idx];
 | 
				
			||||||
		edac_dbg(0, "SAD interleave index: %d (wayness %d) = CPU socket %d\n",
 | 
							edac_dbg(0, "SAD interleave index: %d (wayness %d) = CPU socket %d\n",
 | 
				
			||||||
			 idx, sad_way, *socket);
 | 
								 idx, sad_way, *socket);
 | 
				
			||||||
	} else if (pvt->info.type == HASWELL) {
 | 
						} else if (pvt->info.type == HASWELL || pvt->info.type == BROADWELL) {
 | 
				
			||||||
		int bits, a7mode = A7MODE(dram_rule);
 | 
							int bits, a7mode = A7MODE(dram_rule);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (a7mode) {
 | 
							if (a7mode) {
 | 
				
			||||||
| 
						 | 
					@ -1831,6 +1883,82 @@ static int haswell_mci_bind_devs(struct mem_ctl_info *mci,
 | 
				
			||||||
	return -ENODEV;
 | 
						return -ENODEV;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static int broadwell_mci_bind_devs(struct mem_ctl_info *mci,
 | 
				
			||||||
 | 
									 struct sbridge_dev *sbridge_dev)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						struct sbridge_pvt *pvt = mci->pvt_info;
 | 
				
			||||||
 | 
						struct pci_dev *pdev;
 | 
				
			||||||
 | 
						int i;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* there's only one device per system; not tied to any bus */
 | 
				
			||||||
 | 
						if (pvt->info.pci_vtd == NULL)
 | 
				
			||||||
 | 
							/* result will be checked later */
 | 
				
			||||||
 | 
							pvt->info.pci_vtd = pci_get_device(PCI_VENDOR_ID_INTEL,
 | 
				
			||||||
 | 
											   PCI_DEVICE_ID_INTEL_BROADWELL_IMC_VTD_MISC,
 | 
				
			||||||
 | 
											   NULL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < sbridge_dev->n_devs; i++) {
 | 
				
			||||||
 | 
							pdev = sbridge_dev->pdev[i];
 | 
				
			||||||
 | 
							if (!pdev)
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							switch (pdev->device) {
 | 
				
			||||||
 | 
							case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD0:
 | 
				
			||||||
 | 
								pvt->pci_sad0 = pdev;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_CBO_SAD1:
 | 
				
			||||||
 | 
								pvt->pci_sad1 = pdev;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0:
 | 
				
			||||||
 | 
								pvt->pci_ha0 = pdev;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TA:
 | 
				
			||||||
 | 
								pvt->pci_ta = pdev;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_THERMAL:
 | 
				
			||||||
 | 
								pvt->pci_ras = pdev;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD0:
 | 
				
			||||||
 | 
								pvt->pci_tad[0] = pdev;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD1:
 | 
				
			||||||
 | 
								pvt->pci_tad[1] = pdev;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD2:
 | 
				
			||||||
 | 
								pvt->pci_tad[2] = pdev;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0_TAD3:
 | 
				
			||||||
 | 
								pvt->pci_tad[3] = pdev;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_DDRIO0:
 | 
				
			||||||
 | 
								pvt->pci_ddrio = pdev;
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							default:
 | 
				
			||||||
 | 
								break;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							edac_dbg(0, "Associated PCI %02x.%02d.%d with dev = %p\n",
 | 
				
			||||||
 | 
								 sbridge_dev->bus,
 | 
				
			||||||
 | 
								 PCI_SLOT(pdev->devfn), PCI_FUNC(pdev->devfn),
 | 
				
			||||||
 | 
								 pdev);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/* Check if everything were registered */
 | 
				
			||||||
 | 
						if (!pvt->pci_sad0 || !pvt->pci_ha0 || !pvt->pci_sad1 ||
 | 
				
			||||||
 | 
						    !pvt->pci_ras  || !pvt->pci_ta || !pvt->info.pci_vtd)
 | 
				
			||||||
 | 
							goto enodev;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for (i = 0; i < NUM_CHANNELS; i++) {
 | 
				
			||||||
 | 
							if (!pvt->pci_tad[i])
 | 
				
			||||||
 | 
								goto enodev;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					enodev:
 | 
				
			||||||
 | 
						sbridge_printk(KERN_ERR, "Some needed devices are missing\n");
 | 
				
			||||||
 | 
						return -ENODEV;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/****************************************************************************
 | 
					/****************************************************************************
 | 
				
			||||||
			Error check routines
 | 
								Error check routines
 | 
				
			||||||
 ****************************************************************************/
 | 
					 ****************************************************************************/
 | 
				
			||||||
| 
						 | 
					@ -2243,6 +2371,25 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
 | 
				
			||||||
		if (unlikely(rc < 0))
 | 
							if (unlikely(rc < 0))
 | 
				
			||||||
			goto fail0;
 | 
								goto fail0;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
						case BROADWELL:
 | 
				
			||||||
 | 
							/* rankcfgr isn't used */
 | 
				
			||||||
 | 
							pvt->info.get_tolm = haswell_get_tolm;
 | 
				
			||||||
 | 
							pvt->info.get_tohm = haswell_get_tohm;
 | 
				
			||||||
 | 
							pvt->info.dram_rule = ibridge_dram_rule;
 | 
				
			||||||
 | 
							pvt->info.get_memory_type = haswell_get_memory_type;
 | 
				
			||||||
 | 
							pvt->info.get_node_id = haswell_get_node_id;
 | 
				
			||||||
 | 
							pvt->info.rir_limit = haswell_rir_limit;
 | 
				
			||||||
 | 
							pvt->info.max_sad = ARRAY_SIZE(ibridge_dram_rule);
 | 
				
			||||||
 | 
							pvt->info.interleave_list = ibridge_interleave_list;
 | 
				
			||||||
 | 
							pvt->info.max_interleave = ARRAY_SIZE(ibridge_interleave_list);
 | 
				
			||||||
 | 
							pvt->info.interleave_pkg = ibridge_interleave_pkg;
 | 
				
			||||||
 | 
							mci->ctl_name = kasprintf(GFP_KERNEL, "Broadwell Socket#%d", mci->mc_idx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* Store pci devices at mci for faster access */
 | 
				
			||||||
 | 
							rc = broadwell_mci_bind_devs(mci, sbridge_dev);
 | 
				
			||||||
 | 
							if (unlikely(rc < 0))
 | 
				
			||||||
 | 
								goto fail0;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* Get dimm basic config and the memory layout */
 | 
						/* 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)
 | 
				
			||||||
		rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_haswell_table);
 | 
							rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_haswell_table);
 | 
				
			||||||
		type = HASWELL;
 | 
							type = HASWELL;
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
 | 
						case PCI_DEVICE_ID_INTEL_BROADWELL_IMC_HA0:
 | 
				
			||||||
 | 
							rc = sbridge_get_all_devices(&num_mc, pci_dev_descr_broadwell_table);
 | 
				
			||||||
 | 
							type = BROADWELL;
 | 
				
			||||||
 | 
							break;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if (unlikely(rc < 0))
 | 
						if (unlikely(rc < 0))
 | 
				
			||||||
		goto fail0;
 | 
							goto fail0;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue