Skip to content

Commit 4b72090

Browse files
qzhuo2aegl
authored andcommitted
EDAC/igen6: Make masks of {MCHBAR, TOM, TOUUD, ECC_ERROR_LOG} configurable
The masks used to retrieve base addresses from {MCHBAR, TOM, TOUUD, ECC_ERROR_LOG} registers can be CPU model-specific. Currently, igen6_edac hard-codes these masks with the most significant bit at 38, while some CPUs have extended the most significant bit to bit 41 or bit 45. Systems with more than 512GB (2^39) memory need this extension to get correct masks. But all CPUs currently supported by igen6_edac support max memory less than 512GB (e.g., max memory size for Raptor Lake systems is 192GB, for Alder Lake systems is 128GB, ...), which means the previous hard-coded most significant bit 38 still works properly. So backporting this patch to stable kernels is not necessary. To make these masks reflect the CPUs' real support and easily support future Intel client CPUs supported by igen6_edac that have more than 512GB memory, add four new fields to structure res_config to make these masks CPU model-specific and configure them properly. Signed-off-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com> Signed-off-by: Tony Luck <tony.luck@intel.com> Tested-by: Jianfeng Gao <jianfeng.gao@intel.com> Link: https://patch.msgid.link/20251219042956.3232568-3-qiuxu.zhuo@intel.com
1 parent 41ca215 commit 4b72090

1 file changed

Lines changed: 53 additions & 12 deletions

File tree

drivers/edac/igen6_edac.c

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include <linux/genalloc.h>
2020
#include <linux/edac.h>
2121
#include <linux/bits.h>
22+
#include <linux/bitfield.h>
2223
#include <linux/io.h>
2324
#include <asm/mach_traps.h>
2425
#include <asm/nmi.h>
@@ -79,15 +80,11 @@
7980
#define ECC_ERROR_LOG_OFFSET (IBECC_BASE + res_cfg->ibecc_error_log_offset)
8081
#define ECC_ERROR_LOG_CE BIT_ULL(62)
8182
#define ECC_ERROR_LOG_UE BIT_ULL(63)
82-
#define ECC_ERROR_LOG_ADDR_SHIFT 5
83-
#define ECC_ERROR_LOG_ADDR(v) GET_BITFIELD(v, 5, 38)
84-
#define ECC_ERROR_LOG_ADDR45(v) GET_BITFIELD(v, 5, 45)
8583
#define ECC_ERROR_LOG_SYND(v) GET_BITFIELD(v, 46, 61)
8684

8785
/* Host MMIO base address */
8886
#define MCHBAR_OFFSET 0x48
8987
#define MCHBAR_EN BIT_ULL(0)
90-
#define MCHBAR_BASE(v) (GET_BITFIELD(v, 16, 38) << 16)
9188
#define MCHBAR_SIZE 0x10000
9289

9390
/* Parameters for the channel decode stage */
@@ -129,6 +126,14 @@ static struct res_config {
129126
bool machine_check;
130127
/* The number of present memory controllers. */
131128
int num_imc;
129+
/* Host MMIO configuration */
130+
u64 reg_mchbar_mask;
131+
/* Top of memory */
132+
u64 reg_tom_mask;
133+
/* Top of upper usable DRAM */
134+
u64 reg_touud_mask;
135+
/* IBECC error log */
136+
u64 reg_eccerrlog_addr_mask;
132137
u32 imc_base;
133138
u32 cmf_base;
134139
u32 cmf_size;
@@ -305,7 +310,8 @@ static int get_mchbar(struct pci_dev *pdev, u64 *mchbar)
305310
return -ENODEV;
306311
}
307312

308-
*mchbar = MCHBAR_BASE(u.v);
313+
*mchbar = u.v & res_cfg->reg_mchbar_mask;
314+
edac_dbg(2, "MCHBAR 0x%llx (reg 0x%llx)\n", *mchbar, u.v);
309315

310316
return 0;
311317
}
@@ -481,11 +487,15 @@ static u64 adl_err_addr_to_imc_addr(u64 eaddr, int mc)
481487

