#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>
#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 */
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;
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;
}
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,
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,
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,
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,
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,
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,
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,
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,
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,
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);
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);
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;
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;