@@ -23,6 +23,7 @@ struct mlxsw_env_module_info {
23
23
24
24
struct mlxsw_env_line_card {
25
25
u8 module_count ;
26
+ bool active ;
26
27
struct mlxsw_env_module_info module_info [];
27
28
};
28
29
@@ -35,6 +36,24 @@ struct mlxsw_env {
35
36
struct mlxsw_env_line_card * line_cards [];
36
37
};
37
38
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
+
38
57
static struct
39
58
mlxsw_env_module_info * mlxsw_env_module_info_get (struct mlxsw_core * mlxsw_core ,
40
59
u8 slot_index , u8 module )
@@ -47,9 +66,13 @@ mlxsw_env_module_info *mlxsw_env_module_info_get(struct mlxsw_core *mlxsw_core,
47
66
static int __mlxsw_env_validate_module_type (struct mlxsw_core * core ,
48
67
u8 slot_index , u8 module )
49
68
{
69
+ struct mlxsw_env * mlxsw_env = mlxsw_core_env (core );
50
70
struct mlxsw_env_module_info * module_info ;
51
71
int err ;
52
72
73
+ if (!__mlxsw_env_linecard_is_active (mlxsw_env , slot_index ))
74
+ return 0 ;
75
+
53
76
module_info = mlxsw_env_module_info_get (core , slot_index , module );
54
77
switch (module_info -> type ) {
55
78
case MLXSW_REG_PMTM_MODULE_TYPE_TWISTED_PAIR :
@@ -269,12 +292,18 @@ int mlxsw_env_get_module_info(struct net_device *netdev,
269
292
struct mlxsw_core * mlxsw_core , u8 slot_index ,
270
293
int module , struct ethtool_modinfo * modinfo )
271
294
{
295
+ struct mlxsw_env * mlxsw_env = mlxsw_core_env (mlxsw_core );
272
296
u8 module_info [MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE ];
273
297
u16 offset = MLXSW_REG_MCIA_EEPROM_MODULE_INFO_SIZE ;
274
298
u8 module_rev_id , module_id , diag_mon ;
275
299
unsigned int read_size ;
276
300
int err ;
277
301
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
+
278
307
err = mlxsw_env_validate_module_type (mlxsw_core , slot_index , module );
279
308
if (err ) {
280
309
netdev_err (netdev ,
@@ -359,6 +388,7 @@ int mlxsw_env_get_module_eeprom(struct net_device *netdev,
359
388
int module , struct ethtool_eeprom * ee ,
360
389
u8 * data )
361
390
{
391
+ struct mlxsw_env * mlxsw_env = mlxsw_core_env (mlxsw_core );
362
392
int offset = ee -> offset ;
363
393
unsigned int read_size ;
364
394
bool qsfp , cmis ;
@@ -368,6 +398,11 @@ int mlxsw_env_get_module_eeprom(struct net_device *netdev,
368
398
if (!ee -> len )
369
399
return - EINVAL ;
370
400
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
+
371
406
memset (data , 0 , ee -> len );
372
407
/* Validate module identifier value. */
373
408
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,
428
463
const struct ethtool_module_eeprom * page ,
429
464
struct netlink_ext_ack * extack )
430
465
{
466
+ struct mlxsw_env * mlxsw_env = mlxsw_core_env (mlxsw_core );
431
467
u32 bytes_read = 0 ;
432
468
u16 device_addr ;
433
469
int err ;
434
470
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
+
435
477
err = mlxsw_env_validate_module_type (mlxsw_core , slot_index , module );
436
478
if (err ) {
437
479
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,
497
539
!(req & (ETH_RESET_PHY << ETH_RESET_SHARED_SHIFT )))
498
540
return 0 ;
499
541
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
+
500
547
mutex_lock (& mlxsw_env -> line_cards_lock );
501
548
502
549
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,
543
590
struct mlxsw_env_module_info * module_info ;
544
591
char mcion_pl [MLXSW_REG_MCION_LEN ];
545
592
u32 status_bits ;
546
- int err ;
593
+ int err = 0 ;
547
594
548
595
mutex_lock (& mlxsw_env -> line_cards_lock );
549
596
@@ -556,6 +603,10 @@ mlxsw_env_get_module_power_mode(struct mlxsw_core *mlxsw_core, u8 slot_index,
556
603
module_info = mlxsw_env_module_info_get (mlxsw_core , slot_index , module );
557
604
params -> policy = module_info -> power_mode_policy ;
558
605
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
+
559
610
mlxsw_reg_mcion_pack (mcion_pl , slot_index , module );
560
611
err = mlxsw_reg_query (mlxsw_core , MLXSW_REG (mcion ), mcion_pl );
561
612
if (err ) {
@@ -617,8 +668,16 @@ static int __mlxsw_env_set_module_power_mode(struct mlxsw_core *mlxsw_core,
617
668
bool low_power ,
618
669
struct netlink_ext_ack * extack )
619
670
{
671
+ struct mlxsw_env * mlxsw_env = mlxsw_core_env (mlxsw_core );
620
672
int err ;
621
673
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
+
622
681
err = mlxsw_env_module_enable_set (mlxsw_core , slot_index , module , false);
623
682
if (err ) {
624
683
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)
1208
1267
return 0 ;
1209
1268
}
1210
1269
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
+
1211
1362
int mlxsw_env_init (struct mlxsw_core * mlxsw_core ,
1212
1363
const struct mlxsw_bus_info * bus_info ,
1213
1364
struct mlxsw_env * * p_env )
@@ -1247,6 +1398,11 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core,
1247
1398
mutex_init (& env -> line_cards_lock );
1248
1399
* p_env = env ;
1249
1400
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
+
1250
1406
err = mlxsw_env_temp_warn_event_register (mlxsw_core );
1251
1407
if (err )
1252
1408
goto err_temp_warn_event_register ;
@@ -1271,6 +1427,8 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core,
1271
1427
if (err )
1272
1428
goto err_type_set ;
1273
1429
1430
+ env -> line_cards [0 ]-> active = true;
1431
+
1274
1432
return 0 ;
1275
1433
1276
1434
err_type_set :
@@ -1280,6 +1438,9 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core,
1280
1438
err_module_plug_event_register :
1281
1439
mlxsw_env_temp_warn_event_unregister (env );
1282
1440
err_temp_warn_event_register :
1441
+ mlxsw_linecards_event_ops_unregister (env -> core ,
1442
+ & mlxsw_env_event_ops , env );
1443
+ err_linecards_event_ops_register :
1283
1444
mutex_destroy (& env -> line_cards_lock );
1284
1445
mlxsw_env_line_cards_free (env );
1285
1446
err_mlxsw_env_line_cards_alloc :
@@ -1289,11 +1450,14 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core,
1289
1450
1290
1451
void mlxsw_env_fini (struct mlxsw_env * env )
1291
1452
{
1453
+ env -> line_cards [0 ]-> active = false;
1292
1454
mlxsw_env_module_event_disable (env , 0 );
1293
1455
mlxsw_env_module_plug_event_unregister (env );
1294
1456
/* Make sure there is no more event work scheduled. */
1295
1457
mlxsw_core_flush_owq ();
1296
1458
mlxsw_env_temp_warn_event_unregister (env );
1459
+ mlxsw_linecards_event_ops_unregister (env -> core ,
1460
+ & mlxsw_env_event_ops , env );
1297
1461
mutex_destroy (& env -> line_cards_lock );
1298
1462
mlxsw_env_line_cards_free (env );
1299
1463
kfree (env );
0 commit comments