Skip to content

Commit ad774bd

Browse files
qzhuo2aegl
authored andcommitted
EDAC/igen6: Add Intel Alder Lake SoC support
Alder Lake SoC shares the same memory controller and In-Band ECC (IBECC) IP with Tiger Lake SoC. Like Tiger Lake, it also has two memory controllers each associated one IBECC instance. The minor differences include the MMIO offset of each memory controller and the type of memory error address logged in the IBECC. So add Alder Lake compute die IDs, adjust the MMIO offset for each memory controller and handle the type of memory error address logged in the IBECC for Alder Lake EDAC support. Tested-by: Vrukesh V Panse <[email protected]> Signed-off-by: Qiuxu Zhuo <[email protected]> Signed-off-by: Tony Luck <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 0b7338b commit ad774bd

File tree

1 file changed

+73
-11
lines changed

1 file changed

+73
-11
lines changed

drivers/edac/igen6_edac.c

Lines changed: 73 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
#include "edac_mc.h"
2828
#include "edac_module.h"
2929

30-
#define IGEN6_REVISION "v2.4"
30+
#define IGEN6_REVISION "v2.5"
3131

3232
#define EDAC_MOD_STR "igen6_edac"
3333
#define IGEN6_NMI_NAME "igen6_ibecc"
@@ -75,7 +75,7 @@
7575
#define IBECC_ACTIVATE_EN BIT(0)
7676

7777
/* IBECC error log */
78-
#define ECC_ERROR_LOG_OFFSET (IBECC_BASE + 0x170)
78+
#define ECC_ERROR_LOG_OFFSET (IBECC_BASE + res_cfg->ibecc_error_log_offset)
7979
#define ECC_ERROR_LOG_CE BIT_ULL(62)
8080
#define ECC_ERROR_LOG_UE BIT_ULL(63)
8181
#define ECC_ERROR_LOG_ADDR_SHIFT 5
@@ -89,27 +89,32 @@
8989
#define MCHBAR_SIZE 0x10000
9090

9191
/* Parameters for the channel decode stage */
92-
#define MAD_INTER_CHANNEL_OFFSET 0x5000
92+
#define IMC_BASE (res_cfg->imc_base)
93+
#define MAD_INTER_CHANNEL_OFFSET IMC_BASE
9394
#define MAD_INTER_CHANNEL_DDR_TYPE(v) GET_BITFIELD(v, 0, 2)
9495
#define MAD_INTER_CHANNEL_ECHM(v) GET_BITFIELD(v, 3, 3)
9596
#define MAD_INTER_CHANNEL_CH_L_MAP(v) GET_BITFIELD(v, 4, 4)
9697
#define MAD_INTER_CHANNEL_CH_S_SIZE(v) ((u64)GET_BITFIELD(v, 12, 19) << 29)
9798

9899
/* Parameters for DRAM decode stage */
99-
#define MAD_INTRA_CH0_OFFSET 0x5004
100+
#define MAD_INTRA_CH0_OFFSET (IMC_BASE + 4)
100101
#define MAD_INTRA_CH_DIMM_L_MAP(v) GET_BITFIELD(v, 0, 0)
101102

102103
/* DIMM characteristics */
103-
#define MAD_DIMM_CH0_OFFSET 0x500c
104+
#define MAD_DIMM_CH0_OFFSET (IMC_BASE + 0xc)
104105
#define MAD_DIMM_CH_DIMM_L_SIZE(v) ((u64)GET_BITFIELD(v, 0, 6) << 29)
105106
#define MAD_DIMM_CH_DLW(v) GET_BITFIELD(v, 7, 8)
106107
#define MAD_DIMM_CH_DIMM_S_SIZE(v) ((u64)GET_BITFIELD(v, 16, 22) << 29)
107108
#define MAD_DIMM_CH_DSW(v) GET_BITFIELD(v, 24, 25)
108109

