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"
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
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)
121126static 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
135142struct 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+
212225static 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+
323361static 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
331371static 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 = {
339381static 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+
351406static 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};
370429MODULE_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