Skip to content

Commit 0d08709

Browse files
Dirk van der Merwedavem330
authored andcommitted
nfp: implement ethtool FEC mode settings
Add support in the driver ethtool ops to modify the NFP FEC modes. The FEC modes can be set for vNIC associated with physical ports or for MAC representor netdevs. Signed-off-by: Dirk van der Merwe <[email protected]> Signed-off-by: Simon Horman <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent b471232 commit 0d08709

File tree

1 file changed

+116
-1
lines changed

1 file changed

+116
-1
lines changed

drivers/net/ethernet/netronome/nfp/nfp_net_ethtool.c

Lines changed: 116 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,30 @@ nfp_app_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
244244
nfp_get_drvinfo(app, app->pdev, "*", drvinfo);
245245
}
246246

247+
static void
248+
nfp_net_set_fec_link_mode(struct nfp_eth_table_port *eth_port,
249+
struct ethtool_link_ksettings *c)
250+
{
251+
unsigned int modes;
252+
253+
ethtool_link_ksettings_add_link_mode(c, supported, FEC_NONE);
254+
if (!nfp_eth_can_support_fec(eth_port)) {
255+
ethtool_link_ksettings_add_link_mode(c, advertising, FEC_NONE);
256+
return;
257+
}
258+
259+
modes = nfp_eth_supported_fec_modes(eth_port);
260+
if (modes & NFP_FEC_BASER) {
261+
ethtool_link_ksettings_add_link_mode(c, supported, FEC_BASER);
262+
ethtool_link_ksettings_add_link_mode(c, advertising, FEC_BASER);
263+
}
264+
265+
if (modes & NFP_FEC_REED_SOLOMON) {
266+
ethtool_link_ksettings_add_link_mode(c, supported, FEC_RS);
267+
ethtool_link_ksettings_add_link_mode(c, advertising, FEC_RS);
268+
}
269+
}
270+
247271
/**
248272
* nfp_net_get_link_ksettings - Get Link Speed settings
249273
* @netdev: network interface device structure
@@ -278,9 +302,11 @@ nfp_net_get_link_ksettings(struct net_device *netdev,
278302

279303
port = nfp_port_from_netdev(netdev);
280304
eth_port = nfp_port_get_eth_port(port);
281-
if (eth_port)
305+
if (eth_port) {
282306
cmd->base.autoneg = eth_port->aneg != NFP_ANEG_DISABLED ?
283307
AUTONEG_ENABLE : AUTONEG_DISABLE;
308+
nfp_net_set_fec_link_mode(eth_port, cmd);
309+
}
284310

285311
if (!netif_carrier_ok(netdev))
286312
return 0;
@@ -686,6 +712,91 @@ static int nfp_port_get_sset_count(struct net_device *netdev, int sset)
686712
}
687713
}
688714

715+
static int nfp_port_fec_ethtool_to_nsp(u32 fec)
716+
{
717+
switch (fec) {
718+
case ETHTOOL_FEC_AUTO:
719+
return NFP_FEC_AUTO_BIT;
720+
case ETHTOOL_FEC_OFF:
721+
return NFP_FEC_DISABLED_BIT;
722+
case ETHTOOL_FEC_RS:
723+
return NFP_FEC_REED_SOLOMON_BIT;
724+
case ETHTOOL_FEC_BASER:
725+
return NFP_FEC_BASER_BIT;
726+
default:
727+
/* NSP only supports a single mode at a time */
728+
return -EOPNOTSUPP;
729+
}
730+
}
731+
732+
static u32 nfp_port_fec_nsp_to_ethtool(u32 fec)
733+
{
734+
u32 result = 0;
735+
736+
if (fec & NFP_FEC_AUTO)
737+
result |= ETHTOOL_FEC_AUTO;
738+
if (fec & NFP_FEC_BASER)
739+
result |= ETHTOOL_FEC_BASER;
740+
if (fec & NFP_FEC_REED_SOLOMON)
741+
result |= ETHTOOL_FEC_RS;
742+
if (fec & NFP_FEC_DISABLED)
743+
result |= ETHTOOL_FEC_OFF;
744+
745+
return result ?: ETHTOOL_FEC_NONE;
746+
}
747+
748+
static int
749+
nfp_port_get_fecparam(struct net_device *netdev,
750+
struct ethtool_fecparam *param)
751+
{
752+
struct nfp_eth_table_port *eth_port;
753+
struct nfp_port *port;
754+
755+
param->active_fec = ETHTOOL_FEC_NONE_BIT;
756+
param->fec = ETHTOOL_FEC_NONE_BIT;
757+
758+
port = nfp_port_from_netdev(netdev);
759+
eth_port = nfp_port_get_eth_port(port);
760+
if (!eth_port)
761+
return -EOPNOTSUPP;
762+
763+
if (!nfp_eth_can_support_fec(eth_port))
764+
return 0;
765+
766+
param->fec = nfp_port_fec_nsp_to_ethtool(eth_port->fec_modes_supported);
767+
param->active_fec = nfp_port_fec_nsp_to_ethtool(eth_port->fec);
768+
769+
return 0;
770+
}
771+
772+
static int
773+
nfp_port_set_fecparam(struct net_device *netdev,
774+
struct ethtool_fecparam *param)
775+
{
776+
struct nfp_eth_table_port *eth_port;
777+
struct nfp_port *port;
778+
int err, fec;
779+
780+
port = nfp_port_from_netdev(netdev);
781+
eth_port = nfp_port_get_eth_port(port);
782+
if (!eth_port)
783+
return -EOPNOTSUPP;
784+
785+
if (!nfp_eth_can_support_fec(eth_port))
786+
return -EOPNOTSUPP;
787+
788+
fec = nfp_port_fec_ethtool_to_nsp(param->fec);
789+
if (fec < 0)
790+
return fec;
791+
792+
err = nfp_eth_set_fec(port->app->cpp, eth_port->index, fec);
793+
if (!err)
794+
/* Only refresh if we did something */
795+
nfp_net_refresh_port_table(port);
796+
797+
return err < 0 ? err : 0;
798+
}
799+
689800
/* RX network flow classification (RSS, filters, etc)
690801
*/
691802
static u32 ethtool_flow_to_nfp_flag(u32 flow_type)
@@ -1144,6 +1255,8 @@ static const struct ethtool_ops nfp_net_ethtool_ops = {
11441255
.set_channels = nfp_net_set_channels,
11451256
.get_link_ksettings = nfp_net_get_link_ksettings,
11461257
.set_link_ksettings = nfp_net_set_link_ksettings,
1258+
.get_fecparam = nfp_port_get_fecparam,
1259+
.set_fecparam = nfp_port_set_fecparam,
11471260
};
11481261

11491262
const struct ethtool_ops nfp_port_ethtool_ops = {
@@ -1157,6 +1270,8 @@ const struct ethtool_ops nfp_port_ethtool_ops = {
11571270
.get_dump_data = nfp_app_get_dump_data,
11581271
.get_link_ksettings = nfp_net_get_link_ksettings,
11591272
.set_link_ksettings = nfp_net_set_link_ksettings,
1273+
.get_fecparam = nfp_port_get_fecparam,
1274+
.set_fecparam = nfp_port_set_fecparam,
11601275
};
11611276

11621277
void nfp_net_set_ethtool_ops(struct net_device *netdev)

0 commit comments

Comments
 (0)