110+
/* Hash for memory controller selection */
111+
#define MAD_MC_HASH_OFFSET (IMC_BASE + 0x1b8)
112+
#define MAC_MC_HASH_LSB(v) GET_BITFIELD(v, 1, 3)
113+
109114
/* Hash for channel selection */
110-
#define CHANNEL_HASH_OFFSET 0X5024
115+
#define CHANNEL_HASH_OFFSET (IMC_BASE + 0x24)
111116
/* Hash for enhanced channel selection */
112-
#define CHANNEL_EHASH_OFFSET 0X5028
117+
#define CHANNEL_EHASH_OFFSET (IMC_BASE + 0x28)
113118
#define CHANNEL_HASH_MASK(v) (GET_BITFIELD(v, 6, 19) << 6)
114119
#define CHANNEL_HASH_LSB_MASK_BIT(v) GET_BITFIELD(v, 24, 26)
115120
#define CHANNEL_HASH_MODE(v) GET_BITFIELD(v, 28, 28)
@@ -121,15 +126,17 @@
121126
static struct res_config {
122127
bool machine_check;
123128
int num_imc;
129+
u32 imc_base;
124130
u32 cmf_base;
125131
u32 cmf_size;
126132
u32 ms_hash_offset;
127133
u32 ibecc_base;
134+
u32 ibecc_error_log_offset;
128135
bool (*ibecc_available)(struct pci_dev *pdev);
129136
/* Convert error address logged in IBECC to system physical address */
130137
u64 (*err_addr_to_sys_addr)(u64 eaddr, int mc);
131138
/* Convert error address logged in IBECC to integrated memory controller address */
132-
u64 (*err_addr_to_imc_addr)(u64 eaddr);
139+
u64 (*err_addr_to_imc_addr)(u64 eaddr, int mc);
133140
} *res_cfg;
134141

