Skip to content

Commit 6cfa946

Browse files
ShayAgrosSaeed Mahameed
authored andcommitted
net/mlx5e: Ethtool driver callback for query/set FEC policy
Driver callback function for 'ethtool --show-fec', 'ethtool --set-fec' commands. The query function returns active and configured FEC policy for current link speed. The set function sets FEC policy for all supported link speeds. 1) If current link speed doesn't support requested FEC policy, the function fails. 2) If a different link speed doesn't support requested FEC policy, FEC capbilities for this speed are turned off. Signed-off-by: Shay Agroskin <shayag@mellanox.com> Reviewed-by: Eran Ben Elisha <eranbe@mellanox.com> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
1 parent 2095b26 commit 6cfa946

File tree

1 file changed

+126
-2
lines changed

1 file changed

+126
-2
lines changed

drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c

Lines changed: 126 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -547,6 +547,70 @@ static void ptys2ethtool_adver_link(unsigned long *advertising_modes,
547547
__ETHTOOL_LINK_MODE_MASK_NBITS);
548548
}
549549

550+
static const u32 pplm_fec_2_ethtool[] = {
551+
[MLX5E_FEC_NOFEC] = ETHTOOL_FEC_OFF,
552+
[MLX5E_FEC_FIRECODE] = ETHTOOL_FEC_BASER,
553+
[MLX5E_FEC_RS_528_514] = ETHTOOL_FEC_RS,
554+
};
555+
556+
static u32 pplm2ethtool_fec(u_long fec_mode, unsigned long size)
557+
{
558+
int mode = 0;
559+
560+
if (!fec_mode)
561+
return ETHTOOL_FEC_AUTO;
562+
563+
mode = find_first_bit(&fec_mode, size);
564+
565+
if (mode < ARRAY_SIZE(pplm_fec_2_ethtool))
566+
return pplm_fec_2_ethtool[mode];
567+
568+
return 0;
569+
}
570+
571+
/* we use ETHTOOL_FEC_* offset and apply it to ETHTOOL_LINK_MODE_FEC_*_BIT */
572+
static u32 ethtool_fec2ethtool_caps(u_long ethtool_fec_code)
573+
{
574+
u32 offset;
575+
576+
offset = find_first_bit(&ethtool_fec_code, sizeof(u32));
577+
offset -= ETHTOOL_FEC_OFF_BIT;
578+
offset += ETHTOOL_LINK_MODE_FEC_NONE_BIT;
579+
580+
return offset;
581+
}
582+
583+
static int get_fec_supported_advertised(struct mlx5_core_dev *dev,
584+
struct ethtool_link_ksettings *link_ksettings)
585+
{
586+
u_long fec_caps = 0;
587+
u32 active_fec = 0;
588+
u32 offset;
589+
u32 bitn;
590+
int err;
591+
592+
err = mlx5e_get_fec_caps(dev, (u8 *)&fec_caps);
593+
if (err)
594+
return (err == -EOPNOTSUPP) ? 0 : err;
595+
596+
err = mlx5e_get_fec_mode(dev, &active_fec, NULL);
597+
if (err)
598+
return err;
599+
600+
for_each_set_bit(bitn, &fec_caps, ARRAY_SIZE(pplm_fec_2_ethtool)) {
601+
u_long ethtool_bitmask = pplm_fec_2_ethtool[bitn];
602+
603+
offset = ethtool_fec2ethtool_caps(ethtool_bitmask);
604+
__set_bit(offset, link_ksettings->link_modes.supported);
605+
}
606+
607+
active_fec = pplm2ethtool_fec(active_fec, sizeof(u32) * BITS_PER_BYTE);
608+
offset = ethtool_fec2ethtool_caps(active_fec);
609+
__set_bit(offset, link_ksettings->link_modes.advertising);
610+
611+
return 0;
612+
}
613+
550614
static void ptys2ethtool_supported_advertised_port(struct ethtool_link_ksettings *link_ksettings,
551615
u32 eth_proto_cap,
552616
u8 connector_type)
@@ -742,7 +806,7 @@ static int mlx5e_get_link_ksettings(struct net_device *netdev,
742806
if (err) {
743807
netdev_err(netdev, "%s: query port ptys failed: %d\n",
744808
__func__, err);
745-
goto err_query_ptys;
809+
goto err_query_regs;
746810
}
747811

748812
eth_proto_cap = MLX5_GET(ptys_reg, out, eth_proto_capability);
@@ -778,11 +842,17 @@ static int mlx5e_get_link_ksettings(struct net_device *netdev,
778842
AUTONEG_ENABLE;
779843
ethtool_link_ksettings_add_link_mode(link_ksettings, supported,
780844
Autoneg);
845+
846+
err = get_fec_supported_advertised(mdev, link_ksettings);
847+
if (err)
848+
netdev_dbg(netdev, "%s: FEC caps query failed: %d\n",
849+
__func__, err);
850+
781851
if (!an_disable_admin)
782852
ethtool_link_ksettings_add_link_mode(link_ksettings,
783853
advertising, Autoneg);
784854

785-
err_query_ptys:
855+
err_query_regs:
786856
return err;
787857
}
788858

@@ -1277,6 +1347,58 @@ static int mlx5e_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
12771347
return mlx5_set_port_wol(mdev, mlx5_wol_mode);
12781348
}
12791349

