@@ -23,6 +23,7 @@ struct mlxsw_env_module_info {
2323
2424struct mlxsw_env_line_card {
2525 u8 module_count ;
26+ bool active ;
2627 struct mlxsw_env_module_info module_info [];
2728};
2829
@@ -35,6 +36,24 @@ struct mlxsw_env {
3536 struct mlxsw_env_line_card * line_cards [];
3637};
3738
39+ static bool __mlxsw_env_linecard_is_active (struct mlxsw_env * mlxsw_env ,
40+ u8 slot_index )
41+ {
42+ return mlxsw_env -> line_cards [slot_index ]-> active ;
43+ }
44+
45+ static bool mlxsw_env_linecard_is_active (struct mlxsw_env * mlxsw_env ,
46+ u8 slot_index )
47+ {
48+ bool active ;
49+
50+ mutex_lock (& mlxsw_env -> line_cards_lock );
51+ active = __mlxsw_env_linecard_is_active (mlxsw_env , slot_index );
52+ mutex_unlock (& mlxsw_env -> line_cards_lock );
53+
54+ return active ;
55+ }
56+
3857static struct
3958mlxsw_env_module_info * mlxsw_env_module_info_get (struct mlxsw_core * mlxsw_core ,
4059 u8 slot_index , u8 module )
@@ -47,9 +66,13 @@ mlxsw_env_module_info *mlxsw_env_module_info_get(struct mlxsw_core *mlxsw_core,
4766static int __mlxsw_env_validate_module_type (struct mlxsw_core * core ,
4867 u8 slot_index , u8 module )
4968{
69+ struct mlxsw_env * mlxsw_env = mlxsw_core_env (core );
5070 struct mlxsw_env_module_info * module_info ;
5171 int err ;
5272
73+ if (!__mlxsw_env_linecard_is_active (mlxsw_env , slot_index ))
74+ return 0 ;
75+
5376 module_info = mlxsw_env_module_info_get (core , slot_index , module );
5477 switch (module_info -> type ) {
5578 case MLXSW_REG_PMTM_MODULE_TYPE_TWISTED_PAIR :
@@ -269,12 +292,18 @@ int mlxsw_env_get_module_info(struct net_device *netdev,
269292 struct mlxsw_core * mlxsw_core , u8 slot_index ,
270293 int module , struct ethtool_modinfo * modinfo )
271294{
295+ struct mlxsw_env * mlxsw_env = mlxsw_core_env (mlxsw_core );
272296 u8 module_info [MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE ];
273297 u16 offset = MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE ;
274298 u8 module_rev_id , module_id , diag_mon ;
275299 unsigned int read_size ;
276300 int err ;
277301
302+ if (!mlxsw_env_linecard_is_active (mlxsw_env , slot_index )) {
303+ netdev_err (netdev , "Cannot read EEPROM of module on an inactive line card\n" );
304+ return - EIO ;
305+ }
306+
278307 err = mlxsw_env_validate_module_type (mlxsw_core , slot_index , module );
279308 if (err ) {
280309 netdev_err (netdev ,
@@ -359,6 +388,7 @@ int mlxsw_env_get_module_eeprom(struct net_device *netdev,
359388 int module , struct ethtool_eeprom * ee ,
360389 u8 * data )
361390{
391+ struct mlxsw_env * mlxsw_env = mlxsw_core_env (mlxsw_core );
362392 int offset = ee -> offset ;
363393 unsigned int read_size ;
364394 bool qsfp , cmis ;
@@ -368,6 +398,11 @@ int mlxsw_env_get_module_eeprom(struct net_device *netdev,
368398 if (!ee -> len )
369399 return - EINVAL ;
370400
401+ if (!mlxsw_env_linecard_is_active (mlxsw_env , slot_index )) {
402+ netdev_err (netdev , "Cannot read EEPROM of module on an inactive line card\n" );
403+ return - EIO ;
404+ }
405+
371406 memset (data , 0 , ee -> len );
372407 /* Validate module identifier value. */
373408 err = mlxsw_env_validate_cable_ident (mlxsw_core , slot_index , module ,
@@ -428,10 +463,17 @@ mlxsw_env_get_module_eeprom_by_page(struct mlxsw_core *mlxsw_core,
428463 const struct ethtool_module_eeprom * page ,
429464 struct netlink_ext_ack * extack )
430465{
466+ struct mlxsw_env * mlxsw_env = mlxsw_core_env (mlxsw_core );
431467 u32 bytes_read = 0 ;
432468 u16 device_addr ;
433469 int err ;
434470
471+ if (!mlxsw_env_linecard_is_active (mlxsw_env , slot_index )) {
472+ NL_SET_ERR_MSG_MOD (extack ,
473+ "Cannot read EEPROM of module on an inactive line card" );
474+ return - EIO ;
475+ }
476+
435477 err = mlxsw_env_validate_module_type (mlxsw_core , slot_index , module );
436478 if (err ) {
437479 NL_SET_ERR_MSG_MOD (extack , "EEPROM is not equipped on port module type" );
@@ -497,6 +539,11 @@ int mlxsw_env_reset_module(struct net_device *netdev,
497539 !(req & (ETH_RESET_PHY << ETH_RESET_SHARED_SHIFT )))
498540 return 0 ;
499541
542+ if (!mlxsw_env_linecard_is_active (mlxsw_env , slot_index )) {
543+ netdev_err (netdev , "Cannot reset module on an inactive line card\n" );
544+ return - EIO ;
545+ }
546+
500547 mutex_lock (& mlxsw_env -> line_cards_lock );
501548
502549 err = __mlxsw_env_validate_module_type (mlxsw_core , slot_index , module );
@@ -543,7 +590,7 @@ mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index,
543590 struct mlxsw_env_module_info * module_info ;
544591 char mcion_pl [MLXSW_REG_MCION_LEN ];
545592 u32 status_bits ;
546- int err ;
593+ int err = 0 ;
547594
548595 mutex_lock (& mlxsw_env -> line_cards_lock );
549596
@@ -556,6 +603,10 @@ mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index,
556603 module_info = mlxsw_env_module_info_get (mlxsw_core , slot_index , module );
557604 params -> policy = module_info -> power_mode_policy ;
558605
606+ /* Avoid accessing an inactive line card, as it will result in an error. */
607+ if (!__mlxsw_env_linecard_is_active (mlxsw_env , slot_index ))
608+ goto out ;
609+
559610 mlxsw_reg_mcion_pack (mcion_pl , slot_index , module );
560611 err = mlxsw_reg_query (mlxsw_core , MLXSW_REG (mcion ), mcion_pl );
561612 if (err ) {
@@ -617,8 +668,16 @@ static int __mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core,
617668 bool low_power ,
618669 struct netlink_ext_ack * extack )
619670{
671+ struct mlxsw_env * mlxsw_env = mlxsw_core_env (mlxsw_core );
620672 int err ;
621673
674+ /* Avoid accessing an inactive line card, as it will result in an error.
675+ * Cached configuration will be applied by mlxsw_env_got_active() when
676+ * line card becomes active.
677+ */
678+ if (!__mlxsw_env_linecard_is_active (mlxsw_env , slot_index ))
679+ return 0 ;
680+
622681 err = mlxsw_env_module_enable_set (mlxsw_core , slot_index , module , false);
623682 if (err ) {
624683 NL_SET_ERR_MSG_MOD (extack , "Failed to disable module" );
@@ -1208,6 +1267,98 @@ mlxsw_env_module_type_set(struct mlxsw_core *mlxsw_core, u8 slot_index)
12081267 return 0 ;
12091268}
12101269
1270+ static void
1271+ mlxsw_env_linecard_modules_power_mode_apply (struct mlxsw_core * mlxsw_core ,
1272+ struct mlxsw_env * env ,
1273+ u8 slot_index )
1274+ {
1275+ int i ;
1276+
1277+ for (i = 0 ; i < env -> line_cards [slot_index ]-> module_count ; i ++ ) {
1278+ enum ethtool_module_power_mode_policy policy ;
1279+ struct mlxsw_env_module_info * module_info ;
1280+ struct netlink_ext_ack extack ;
1281+ int err ;
1282+
1283+ module_info = & env -> line_cards [slot_index ]-> module_info [i ];
1284+ policy = module_info -> power_mode_policy ;
1285+ err = mlxsw_env_set_module_power_mode_apply (mlxsw_core ,
1286+ slot_index , i ,
1287+ policy , & extack );
1288+ if (err )
1289+ dev_err (env -> bus_info -> dev , "%s\n" , extack ._msg );
1290+ }
1291+ }
1292+
1293+ static void
1294+ mlxsw_env_got_active (struct mlxsw_core * mlxsw_core , u8 slot_index , void * priv )
1295+ {
1296+ struct mlxsw_env * mlxsw_env = priv ;
1297+ char mgpir_pl [MLXSW_REG_MGPIR_LEN ];
1298+ int err ;
1299+
1300+ mutex_lock (& mlxsw_env -> line_cards_lock );
1301+ if (__mlxsw_env_linecard_is_active (mlxsw_env , slot_index ))
1302+ goto out_unlock ;
1303+
1304+ mlxsw_reg_mgpir_pack (mgpir_pl , slot_index );
1305+ err = mlxsw_reg_query (mlxsw_env -> core , MLXSW_REG (mgpir ), mgpir_pl );
1306+ if (err )
1307+ goto out_unlock ;
1308+
1309+ mlxsw_reg_mgpir_unpack (mgpir_pl , NULL , NULL , NULL ,
1310+ & mlxsw_env -> line_cards [slot_index ]-> module_count ,
1311+ NULL );
1312+
1313+ err = mlxsw_env_module_event_enable (mlxsw_env , slot_index );
1314+ if (err ) {
1315+ dev_err (mlxsw_env -> bus_info -> dev , "Failed to enable port module events for line card in slot %d\n" ,
1316+ slot_index );
1317+ goto err_mlxsw_env_module_event_enable ;
1318+ }
1319+ err = mlxsw_env_module_type_set (mlxsw_env -> core , slot_index );
1320+ if (err ) {
1321+ dev_err (mlxsw_env -> bus_info -> dev , "Failed to set modules' type for line card in slot %d\n" ,
1322+ slot_index );
1323+ goto err_type_set ;
1324+ }
1325+
1326+ mlxsw_env -> line_cards [slot_index ]-> active = true;
1327+ /* Apply power mode policy. */
1328+ mlxsw_env_linecard_modules_power_mode_apply (mlxsw_core , mlxsw_env ,
1329+ slot_index );
1330+ mutex_unlock (& mlxsw_env -> line_cards_lock );
1331+
1332+ return ;
1333+
1334+ err_type_set :
1335+ mlxsw_env_module_event_disable (mlxsw_env , slot_index );
1336+ err_mlxsw_env_module_event_enable :
1337+ out_unlock :
1338+ mutex_unlock (& mlxsw_env -> line_cards_lock );
1339+ }
1340+
1341+ static void
1342+ mlxsw_env_got_inactive (struct mlxsw_core * mlxsw_core , u8 slot_index ,
1343+ void * priv )
1344+ {
1345+ struct mlxsw_env * mlxsw_env = priv ;
1346+
1347+ mutex_lock (& mlxsw_env -> line_cards_lock );
1348+ if (!__mlxsw_env_linecard_is_active (mlxsw_env , slot_index ))
1349+ goto out_unlock ;
1350+ mlxsw_env -> line_cards [slot_index ]-> active = false;
1351+ mlxsw_env_module_event_disable (mlxsw_env , slot_index );
1352+ mlxsw_env -> line_cards [slot_index ]-> module_count = 0 ;
1353+ out_unlock :
1354+ mutex_unlock (& mlxsw_env -> line_cards_lock );
1355+ }
1356+
1357+ static struct mlxsw_linecards_event_ops mlxsw_env_event_ops = {
1358+ .got_active = mlxsw_env_got_active ,
1359+ .got_inactive = mlxsw_env_got_inactive ,
1360+ };
1361+
12111362int mlxsw_env_init (struct mlxsw_core * mlxsw_core ,
12121363 const struct mlxsw_bus_info * bus_info ,
12131364 struct mlxsw_env * * p_env )
@@ -1247,6 +1398,11 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core,
12471398 mutex_init (& env -> line_cards_lock );
12481399 * p_env = env ;
12491400
1401+ err = mlxsw_linecards_event_ops_register (env -> core ,
1402+ & mlxsw_env_event_ops , env );
1403+ if (err )
1404+ goto err_linecards_event_ops_register ;
1405+
12501406 err = mlxsw_env_temp_warn_event_register (mlxsw_core );
12511407 if (err )
12521408 goto err_temp_warn_event_register ;
@@ -1271,6 +1427,8 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core,
12711427 if (err )
12721428 goto err_type_set ;
12731429
1430+ env -> line_cards [0 ]-> active = true;
1431+
12741432 return 0 ;
12751433
12761434err_type_set :
@@ -1280,6 +1438,9 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core,
12801438err_module_plug_event_register :
12811439 mlxsw_env_temp_warn_event_unregister (env );
12821440err_temp_warn_event_register :
1441+ mlxsw_linecards_event_ops_unregister (env -> core ,
1442+ & mlxsw_env_event_ops , env );
1443+ err_linecards_event_ops_register :
12831444 mutex_destroy (& env -> line_cards_lock );
12841445 mlxsw_env_line_cards_free (env );
12851446err_mlxsw_env_line_cards_alloc :
@@ -1289,11 +1450,14 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core,
12891450
12901451void mlxsw_env_fini (struct mlxsw_env * env )
12911452{
1453+ env -> line_cards [0 ]-> active = false;
12921454 mlxsw_env_module_event_disable (env , 0 );
12931455 mlxsw_env_module_plug_event_unregister (env );
12941456 /* Make sure there is no more event work scheduled. */
12951457 mlxsw_core_flush_owq ();
12961458 mlxsw_env_temp_warn_event_unregister (env );
1459+ mlxsw_linecards_event_ops_unregister (env -> core ,
1460+ & mlxsw_env_event_ops , env );
12971461 mutex_destroy (& env -> line_cards_lock );
12981462 mlxsw_env_line_cards_free (env );
12991463 kfree (env );
0 commit comments