482488
static u64 rpl_p_err_addr(u64 ecclog)
483489
{
484-
return ECC_ERROR_LOG_ADDR45(ecclog);
490+
return field_get(res_cfg->reg_eccerrlog_addr_mask, ecclog);
485491
}
486492

487493
static struct res_config ehl_cfg = {
488494
.num_imc = 1,
495+
.reg_mchbar_mask = GENMASK_ULL(38, 16),
496+
.reg_tom_mask = GENMASK_ULL(38, 20),
497+
.reg_touud_mask = GENMASK_ULL(38, 20),
498+
.reg_eccerrlog_addr_mask = GENMASK_ULL(38, 5),
489499
.imc_base = 0x5000,
490500
.ibecc_base = 0xdc00,
491501
.ibecc_available = ehl_ibecc_available,
@@ -496,6 +506,10 @@ static struct res_config ehl_cfg = {
496506

497507
static struct res_config icl_cfg = {
498508
.num_imc = 1,
509+
.reg_mchbar_mask = GENMASK_ULL(38, 16),
510+
.reg_tom_mask = GENMASK_ULL(38, 20),
511+
.reg_touud_mask = GENMASK_ULL(38, 20),
512+
.reg_eccerrlog_addr_mask = GENMASK_ULL(38, 5),
499513
.imc_base = 0x5000,
500514
.ibecc_base = 0xd800,
501515
.ibecc_error_log_offset = 0x170,
@@ -507,6 +521,10 @@ static struct res_config icl_cfg = {
507521
static struct res_config tgl_cfg = {
508522
.machine_check = true,
509523
.num_imc = 2,
524+
.reg_mchbar_mask = GENMASK_ULL(38, 17),
525+
.reg_tom_mask = GENMASK_ULL(38, 20),
526+
.reg_touud_mask = GENMASK_ULL(38, 20),
527+
.reg_eccerrlog_addr_mask = GENMASK_ULL(38, 5),
510528
.imc_base = 0x5000,
511529
.cmf_base = 0x11000,
512530
.cmf_size = 0x800,
@@ -521,6 +539,10 @@ static struct res_config tgl_cfg = {
521539
static struct res_config adl_cfg = {
522540
.machine_check = true,
523541
.num_imc = 2,
542+
.reg_mchbar_mask = GENMASK_ULL(41, 17),
543+
.reg_tom_mask = GENMASK_ULL(41, 20),
544+
.reg_touud_mask = GENMASK_ULL(41, 20),
545+
.reg_eccerrlog_addr_mask = GENMASK_ULL(45, 5),
524546
.imc_base = 0xd800,
525547
.ibecc_base = 0xd400,
526548
.ibecc_error_log_offset = 0x68,
@@ -532,6 +554,10 @@ static struct res_config adl_cfg = {
532554
static struct res_config adl_n_cfg = {
533555
.machine_check = true,
534556
.num_imc = 1,
557+
.reg_mchbar_mask = GENMASK_ULL(41, 17),
558+
.reg_tom_mask = GENMASK_ULL(41, 20),
559+
.reg_touud_mask = GENMASK_ULL(41, 20),
560+
.reg_eccerrlog_addr_mask = GENMASK_ULL(45, 5),
535561
.imc_base = 0xd800,
536562
.ibecc_base = 0xd400,
537563
.ibecc_error_log_offset = 0x68,
@@ -543,6 +569,10 @@ static struct res_config adl_n_cfg = {
543569
static struct res_config rpl_p_cfg = {
544570
.machine_check = true,
545571
.num_imc = 2,
572+
.reg_mchbar_mask = GENMASK_ULL(41, 17),
573+
.reg_tom_mask = GENMASK_ULL(41, 20),
574+
.reg_touud_mask = GENMASK_ULL(41, 20),
575+
.reg_eccerrlog_addr_mask = GENMASK_ULL(45, 5),
546576
.imc_base = 0xd800,
547577
.ibecc_base = 0xd400,
548578
.ibecc_error_log_offset = 0x68,
@@ -555,6 +585,10 @@ static struct res_config rpl_p_cfg = {
555585
static struct res_config mtl_ps_cfg = {
556586
.machine_check = true,
557587
.num_imc = 2,
588+
.reg_mchbar_mask = GENMASK_ULL(41, 17),
589+
.reg_tom_mask = GENMASK_ULL(41, 20),
590+
.reg_touud_mask = GENMASK_ULL(41, 20),
591+
.reg_eccerrlog_addr_mask = GENMASK_ULL(38, 5),
558592
.imc_base = 0xd800,
559593
.ibecc_base = 0xd400,
560594
.ibecc_error_log_offset = 0x170,
@@ -566,6 +600,10 @@ static struct res_config mtl_ps_cfg = {
566600
static struct res_config mtl_p_cfg = {
567601
.machine_check = true,
568602
.num_imc = 2,
603+
.reg_mchbar_mask = GENMASK_ULL(41, 17),
604+
.reg_tom_mask = GENMASK_ULL(41, 20),
605+
.reg_touud_mask = GENMASK_ULL(41, 20),
606+
.reg_eccerrlog_addr_mask = GENMASK_ULL(38, 5),
569607
.imc_base = 0xd800,
570608
.ibecc_base = 0xd400,
571609
.ibecc_error_log_offset = 0x170,
@@ -577,6 +615,10 @@ static struct res_config mtl_p_cfg = {
577615
static struct res_config wcl_cfg = {
578616
.machine_check = true,
579617
.num_imc = 1,
618+
.reg_mchbar_mask = GENMASK_ULL(41, 17),
619+
.reg_tom_mask = GENMASK_ULL(41, 20),
620+
.reg_touud_mask = GENMASK_ULL(41, 20),
621+
.reg_eccerrlog_addr_mask = GENMASK_ULL(38, 5),
580622
.imc_base = 0xd800,
581623
.ibecc_base = 0xd400,
582624
.ibecc_error_log_offset = 0x170,
@@ -908,8 +950,8 @@ static void ecclog_work_cb(struct work_struct *work)
908950
if (res_cfg->err_addr)
909951
eaddr = res_cfg->err_addr(node->ecclog);
910952
else
911-
eaddr = ECC_ERROR_LOG_ADDR(node->ecclog) <<
912-
ECC_ERROR_LOG_ADDR_SHIFT;
953+
eaddr = node->ecclog & res_cfg->reg_eccerrlog_addr_mask;
954+
913955
res.mc = node->mc;
914956
res.sys_addr = res_cfg->err_addr_to_sys_addr(eaddr, res.mc);
915957
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)
11291171

11301172
pr_warn_once("Fake error to 0x%llx injected via debugfs\n", val);
11311173

1132-
val >>= ECC_ERROR_LOG_ADDR_SHIFT;
1133-
ecclog = (val << ECC_ERROR_LOG_ADDR_SHIFT) | ECC_ERROR_LOG_CE;
1174+
ecclog = (val & res_cfg->reg_eccerrlog_addr_mask) | ECC_ERROR_LOG_CE;
11341175

11351176
if (!ecclog_gen_pool_add(0, ecclog))
11361177
irq_work_queue(&ecclog_irq_work);
@@ -1196,7 +1237,7 @@ static int igen6_pci_setup(struct pci_dev *pdev, u64 *mchbar)
11961237
goto fail;
11971238
}
11981239

1199-
igen6_tom = u.v & GENMASK_ULL(38, 20);
1240+
igen6_tom = u.v & res_cfg->reg_tom_mask;
12001241

12011242
if (get_mchbar(pdev, mchbar))
12021243
goto fail;
@@ -1207,7 +1248,7 @@ static int igen6_pci_setup(struct pci_dev *pdev, u64 *mchbar)
12071248
else if (pci_read_config_dword(pdev, TOUUD_OFFSET + 4, &u.v_hi))
12081249
edac_dbg(2, "Failed to read upper TOUUD\n");
12091250
else
1210-
igen6_touud = u.v & GENMASK_ULL(38, 20);
1251+
igen6_touud = u.v & res_cfg->reg_touud_mask;
12111252
#endif
12121253

12131254
return 0;

0 commit comments

Comments
 (0)