1350+
static int mlx5e_get_fecparam(struct net_device *netdev,
1351+
struct ethtool_fecparam *fecparam)
1352+
{
1353+
struct mlx5e_priv *priv = netdev_priv(netdev);
1354+
struct mlx5_core_dev *mdev = priv->mdev;
1355+
u8 fec_configured = 0;
1356+
u32 fec_active = 0;
1357+
int err;
1358+
1359+
err = mlx5e_get_fec_mode(mdev, &fec_active, &fec_configured);
1360+
1361+
if (err)
1362+
return err;
1363+
1364+
fecparam->active_fec = pplm2ethtool_fec((u_long)fec_active,
1365+
sizeof(u32) * BITS_PER_BYTE);
1366+
1367+
if (!fecparam->active_fec)
1368+
return -EOPNOTSUPP;
1369+
1370+
fecparam->fec = pplm2ethtool_fec((u_long)fec_configured,
1371+
sizeof(u8) * BITS_PER_BYTE);
1372+
1373+
return 0;
1374+
}
1375+
1376+
static int mlx5e_set_fecparam(struct net_device *netdev,
1377+
struct ethtool_fecparam *fecparam)
1378+
{
1379+
struct mlx5e_priv *priv = netdev_priv(netdev);
1380+
struct mlx5_core_dev *mdev = priv->mdev;
1381+
u8 fec_policy = 0;
1382+
int mode;
1383+
int err;
1384+
1385+
for (mode = 0; mode < ARRAY_SIZE(pplm_fec_2_ethtool); mode++) {
1386+
if (!(pplm_fec_2_ethtool[mode] & fecparam->fec))
1387+
continue;
1388+
fec_policy |= (1 << mode);
1389+
break;
1390+
}
1391+
1392+
err = mlx5e_set_fec_mode(mdev, fec_policy);
1393+
1394+
if (err)
1395+
return err;
1396+
1397+
mlx5_toggle_port_link(mdev);
1398+
1399+
return 0;
1400+
}
1401+
12801402
static u32 mlx5e_get_msglevel(struct net_device *dev)
12811403
{
12821404
return ((struct mlx5e_priv *)netdev_priv(dev))->msglevel;
@@ -1699,4 +1821,6 @@ const struct ethtool_ops mlx5e_ethtool_ops = {
16991821
.self_test = mlx5e_self_test,
17001822
.get_msglevel = mlx5e_get_msglevel,
17011823
.set_msglevel = mlx5e_set_msglevel,
1824+
.get_fecparam = mlx5e_get_fecparam,
1825+
.set_fecparam = mlx5e_set_fecparam,
17021826
};

0 commit comments

Comments
 (0)