@@ -226,6 +226,13 @@ static void __init uv_tsc_check_sync(void)
226226 mark_tsc_unstable ("UV BIOS" );
227227}
228228
229+ /* Selector for (4|4A|5) structs */
230+ #define uvxy_field (sname , field , undef ) ( \
231+ is_uv(UV4A) ? sname.s4a.field : \
232+ is_uv(UV4) ? sname.s4.field : \
233+ is_uv(UV3) ? sname.s3.field : \
234+ undef)
235+
229236/* [Copied from arch/x86/kernel/cpu/topology.c:detect_extended_topology()] */
230237
231238#define SMT_LEVEL 0 /* Leaf 0xb SMT level */
@@ -878,6 +885,7 @@ static __init void get_lowmem_redirect(unsigned long *base, unsigned long *size)
878885}
879886
880887enum map_type {map_wb , map_uc };
888+ static const char * const mt [] = { "WB" , "UC" };
881889
882890static __init void map_high (char * id , unsigned long base , int pshift , int bshift , int max_pnode , enum map_type map_type )
883891{
@@ -889,11 +897,13 @@ static __init void map_high(char *id, unsigned long base, int pshift, int bshift
889897 pr_info ("UV: Map %s_HI base address NULL\n" , id );
890898 return ;
891899 }
892- pr_debug ("UV: Map %s_HI 0x%lx - 0x%lx\n" , id , paddr , paddr + bytes );
893900 if (map_type == map_uc )
894901 init_extra_mapping_uc (paddr , bytes );
895902 else
896903 init_extra_mapping_wb (paddr , bytes );
904+
905+ pr_info ("UV: Map %s_HI 0x%lx - 0x%lx %s (%d segments)\n" ,
906+ id , paddr , paddr + bytes , mt [map_type ], max_pnode + 1 );
897907}
898908
899909static __init void map_gru_high (int max_pnode )
@@ -927,52 +937,74 @@ static __init void map_mmr_high(int max_pnode)
927937 pr_info ("UV: MMR disabled\n" );
928938}
929939
930- /* UV3/4 have identical MMIOH overlay configs, UV4A is slightly different */
931- static __init void map_mmioh_high_uv34 (int index , int min_pnode , int max_pnode )
932- {
933- unsigned long overlay ;
934- unsigned long mmr ;
935- unsigned long base ;
936- unsigned long nasid_mask ;
937- unsigned long m_overlay ;
938- int i , n , shift , m_io , max_io ;
939- int nasid , lnasid , fi , li ;
940- char * id ;
941-
942- if (index == 0 ) {
943- id = "MMIOH0" ;
944- m_overlay = UVH_RH_GAM_MMIOH_OVERLAY_CONFIG0 ;
945- overlay = uv_read_local_mmr (m_overlay );
946- base = overlay & UV3H_RH_GAM_MMIOH_OVERLAY_CONFIG0_BASE_MASK ;
940+ /* Arch specific ENUM cases */
941+ enum mmioh_arch {
942+ UV2_MMIOH = -1 ,
943+ UVY_MMIOH0 , UVY_MMIOH1 ,
944+ UVX_MMIOH0 , UVX_MMIOH1 ,
945+ };
946+
947+ /* Calculate and Map MMIOH Regions */
948+ static void __init calc_mmioh_map (enum mmioh_arch index ,
949+ int min_pnode , int max_pnode ,
950+ int shift , unsigned long base , int m_io , int n_io )
951+ {
952+ unsigned long mmr , nasid_mask ;
953+ int nasid , min_nasid , max_nasid , lnasid , mapped ;
954+ int i , fi , li , n , max_io ;
955+ char id [8 ];
956+
957+ /* One (UV2) mapping */
958+ if (index == UV2_MMIOH ) {
959+ strncpy (id , "MMIOH" , sizeof (id ));
960+ max_io = max_pnode ;
961+ mapped = 0 ;
962+ goto map_exit ;
963+ }
964+
965+ /* small and large MMIOH mappings */
966+ switch (index ) {
967+ case UVY_MMIOH0 :
968+ mmr = UVH_RH10_GAM_MMIOH_REDIRECT_CONFIG0 ;
969+ nasid_mask = UVH_RH10_GAM_MMIOH_OVERLAY_CONFIG0_BASE_MASK ;
970+ n = UVH_RH10_GAM_MMIOH_REDIRECT_CONFIG0_DEPTH ;
971+ min_nasid = min_pnode ;
972+ max_nasid = max_pnode ;
973+ mapped = 1 ;
974+ break ;
975+ case UVY_MMIOH1 :
976+ mmr = UVH_RH10_GAM_MMIOH_REDIRECT_CONFIG1 ;
977+ nasid_mask = UVH_RH10_GAM_MMIOH_OVERLAY_CONFIG1_BASE_MASK ;
978+ n = UVH_RH10_GAM_MMIOH_REDIRECT_CONFIG1_DEPTH ;
979+ min_nasid = min_pnode ;
980+ max_nasid = max_pnode ;
981+ mapped = 1 ;
982+ break ;
983+ case UVX_MMIOH0 :
947984 mmr = UVH_RH_GAM_MMIOH_REDIRECT_CONFIG0 ;
948- m_io = (overlay & UV3H_RH_GAM_MMIOH_OVERLAY_CONFIG0_M_IO_MASK )
949- >> UV3H_RH_GAM_MMIOH_OVERLAY_CONFIG0_M_IO_SHFT ;
950- shift = UV3H_RH_GAM_MMIOH_OVERLAY_CONFIG0_M_IO_SHFT ;
985+ nasid_mask = UVH_RH_GAM_MMIOH_OVERLAY_CONFIG0_BASE_MASK ;
951986 n = UVH_RH_GAM_MMIOH_REDIRECT_CONFIG0_DEPTH ;
952- nasid_mask = UV3H_RH_GAM_MMIOH_REDIRECT_CONFIG0_NASID_MASK ;
953- } else {
954- id = "MMIOH1" ;
955- m_overlay = UVH_RH_GAM_MMIOH_OVERLAY_CONFIG1 ;
956- overlay = uv_read_local_mmr (m_overlay );
957- base = overlay & UV3H_RH_GAM_MMIOH_OVERLAY_CONFIG1_BASE_MASK ;
987+ min_nasid = min_pnode * 2 ;
988+ max_nasid = max_pnode * 2 ;
989+ mapped = 1 ;
990+ break ;
991+ case UVX_MMIOH1 :
958992 mmr = UVH_RH_GAM_MMIOH_REDIRECT_CONFIG1 ;
959- m_io = (overlay & UV3H_RH_GAM_MMIOH_OVERLAY_CONFIG1_M_IO_MASK )
960- >> UV3H_RH_GAM_MMIOH_OVERLAY_CONFIG1_M_IO_SHFT ;
961- shift = UV3H_RH_GAM_MMIOH_OVERLAY_CONFIG1_M_IO_SHFT ;
993+ nasid_mask = UVH_RH_GAM_MMIOH_OVERLAY_CONFIG1_BASE_MASK ;
962994 n = UVH_RH_GAM_MMIOH_REDIRECT_CONFIG1_DEPTH ;
963- nasid_mask = UV3H_RH_GAM_MMIOH_REDIRECT_CONFIG1_NASID_MASK ;
964- }
965- pr_info ("UV: %s overlay 0x%lx base:0x%lx m_io:%d\n" , id , overlay , base , m_io );
966- if (!(overlay & UV3H_RH_GAM_MMIOH_OVERLAY_CONFIG0_ENABLE_MASK )) {
967- pr_info ("UV: %s disabled\n" , id );
995+ min_nasid = min_pnode * 2 ;
996+ max_nasid = max_pnode * 2 ;
997+ mapped = 1 ;
998+ break ;
999+ default :
1000+ pr_err ("UV:%s:Invalid mapping type:%d\n" , __func__ , index );
9681001 return ;
9691002 }
9701003
971- /* Convert to NASID: */
972- min_pnode *= 2 ;
973- max_pnode *= 2 ;
974- max_io = lnasid = fi = li = -1 ;
1004+ /* enum values chosen so (index mod 2) is MMIOH 0/1 (low/high) */
1005+ snprintf (id , sizeof (id ), "MMIOH%d" , index %2 );
9751006
1007+ max_io = lnasid = fi = li = -1 ;
9761008 for (i = 0 ; i < n ; i ++ ) {
9771009 unsigned long m_redirect = mmr + i * 8 ;
9781010 unsigned long redirect = uv_read_local_mmr (m_redirect );
@@ -982,9 +1014,12 @@ static __init void map_mmioh_high_uv34(int index, int min_pnode, int max_pnode)
9821014 pr_info ("UV: %s redirect base 0x%lx(@0x%lx) 0x%04x\n" ,
9831015 id , redirect , m_redirect , nasid );
9841016
985- /* Invalid NASID: */
986- if (nasid < min_pnode || max_pnode < nasid )
1017+ /* Invalid NASID check */
1018+ if (nasid < min_nasid || max_nasid < nasid ) {
1019+ pr_err ("UV:%s:Invalid NASID:%x (range:%x..%x)\n" ,
1020+ __func__ , index , min_nasid , max_nasid );
9871021 nasid = -1 ;
1022+ }
9881023
9891024 if (nasid == lnasid ) {
9901025 li = i ;
@@ -1007,51 +1042,92 @@ static __init void map_mmioh_high_uv34(int index, int min_pnode, int max_pnode)
10071042 }
10081043 addr1 = (base << shift ) + f * (1ULL << m_io );
10091044 addr2 = (base << shift ) + (l + 1 ) * (1ULL << m_io );
1010- pr_info ("UV: %s[%03d..%03d] NASID 0x%04x ADDR 0x%016lx - 0x%016lx\n" , id , fi , li , lnasid , addr1 , addr2 );
1045+ pr_info ("UV: %s[%03d..%03d] NASID 0x%04x ADDR 0x%016lx - 0x%016lx\n" ,
1046+ id , fi , li , lnasid , addr1 , addr2 );
10111047 if (max_io < l )
10121048 max_io = l ;
10131049 }
10141050 fi = li = i ;
10151051 lnasid = nasid ;
10161052 }
10171053
1018- pr_info ("UV: %s base:0x%lx shift:%d M_IO:%d MAX_IO:%d\n" , id , base , shift , m_io , max_io );
1054+ map_exit :
1055+ pr_info ("UV: %s base:0x%lx shift:%d m_io:%d max_io:%d max_pnode:0x%x\n" ,
1056+ id , base , shift , m_io , max_io , max_pnode );
10191057
1020- if (max_io >= 0 )
1058+ if (max_io >= 0 && ! mapped )
10211059 map_high (id , base , shift , m_io , max_io , map_uc );
10221060}
10231061
10241062static __init void map_mmioh_high (int min_pnode , int max_pnode )
10251063{
1026- union uvh_rh_gam_mmioh_overlay_config_u mmioh ;
1027- unsigned long mmr , base ;
1028- int shift , enable , m_io , n_io ;
1064+ /* UVY flavor */
1065+ if (UVH_RH10_GAM_MMIOH_OVERLAY_CONFIG0 ) {
1066+ union uvh_rh10_gam_mmioh_overlay_config0_u mmioh0 ;
1067+ union uvh_rh10_gam_mmioh_overlay_config1_u mmioh1 ;
1068+
1069+ mmioh0 .v = uv_read_local_mmr (UVH_RH10_GAM_MMIOH_OVERLAY_CONFIG0 );
1070+ if (unlikely (mmioh0 .s .enable == 0 ))
1071+ pr_info ("UV: MMIOH0 disabled\n" );
1072+ else
1073+ calc_mmioh_map (UVY_MMIOH0 , min_pnode , max_pnode ,
1074+ UVH_RH10_GAM_MMIOH_OVERLAY_CONFIG0_BASE_SHFT ,
1075+ mmioh0 .s .base , mmioh0 .s .m_io , mmioh0 .s .n_io );
10291076
1030- if (is_uv3_hub () || is_uv4_hub ()) {
1031- /* Map both MMIOH regions: */
1032- map_mmioh_high_uv34 (0 , min_pnode , max_pnode );
1033- map_mmioh_high_uv34 (1 , min_pnode , max_pnode );
1077+ mmioh1 .v = uv_read_local_mmr (UVH_RH10_GAM_MMIOH_OVERLAY_CONFIG1 );
1078+ if (unlikely (mmioh1 .s .enable == 0 ))
1079+ pr_info ("UV: MMIOH1 disabled\n" );
1080+ else
1081+ calc_mmioh_map (UVY_MMIOH1 , min_pnode , max_pnode ,
1082+ UVH_RH10_GAM_MMIOH_OVERLAY_CONFIG1_BASE_SHFT ,
1083+ mmioh1 .s .base , mmioh1 .s .m_io , mmioh1 .s .n_io );
10341084 return ;
10351085 }
1086+ /* UVX flavor */
1087+ if (UVH_RH_GAM_MMIOH_OVERLAY_CONFIG0 ) {
1088+ union uvh_rh_gam_mmioh_overlay_config0_u mmioh0 ;
1089+ union uvh_rh_gam_mmioh_overlay_config1_u mmioh1 ;
1090+
1091+ mmioh0 .v = uv_read_local_mmr (UVH_RH_GAM_MMIOH_OVERLAY_CONFIG0 );
1092+ if (unlikely (mmioh0 .s .enable == 0 ))
1093+ pr_info ("UV: MMIOH0 disabled\n" );
1094+ else {
1095+ unsigned long base = uvxy_field (mmioh0 , base , 0 );
1096+ int m_io = uvxy_field (mmioh0 , m_io , 0 );
1097+ int n_io = uvxy_field (mmioh0 , n_io , 0 );
1098+
1099+ calc_mmioh_map (UVX_MMIOH0 , min_pnode , max_pnode ,
1100+ UVH_RH_GAM_MMIOH_OVERLAY_CONFIG0_BASE_SHFT ,
1101+ base , m_io , n_io );
1102+ }
10361103
1037- if (is_uv2_hub ()) {
1038- mmr = UVH_RH_GAM_MMIOH_OVERLAY_CONFIG ;
1039- shift = UVH_RH_GAM_MMIOH_OVERLAY_CONFIG_BASE_SHFT ;
1040- mmioh .v = uv_read_local_mmr (mmr );
1041- enable = !!mmioh .s2 .enable ;
1042- base = mmioh .s2 .base ;
1043- m_io = mmioh .s2 .m_io ;
1044- n_io = mmioh .s2 .n_io ;
1045-
1046- if (enable ) {
1047- max_pnode &= (1 << n_io ) - 1 ;
1048- pr_info (
1049- "UV: base:0x%lx shift:%d N_IO:%d M_IO:%d max_pnode:0x%x\n" ,
1050- base , shift , m_io , n_io , max_pnode );
1051- map_high ("MMIOH" , base , shift , m_io , max_pnode , map_uc );
1052- } else {
1053- pr_info ("UV: MMIOH disabled\n" );
1104+ mmioh1 .v = uv_read_local_mmr (UVH_RH_GAM_MMIOH_OVERLAY_CONFIG1 );
1105+ if (unlikely (mmioh1 .s .enable == 0 ))
1106+ pr_info ("UV: MMIOH1 disabled\n" );
1107+ else {
1108+ unsigned long base = uvxy_field (mmioh1 , base , 0 );
1109+ int m_io = uvxy_field (mmioh1 , m_io , 0 );
1110+ int n_io = uvxy_field (mmioh1 , n_io , 0 );
1111+
1112+ calc_mmioh_map (UVX_MMIOH1 , min_pnode , max_pnode ,
1113+ UVH_RH_GAM_MMIOH_OVERLAY_CONFIG1_BASE_SHFT ,
1114+ base , m_io , n_io );
10541115 }
1116+ return ;
1117+ }
1118+
1119+ /* UV2 flavor */
1120+ if (UVH_RH_GAM_MMIOH_OVERLAY_CONFIG ) {
1121+ union uvh_rh_gam_mmioh_overlay_config_u mmioh ;
1122+
1123+ mmioh .v = uv_read_local_mmr (UVH_RH_GAM_MMIOH_OVERLAY_CONFIG );
1124+ if (unlikely (mmioh .s2 .enable == 0 ))
1125+ pr_info ("UV: MMIOH disabled\n" );
1126+ else
1127+ calc_mmioh_map (UV2_MMIOH , min_pnode , max_pnode ,
1128+ UV2H_RH_GAM_MMIOH_OVERLAY_CONFIG_BASE_SHFT ,
1129+ mmioh .s2 .base , mmioh .s2 .m_io , mmioh .s2 .n_io );
1130+ return ;
10551131 }
10561132}
10571133
0 commit comments