@@ -362,6 +362,7 @@ struct sbridge_pvt {
362362
363363 /* Memory type detection */
364364 bool is_mirrored , is_lockstep , is_close_pg ;
365+ bool is_chan_hash ;
365366
366367 /* Fifo double buffers */
367368 struct mce mce_entry [MCE_LOG_LEN ];
@@ -1060,6 +1061,20 @@ static inline u8 sad_pkg_ha(u8 pkg)
10601061 return (pkg >> 2 ) & 0x1 ;
10611062}
10621063
1064+ static int haswell_chan_hash (int idx , u64 addr )
1065+ {
1066+ int i ;
1067+
1068+ /*
1069+ * XOR even bits from 12:26 to bit0 of idx,
1070+ * odd bits from 13:27 to bit1
1071+ */
1072+ for (i = 12 ; i < 28 ; i += 2 )
1073+ idx ^= (addr >> i ) & 3 ;
1074+
1075+ return idx ;
1076+ }
1077+
10631078/****************************************************************************
10641079 Memory check routines
10651080 ****************************************************************************/
@@ -1616,6 +1631,10 @@ static int get_dimm_config(struct mem_ctl_info *mci)
16161631 KNL_MAX_CHANNELS : NUM_CHANNELS ;
16171632 u64 knl_mc_sizes [KNL_MAX_CHANNELS ];
16181633
1634+ if (pvt -> info .type == HASWELL || pvt -> info .type == BROADWELL ) {
1635+ pci_read_config_dword (pvt -> pci_ha0 , HASWELL_HASYSDEFEATURE2 , & reg );
1636+ pvt -> is_chan_hash = GET_BITFIELD (reg , 21 , 21 );
1637+ }
16191638 if (pvt -> info .type == HASWELL || pvt -> info .type == BROADWELL ||
16201639 pvt -> info .type == KNIGHTS_LANDING )
16211640 pci_read_config_dword (pvt -> pci_sad1 , SAD_TARGET , & reg );
@@ -2122,8 +2141,11 @@ static int get_memory_error_data(struct mem_ctl_info *mci,
21222141
21232142 if (ch_way == 3 )
21242143 idx = addr >> 6 ;
2125- else
2144+ else {
21262145 idx = (addr >> (6 + sck_way + shiftup )) & 0x3 ;
2146+ if (pvt -> is_chan_hash )
2147+ idx = haswell_chan_hash (idx , addr );
2148+ }
21272149 idx = idx % ch_way ;
21282150
21292151 /*
0 commit comments