From: Dietmar Maurer Date: Wed, 24 Aug 2016 04:57:54 +0000 (+0200) Subject: EDAC, ie31200_edac: Add Skylake support X-Git-Url: https://git.proxmox.com/?a=commitdiff_plain;h=2210cf391301fd0e5560e8943e6459e83260d473;p=pve-kernel-jessie.git EDAC, ie31200_edac: Add Skylake support --- diff --git a/Makefile b/Makefile index 69fb6f2..05c87f5 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ RELEASE=4.2 # also update proxmox-ve/changelog if you change KERNEL_VER or KREL KERNEL_VER=4.4.15 -PKGREL=60 +PKGREL=61 # also include firmware of previous version into # the fw package: fwlist-2.6.32-PREV-pve KREL=1 @@ -256,6 +256,7 @@ ${KERNEL_SRC}/README ${KERNEL_CFG_ORG}: ${KERNELSRCTAR} cd ${KERNEL_SRC}; patch -p1 < ../981-2-PCI-Quirk-PCH-root-port-ACS-for-Sunrise-Point.patch cd ${KERNEL_SRC}; patch -p1 < ../kvm-dynamic-halt-polling-disable-default.patch cd ${KERNEL_SRC}; patch -p1 < ../ceph-scheduler-fix.patch + cd ${KERNEL_SRC}; patch -p1 < ../ie31200_edac-add-skylake-support.patch sed -i ${KERNEL_SRC}/Makefile -e 's/^EXTRAVERSION.*$$/EXTRAVERSION=${EXTRAVERSION}/' touch $@ diff --git a/changelog.Debian b/changelog.Debian index f60057b..0f38da8 100644 --- a/changelog.Debian +++ b/changelog.Debian @@ -1,3 +1,9 @@ +pve-kernel (4.4.15-61) unstable; urgency=medium + + * EDAC, ie31200_edac: Add Skylake support + + -- Proxmox Support Team Wed, 24 Aug 2016 06:57:21 +0200 + pve-kernel (4.4.15-60) unstable; urgency=medium * update to Ubuntu-4.4.0-33.52 diff --git a/ie31200_edac-add-skylake-support.patch b/ie31200_edac-add-skylake-support.patch new file mode 100644 index 0000000..2759a3a --- /dev/null +++ b/ie31200_edac-add-skylake-support.patch @@ -0,0 +1,298 @@ +From 953dee9bbd245f5515173126b9cc8b1a2c340797 Mon Sep 17 00:00:00 2001 +From: Jason Baron +Date: Fri, 6 May 2016 11:18:47 -0400 +Subject: EDAC, ie31200_edac: Add Skylake support + +Skylake adjusts some register locations, but otherwise follows the +existing model quite closely. I was able to verify that the 'ce_count' +increments when 'bad dimms' are used. The accounting of 'ce_count' and +'ue_count' is the primary functionality of interest for us. Tested on +Intel(R) Xeon(R) CPU E3-1260L v5 @ 2.90GHz. + +Signed-off-by: Jason Baron +Acked-by: Tony Luck +Cc: linux-edac +Link: http://lkml.kernel.org/r/1462547927-22679-1-git-send-email-jbaron@akamai.com +Signed-off-by: Borislav Petkov +--- + drivers/edac/ie31200_edac.c | 121 ++++++++++++++++++++++++++++++++------------ + 1 file changed, 90 insertions(+), 31 deletions(-) + +diff --git a/drivers/edac/ie31200_edac.c b/drivers/edac/ie31200_edac.c +index 18d77ac..1c88d97 100644 +--- a/drivers/edac/ie31200_edac.c ++++ b/drivers/edac/ie31200_edac.c +@@ -17,6 +17,7 @@ + * 015c: Xeon E3-1200 v2/3rd Gen Core processor DRAM Controller + * 0c04: Xeon E3-1200 v3/4th Gen Core Processor DRAM Controller + * 0c08: Xeon E3-1200 v3 Processor DRAM Controller ++ * 1918: Xeon E3-1200 v5 Skylake Host Bridge/DRAM Registers + * + * Based on Intel specification: + * http://www.intel.com/content/dam/www/public/us/en/documents/datasheets/xeon-e3-1200v3-vol-2-datasheet.pdf +@@ -55,6 +56,7 @@ + #define PCI_DEVICE_ID_INTEL_IE31200_HB_5 0x015c + #define PCI_DEVICE_ID_INTEL_IE31200_HB_6 0x0c04 + #define PCI_DEVICE_ID_INTEL_IE31200_HB_7 0x0c08 ++#define PCI_DEVICE_ID_INTEL_IE31200_HB_8 0x1918 + + #define IE31200_DIMMS 4 + #define IE31200_RANKS 8 +@@ -105,8 +107,11 @@ + * 1 Multiple Bit Error Status (MERRSTS) + * 0 Correctable Error Status (CERRSTS) + */ ++ + #define IE31200_C0ECCERRLOG 0x40c8 + #define IE31200_C1ECCERRLOG 0x44c8 ++#define IE31200_C0ECCERRLOG_SKL 0x4048 ++#define IE31200_C1ECCERRLOG_SKL 0x4448 + #define IE31200_ECCERRLOG_CE BIT(0) + #define IE31200_ECCERRLOG_UE BIT(1) + #define IE31200_ECCERRLOG_RANK_BITS GENMASK_ULL(28, 27) +@@ -123,17 +128,28 @@ + #define IE31200_CAPID0_DDPCD BIT(6) + #define IE31200_CAPID0_ECC BIT(1) + +-#define IE31200_MAD_DIMM_0_OFFSET 0x5004 +-#define IE31200_MAD_DIMM_SIZE GENMASK_ULL(7, 0) +-#define IE31200_MAD_DIMM_A_RANK BIT(17) +-#define IE31200_MAD_DIMM_A_WIDTH BIT(19) +- +-#define IE31200_PAGES(n) (n << (28 - PAGE_SHIFT)) ++#define IE31200_MAD_DIMM_0_OFFSET 0x5004 ++#define IE31200_MAD_DIMM_0_OFFSET_SKL 0x500C ++#define IE31200_MAD_DIMM_SIZE GENMASK_ULL(7, 0) ++#define IE31200_MAD_DIMM_A_RANK BIT(17) ++#define IE31200_MAD_DIMM_A_RANK_SHIFT 17 ++#define IE31200_MAD_DIMM_A_RANK_SKL BIT(10) ++#define IE31200_MAD_DIMM_A_RANK_SKL_SHIFT 10 ++#define IE31200_MAD_DIMM_A_WIDTH BIT(19) ++#define IE31200_MAD_DIMM_A_WIDTH_SHIFT 19 ++#define IE31200_MAD_DIMM_A_WIDTH_SKL GENMASK_ULL(9, 8) ++#define IE31200_MAD_DIMM_A_WIDTH_SKL_SHIFT 8 ++ ++/* Skylake reports 1GB increments, everything else is 256MB */ ++#define IE31200_PAGES(n, skl) \ ++ (n << (28 + (2 * skl) - PAGE_SHIFT)) + + static int nr_channels; + + struct ie31200_priv { + void __iomem *window; ++ void __iomem *c0errlog; ++ void __iomem *c1errlog; + }; + + enum ie31200_chips { +@@ -157,9 +173,9 @@ static const struct ie31200_dev_info ie31200_devs[] = { + }; + + struct dimm_data { +- u8 size; /* in 256MB multiples */ ++ u8 size; /* in multiples of 256MB, except Skylake is 1GB */ + u8 dual_rank : 1, +- x16_width : 1; /* 0 means x8 width */ ++ x16_width : 2; /* 0 means x8 width */ + }; + + static int how_many_channels(struct pci_dev *pdev) +@@ -197,11 +213,10 @@ static bool ecc_capable(struct pci_dev *pdev) + return true; + } + +-static int eccerrlog_row(int channel, u64 log) ++static int eccerrlog_row(u64 log) + { +- int rank = ((log & IE31200_ECCERRLOG_RANK_BITS) >> +- IE31200_ECCERRLOG_RANK_SHIFT); +- return rank | (channel * IE31200_RANKS_PER_CHANNEL); ++ return ((log & IE31200_ECCERRLOG_RANK_BITS) >> ++ IE31200_ECCERRLOG_RANK_SHIFT); + } + + static void ie31200_clear_error_info(struct mem_ctl_info *mci) +@@ -219,7 +234,6 @@ static void ie31200_get_and_clear_error_info(struct mem_ctl_info *mci, + { + struct pci_dev *pdev; + struct ie31200_priv *priv = mci->pvt_info; +- void __iomem *window = priv->window; + + pdev = to_pci_dev(mci->pdev); + +@@ -232,9 +246,9 @@ static void ie31200_get_and_clear_error_info(struct mem_ctl_info *mci, + if (!(info->errsts & IE31200_ERRSTS_BITS)) + return; + +- info->eccerrlog[0] = lo_hi_readq(window + IE31200_C0ECCERRLOG); ++ info->eccerrlog[0] = lo_hi_readq(priv->c0errlog); + if (nr_channels == 2) +- info->eccerrlog[1] = lo_hi_readq(window + IE31200_C1ECCERRLOG); ++ info->eccerrlog[1] = lo_hi_readq(priv->c1errlog); + + pci_read_config_word(pdev, IE31200_ERRSTS, &info->errsts2); + +@@ -245,10 +259,10 @@ static void ie31200_get_and_clear_error_info(struct mem_ctl_info *mci, + * should be UE info. + */ + if ((info->errsts ^ info->errsts2) & IE31200_ERRSTS_BITS) { +- info->eccerrlog[0] = lo_hi_readq(window + IE31200_C0ECCERRLOG); ++ info->eccerrlog[0] = lo_hi_readq(priv->c0errlog); + if (nr_channels == 2) + info->eccerrlog[1] = +- lo_hi_readq(window + IE31200_C1ECCERRLOG); ++ lo_hi_readq(priv->c1errlog); + } + + ie31200_clear_error_info(mci); +@@ -274,14 +288,14 @@ static void ie31200_process_error_info(struct mem_ctl_info *mci, + if (log & IE31200_ECCERRLOG_UE) { + edac_mc_handle_error(HW_EVENT_ERR_UNCORRECTED, mci, 1, + 0, 0, 0, +- eccerrlog_row(channel, log), ++ eccerrlog_row(log), + channel, -1, + "ie31200 UE", ""); + } else if (log & IE31200_ECCERRLOG_CE) { + edac_mc_handle_error(HW_EVENT_ERR_CORRECTED, mci, 1, + 0, 0, + IE31200_ECCERRLOG_SYNDROME(log), +- eccerrlog_row(channel, log), ++ eccerrlog_row(log), + channel, -1, + "ie31200 CE", ""); + } +@@ -326,6 +340,33 @@ static void __iomem *ie31200_map_mchbar(struct pci_dev *pdev) + return window; + } + ++static void __skl_populate_dimm_info(struct dimm_data *dd, u32 addr_decode, ++ int chan) ++{ ++ dd->size = (addr_decode >> (chan << 4)) & IE31200_MAD_DIMM_SIZE; ++ dd->dual_rank = (addr_decode & (IE31200_MAD_DIMM_A_RANK_SKL << (chan << 4))) ? 1 : 0; ++ dd->x16_width = ((addr_decode & (IE31200_MAD_DIMM_A_WIDTH_SKL << (chan << 4))) >> ++ (IE31200_MAD_DIMM_A_WIDTH_SKL_SHIFT + (chan << 4))); ++} ++ ++static void __populate_dimm_info(struct dimm_data *dd, u32 addr_decode, ++ int chan) ++{ ++ dd->size = (addr_decode >> (chan << 3)) & IE31200_MAD_DIMM_SIZE; ++ dd->dual_rank = (addr_decode & (IE31200_MAD_DIMM_A_RANK << chan)) ? 1 : 0; ++ dd->x16_width = (addr_decode & (IE31200_MAD_DIMM_A_WIDTH << chan)) ? 1 : 0; ++} ++ ++static void populate_dimm_info(struct dimm_data *dd, u32 addr_decode, int chan, ++ bool skl) ++{ ++ if (skl) ++ __skl_populate_dimm_info(dd, addr_decode, chan); ++ else ++ __populate_dimm_info(dd, addr_decode, chan); ++} ++ ++ + static int ie31200_probe1(struct pci_dev *pdev, int dev_idx) + { + int i, j, ret; +@@ -334,7 +375,8 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx) + struct dimm_data dimm_info[IE31200_CHANNELS][IE31200_DIMMS_PER_CHANNEL]; + void __iomem *window; + struct ie31200_priv *priv; +- u32 addr_decode; ++ u32 addr_decode, mad_offset; ++ bool skl = (pdev->device == PCI_DEVICE_ID_INTEL_IE31200_HB_8); + + edac_dbg(0, "MC:\n"); + +@@ -363,7 +405,10 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx) + + edac_dbg(3, "MC: init mci\n"); + mci->pdev = &pdev->dev; +- mci->mtype_cap = MEM_FLAG_DDR3; ++ if (skl) ++ mci->mtype_cap = MEM_FLAG_DDR4; ++ else ++ mci->mtype_cap = MEM_FLAG_DDR3; + mci->edac_ctl_cap = EDAC_FLAG_SECDED; + mci->edac_cap = EDAC_FLAG_SECDED; + mci->mod_name = EDAC_MOD_STR; +@@ -374,19 +419,24 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx) + mci->ctl_page_to_phys = NULL; + priv = mci->pvt_info; + priv->window = window; ++ if (skl) { ++ priv->c0errlog = window + IE31200_C0ECCERRLOG_SKL; ++ priv->c1errlog = window + IE31200_C1ECCERRLOG_SKL; ++ mad_offset = IE31200_MAD_DIMM_0_OFFSET_SKL; ++ } else { ++ priv->c0errlog = window + IE31200_C0ECCERRLOG; ++ priv->c1errlog = window + IE31200_C1ECCERRLOG; ++ mad_offset = IE31200_MAD_DIMM_0_OFFSET; ++ } + + /* populate DIMM info */ + for (i = 0; i < IE31200_CHANNELS; i++) { +- addr_decode = readl(window + IE31200_MAD_DIMM_0_OFFSET + ++ addr_decode = readl(window + mad_offset + + (i * 4)); + edac_dbg(0, "addr_decode: 0x%x\n", addr_decode); + for (j = 0; j < IE31200_DIMMS_PER_CHANNEL; j++) { +- dimm_info[i][j].size = (addr_decode >> (j * 8)) & +- IE31200_MAD_DIMM_SIZE; +- dimm_info[i][j].dual_rank = (addr_decode & +- (IE31200_MAD_DIMM_A_RANK << j)) ? 1 : 0; +- dimm_info[i][j].x16_width = (addr_decode & +- (IE31200_MAD_DIMM_A_WIDTH << j)) ? 1 : 0; ++ populate_dimm_info(&dimm_info[i][j], addr_decode, j, ++ skl); + edac_dbg(0, "size: 0x%x, rank: %d, width: %d\n", + dimm_info[i][j].size, + dimm_info[i][j].dual_rank, +@@ -405,7 +455,7 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx) + struct dimm_info *dimm; + unsigned long nr_pages; + +- nr_pages = IE31200_PAGES(dimm_info[j][i].size); ++ nr_pages = IE31200_PAGES(dimm_info[j][i].size, skl); + if (nr_pages == 0) + continue; + +@@ -417,7 +467,10 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx) + dimm->nr_pages = nr_pages; + edac_dbg(0, "set nr pages: 0x%lx\n", nr_pages); + dimm->grain = 8; /* just a guess */ +- dimm->mtype = MEM_DDR3; ++ if (skl) ++ dimm->mtype = MEM_DDR4; ++ else ++ dimm->mtype = MEM_DDR3; + dimm->dtype = DEV_UNKNOWN; + dimm->edac_mode = EDAC_UNKNOWN; + } +@@ -426,7 +479,10 @@ static int ie31200_probe1(struct pci_dev *pdev, int dev_idx) + dimm->nr_pages = nr_pages; + edac_dbg(0, "set nr pages: 0x%lx\n", nr_pages); + dimm->grain = 8; /* same guess */ +- dimm->mtype = MEM_DDR3; ++ if (skl) ++ dimm->mtype = MEM_DDR4; ++ else ++ dimm->mtype = MEM_DDR3; + dimm->dtype = DEV_UNKNOWN; + dimm->edac_mode = EDAC_UNKNOWN; + } +@@ -501,6 +557,9 @@ static const struct pci_device_id ie31200_pci_tbl[] = { + PCI_VEND_DEV(INTEL, IE31200_HB_7), PCI_ANY_ID, PCI_ANY_ID, 0, 0, + IE31200}, + { ++ PCI_VEND_DEV(INTEL, IE31200_HB_8), PCI_ANY_ID, PCI_ANY_ID, 0, 0, ++ IE31200}, ++ { + 0, + } /* 0 terminated list. */ + }; +-- +cgit v0.12 +