@@ -438,6 +438,8 @@ static const struct i40e_priv_flags i40e_gstrings_priv_flags[] = {
438
438
I40E_PRIV_FLAG ("disable-source-pruning" ,
439
439
I40E_FLAG_SOURCE_PRUNING_DISABLED , 0 ),
440
440
I40E_PRIV_FLAG ("disable-fw-lldp" , I40E_FLAG_DISABLE_FW_LLDP , 0 ),
441
+ I40E_PRIV_FLAG ("rs-fec" , I40E_FLAG_RS_FEC , 0 ),
442
+ I40E_PRIV_FLAG ("base-r-fec" , I40E_FLAG_BASE_R_FEC , 0 ),
441
443
};
442
444
443
445
#define I40E_PRIV_FLAGS_STR_LEN ARRAY_SIZE(i40e_gstrings_priv_flags)
@@ -606,6 +608,24 @@ static void i40e_phy_type_to_ethtool(struct i40e_pf *pf,
606
608
ethtool_link_ksettings_add_link_mode (ks , advertising ,
607
609
25000b aseCR_Full );
608
610
}
611
+ if (phy_types & I40E_CAP_PHY_TYPE_25GBASE_KR ||
612
+ phy_types & I40E_CAP_PHY_TYPE_25GBASE_CR ||
613
+ phy_types & I40E_CAP_PHY_TYPE_25GBASE_SR ||
614
+ phy_types & I40E_CAP_PHY_TYPE_25GBASE_LR ||
615
+ phy_types & I40E_CAP_PHY_TYPE_25GBASE_AOC ||
616
+ phy_types & I40E_CAP_PHY_TYPE_25GBASE_ACC ) {
617
+ ethtool_link_ksettings_add_link_mode (ks , supported , FEC_NONE );
618
+ ethtool_link_ksettings_add_link_mode (ks , supported , FEC_RS );
619
+ ethtool_link_ksettings_add_link_mode (ks , supported , FEC_BASER );
620
+ if (hw_link_info -> requested_speeds & I40E_LINK_SPEED_25GB ) {
621
+ ethtool_link_ksettings_add_link_mode (ks , advertising ,
622
+ FEC_NONE );
623
+ ethtool_link_ksettings_add_link_mode (ks , advertising ,
624
+ FEC_RS );
625
+ ethtool_link_ksettings_add_link_mode (ks , advertising ,
626
+ FEC_BASER );
627
+ }
628
+ }
609
629
/* need to add new 10G PHY types */
610
630
if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_CR1 ||
611
631
phy_types & I40E_CAP_PHY_TYPE_10GBASE_CR1_CU ) {
@@ -721,6 +741,13 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw,
721
741
25000b aseSR_Full );
722
742
ethtool_link_ksettings_add_link_mode (ks , advertising ,
723
743
25000b aseSR_Full );
744
+ ethtool_link_ksettings_add_link_mode (ks , supported , FEC_NONE );
745
+ ethtool_link_ksettings_add_link_mode (ks , supported , FEC_RS );
746
+ ethtool_link_ksettings_add_link_mode (ks , supported , FEC_BASER );
747
+ ethtool_link_ksettings_add_link_mode (ks , advertising , FEC_NONE );
748
+ ethtool_link_ksettings_add_link_mode (ks , advertising , FEC_RS );
749
+ ethtool_link_ksettings_add_link_mode (ks , advertising ,
750
+ FEC_BASER );
724
751
ethtool_link_ksettings_add_link_mode (ks , supported ,
725
752
10000b aseSR_Full );
726
753
ethtool_link_ksettings_add_link_mode (ks , advertising ,
@@ -825,6 +852,9 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw,
825
852
40000b aseKR4_Full );
826
853
ethtool_link_ksettings_add_link_mode (ks , supported ,
827
854
25000b aseKR_Full );
855
+ ethtool_link_ksettings_add_link_mode (ks , supported , FEC_NONE );
856
+ ethtool_link_ksettings_add_link_mode (ks , supported , FEC_RS );
857
+ ethtool_link_ksettings_add_link_mode (ks , supported , FEC_BASER );
828
858
ethtool_link_ksettings_add_link_mode (ks , supported ,
829
859
20000b aseKR2_Full );
830
860
ethtool_link_ksettings_add_link_mode (ks , supported ,
@@ -838,6 +868,10 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw,
838
868
40000b aseKR4_Full );
839
869
ethtool_link_ksettings_add_link_mode (ks , advertising ,
840
870
25000b aseKR_Full );
871
+ ethtool_link_ksettings_add_link_mode (ks , advertising , FEC_NONE );
872
+ ethtool_link_ksettings_add_link_mode (ks , advertising , FEC_RS );
873
+ ethtool_link_ksettings_add_link_mode (ks , advertising ,
874
+ FEC_BASER );
841
875
ethtool_link_ksettings_add_link_mode (ks , advertising ,
842
876
20000b aseKR2_Full );
843
877
ethtool_link_ksettings_add_link_mode (ks , advertising ,
@@ -855,16 +889,29 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw,
855
889
25000b aseCR_Full );
856
890
ethtool_link_ksettings_add_link_mode (ks , advertising ,
857
891
25000b aseCR_Full );
892
+ ethtool_link_ksettings_add_link_mode (ks , supported , FEC_NONE );
893
+ ethtool_link_ksettings_add_link_mode (ks , supported , FEC_RS );
894
+ ethtool_link_ksettings_add_link_mode (ks , supported , FEC_BASER );
895
+ ethtool_link_ksettings_add_link_mode (ks , advertising , FEC_NONE );
896
+ ethtool_link_ksettings_add_link_mode (ks , advertising , FEC_RS );
897
+ ethtool_link_ksettings_add_link_mode (ks , advertising ,
898
+ FEC_BASER );
858
899
break ;
859
900
case I40E_PHY_TYPE_25GBASE_AOC :
860
901
case I40E_PHY_TYPE_25GBASE_ACC :
861
902
ethtool_link_ksettings_add_link_mode (ks , supported , Autoneg );
862
903
ethtool_link_ksettings_add_link_mode (ks , advertising , Autoneg );
863
904
ethtool_link_ksettings_add_link_mode (ks , supported ,
864
905
25000b aseCR_Full );
865
-
866
906
ethtool_link_ksettings_add_link_mode (ks , advertising ,
867
907
25000b aseCR_Full );
908
+ ethtool_link_ksettings_add_link_mode (ks , supported , FEC_NONE );
909
+ ethtool_link_ksettings_add_link_mode (ks , supported , FEC_RS );
910
+ ethtool_link_ksettings_add_link_mode (ks , supported , FEC_BASER );
911
+ ethtool_link_ksettings_add_link_mode (ks , advertising , FEC_NONE );
912
+ ethtool_link_ksettings_add_link_mode (ks , advertising , FEC_RS );
913
+ ethtool_link_ksettings_add_link_mode (ks , advertising ,
914
+ FEC_BASER );
868
915
ethtool_link_ksettings_add_link_mode (ks , supported ,
869
916
10000b aseCR_Full );
870
917
ethtool_link_ksettings_add_link_mode (ks , advertising ,
@@ -1261,6 +1308,154 @@ static int i40e_set_link_ksettings(struct net_device *netdev,
1261
1308
return err ;
1262
1309
}
1263
1310
1311
+ static int i40e_set_fec_cfg (struct net_device * netdev , u8 fec_cfg )
1312
+ {
1313
+ struct i40e_netdev_priv * np = netdev_priv (netdev );
1314
+ struct i40e_aq_get_phy_abilities_resp abilities ;
1315
+ struct i40e_pf * pf = np -> vsi -> back ;
1316
+ struct i40e_hw * hw = & pf -> hw ;
1317
+ i40e_status status = 0 ;
1318
+ u32 flags = 0 ;
1319
+ int err = 0 ;
1320
+
1321
+ flags = READ_ONCE (pf -> flags );
1322
+ i40e_set_fec_in_flags (fec_cfg , & flags );
1323
+
1324
+ /* Get the current phy config */
1325
+ memset (& abilities , 0 , sizeof (abilities ));
1326
+ status = i40e_aq_get_phy_capabilities (hw , false, false, & abilities ,
1327
+ NULL );
1328
+ if (status ) {
1329
+ err = - EAGAIN ;
1330
+ goto done ;
1331
+ }
1332
+
1333
+ if (abilities .fec_cfg_curr_mod_ext_info != fec_cfg ) {
1334
+ struct i40e_aq_set_phy_config config ;
1335
+
1336
+ memset (& config , 0 , sizeof (config ));
1337
+ config .phy_type = abilities .phy_type ;
1338
+ config .abilities = abilities .abilities ;
1339
+ config .phy_type_ext = abilities .phy_type_ext ;
1340
+ config .link_speed = abilities .link_speed ;
1341
+ config .eee_capability = abilities .eee_capability ;
1342
+ config .eeer = abilities .eeer_val ;
1343
+ config .low_power_ctrl = abilities .d3_lpan ;
1344
+ config .fec_config = fec_cfg & I40E_AQ_PHY_FEC_CONFIG_MASK ;
1345
+ status = i40e_aq_set_phy_config (hw , & config , NULL );
1346
+ if (status ) {
1347
+ netdev_info (netdev ,
1348
+ "Set phy config failed, err %s aq_err %s\n" ,
1349
+ i40e_stat_str (hw , status ),
1350
+ i40e_aq_str (hw , hw -> aq .asq_last_status ));
1351
+ err = - EAGAIN ;
1352
+ goto done ;
1353
+ }
1354
+ pf -> flags = flags ;
1355
+ status = i40e_update_link_info (hw );
1356
+ if (status )
1357
+ /* debug level message only due to relation to the link
1358
+ * itself rather than to the FEC settings
1359
+ * (e.g. no physical connection etc.)
1360
+ */
1361
+ netdev_dbg (netdev ,
1362
+ "Updating link info failed with err %s aq_err %s\n" ,
1363
+ i40e_stat_str (hw , status ),
1364
+ i40e_aq_str (hw , hw -> aq .asq_last_status ));
1365
+ }
1366
+
1367
+ done :
1368
+ return err ;
1369
+ }
1370
+
1371
+ static int i40e_get_fec_param (struct net_device * netdev ,
1372
+ struct ethtool_fecparam * fecparam )
1373
+ {
1374
+ struct i40e_netdev_priv * np = netdev_priv (netdev );
1375
+ struct i40e_aq_get_phy_abilities_resp abilities ;
1376
+ struct i40e_pf * pf = np -> vsi -> back ;
1377
+ struct i40e_hw * hw = & pf -> hw ;
1378
+ i40e_status status = 0 ;
1379
+ int err = 0 ;
1380
+
1381
+ /* Get the current phy config */
1382
+ memset (& abilities , 0 , sizeof (abilities ));
1383
+ status = i40e_aq_get_phy_capabilities (hw , false, false, & abilities ,
1384
+ NULL );
1385
+ if (status ) {
1386
+ err = - EAGAIN ;
1387
+ goto done ;
1388
+ }
1389
+
1390
+ fecparam -> fec = 0 ;
1391
+ if (abilities .fec_cfg_curr_mod_ext_info & I40E_AQ_SET_FEC_AUTO )
1392
+ fecparam -> fec |= ETHTOOL_FEC_AUTO ;
1393
+ if ((abilities .fec_cfg_curr_mod_ext_info &
1394
+ I40E_AQ_SET_FEC_REQUEST_RS ) ||
1395
+ (abilities .fec_cfg_curr_mod_ext_info &
1396
+ I40E_AQ_SET_FEC_ABILITY_RS ))
1397
+ fecparam -> fec |= ETHTOOL_FEC_RS ;
1398
+ if ((abilities .fec_cfg_curr_mod_ext_info &
1399
+ I40E_AQ_SET_FEC_REQUEST_KR ) ||
1400
+ (abilities .fec_cfg_curr_mod_ext_info & I40E_AQ_SET_FEC_ABILITY_KR ))
1401
+ fecparam -> fec |= ETHTOOL_FEC_BASER ;
1402
+ if (abilities .fec_cfg_curr_mod_ext_info == 0 )
1403
+ fecparam -> fec |= ETHTOOL_FEC_OFF ;
1404
+
1405
+ if (hw -> phy .link_info .fec_info & I40E_AQ_CONFIG_FEC_KR_ENA )
1406
+ fecparam -> active_fec = ETHTOOL_FEC_BASER ;
1407
+ else if (hw -> phy .link_info .fec_info & I40E_AQ_CONFIG_FEC_RS_ENA )
1408
+ fecparam -> active_fec = ETHTOOL_FEC_RS ;
1409
+ else
1410
+ fecparam -> active_fec = ETHTOOL_FEC_OFF ;
1411
+ done :
1412
+ return err ;
1413
+ }
1414
+
1415
+ static int i40e_set_fec_param (struct net_device * netdev ,
1416
+ struct ethtool_fecparam * fecparam )
1417
+ {
1418
+ struct i40e_netdev_priv * np = netdev_priv (netdev );
1419
+ struct i40e_pf * pf = np -> vsi -> back ;
1420
+ struct i40e_hw * hw = & pf -> hw ;
1421
+ u8 fec_cfg = 0 ;
1422
+ int err = 0 ;
1423
+
1424
+ if (hw -> device_id != I40E_DEV_ID_25G_SFP28 &&
1425
+ hw -> device_id != I40E_DEV_ID_25G_B ) {
1426
+ err = - EPERM ;
1427
+ goto done ;
1428
+ }
1429
+
1430
+ switch (fecparam -> fec ) {
1431
+ case ETHTOOL_FEC_AUTO :
1432
+ fec_cfg = I40E_AQ_SET_FEC_AUTO ;
1433
+ break ;
1434
+ case ETHTOOL_FEC_RS :
1435
+ fec_cfg = (I40E_AQ_SET_FEC_REQUEST_RS |
1436
+ I40E_AQ_SET_FEC_ABILITY_RS );
1437
+ break ;
1438
+ case ETHTOOL_FEC_BASER :
1439
+ fec_cfg = (I40E_AQ_SET_FEC_REQUEST_KR |
1440
+ I40E_AQ_SET_FEC_ABILITY_KR );
1441
+ break ;
1442
+ case ETHTOOL_FEC_OFF :
1443
+ case ETHTOOL_FEC_NONE :
1444
+ fec_cfg = 0 ;
1445
+ break ;
1446
+ default :
1447
+ dev_warn (& pf -> pdev -> dev , "Unsupported FEC mode: %d" ,
1448
+ fecparam -> fec );
1449
+ err = - EINVAL ;
1450
+ goto done ;
1451
+ }
1452
+
1453
+ err = i40e_set_fec_cfg (netdev , fec_cfg );
1454
+
1455
+ done :
1456
+ return err ;
1457
+ }
1458
+
1264
1459
static int i40e_nway_reset (struct net_device * netdev )
1265
1460
{
1266
1461
/* restart autonegotiation */
@@ -1376,7 +1571,7 @@ static int i40e_set_pauseparam(struct net_device *netdev,
1376
1571
else if (!pause -> rx_pause && !pause -> tx_pause )
1377
1572
hw -> fc .requested_mode = I40E_FC_NONE ;
1378
1573
else
1379
- return - EINVAL ;
1574
+ return - EINVAL ;
1380
1575
1381
1576
/* Tell the OS link is going down, the link will go back up when fw
1382
1577
* says it is ready asynchronously
@@ -4676,6 +4871,15 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags)
4676
4871
}
4677
4872
}
4678
4873
4874
+ if (((changed_flags & I40E_FLAG_RS_FEC ) ||
4875
+ (changed_flags & I40E_FLAG_BASE_R_FEC )) &&
4876
+ pf -> hw .device_id != I40E_DEV_ID_25G_SFP28 &&
4877
+ pf -> hw .device_id != I40E_DEV_ID_25G_B ) {
4878
+ dev_warn (& pf -> pdev -> dev ,
4879
+ "Device does not support changing FEC configuration\n" );
4880
+ return - EOPNOTSUPP ;
4881
+ }
4882
+
4679
4883
/* Now that we've checked to ensure that the new flags are valid, load
4680
4884
* them into place. Since we only modify flags either (a) during
4681
4885
* initialization or (b) while holding the RTNL lock, we don't need
@@ -4714,6 +4918,24 @@ static int i40e_set_priv_flags(struct net_device *dev, u32 flags)
4714
4918
}
4715
4919
}
4716
4920
4921
+ if ((changed_flags & I40E_FLAG_RS_FEC ) ||
4922
+ (changed_flags & I40E_FLAG_BASE_R_FEC )) {
4923
+ u8 fec_cfg = 0 ;
4924
+
4925
+ if (pf -> flags & I40E_FLAG_RS_FEC &&
4926
+ pf -> flags & I40E_FLAG_BASE_R_FEC ) {
4927
+ fec_cfg = I40E_AQ_SET_FEC_AUTO ;
4928
+ } else if (pf -> flags & I40E_FLAG_RS_FEC ) {
4929
+ fec_cfg = (I40E_AQ_SET_FEC_REQUEST_RS |
4930
+ I40E_AQ_SET_FEC_ABILITY_RS );
4931
+ } else if (pf -> flags & I40E_FLAG_BASE_R_FEC ) {
4932
+ fec_cfg = (I40E_AQ_SET_FEC_REQUEST_KR |
4933
+ I40E_AQ_SET_FEC_ABILITY_KR );
4934
+ }
4935
+ if (i40e_set_fec_cfg (dev , fec_cfg ))
4936
+ dev_warn (& pf -> pdev -> dev , "Cannot change FEC config\n" );
4937
+ }
4938
+
4717
4939
if ((changed_flags & pf -> flags &
4718
4940
I40E_FLAG_LINK_DOWN_ON_CLOSE_ENABLED ) &&
4719
4941
(pf -> flags & I40E_FLAG_MFP_ENABLED ))
@@ -4948,6 +5170,8 @@ static const struct ethtool_ops i40e_ethtool_ops = {
4948
5170
.set_per_queue_coalesce = i40e_set_per_queue_coalesce ,
4949
5171
.get_link_ksettings = i40e_get_link_ksettings ,
4950
5172
.set_link_ksettings = i40e_set_link_ksettings ,
5173
+ .get_fecparam = i40e_get_fec_param ,
5174
+ .set_fecparam = i40e_set_fec_param ,
4951
5175
};
4952
5176
4953
5177
void i40e_set_ethtool_ops (struct net_device * netdev )
0 commit comments