diff options
| -rw-r--r-- | drivers/edac/igen6_edac.c | 65 |
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; |
