@@ -211,8 +211,6 @@ static int amd64_get_scrub_rate(struct mem_ctl_info *mci)
211
211
212
212
scrubval = scrubval & 0x001F ;
213
213
214
- amd64_debug ("pci-read, sdram scrub control value: %d\n" , scrubval );
215
-
216
214
for (i = 0 ; i < ARRAY_SIZE (scrubrates ); i ++ ) {
217
215
if (scrubrates [i ].scrubval == scrubval ) {
218
216
retval = scrubrates [i ].bandwidth ;
@@ -933,32 +931,106 @@ static int k8_early_channel_count(struct amd64_pvt *pvt)
933
931
/* On F10h and later ErrAddr is MC4_ADDR[47:1] */
934
932
static u64 get_error_address (struct mce * m )
935
933
{
934
+ struct cpuinfo_x86 * c = & boot_cpu_data ;
935
+ u64 addr ;
936
936
u8 start_bit = 1 ;
937
937
u8 end_bit = 47 ;
938
938
939
- if (boot_cpu_data . x86 == 0xf ) {
939
+ if (c -> x86 == 0xf ) {
940
940
start_bit = 3 ;
941
941
end_bit = 39 ;
942
942
}
943
943
944
- return m -> addr & GENMASK (start_bit , end_bit );
944
+ addr = m -> addr & GENMASK (start_bit , end_bit );
945
+
946
+ /*
947
+ * Erratum 637 workaround
948
+ */
949
+ if (c -> x86 == 0x15 ) {
950
+ struct amd64_pvt * pvt ;
951
+ u64 cc6_base , tmp_addr ;
952
+ u32 tmp ;
953
+ u8 mce_nid , intlv_en ;
954
+
955
+ if ((addr & GENMASK (24 , 47 )) >> 24 != 0x00fdf7 )
956
+ return addr ;
957
+
958
+ mce_nid = amd_get_nb_id (m -> extcpu );
959
+ pvt = mcis [mce_nid ]-> pvt_info ;
960
+
961
+ amd64_read_pci_cfg (pvt -> F1 , DRAM_LOCAL_NODE_LIM , & tmp );
962
+ intlv_en = tmp >> 21 & 0x7 ;
963
+
964
+ /* add [47:27] + 3 trailing bits */
965
+ cc6_base = (tmp & GENMASK (0 , 20 )) << 3 ;
966
+
967
+ /* reverse and add DramIntlvEn */
968
+ cc6_base |= intlv_en ^ 0x7 ;
969
+
970
+ /* pin at [47:24] */
971
+ cc6_base <<= 24 ;
972
+
973
+ if (!intlv_en )
974
+ return cc6_base | (addr & GENMASK (0 , 23 ));
975
+
976
+ amd64_read_pci_cfg (pvt -> F1 , DRAM_LOCAL_NODE_BASE , & tmp );
977
+
978
+ /* faster log2 */
979
+ tmp_addr = (addr & GENMASK (12 , 23 )) << __fls (intlv_en + 1 );
980
+
981
+ /* OR DramIntlvSel into bits [14:12] */
982
+ tmp_addr |= (tmp & GENMASK (21 , 23 )) >> 9 ;
983
+
984
+ /* add remaining [11:0] bits from original MC4_ADDR */
985
+ tmp_addr |= addr & GENMASK (0 , 11 );
986
+
987
+ return cc6_base | tmp_addr ;
988
+ }
989
+
990
+ return addr ;
945
991
}
946
992
947
993
static void read_dram_base_limit_regs (struct amd64_pvt * pvt , unsigned range )
948
994
{
995
+ struct cpuinfo_x86 * c = & boot_cpu_data ;
949
996
int off = range << 3 ;
950
997
951
998
amd64_read_pci_cfg (pvt -> F1 , DRAM_BASE_LO + off , & pvt -> ranges [range ].base .lo );
952
999
amd64_read_pci_cfg (pvt -> F1 , DRAM_LIMIT_LO + off , & pvt -> ranges [range ].lim .lo );
953
1000
954
- if (boot_cpu_data . x86 == 0xf )
1001
+ if (c -> x86 == 0xf )
955
1002
return ;
956
1003
957
1004
if (!dram_rw (pvt , range ))
958
1005
return ;
959
1006
960
1007
amd64_read_pci_cfg (pvt -> F1 , DRAM_BASE_HI + off , & pvt -> ranges [range ].base .hi );
961
1008
amd64_read_pci_cfg (pvt -> F1 , DRAM_LIMIT_HI + off , & pvt -> ranges [range ].lim .hi );
1009
+
1010
+ /* Factor in CC6 save area by reading dst node's limit reg */
1011
+ if (c -> x86 == 0x15 ) {
1012
+ struct pci_dev * f1 = NULL ;
1013
+ u8 nid = dram_dst_node (pvt , range );
1014
+ u32 llim ;
1015
+
1016
+ f1 = pci_get_domain_bus_and_slot (0 , 0 , PCI_DEVFN (0x18 + nid , 1 ));
1017
+ if (WARN_ON (!f1 ))
1018
+ return ;
1019
+
1020
+ amd64_read_pci_cfg (f1 , DRAM_LOCAL_NODE_LIM , & llim );
1021
+
1022
+ pvt -> ranges [range ].lim .lo &= GENMASK (0 , 15 );
1023
+
1024
+ /* {[39:27],111b} */
1025
+ pvt -> ranges [range ].lim .lo |= ((llim & 0x1fff ) << 3 | 0x7 ) << 16 ;
1026
+
1027
+ pvt -> ranges [range ].lim .hi &= GENMASK (0 , 7 );
1028
+
1029
+ /* [47:40] */
1030
+ pvt -> ranges [range ].lim .hi |= llim >> 13 ;
1031
+
1032
+ pci_dev_put (f1 );
1033
+ }
962
1034
}
963
1035
964
1036
static void k8_map_sysaddr_to_csrow (struct mem_ctl_info * mci , u64 sys_addr ,
@@ -1403,12 +1475,8 @@ static int f1x_match_to_this_node(struct amd64_pvt *pvt, unsigned range,
1403
1475
return - EINVAL ;
1404
1476
}
1405
1477
1406
- if (intlv_en &&
1407
- (intlv_sel != ((sys_addr >> 12 ) & intlv_en ))) {
1408
- amd64_warn ("Botched intlv bits, en: 0x%x, sel: 0x%x\n" ,
1409
- intlv_en , intlv_sel );
1478
+ if (intlv_en && (intlv_sel != ((sys_addr >> 12 ) & intlv_en )))
1410
1479
return - EINVAL ;
1411
- }
1412
1480
1413
1481
sys_addr = f1x_swap_interleaved_region (pvt , sys_addr );
1414
1482
0 commit comments