Re: [PATCHv2] sb_edac: Add support for Broadwell-DE processor

From: Mauro Carvalho Chehab
Date: Tue Dec 02 2014 - 14:08:12 EST


Em Tue, 02 Dec 2014 09:27:30 -0800
Tony Luck <tony.luck@xxxxxxxxx> escreveu:

> 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@xxxxxxxxxx>
> Signed-off-by: Tony Luck <tony.luck@xxxxxxxxx>

Applied, thanks!

> ---
>
> v2fixes:
> 1) TAD2 abd TAD3 are not optional - Aristeu
> 2) Fix multi-line comment to conform to style - Mauro
>
> drivers/edac/sb_edac.c | 163 +++++++++++++++++++++++++++++++++++++++++++++++--
> 1 file 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 {
> SANDY_BRIDGE,
> IVY_BRIDGE,
> HASWELL,
> + BROADWELL,
> };
>
> 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 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 PCI_DEVICE_ID_INTEL_HASWELL_IMC_VTD_MISC 0x2f28
> #define PCI_DEVICE_ID_INTEL_HASWELL_IMC_HA0 0x2fa0
> @@ -498,12 +499,53 @@ static const struct pci_id_table pci_dev_descr_haswell_table[] = {
> };
>
> /*
> + * 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
> */
> 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_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_BROADWELL_IMC_HA0)},
> {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;
> u32 mcmtr, id;
>
> - if (type == IVY_BRIDGE)
> + switch (type) {
> + case IVY_BRIDGE:
> 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;
> - else
> + break;
> + case SANDY_BRIDGE:
> 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);
> if (!pdev) {
> @@ -801,7 +853,7 @@ static int get_dimm_config(struct mem_ctl_info *mci)
> enum edac_type mode;
> 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, &reg);
> else
> 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,
> *socket = sad_interleave[idx];
> edac_dbg(0, "SAD interleave index: %d (wayness %d) = CPU socket %d\n",
> 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);
>
> if (a7mode) {
> @@ -1831,6 +1883,82 @@ 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
> ****************************************************************************/
> @@ -2243,6 +2371,25 @@ static int sbridge_register_mci(struct sbridge_dev *sbridge_dev, enum type type)
> if (unlikely(rc < 0))
> goto fail0;
> 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 */
> @@ -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);
> type = HASWELL;
> 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))
> goto fail0;
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/