[PATCH 4/4] sb_edac: add Knights Landing (Xeon Phi gen 2) support

2015-12-03 Thread Hubert Chrzaniuk
From: Jim Snow 

Knights Landing is gen next architecture for HPC market.

KNL introduces concept of a tile and CHA - Cache/Home Agent for
memory accesses.

Some things are fixed in KNL:
() There's single DIMM slot per channel
() There's 2 memory controllers with 3 channels each, however,
   from EDAC standpoint, it is presented as single memory controller
   with 6 channels. In order to represent 2 MCs w/ 3 CH, it would
   require major redesign of EDAC core driver.

Basically, two functionalities are added/extended:
() during driver initialization KNL topology is being recognized, i.e.
   which channels are populated with what DIMM sizes
   (knl_get_dimm_capacity function)
() handle MCE errors - channel swizzling

Reviewed-by: Tony Luck 
Signed-off-by: Jim Snow 
[hubert.chrzan...@intel.com: patch rebase to 4.4-rc3]
Signed-off-by: Hubert Chrzaniuk 
---
 drivers/edac/sb_edac.c | 966 ++---
 1 file changed, 921 insertions(+), 45 deletions(-)

diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index c8fbde2..b3d924d 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -65,6 +65,14 @@ static const u32 ibridge_dram_rule[] = {
0xd8, 0xe0, 0xe8, 0xf0, 0xf8,
 };
 
+static const u32 knl_dram_rule[] = {
+   0x60, 0x68, 0x70, 0x78, 0x80, /* 0-4 */
+   0x88, 0x90, 0x98, 0xa0, 0xa8, /* 5-9 */
+   0xb0, 0xb8, 0xc0, 0xc8, 0xd0, /* 10-14 */
+   0xd8, 0xe0, 0xe8, 0xf0, 0xf8, /* 15-19 */
+   0x100, 0x108, 0x110, 0x118,   /* 20-23 */
+};
+
 #define DRAM_RULE_ENABLE(reg)  GET_BITFIELD(reg, 0,  0)
 #define A7MODE(reg)GET_BITFIELD(reg, 26, 26)
 
@@ -94,6 +102,14 @@ static const u32 ibridge_interleave_list[] = {
0xdc, 0xe4, 0xec, 0xf4, 0xfc,
 };
 
