Skip to content

Commit 06a0fc4

Browse files
vadimp-nvidiadavem330
authored andcommitted
mlxsw: core_env: Add interfaces for line card initialization and de-initialization
Netdevs for ports found on line cards are registered upon provisioning. However, user space is not allowed to access the transceiver modules found on a line card until the line card becomes active. Therefore, register event operations with the line card core to get notifications whenever a line card becomes active or inactive. When user space tries to dump the EEPROM of a transceiver module or reset it and the corresponding line card is inactive, emit an error message: ethtool -m enp1s0nl7p9 netlink error: mlxsw_core: Cannot read EEPROM of module on an inactive line card netlink error: Input/output error When user space tries to set the power mode policy of such a transceiver, cache the configuration and apply it when the line card becomes active. This is consistent with other port configuration (e.g., MTU setting) that user space is able to perform while the line card is provisioned, but inactive. Signed-off-by: Vadim Pasternak <[email protected]> Signed-off-by: Ido Schimmel <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent a11e1ec commit 06a0fc4

File tree

1 file changed

+165
-1
lines changed

1 file changed

+165
-1
lines changed

drivers/net/ethernet/mellanox/mlxsw/core_env.c

Lines changed: 165 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ struct mlxsw_env_module_info {
2323

2424
struct 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+
3857
static struct
3958
mlxsw_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,
4766
static 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+
12111362
int 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

12761434
err_type_set:
@@ -1280,6 +1438,9 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core,
12801438
err_module_plug_event_register:
12811439
mlxsw_env_temp_warn_event_unregister(env);
12821440
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:
12831444
mutex_destroy(&env->line_cards_lock);
12841445
mlxsw_env_line_cards_free(env);
12851446
err_mlxsw_env_line_cards_alloc:
@@ -1289,11 +1450,14 @@ int mlxsw_env_init(struct mlxsw_core *mlxsw_core,
12891450

12901451
void 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

Comments
 (0)