@@ -362,6 +362,7 @@ struct sbridge_pvt {
362
362
363
363
/* Memory type detection */
364
364
bool is_mirrored , is_lockstep , is_close_pg ;
365
+ bool is_chan_hash ;
365
366
366
367
/* Fifo double buffers */
367
368
struct mce mce_entry [MCE_LOG_LEN ];
@@ -1060,6 +1061,20 @@ static inline u8 sad_pkg_ha(u8 pkg)
1060
1061
return (pkg >> 2 ) & 0x1 ;
1061
1062
}
1062
1063
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
+
1063
1078
/****************************************************************************
1064
1079
Memory check routines
1065
1080
****************************************************************************/
@@ -1616,6 +1631,10 @@ static int get_dimm_config(struct mem_ctl_info *mci)
1616
1631
KNL_MAX_CHANNELS : NUM_CHANNELS ;
1617
1632
u64 knl_mc_sizes [KNL_MAX_CHANNELS ];
1618
1633
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
+ }
1619
1638
if (pvt -> info .type == HASWELL || pvt -> info .type == BROADWELL ||
1620
1639
pvt -> info .type == KNIGHTS_LANDING )
1621
1640
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,
2122
2141
2123
2142
if (ch_way == 3 )
2124
2143
idx = addr >> 6 ;
2125
- else
2144
+ else {
2126
2145
idx = (addr >> (6 + sck_way + shiftup )) & 0x3 ;
2146
+ if (pvt -> is_chan_hash )
2147
+ idx = haswell_chan_hash (idx , addr );
2148
+ }
2127
2149
idx = idx % ch_way ;
2128
2150
2129
2151
/*
0 commit comments