135142
struct igen6_imc {
@@ -209,6 +216,12 @@ static struct work_struct ecclog_work;
209216
/* Compute die IDs for Tiger Lake with IBECC */
210217
#define DID_TGL_SKU 0x9a14
211218

219+
/* Compute die IDs for Alder Lake with IBECC */
220+
#define DID_ADL_SKU1 0x4601
221+
#define DID_ADL_SKU2 0x4602
222+
#define DID_ADL_SKU3 0x4621
223+
#define DID_ADL_SKU4 0x4641
224+
212225
static bool ehl_ibecc_available(struct pci_dev *pdev)
213226
{
214227
u32 v;
@@ -224,7 +237,7 @@ static u64 ehl_err_addr_to_sys_addr(u64 eaddr, int mc)
224237
return eaddr;
225238
}
226239

227-
static u64 ehl_err_addr_to_imc_addr(u64 eaddr)
240+
static u64 ehl_err_addr_to_imc_addr(u64 eaddr, int mc)
228241
{
229242
if (eaddr < igen6_tolud)
230243
return eaddr;
@@ -315,22 +328,51 @@ static u64 tgl_err_addr_to_sys_addr(u64 eaddr, int mc)
315328
return mem_addr_to_sys_addr(maddr);
316329
}
317330

318-
static u64 tgl_err_addr_to_imc_addr(u64 eaddr)
331+
static u64 tgl_err_addr_to_imc_addr(u64 eaddr, int mc)
319332
{
320333
return eaddr;
321334
}
322335

336+
static u64 adl_err_addr_to_sys_addr(u64 eaddr, int mc)
337+
{
338+
return mem_addr_to_sys_addr(eaddr);
339+
}
340+
341+
static u64 adl_err_addr_to_imc_addr(u64 eaddr, int mc)
342+
{
343+
u64 imc_addr, ms_s_size = igen6_pvt->ms_s_size;
344+
struct igen6_imc *imc = &igen6_pvt->imc[mc];
345+
int intlv_bit;
346+
u32 mc_hash;
347+
348+
if (eaddr >= 2 * ms_s_size)
349+
return eaddr - ms_s_size;
350+
351+
mc_hash = readl(imc->window + MAD_MC_HASH_OFFSET);
352+
353+
intlv_bit = MAC_MC_HASH_LSB(mc_hash) + 6;
354+
355+
imc_addr = GET_BITFIELD(eaddr, intlv_bit + 1, 63) << intlv_bit |
356+
GET_BITFIELD(eaddr, 0, intlv_bit - 1);
357+
358+
return imc_addr;
359+
}
360+
323361
static struct res_config ehl_cfg = {
324362
.num_imc = 1,
363+
.imc_base = 0x5000,
325364
.ibecc_base = 0xdc00,
326365
.ibecc_available = ehl_ibecc_available,
366+
.ibecc_error_log_offset = 0x170,
327367
.err_addr_to_sys_addr = ehl_err_addr_to_sys_addr,
328368
.err_addr_to_imc_addr = ehl_err_addr_to_imc_addr,
329369
};
330370

331371
static struct res_config icl_cfg = {
332372
.num_imc = 1,
373+
.imc_base = 0x5000,
333374
.ibecc_base = 0xd800,
375+
.ibecc_error_log_offset = 0x170,
334376
.ibecc_available = icl_ibecc_available,
335377
.err_addr_to_sys_addr = ehl_err_addr_to_sys_addr,
336378
.err_addr_to_imc_addr = ehl_err_addr_to_imc_addr,
@@ -339,15 +381,28 @@ static struct res_config icl_cfg = {
339381
static struct res_config tgl_cfg = {
340382
.machine_check = true,
341383
.num_imc = 2,
384+
.imc_base = 0x5000,
342385
.cmf_base = 0x11000,
343386
.cmf_size = 0x800,
344387
.ms_hash_offset = 0xac,
345388
.ibecc_base = 0xd400,
389+
.ibecc_error_log_offset = 0x170,
346390
.ibecc_available = tgl_ibecc_available,
347391
.err_addr_to_sys_addr = tgl_err_addr_to_sys_addr,
348392
.err_addr_to_imc_addr = tgl_err_addr_to_imc_addr,
349393
};
350394

395+
static struct res_config adl_cfg = {
396+
.machine_check = true,
397+
.num_imc = 2,
398+
.imc_base = 0xd800,
399+
.ibecc_base = 0xd400,
400+
.ibecc_error_log_offset = 0x68,
401+
.ibecc_available = tgl_ibecc_available,
402+
.err_addr_to_sys_addr = adl_err_addr_to_sys_addr,
403+
.err_addr_to_imc_addr = adl_err_addr_to_imc_addr,
404+
};
405+
351406
static const struct pci_device_id igen6_pci_tbl[] = {
352407
{ PCI_VDEVICE(INTEL, DID_EHL_SKU5), (kernel_ulong_t)&ehl_cfg },
353408
{ PCI_VDEVICE(INTEL, DID_EHL_SKU6), (kernel_ulong_t)&ehl_cfg },
@@ -365,6 +420,10 @@ static const struct pci_device_id igen6_pci_tbl[] = {
365420
{ PCI_VDEVICE(INTEL, DID_ICL_SKU11), (kernel_ulong_t)&icl_cfg },
366421
{ PCI_VDEVICE(INTEL, DID_ICL_SKU12), (kernel_ulong_t)&icl_cfg },
367422
{ PCI_VDEVICE(INTEL, DID_TGL_SKU), (kernel_ulong_t)&tgl_cfg },
423+
{ PCI_VDEVICE(INTEL, DID_ADL_SKU1), (kernel_ulong_t)&adl_cfg },
424+
{ PCI_VDEVICE(INTEL, DID_ADL_SKU2), (kernel_ulong_t)&adl_cfg },
425+
{ PCI_VDEVICE(INTEL, DID_ADL_SKU3), (kernel_ulong_t)&adl_cfg },
426+
{ PCI_VDEVICE(INTEL, DID_ADL_SKU4), (kernel_ulong_t)&adl_cfg },
368427
{ },
369428
};
370429
MODULE_DEVICE_TABLE(pci, igen6_pci_tbl);
@@ -624,7 +683,7 @@ static void ecclog_work_cb(struct work_struct *work)
624683
ECC_ERROR_LOG_ADDR_SHIFT;
625684
res.mc = node->mc;
626685
res.sys_addr = res_cfg->err_addr_to_sys_addr(eaddr, res.mc);
627-
res.imc_addr = res_cfg->err_addr_to_imc_addr(eaddr);
686+
res.imc_addr = res_cfg->err_addr_to_imc_addr(eaddr, res.mc);
628687

629688
mci = igen6_pvt->imc[res.mc].mci;
630689

@@ -1071,6 +1130,9 @@ static int igen6_mem_slice_setup(u64 mchbar)
10711130
edac_dbg(0, "ms_s_size: %llu MiB, ms_l_map %d\n",
10721131
ms_s_size >> 20, ms_l_map);
10731132

1133+
if (!size)
1134+
return 0;
1135+
10741136
cmf = ioremap(base, size);
10751137
if (!cmf) {
10761138
igen6_printk(KERN_ERR, "Failed to ioremap cmf 0x%llx\n", base);

0 commit comments

Comments
 (0)