@@ -21,12 +21,11 @@ struct cxl_rwsem cxl_rwsem = {
2121 .dpa = __RWSEM_INITIALIZER (cxl_rwsem .dpa ),
2222};
2323
24- static int add_hdm_decoder (struct cxl_port * port , struct cxl_decoder * cxld ,
25- int * target_map )
24+ static int add_hdm_decoder (struct cxl_port * port , struct cxl_decoder * cxld )
2625{
2726 int rc ;
2827
29- rc = cxl_decoder_add_locked (cxld , target_map );
28+ rc = cxl_decoder_add_locked (cxld );
3029 if (rc ) {
3130 put_device (& cxld -> dev );
3231 dev_err (& port -> dev , "Failed to add decoder\n" );
@@ -50,12 +49,9 @@ static int add_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
5049 * are claimed and passed to the single dport. Disable the range until the first
5150 * CXL region is enumerated / activated.
5251 */
53- int devm_cxl_add_passthrough_decoder (struct cxl_port * port )
52+ static int devm_cxl_add_passthrough_decoder (struct cxl_port * port )
5453{
5554 struct cxl_switch_decoder * cxlsd ;
56- struct cxl_dport * dport = NULL ;
57- int single_port_map [1 ];
58- unsigned long index ;
5955 struct cxl_hdm * cxlhdm = dev_get_drvdata (& port -> dev );
6056
6157 /*
@@ -71,13 +67,8 @@ int devm_cxl_add_passthrough_decoder(struct cxl_port *port)
7167
7268 device_lock_assert (& port -> dev );
7369
74- xa_for_each (& port -> dports , index , dport )
75- break ;
76- single_port_map [0 ] = dport -> port_id ;
77-
78- return add_hdm_decoder (port , & cxlsd -> cxld , single_port_map );
70+ return add_hdm_decoder (port , & cxlsd -> cxld );
7971}
80- EXPORT_SYMBOL_NS_GPL (devm_cxl_add_passthrough_decoder , "CXL" );
8172
8273static void parse_hdm_decoder_caps (struct cxl_hdm * cxlhdm )
8374{
@@ -147,8 +138,8 @@ static bool should_emulate_decoders(struct cxl_endpoint_dvsec_info *info)
147138 * @port: cxl_port to map
148139 * @info: cached DVSEC range register info
149140 */
150- struct cxl_hdm * devm_cxl_setup_hdm (struct cxl_port * port ,
151- struct cxl_endpoint_dvsec_info * info )
141+ static struct cxl_hdm * devm_cxl_setup_hdm (struct cxl_port * port ,
142+ struct cxl_endpoint_dvsec_info * info )
152143{
153144 struct cxl_register_map * reg_map = & port -> reg_map ;
154145 struct device * dev = & port -> dev ;
@@ -203,7 +194,6 @@ struct cxl_hdm *devm_cxl_setup_hdm(struct cxl_port *port,
203194
204195 return cxlhdm ;
205196}
206- EXPORT_SYMBOL_NS_GPL (devm_cxl_setup_hdm , "CXL" );
207197
208198static void __cxl_dpa_debug (struct seq_file * file , struct resource * r , int depth )
209199{
@@ -984,7 +974,7 @@ static int cxl_setup_hdm_decoder_from_dvsec(
984974}
985975
986976static int init_hdm_decoder (struct cxl_port * port , struct cxl_decoder * cxld ,
987- int * target_map , void __iomem * hdm , int which ,
977+ void __iomem * hdm , int which ,
988978 u64 * dpa_base , struct cxl_endpoint_dvsec_info * info )
989979{
990980 struct cxl_endpoint_decoder * cxled = NULL ;
@@ -1103,7 +1093,7 @@ static int init_hdm_decoder(struct cxl_port *port, struct cxl_decoder *cxld,
11031093 hi = readl (hdm + CXL_HDM_DECODER0_TL_HIGH (which ));
11041094 target_list .value = (hi << 32 ) + lo ;
11051095 for (i = 0 ; i < cxld -> interleave_ways ; i ++ )
1106- target_map [i ] = target_list .target_id [i ];
1096+ cxld -> target_map [i ] = target_list .target_id [i ];
11071097
11081098 return 0 ;
11091099 }
@@ -1168,8 +1158,8 @@ static void cxl_settle_decoders(struct cxl_hdm *cxlhdm)
11681158 * @cxlhdm: Structure to populate with HDM capabilities
11691159 * @info: cached DVSEC range register info
11701160 */
1171- int devm_cxl_enumerate_decoders (struct cxl_hdm * cxlhdm ,
1172- struct cxl_endpoint_dvsec_info * info )
1161+ static int devm_cxl_enumerate_decoders (struct cxl_hdm * cxlhdm ,
1162+ struct cxl_endpoint_dvsec_info * info )
11731163{
11741164 void __iomem * hdm = cxlhdm -> regs .hdm_decoder ;
11751165 struct cxl_port * port = cxlhdm -> port ;
@@ -1179,7 +1169,6 @@ int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm,
11791169 cxl_settle_decoders (cxlhdm );
11801170
11811171 for (i = 0 ; i < cxlhdm -> decoder_count ; i ++ ) {
1182- int target_map [CXL_DECODER_MAX_INTERLEAVE ] = { 0 };
11831172 int rc , target_count = cxlhdm -> target_count ;
11841173 struct cxl_decoder * cxld ;
11851174
@@ -1207,16 +1196,15 @@ int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm,
12071196 cxld = & cxlsd -> cxld ;
12081197 }
12091198
1210- rc = init_hdm_decoder (port , cxld , target_map , hdm , i ,
1211- & dpa_base , info );
1199+ rc = init_hdm_decoder (port , cxld , hdm , i , & dpa_base , info );
12121200 if (rc ) {
12131201 dev_warn (& port -> dev ,
12141202 "Failed to initialize decoder%d.%d\n" ,
12151203 port -> id , i );
12161204 put_device (& cxld -> dev );
12171205 return rc ;
12181206 }
1219- rc = add_hdm_decoder (port , cxld , target_map );
1207+ rc = add_hdm_decoder (port , cxld );
12201208 if (rc ) {
12211209 dev_warn (& port -> dev ,
12221210 "Failed to add decoder%d.%d\n" , port -> id , i );
@@ -1226,4 +1214,71 @@ int devm_cxl_enumerate_decoders(struct cxl_hdm *cxlhdm,
12261214
12271215 return 0 ;
12281216}
1229- EXPORT_SYMBOL_NS_GPL (devm_cxl_enumerate_decoders , "CXL" );
1217+
1218+ /**
1219+ * __devm_cxl_switch_port_decoders_setup - allocate and setup switch decoders
1220+ * @port: CXL port context
1221+ *
1222+ * Return 0 or -errno on error
1223+ */
1224+ int __devm_cxl_switch_port_decoders_setup (struct cxl_port * port )
1225+ {
1226+ struct cxl_hdm * cxlhdm ;
1227+
1228+ if (is_cxl_root (port ) || is_cxl_endpoint (port ))
1229+ return - EOPNOTSUPP ;
1230+
1231+ cxlhdm = devm_cxl_setup_hdm (port , NULL );
1232+ if (!IS_ERR (cxlhdm ))
1233+ return devm_cxl_enumerate_decoders (cxlhdm , NULL );
1234+
1235+ if (PTR_ERR (cxlhdm ) != - ENODEV ) {
1236+ dev_err (& port -> dev , "Failed to map HDM decoder capability\n" );
1237+ return PTR_ERR (cxlhdm );
1238+ }
1239+
1240+ if (cxl_port_get_possible_dports (port ) == 1 ) {
1241+ dev_dbg (& port -> dev , "Fallback to passthrough decoder\n" );
1242+ return devm_cxl_add_passthrough_decoder (port );
1243+ }
1244+
1245+ dev_err (& port -> dev , "HDM decoder capability not found\n" );
1246+ return - ENXIO ;
1247+ }
1248+ EXPORT_SYMBOL_NS_GPL (__devm_cxl_switch_port_decoders_setup , "CXL" );
1249+
1250+ /**
1251+ * devm_cxl_endpoint_decoders_setup - allocate and setup endpoint decoders
1252+ * @port: CXL port context
1253+ *
1254+ * Return 0 or -errno on error
1255+ */
1256+ int devm_cxl_endpoint_decoders_setup (struct cxl_port * port )
1257+ {
1258+ struct cxl_memdev * cxlmd = to_cxl_memdev (port -> uport_dev );
1259+ struct cxl_endpoint_dvsec_info info = { .port = port };
1260+ struct cxl_dev_state * cxlds = cxlmd -> cxlds ;
1261+ struct cxl_hdm * cxlhdm ;
1262+ int rc ;
1263+
1264+ if (!is_cxl_endpoint (port ))
1265+ return - EOPNOTSUPP ;
1266+
1267+ rc = cxl_dvsec_rr_decode (cxlds , & info );
1268+ if (rc < 0 )
1269+ return rc ;
1270+
1271+ cxlhdm = devm_cxl_setup_hdm (port , & info );
1272+ if (IS_ERR (cxlhdm )) {
1273+ if (PTR_ERR (cxlhdm ) == - ENODEV )
1274+ dev_err (& port -> dev , "HDM decoder registers not found\n" );
1275+ return PTR_ERR (cxlhdm );
1276+ }
1277+
1278+ rc = cxl_hdm_decode_init (cxlds , cxlhdm , & info );
1279+ if (rc )
1280+ return rc ;
1281+
1282+ return devm_cxl_enumerate_decoders (cxlhdm , & info );
1283+ }
1284+ EXPORT_SYMBOL_NS_GPL (devm_cxl_endpoint_decoders_setup , "CXL" );
0 commit comments