]> git.proxmox.com Git - pve-kernel-jessie.git/commitdiff
EDAC, ie31200_edac: Add Skylake support
authorDietmar Maurer <dietmar@proxmox.com>
Wed, 24 Aug 2016 04:57:54 +0000 (06:57 +0200)
committerDietmar Maurer <dietmar@proxmox.com>
Wed, 24 Aug 2016 04:57:54 +0000 (06:57 +0200)
Makefile
changelog.Debian
ie31200_edac-add-skylake-support.patch [new file with mode: 0644]

index 69fb6f23a8613d565d955e060f10c6dab6feac20..05c87f5dfc23329519caa7bd59340bc6cf23f978 100644 (file)
--- 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 $@
 
index f60057b36064e33686aaa4e62636fd2fde40e409..0f38da8bec91f76f1aeb2a3b759bcfd4289207dc 100644 (file)
@@ -1,3 +1,9 @@
+pve-kernel (4.4.15-61) unstable; urgency=medium
+
+  * EDAC, ie31200_edac: Add Skylake support
+
+ -- Proxmox Support Team <support@proxmox.com>  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 (file)
index 0000000..2759a3a
--- /dev/null
@@ -0,0 +1,298 @@
+From 953dee9bbd245f5515173126b9cc8b1a2c340797 Mon Sep 17 00:00:00 2001
+From: Jason Baron <jbaron@akamai.com>
+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 <jbaron@akamai.com>
+Acked-by: Tony Luck <tony.luck@intel.com>
+Cc: linux-edac <linux-edac@vger.kernel.org>
+Link: http://lkml.kernel.org/r/1462547927-22679-1-git-send-email-jbaron@akamai.com
+Signed-off-by: Borislav Petkov <bp@suse.de>
+---
+ 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
+