27
27
#include "edac_mc.h"
28
28
#include "edac_module.h"
29
29
30
- #define IGEN6_REVISION "v2.4 "
30
+ #define IGEN6_REVISION "v2.5 "
31
31
32
32
#define EDAC_MOD_STR "igen6_edac"
33
33
#define IGEN6_NMI_NAME "igen6_ibecc"
75
75
#define IBECC_ACTIVATE_EN BIT(0)
76
76
77
77
/* 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 )
79
79
#define ECC_ERROR_LOG_CE BIT_ULL(62)
80
80
#define ECC_ERROR_LOG_UE BIT_ULL(63)
81
81
#define ECC_ERROR_LOG_ADDR_SHIFT 5
89
89
#define MCHBAR_SIZE 0x10000
90
90
91
91
/* 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
93
94
#define MAD_INTER_CHANNEL_DDR_TYPE (v ) GET_BITFIELD(v, 0, 2)
94
95
#define MAD_INTER_CHANNEL_ECHM (v ) GET_BITFIELD(v, 3, 3)
95
96
#define MAD_INTER_CHANNEL_CH_L_MAP (v ) GET_BITFIELD(v, 4, 4)
96
97
#define MAD_INTER_CHANNEL_CH_S_SIZE (v ) ((u64)GET_BITFIELD(v, 12, 19) << 29)
97
98
98
99
/* Parameters for DRAM decode stage */
99
- #define MAD_INTRA_CH0_OFFSET 0x5004
100
+ #define MAD_INTRA_CH0_OFFSET (IMC_BASE + 4)
100
101
#define MAD_INTRA_CH_DIMM_L_MAP (v ) GET_BITFIELD(v, 0, 0)
101
102
102
103
/* DIMM characteristics */
103
- #define MAD_DIMM_CH0_OFFSET 0x500c
104
+ #define MAD_DIMM_CH0_OFFSET (IMC_BASE + 0xc)
104
105
#define MAD_DIMM_CH_DIMM_L_SIZE (v ) ((u64)GET_BITFIELD(v, 0, 6) << 29)
105
106
#define MAD_DIMM_CH_DLW (v ) GET_BITFIELD(v, 7, 8)
106
107
#define MAD_DIMM_CH_DIMM_S_SIZE (v ) ((u64)GET_BITFIELD(v, 16, 22) << 29)
107
108
#define MAD_DIMM_CH_DSW (v ) GET_BITFIELD(v, 24, 25)
108
109
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
+
109
114
/* Hash for channel selection */
110
- #define CHANNEL_HASH_OFFSET 0X5024
115
+ #define CHANNEL_HASH_OFFSET (IMC_BASE + 0x24)
111
116
/* Hash for enhanced channel selection */
112
- #define CHANNEL_EHASH_OFFSET 0X5028
117
+ #define CHANNEL_EHASH_OFFSET (IMC_BASE + 0x28)
113
118
#define CHANNEL_HASH_MASK (v ) (GET_BITFIELD(v, 6, 19) << 6)
114
119
#define CHANNEL_HASH_LSB_MASK_BIT (v ) GET_BITFIELD(v, 24, 26)
115
120
#define CHANNEL_HASH_MODE (v ) GET_BITFIELD(v, 28, 28)
121
126
static struct res_config {
122
127
bool machine_check ;
123
128
int num_imc ;
129
+ u32 imc_base ;
124
130
u32 cmf_base ;
125
131
u32 cmf_size ;
126
132
u32 ms_hash_offset ;
127
133
u32 ibecc_base ;
134
+ u32 ibecc_error_log_offset ;
128
135
bool (* ibecc_available )(struct pci_dev * pdev );
129
136
/* Convert error address logged in IBECC to system physical address */
130
137
u64 (* err_addr_to_sys_addr )(u64 eaddr , int mc );
131
138
/* 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 );
133
140
} * res_cfg ;
134
141
135
142
struct igen6_imc {
@@ -209,6 +216,12 @@ static struct work_struct ecclog_work;
209
216
/* Compute die IDs for Tiger Lake with IBECC */
210
217
#define DID_TGL_SKU 0x9a14
211
218
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
+
212
225
static bool ehl_ibecc_available (struct pci_dev * pdev )
213
226
{
214
227
u32 v ;
@@ -224,7 +237,7 @@ static u64 ehl_err_addr_to_sys_addr(u64 eaddr, int mc)
224
237
return eaddr ;
225
238
}
226
239
227
- static u64 ehl_err_addr_to_imc_addr (u64 eaddr )
240
+ static u64 ehl_err_addr_to_imc_addr (u64 eaddr , int mc )
228
241
{
229
242
if (eaddr < igen6_tolud )
230
243
return eaddr ;
@@ -315,22 +328,51 @@ static u64 tgl_err_addr_to_sys_addr(u64 eaddr, int mc)
315
328
return mem_addr_to_sys_addr (maddr );
316
329
}
317
330
318
- static u64 tgl_err_addr_to_imc_addr (u64 eaddr )
331
+ static u64 tgl_err_addr_to_imc_addr (u64 eaddr , int mc )
319
332
{
320
333
return eaddr ;
321
334
}
322
335
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
+
323
361
static struct res_config ehl_cfg = {
324
362
.num_imc = 1 ,
363
+ .imc_base = 0x5000 ,
325
364
.ibecc_base = 0xdc00 ,
326
365
.ibecc_available = ehl_ibecc_available ,
366
+ .ibecc_error_log_offset = 0x170 ,
327
367
.err_addr_to_sys_addr = ehl_err_addr_to_sys_addr ,
328
368
.err_addr_to_imc_addr = ehl_err_addr_to_imc_addr ,
329
369
};
330
370
331
371
static struct res_config icl_cfg = {
332
372
.num_imc = 1 ,
373
+ .imc_base = 0x5000 ,
333
374
.ibecc_base = 0xd800 ,
375
+ .ibecc_error_log_offset = 0x170 ,
334
376
.ibecc_available = icl_ibecc_available ,
335
377
.err_addr_to_sys_addr = ehl_err_addr_to_sys_addr ,
336
378
.err_addr_to_imc_addr = ehl_err_addr_to_imc_addr ,
@@ -339,15 +381,28 @@ static struct res_config icl_cfg = {
339
381
static struct res_config tgl_cfg = {
340
382
.machine_check = true,
341
383
.num_imc = 2 ,
384
+ .imc_base = 0x5000 ,
342
385
.cmf_base = 0x11000 ,
343
386
.cmf_size = 0x800 ,
344
387
.ms_hash_offset = 0xac ,
345
388
.ibecc_base = 0xd400 ,
389
+ .ibecc_error_log_offset = 0x170 ,
346
390
.ibecc_available = tgl_ibecc_available ,
347
391
.err_addr_to_sys_addr = tgl_err_addr_to_sys_addr ,
348
392
.err_addr_to_imc_addr = tgl_err_addr_to_imc_addr ,
349
393
};
350
394
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
+
351
406
static const struct pci_device_id igen6_pci_tbl [] = {
352
407
{ PCI_VDEVICE (INTEL , DID_EHL_SKU5 ), (kernel_ulong_t )& ehl_cfg },
353
408
{ PCI_VDEVICE (INTEL , DID_EHL_SKU6 ), (kernel_ulong_t )& ehl_cfg },
@@ -365,6 +420,10 @@ static const struct pci_device_id igen6_pci_tbl[] = {
365
420
{ PCI_VDEVICE (INTEL , DID_ICL_SKU11 ), (kernel_ulong_t )& icl_cfg },
366
421
{ PCI_VDEVICE (INTEL , DID_ICL_SKU12 ), (kernel_ulong_t )& icl_cfg },
367
422
{ 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 },
368
427
{ },
369
428
};
370
429
MODULE_DEVICE_TABLE (pci , igen6_pci_tbl );
@@ -624,7 +683,7 @@ static void ecclog_work_cb(struct work_struct *work)
624
683
ECC_ERROR_LOG_ADDR_SHIFT ;
625
684
res .mc = node -> mc ;
626
685
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 );
628
687
629
688
mci = igen6_pvt -> imc [res .mc ].mci ;
630
689
@@ -1071,6 +1130,9 @@ static int igen6_mem_slice_setup(u64 mchbar)
1071
1130
edac_dbg (0 , "ms_s_size: %llu MiB, ms_l_map %d\n" ,
1072
1131
ms_s_size >> 20 , ms_l_map );
1073
1132
1133
+ if (!size )
1134
+ return 0 ;
1135
+
1074
1136
cmf = ioremap (base , size );
1075
1137
if (!cmf ) {
1076
1138
igen6_printk (KERN_ERR , "Failed to ioremap cmf 0x%llx\n" , base );
0 commit comments