@@ -244,6 +244,30 @@ nfp_app_get_drvinfo(struct net_device *netdev, struct ethtool_drvinfo *drvinfo)
244
244
nfp_get_drvinfo (app , app -> pdev , "*" , drvinfo );
245
245
}
246
246
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
+
247
271
/**
248
272
* nfp_net_get_link_ksettings - Get Link Speed settings
249
273
* @netdev: network interface device structure
@@ -278,9 +302,11 @@ nfp_net_get_link_ksettings(struct net_device *netdev,
278
302
279
303
port = nfp_port_from_netdev (netdev );
280
304
eth_port = nfp_port_get_eth_port (port );
281
- if (eth_port )
305
+ if (eth_port ) {
282
306
cmd -> base .autoneg = eth_port -> aneg != NFP_ANEG_DISABLED ?
283
307
AUTONEG_ENABLE : AUTONEG_DISABLE ;
308
+ nfp_net_set_fec_link_mode (eth_port , cmd );
309
+ }
284
310
285
311
if (!netif_carrier_ok (netdev ))
286
312
return 0 ;
@@ -686,6 +712,91 @@ static int nfp_port_get_sset_count(struct net_device *netdev, int sset)
686
712
}
687
713
}
688
714
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
+
689
800
/* RX network flow classification (RSS, filters, etc)
690
801
*/
691
802
static u32 ethtool_flow_to_nfp_flag (u32 flow_type )
@@ -1144,6 +1255,8 @@ static const struct ethtool_ops nfp_net_ethtool_ops = {
1144
1255
.set_channels = nfp_net_set_channels ,
1145
1256
.get_link_ksettings = nfp_net_get_link_ksettings ,
1146
1257
.set_link_ksettings = nfp_net_set_link_ksettings ,
1258
+ .get_fecparam = nfp_port_get_fecparam ,
1259
+ .set_fecparam = nfp_port_set_fecparam ,
1147
1260
};
1148
1261
1149
1262
const struct ethtool_ops nfp_port_ethtool_ops = {
@@ -1157,6 +1270,8 @@ const struct ethtool_ops nfp_port_ethtool_ops = {
1157
1270
.get_dump_data = nfp_app_get_dump_data ,
1158
1271
.get_link_ksettings = nfp_net_get_link_ksettings ,
1159
1272
.set_link_ksettings = nfp_net_set_link_ksettings ,
1273
+ .get_fecparam = nfp_port_get_fecparam ,
1274
+ .set_fecparam = nfp_port_set_fecparam ,
1160
1275
};
1161
1276
1162
1277
void nfp_net_set_ethtool_ops (struct net_device * netdev )
0 commit comments