+static const u32 knl_interleave_list[] = {
+   0x64, 0x6c, 0x74, 0x7c, 0x84, /* 0-4 */
+   0x8c, 0x94, 0x9c, 0xa4, 0xac, /* 5-9 */
+   0xb4, 0xbc, 0xc4, 0xcc, 0xd4, /* 10-14 */
+   0xdc, 0xe4, 0xec, 0xf4, 0xfc, /* 15-19 */
+   0x104, 0x10c, 0x114, 0x11c,   /* 20-23 */
+};
+
 struct interleave_pkg {
unsigned char start;
unsigned char end;
@@ -131,10 +147,13 @@ static inline int sad_pkg(const struct interleave_pkg 
*table, u32 reg,
 /* Devices 12 Function 7 */
 
 #define TOLM   0x80
-#defineTOHM0x84
+#define TOHM   0x84
 #define HASWELL_TOLM   0xd0
 #define HASWELL_TOHM_0 0xd4
 #define HASWELL_TOHM_1 0xd8
+#define KNL_TOLM   0xd0
+#define KNL_TOHM_0 0xd4
+#define KNL_TOHM_1 0xd8
 
 #define GET_TOLM(reg)  ((GET_BITFIELD(reg, 0,  3) << 28) | 0x3ff)
 #define GET_TOHM(reg)  ((GET_BITFIELD(reg, 0, 20) << 25) | 0x3ff)
@@ -145,6 +164,8 @@ static inline int sad_pkg(const struct interleave_pkg 
*table, u32 reg,
 
 #define SOURCE_ID(reg) GET_BITFIELD(reg, 9, 11)
 
+#define SOURCE_ID_KNL(reg) GET_BITFIELD(reg, 12, 14)
+
 #define SAD_CONTROL0xf4
 
 /* Device 14 function 0 */
@@ -167,6 +188,7 @@ static const u32 tad_dram_rule[] = {
 /* Device 15, function 0 */
 
 #define MCMTR  0x7c
+#define KNL_MCMTR  0x624
 
 #define IS_ECC_ENABLED(mcmtr)  GET_BITFIELD(mcmtr, 2, 2)
 #define IS_LOCKSTEP_ENABLED(mcmtr) GET_BITFIELD(mcmtr, 1, 1)
@@ -183,6 +205,8 @@ static const int mtr_regs[] = {
0x80, 0x84, 0x88,
 };
 
+static const int knl_mtr_reg = 0xb60;
+
 #define RANK_DISABLE(mtr)  GET_BITFIELD(mtr, 16, 19)
 #define IS_DIMM_PRESENT(mtr)   GET_BITFIELD(mtr, 14, 14)
 #define RANK_CNT_BITS(mtr) GET_BITFIELD(mtr, 12, 13)
@@ -253,6 +277,9 @@ static const u32 correrrthrsld[] = {
 
 #define NUM_CHANNELS   8   /* 2MC per socket, four chan per MC */
 #define MAX_DIMMS  3   /* Max DIMMS per channel */
+#define KNL_MAX_CHAS   38  /* KNL max num. of Cache Home Agents */
+#define KNL_MAX_CHANNELS   6   /* KNL max num. of PCI channels */
+#define KNL_MAX_EDCS   8   /* Embedded DRAM controllers */
 #define CHANNEL_UNSPECIFIED0xf /* Intel IA32 SDM 15-14 */
 
 enum type {
@@ -260,6 +287,7 @@ enum type {
IVY_BRIDGE,
HASWELL,
BROADWELL,
+   KNIGHTS_LANDING,
 };
 
 struct sbridge_pvt;
@@ -309,6 +337,16 @@ struct sbridge_dev {
struct mem_ctl_info *mci;
 };
 
+struct knl_pvt {
+   struct pci_dev  *pci_cha[KNL_MAX_CHAS];
+   struct pci_dev  *pci_channel[KNL_MAX_CHANNELS];
+   struct pci_dev  *pci_mc0;
+   struct pci_dev  *pci_mc1;
+   struct pci_dev  *pci_mc0_misc;
+   struct pci_dev  *pci_mc1_misc;
+   struct pci_dev  *pci_mc_info; /* tolm, tohm */
+};
+
 struct sbridge_pvt {
struct pci_dev  *pci_ta, *pci_ddrio, *pci_ras;
struct pci_dev  *pci_sad0, *pci_sad1;
@@ -337,6 +375,7 @@ struct sbridge_pvt {
 
/* Memory description */
u64 tolm, tohm;
+   struct knl_pv

[PATCH 4/4] sb_edac: add Knights Landing (Xeon Phi gen 2) support

2015-12-02 Thread Hubert Chrzaniuk
From: Jim Snow 

Knights Landing is gen next architecture for HPC market.

KNL introduces concept of a tile and CHA - Cache/Home Agent for
memory accesses.

Some things are fixed in KNL:
() There's single DIMM slot per channel
() There's 2 memory controllers with 3 channels each, however,
   from EDAC standpoint, it is presented as single memory controller
   with 6 channels. In order to represent 2 MCs w/ 3 CH, it would
   require major redesign of EDAC core driver.

Basically, two functionalities are added/extended:
() during driver initialization KNL topology is being recognized, i.e.
   which channels are populated with what DIMM sizes
   (knl_get_dimm_capacity function)
() handle MCE errors - channel swizzling

Reviewed-by: Tony Luck 
Signed-off-by: Jim Snow 
Signed-off-by: Lukasz Anaczkowski 
Signed-off-by: Hubert Chrzaniuk 
---
 drivers/edac/sb_edac.c | 966 ++---
 1 file changed, 921 insertions(+), 45 deletions(-)

diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index c8fbde2..b3d924d 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -65,6 +65,14 @@ static const u32 ibridge_dram_rule[] = {
0xd8, 0xe0, 0xe8, 0xf0, 0xf8,
 };
 
+static const u32 knl_dram_rule[] = {
+   0x60, 0x68, 0x70, 0x78, 0x80, /* 0-4 */
+   0x88, 0x90, 0x98, 0xa0, 0xa8, /* 5-9 */
+   0xb0, 0xb8, 0xc0, 0xc8, 0xd0, /* 10-14 */
+   0xd8, 0xe0, 0xe8, 0xf0, 0xf8, /* 15-19 */
+   0x100, 0x108, 0x110, 0x118,   /* 20-23 */
+};
+
 #define DRAM_RULE_ENABLE(reg)  GET_BITFIELD(reg, 0,  0)
 #define A7MODE(reg)GET_BITFIELD(reg, 26, 26)
 
@@ -94,6 +102,14 @@ static const u32 ibridge_interleave_list[] = {
0xdc, 0xe4, 0xec, 0xf4, 0xfc,
 };
 
+static const u32 knl_interleave_list[] = {
+   0x64, 0x6c, 0x74, 0x7c, 0x84, /* 0-4 */
+   0x8c, 0x94, 0x9c, 0xa4, 0xac, /* 5-9 */
+   0xb4, 0xbc, 0xc4, 0xcc, 0xd4, /* 10-14 */
+   0xdc, 0xe4, 0xec, 0xf4, 0xfc, /* 15-19 */
+   0x104, 0x10c, 0x114, 0x11c,   /* 20-23 */
+};
+
 struct interleave_pkg {
unsigned char start;
unsigned char end;
@@ -131,10 +147,13 @@ static inline int sad_pkg(const struct interleave_pkg 
*table, u32 reg,
 /* Devices 12 Function 7 */
 
 #define TOLM   0x80
-#defineTOHM0x84
+#define TOHM   0x84
 #define HASWELL_TOLM   0xd0
 #define HASWELL_TOHM_0 0xd4
 #define HASWELL_TOHM_1 0xd8
+#define KNL_TOLM   0xd0
+#define KNL_TOHM_0 0xd4
+#define KNL_TOHM_1 0xd8
 
 #define GET_TOLM(reg)  ((GET_BITFIELD(reg, 0,  3) << 28) | 0x3ff)
 #define GET_TOHM(reg)  ((GET_BITFIELD(reg, 0, 20) << 25) | 0x3ff)
@@ -145,6 +164,8 @@ static inline int sad_pkg(const struct interleave_pkg 
*table, u32 reg,
 
 #define SOURCE_ID(reg) GET_BITFIELD(reg, 9, 11)
 
+#define SOURCE_ID_KNL(reg) GET_BITFIELD(reg, 12, 14)
+
 #define SAD_CONTROL0xf4
 
 /* Device 14 function 0 */
@@ -167,6 +188,7 @@ static const u32 tad_dram_rule[] = {
 /* Device 15, function 0 */
 
 #define MCMTR  0x7c
+#define KNL_MCMTR  0x624
 
 #define IS_ECC_ENABLED(mcmtr)  GET_BITFIELD(mcmtr, 2, 2)
 #define IS_LOCKSTEP_ENABLED(mcmtr) GET_BITFIELD(mcmtr, 1, 1)
@@ -183,6 +205,8 @@ static const int mtr_regs[] = {
0x80, 0x84, 0x88,
 };
 
+static const int knl_mtr_reg = 0xb60;
+
 #define RANK_DISABLE(mtr)  GET_BITFIELD(mtr, 16, 19)
 #define IS_DIMM_PRESENT(mtr)   GET_BITFIELD(mtr, 14, 14)
 #define RANK_CNT_BITS(mtr) GET_BITFIELD(mtr, 12, 13)
@@ -253,6 +277,9 @@ static const u32 correrrthrsld[] = {
 
 #define NUM_CHANNELS   8   /* 2MC per socket, four chan per MC */
 #define MAX_DIMMS  3   /* Max DIMMS per channel */
+#define KNL_MAX_CHAS   38  /* KNL max num. of Cache Home Agents */
+#define KNL_MAX_CHANNELS   6   /* KNL max num. of PCI channels */
+#define KNL_MAX_EDCS   8   /* Embedded DRAM controllers */
 #define CHANNEL_UNSPECIFIED0xf /* Intel IA32 SDM 15-14 */
 
 enum type {
@@ -260,6 +287,7 @@ enum type {
IVY_BRIDGE,
HASWELL,
BROADWELL,
+   KNIGHTS_LANDING,
 };
 
 struct sbridge_pvt;
@@ -309,6 +337,16 @@ struct sbridge_dev {
struct mem_ctl_info *mci;
 };
 
+struct knl_pvt {
+   struct pci_dev  *pci_cha[KNL_MAX_CHAS];
+   struct pci_dev  *pci_channel[KNL_MAX_CHANNELS];
+   struct pci_dev  *pci_mc0;
+   struct pci_dev  *pci_mc1;
+   struct pci_dev  *pci_mc0_misc;
+   struct pci_dev  *pci_mc1_misc;
+   struct pci_dev  *pci_mc_info; /* tolm, tohm */
+};
+
 struct sbridge_pvt {
struct pci_dev  *pci_ta, *pci_ddrio, *pci_ras;
struct pci_dev  *pci_sad0, *pci_sad1;
@@ -337,6 +375,7 @@ struct sbridge_pvt {
 
/* Memory description */
u64 tolm, tohm;
+   struct knl_pvt knl;
 };
 
 #defi

[PATCH 4/4] sb_edac: add Knights Landing (Xeon Phi gen 2) support

2015-11-30 Thread Chrzaniuk, Hubert
Knights Landing is gen next architecture for HPC market.

KNL introduces concept of a tile and CHA - Cache/Home Agent for
memory accesses.

Some things are fixed in KNL:
() There's single DIMM slot per channel
() There's 2 memory controllers with 3 channels each, however,
   from EDAC standpoint, it is presented as single memory controller
   with 6 channels. In order to represent 2 MCs w/ 3 CH, it would
   require major redesign of EDAC core driver.

Basically, two functionalities are added/extended:
() during driver initialization KNL topology is being recognized, i.e.
   which channels are populated with what DIMM sizes
   (knl_get_dimm_capacity function)
() handle MCE errors - channel swizzling

Reviewed-by: Tony Luck 
Signed-off-by: Jim Snow 
Signed-off-by: Lukasz Anaczkowski 
Signed-off-by: Hubert Chrzaniuk 
---
 drivers/edac/sb_edac.c | 966 ++---
 1 file changed, 921 insertions(+), 45 deletions(-)

diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index c8fbde2..b3d924d 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -65,6 +65,14 @@ static const u32 ibridge_dram_rule[] = {
0xd8, 0xe0, 0xe8, 0xf0, 0xf8,
 };
 
+static const u32 knl_dram_rule[] = {
+   0x60, 0x68, 0x70, 0x78, 0x80, /* 0-4 */
+   0x88, 0x90, 0x98, 0xa0, 0xa8, /* 5-9 */
+   0xb0, 0xb8, 0xc0, 0xc8, 0xd0, /* 10-14 */
+   0xd8, 0xe0, 0xe8, 0xf0, 0xf8, /* 15-19 */
+   0x100, 0x108, 0x110, 0x118,   /* 20-23 */
+};
+
 #define DRAM_RULE_ENABLE(reg)  GET_BITFIELD(reg, 0,  0)
 #define A7MODE(reg)GET_BITFIELD(reg, 26, 26)
 
@@ -94,6 +102,14 @@ static const u32 ibridge_interleave_list[] = {
0xdc, 0xe4, 0xec, 0xf4, 0xfc,
 };
 
+static const u32 knl_interleave_list[] = {
+   0x64, 0x6c, 0x74, 0x7c, 0x84, /* 0-4 */
+   0x8c, 0x94, 0x9c, 0xa4, 0xac, /* 5-9 */
+   0xb4, 0xbc, 0xc4, 0xcc, 0xd4, /* 10-14 */
+   0xdc, 0xe4, 0xec, 0xf4, 0xfc, /* 15-19 */
+   0x104, 0x10c, 0x114, 0x11c,   /* 20-23 */
+};
+
 struct interleave_pkg {
unsigned char start;
unsigned char end;
@@ -131,10 +147,13 @@ static inline int sad_pkg(const struct interleave_pkg 
*table, u32 reg,
 /* Devices 12 Function 7 */
 
 #define TOLM   0x80
-#defineTOHM0x84
+#define TOHM   0x84
 #define HASWELL_TOLM   0xd0
 #define HASWELL_TOHM_0 0xd4
 #define HASWELL_TOHM_1 0xd8
+#define KNL_TOLM   0xd0
+#define KNL_TOHM_0 0xd4
+#define KNL_TOHM_1 0xd8
 
 #define GET_TOLM(reg)  ((GET_BITFIELD(reg, 0,  3) << 28) | 0x3ff)
 #define GET_TOHM(reg)  ((GET_BITFIELD(reg, 0, 20) << 25) | 0x3ff)
@@ -145,6 +164,8 @@ static inline int sad_pkg(const struct interleave_pkg 
*table, u32 reg,
 
 #define SOURCE_ID(reg) GET_BITFIELD(reg, 9, 11)
 
+#define SOURCE_ID_KNL(reg) GET_BITFIELD(reg, 12, 14)
+
 #define SAD_CONTROL0xf4
 
 /* Device 14 function 0 */
@@ -167,6 +188,7 @@ static const u32 tad_dram_rule[] = {
 /* Device 15, function 0 */
 
 #define MCMTR  0x7c
+#define KNL_MCMTR  0x624
 
 #define IS_ECC_ENABLED(mcmtr)  GET_BITFIELD(mcmtr, 2, 2)
 #define IS_LOCKSTEP_ENABLED(mcmtr) GET_BITFIELD(mcmtr, 1, 1)
@@ -183,6 +205,8 @@ static const int mtr_regs[] = {
0x80, 0x84, 0x88,
 };
 
+static const int knl_mtr_reg = 0xb60;
+
 #define RANK_DISABLE(mtr)  GET_BITFIELD(mtr, 16, 19)
 #define IS_DIMM_PRESENT(mtr)   GET_BITFIELD(mtr, 14, 14)
 #define RANK_CNT_BITS(mtr) GET_BITFIELD(mtr, 12, 13)
@@ -253,6 +277,9 @@ static const u32 correrrthrsld[] = {
 
 #define NUM_CHANNELS   8   /* 2MC per socket, four chan per MC */
 #define MAX_DIMMS  3   /* Max DIMMS per channel */
+#define KNL_MAX_CHAS   38  /* KNL max num. of Cache Home Agents */
+#define KNL_MAX_CHANNELS   6   /* KNL max num. of PCI channels */
+#define KNL_MAX_EDCS   8   /* Embedded DRAM controllers */
 #define CHANNEL_UNSPECIFIED0xf /* Intel IA32 SDM 15-14 */
 
 enum type {
@@ -260,6 +287,7 @@ enum type {
IVY_BRIDGE,
HASWELL,
BROADWELL,
+   KNIGHTS_LANDING,
 };
 
 struct sbridge_pvt;
@@ -309,6 +337,16 @@ struct sbridge_dev {
struct mem_ctl_info *mci;
 };
 
+struct knl_pvt {
+   struct pci_dev  *pci_cha[KNL_MAX_CHAS];
+   struct pci_dev  *pci_channel[KNL_MAX_CHANNELS];
+   struct pci_dev  *pci_mc0;
+   struct pci_dev  *pci_mc1;
+   struct pci_dev  *pci_mc0_misc;
+   struct pci_dev  *pci_mc1_misc;
+   struct pci_dev  *pci_mc_info; /* tolm, tohm */
+};
+
 struct sbridge_pvt {
struct pci_dev  *pci_ta, *pci_ddrio, *pci_ras;
struct pci_dev  *pci_sad0, *pci_sad1;
@@ -337,6 +375,7 @@ struct sbridge_pvt {
 
/* Memory description */
u64 tolm, tohm;
+   struct knl_pvt knl;
 };
 
 #define PCI_DESCR(devi