sb_edac: make memory type detection per memory controller
Haswell has different register, offset to determine memory type and supports
DDR4 in some models. This patch makes it easier to have a different method
depending on the memory controller type.
Cc: Tony Luck <tony.luck@intel.com>
Signed-off-by: Aristeu Rozanski <aris@redhat.com>
Signed-off-by: Mauro Carvalho Chehab <m.chehab@samsung.com>
diff --git a/drivers/edac/sb_edac.c b/drivers/edac/sb_edac.c
index deea0dc..44336cb 100644
--- a/drivers/edac/sb_edac.c
+++ b/drivers/edac/sb_edac.c
@@ -279,8 +279,6 @@
#define IB_RANK_CFG_A 0x0320
-#define IS_RDIMM_ENABLED(reg) GET_BITFIELD(reg, 11, 11)
-
/*
* sbridge structs
*/
@@ -305,6 +303,7 @@
const struct interleave_pkg *interleave_pkg;
u8 max_sad;
u8 max_interleave;
+ enum mem_type (*get_memory_type)(struct sbridge_pvt *pvt);
};
struct sbridge_channel {
@@ -588,6 +587,25 @@
return GET_TOHM(reg);
}
+static enum mem_type get_memory_type(struct sbridge_pvt *pvt)
+{
+ u32 reg;
+ enum mem_type mtype;
+
+ if (pvt->pci_ddrio) {
+ pci_read_config_dword(pvt->pci_ddrio, pvt->info.rankcfgr,
+ ®);
+ if (GET_BITFIELD(reg, 11, 11))
+ /* FIXME: Can also be LRDIMM */
+ mtype = MEM_RDDR3;
+ else
+ mtype = MEM_DDR3;
+ } else
+ mtype = MEM_UNKNOWN;
+
+ return mtype;
+}
+
static inline u8 sad_pkg_socket(u8 pkg)
{
/* on Ivy Bridge, nodeID is SASS, where A is HA and S is node id */
@@ -698,21 +716,13 @@
pvt->is_close_pg = false;
}
- if (pvt->pci_ddrio) {
- pci_read_config_dword(pvt->pci_ddrio, pvt->info.rankcfgr,
- ®);
- if (IS_RDIMM_ENABLED(reg)) {
- /* FIXME: Can also be LRDIMM */
- edac_dbg(0, "Memory is registered\n");
- mtype = MEM_RDDR3;
- } else {
- edac_dbg(0, "Memory is unregistered\n");
- mtype = MEM_DDR3;
- }
- } else {
+ mtype = pvt->info.get_memory_type(pvt);
+ if (mtype == MEM_RDDR3)
+ edac_dbg(0, "Memory is registered\n");
+ else if (mtype == MEM_UNKNOWN)
edac_dbg(0, "Cannot determine memory type\n");
- mtype = MEM_UNKNOWN;
- }
+ else
+ edac_dbg(0, "Memory is unregistered\n");
/* On all supported DDR3 DIMM types, there are 8 banks available */
banks = 8;
@@ -1976,6 +1986,7 @@
pvt->info.get_tolm = ibridge_get_tolm;
pvt->info.get_tohm = ibridge_get_tohm;
pvt->info.dram_rule = ibridge_dram_rule;
+ pvt->info.get_memory_type = get_memory_type;
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);
@@ -1991,6 +2002,7 @@
pvt->info.get_tolm = sbridge_get_tolm;
pvt->info.get_tohm = sbridge_get_tohm;
pvt->info.dram_rule = sbridge_dram_rule;
+ pvt->info.get_memory_type = get_memory_type;
pvt->info.max_sad = ARRAY_SIZE(sbridge_dram_rule);
pvt->info.interleave_list = sbridge_interleave_list;
pvt->info.max_interleave = ARRAY_SIZE(sbridge_interleave_list);