summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/edac/igen6_edac.c65
1 files changed, 53 insertions, 12 deletions
diff --git a/drivers/edac/igen6_edac.c b/drivers/edac/igen6_edac.c
index d29cfc7fad93..717862dc4765 100644
--- a/drivers/edac/igen6_edac.c
+++ b/drivers/edac/igen6_edac.c
@@ -19,6 +19,7 @@
#include <linux/genalloc.h>
#include <linux/edac.h>
#include <linux/bits.h>
+#include <linux/bitfield.h>
#include <linux/io.h>
#include <asm/mach_traps.h>
#include <asm/nmi.h>
@@ -79,15 +80,11 @@
#define ECC_ERROR_LOG_OFFSET (IBECC_BASE + res_cfg->ibecc_error_log_offset)
#define ECC_ERROR_LOG_CE BIT_ULL(62)
#define ECC_ERROR_LOG_UE BIT_ULL(63)
-#define ECC_ERROR_LOG_ADDR_SHIFT 5
-#define ECC_ERROR_LOG_ADDR(v) GET_BITFIELD(v, 5, 38)
-#define ECC_ERROR_LOG_ADDR45(v) GET_BITFIELD(v, 5, 45)
#define ECC_ERROR_LOG_SYND(v) GET_BITFIELD(v, 46, 61)
/* Host MMIO base address */
#define MCHBAR_OFFSET 0x48
#define MCHBAR_EN BIT_ULL(0)
-#define MCHBAR_BASE(v) (GET_BITFIELD(v, 16, 38) << 16)
#define MCHBAR_SIZE 0x10000
/* Parameters for the channel decode stage */
@@ -129,6 +126,14 @@ static struct res_config {
bool machine_check;
/* The number of present memory controllers. */
int num_imc;
+ /* Host MMIO configuration */
+ u64 reg_mchbar_mask;
+ /* Top of memory */
+ u64 reg_tom_mask;
+ /* Top of upper usable DRAM */
+ u64 reg_touud_mask;
+ /* IBECC error log */
+ u64 reg_eccerrlog_addr_mask;
u32 imc_base;
u32 cmf_base;
u32 cmf_size;
@@ -305,7 +310,8 @@ static int get_mchbar(struct pci_dev *pdev, u64 *mchbar)
return -ENODEV;
}
- *mchbar = MCHBAR_BASE(u.v);
+ *mchbar = u.v & res_cfg->reg_mchbar_mask;
+ edac_dbg(2, "MCHBAR 0x%llx (reg 0x%llx)\n", *mchbar, u.v);
return 0;
}
@@ -481,11 +487,15 @@ static u64 adl_err_addr_to_imc_addr(u64 eaddr, int mc)
static u64 rpl_p_err_addr(u64 ecclog)
{
- return ECC_ERROR_LOG_ADDR45(ecclog);
+ return field_get(res_cfg->reg_eccerrlog_addr_mask, ecclog);
}
static struct res_config ehl_cfg = {
.num_imc = 1,
+ .reg_mchbar_mask = GENMASK_ULL(38, 16),
+ .reg_tom_mask = GENMASK_ULL(38, 20),
+ .reg_touud_mask = GENMASK_ULL(38, 20),
+ .reg_eccerrlog_addr_mask = GENMASK_ULL(38, 5),
.imc_base = 0x5000,
.ibecc_base = 0xdc00,
.ibecc_available = ehl_ibecc_available,
@@ -496,6 +506,10 @@ static struct res_config ehl_cfg = {
static struct res_config icl_cfg = {
.num_imc = 1,
+ .reg_mchbar_mask = GENMASK_ULL(38, 16),
+ .reg_tom_mask = GENMASK_ULL(38, 20),
+ .reg_touud_mask = GENMASK_ULL(38, 20),
+ .reg_eccerrlog_addr_mask = GENMASK_ULL(38, 5),
.imc_base = 0x5000,
.ibecc_base = 0xd800,
.ibecc_error_log_offset = 0x170,
@@ -507,6 +521,10 @@ static struct res_config icl_cfg = {
static struct res_config tgl_cfg = {
.machine_check = true,
.num_imc = 2,
+ .reg_mchbar_mask = GENMASK_ULL(38, 17),
+ .reg_tom_mask = GENMASK_ULL(38, 20),
+ .reg_touud_mask = GENMASK_ULL(38, 20),
+ .reg_eccerrlog_addr_mask = GENMASK_ULL(38, 5),
.imc_base = 0x5000,
.cmf_base = 0x11000,
.cmf_size = 0x800,
@@ -521,6 +539,10 @@ static struct res_config tgl_cfg = {
static struct res_config adl_cfg = {
.machine_check = true,
.num_imc = 2,
+ .reg_mchbar_mask = GENMASK_ULL(41, 17),
+ .reg_tom_mask = GENMASK_ULL(41, 20),
+ .reg_touud_mask = GENMASK_ULL(41, 20),
+ .reg_eccerrlog_addr_mask = GENMASK_ULL(45, 5),
.imc_base = 0xd800,
.ibecc_base = 0xd400,
.ibecc_error_log_offset = 0x68,
@@ -532,6 +554,10 @@ static struct res_config adl_cfg = {
static struct res_config adl_n_cfg = {
.machine_check = true,
.num_imc = 1,
+ .reg_mchbar_mask = GENMASK_ULL(41, 17),
+ .reg_tom_mask = GENMASK_ULL(41, 20),
+ .reg_touud_mask = GENMASK_ULL(41, 20),
+ .reg_eccerrlog_addr_mask = GENMASK_ULL(45, 5),
.imc_base = 0xd800,
.ibecc_base = 0xd400,
.ibecc_error_log_offset = 0x68,
@@ -543,6 +569,10 @@ static struct res_config adl_n_cfg = {
static struct res_config rpl_p_cfg = {
.machine_check = true,
.num_imc = 2,
+ .reg_mchbar_mask = GENMASK_ULL(41, 17),
+ .reg_tom_mask = GENMASK_ULL(41, 20),
+ .reg_touud_mask = GENMASK_ULL(41, 20),
+ .reg_eccerrlog_addr_mask = GENMASK_ULL(45, 5),
.imc_base = 0xd800,
.ibecc_base = 0xd400,
.ibecc_error_log_offset = 0x68,
@@ -555,6 +585,10 @@ static struct res_config rpl_p_cfg = {
static struct res_config mtl_ps_cfg = {
.machine_check = true,
.num_imc = 2,
+ .reg_mchbar_mask = GENMASK_ULL(41, 17),
+ .reg_tom_mask = GENMASK_ULL(41, 20),
+ .reg_touud_mask = GENMASK_ULL(41, 20),
+ .reg_eccerrlog_addr_mask = GENMASK_ULL(38, 5),
.imc_base = 0xd800,
.ibecc_base = 0xd400,
.ibecc_error_log_offset = 0x170,
@@ -566,6 +600,10 @@ static struct res_config mtl_ps_cfg = {
static struct res_config mtl_p_cfg = {
.machine_check = true,
.num_imc = 2,
+ .reg_mchbar_mask = GENMASK_ULL(41, 17),
+ .reg_tom_mask = GENMASK_ULL(41, 20),
+ .reg_touud_mask = GENMASK_ULL(41, 20),
+ .reg_eccerrlog_addr_mask = GENMASK_ULL(38, 5),
.imc_base = 0xd800,
.ibecc_base = 0xd400,
.ibecc_error_log_offset = 0x170,
@@ -577,6 +615,10 @@ static struct res_config mtl_p_cfg = {
static struct res_config wcl_cfg = {
.machine_check = true,
.num_imc = 1,
+ .reg_mchbar_mask = GENMASK_ULL(41, 17),
+ .reg_tom_mask = GENMASK_ULL(41, 20),
+ .reg_touud_mask = GENMASK_ULL(41, 20),
+ .reg_eccerrlog_addr_mask = GENMASK_ULL(38, 5),
.imc_base = 0xd800,
.ibecc_base = 0xd400,
.ibecc_error_log_offset = 0x170,
@@ -908,8 +950,8 @@ static void ecclog_work_cb(struct work_struct *work)
if (res_cfg->err_addr)
eaddr = res_cfg->err_addr(node->ecclog);
else
- eaddr = ECC_ERROR_LOG_ADDR(node->ecclog) <<
- ECC_ERROR_LOG_ADDR_SHIFT;
+ eaddr = node->ecclog & res_cfg->reg_eccerrlog_addr_mask;
+
res.mc = node->mc;
res.sys_addr = res_cfg->err_addr_to_sys_addr(eaddr, res.mc);
res.imc_addr = res_cfg->err_addr_to_imc_addr(eaddr, res.mc);
@@ -1129,8 +1171,7 @@ static int debugfs_u64_set(void *data, u64 val)
pr_warn_once("Fake error to 0x%llx injected via debugfs\n", val);
- val >>= ECC_ERROR_LOG_ADDR_SHIFT;
- ecclog = (val << ECC_ERROR_LOG_ADDR_SHIFT) | ECC_ERROR_LOG_CE;
+ ecclog = (val & res_cfg->reg_eccerrlog_addr_mask) | ECC_ERROR_LOG_CE;
if (!ecclog_gen_pool_add(0, ecclog))
irq_work_queue(&ecclog_irq_work);
@@ -1196,7 +1237,7 @@ static int igen6_pci_setup(struct pci_dev *pdev, u64 *mchbar)
goto fail;
}
- igen6_tom = u.v & GENMASK_ULL(38, 20);
+ igen6_tom = u.v & res_cfg->reg_tom_mask;
if (get_mchbar(pdev, mchbar))
goto fail;
@@ -1207,7 +1248,7 @@ static int igen6_pci_setup(struct pci_dev *pdev, u64 *mchbar)
else if (pci_read_config_dword(pdev, TOUUD_OFFSET + 4, &u.v_hi))
edac_dbg(2, "Failed to read upper TOUUD\n");
else
- igen6_touud = u.v & GENMASK_ULL(38, 20);
+ igen6_touud = u.v & res_cfg->reg_touud_mask;
#endif
return 0;