@@ -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 */
691802static 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
11491262const 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
11621277void nfp_net_set_ethtool_ops (struct net_device * netdev )
0 commit comments