1
1
/* Broadcom NetXtreme-C/E network driver.
2
2
*
3
- * Copyright (c) 2014-2015 Broadcom Corporation
3
+ * Copyright (c) 2014-2016 Broadcom Corporation
4
4
*
5
5
* This program is free software; you can redistribute it and/or modify
6
6
* it under the terms of the GNU General Public License as published by
@@ -597,7 +597,7 @@ static void bnxt_get_drvinfo(struct net_device *dev,
597
597
kfree (pkglog );
598
598
}
599
599
600
- static u32 _bnxt_fw_to_ethtool_adv_spds (u16 fw_speeds , u8 fw_pause )
600
+ u32 _bnxt_fw_to_ethtool_adv_spds (u16 fw_speeds , u8 fw_pause )
601
601
{
602
602
u32 speed_mask = 0 ;
603
603
@@ -698,10 +698,23 @@ static int bnxt_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
698
698
if (link_info -> phy_link_status == BNXT_LINK_LINK )
699
699
cmd -> lp_advertising =
700
700
bnxt_fw_to_ethtool_lp_adv (link_info );
701
+ ethtool_speed = bnxt_fw_to_ethtool_speed (link_info -> link_speed );
702
+ if (!netif_carrier_ok (dev ))
703
+ cmd -> duplex = DUPLEX_UNKNOWN ;
704
+ else if (link_info -> duplex & BNXT_LINK_DUPLEX_FULL )
705
+ cmd -> duplex = DUPLEX_FULL ;
706
+ else
707
+ cmd -> duplex = DUPLEX_HALF ;
701
708
} else {
702
709
cmd -> autoneg = AUTONEG_DISABLE ;
703
710
cmd -> advertising = 0 ;
711
+ ethtool_speed =
712
+ bnxt_fw_to_ethtool_speed (link_info -> req_link_speed );
713
+ cmd -> duplex = DUPLEX_HALF ;
714
+ if (link_info -> req_duplex == BNXT_LINK_DUPLEX_FULL )
715
+ cmd -> duplex = DUPLEX_FULL ;
704
716
}
717
+ ethtool_cmd_speed_set (cmd , ethtool_speed );
705
718
706
719
cmd -> port = PORT_NONE ;
707
720
if (link_info -> media_type == PORT_PHY_QCFG_RESP_MEDIA_TYPE_TP ) {
@@ -719,16 +732,8 @@ static int bnxt_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
719
732
cmd -> port = PORT_FIBRE ;
720
733
}
721
734
722
- if (link_info -> phy_link_status == BNXT_LINK_LINK ) {
723
- if (link_info -> duplex & BNXT_LINK_DUPLEX_FULL )
724
- cmd -> duplex = DUPLEX_FULL ;
725
- } else {
726
- cmd -> duplex = DUPLEX_UNKNOWN ;
727
- }
728
- ethtool_speed = bnxt_fw_to_ethtool_speed (link_info -> link_speed );
729
- ethtool_cmd_speed_set (cmd , ethtool_speed );
730
735
if (link_info -> transceiver ==
731
- PORT_PHY_QCFG_RESP_TRANSCEIVER_TYPE_XCVR_INTERNAL )
736
+ PORT_PHY_QCFG_RESP_XCVR_PKG_TYPE_XCVR_INTERNAL )
732
737
cmd -> transceiver = XCVR_INTERNAL ;
733
738
else
734
739
cmd -> transceiver = XCVR_EXTERNAL ;
@@ -739,31 +744,52 @@ static int bnxt_get_settings(struct net_device *dev, struct ethtool_cmd *cmd)
739
744
740
745
static u32 bnxt_get_fw_speed (struct net_device * dev , u16 ethtool_speed )
741
746
{
747
+ struct bnxt * bp = netdev_priv (dev );
748
+ struct bnxt_link_info * link_info = & bp -> link_info ;
749
+ u16 support_spds = link_info -> support_speeds ;
750
+ u32 fw_speed = 0 ;
751
+
742
752
switch (ethtool_speed ) {
743
753
case SPEED_100 :
744
- return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_100MB ;
754
+ if (support_spds & BNXT_LINK_SPEED_MSK_100MB )
755
+ fw_speed = PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_100MB ;
756
+ break ;
745
757
case SPEED_1000 :
746
- return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_1GB ;
758
+ if (support_spds & BNXT_LINK_SPEED_MSK_1GB )
759
+ fw_speed = PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_1GB ;
760
+ break ;
747
761
case SPEED_2500 :
748
- return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_2_5GB ;
762
+ if (support_spds & BNXT_LINK_SPEED_MSK_2_5GB )
763
+ fw_speed = PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_2_5GB ;
764
+ break ;
749
765
case SPEED_10000 :
750
- return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_10GB ;
766
+ if (support_spds & BNXT_LINK_SPEED_MSK_10GB )
767
+ fw_speed = PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_10GB ;
768
+ break ;
751
769
case SPEED_20000 :
752
- return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_20GB ;
770
+ if (support_spds & BNXT_LINK_SPEED_MSK_20GB )
771
+ fw_speed = PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_20GB ;
772
+ break ;
753
773
case SPEED_25000 :
754
- return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_25GB ;
774
+ if (support_spds & BNXT_LINK_SPEED_MSK_25GB )
775
+ fw_speed = PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_25GB ;
776
+ break ;
755
777
case SPEED_40000 :
756
- return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_40GB ;
778
+ if (support_spds & BNXT_LINK_SPEED_MSK_40GB )
779
+ fw_speed = PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_40GB ;
780
+ break ;
757
781
case SPEED_50000 :
758
- return PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_50GB ;
782
+ if (support_spds & BNXT_LINK_SPEED_MSK_50GB )
783
+ fw_speed = PORT_PHY_CFG_REQ_AUTO_LINK_SPEED_50GB ;
784
+ break ;
759
785
default :
760
786
netdev_err (dev , "unsupported speed!\n" );
761
787
break ;
762
788
}
763
- return 0 ;
789
+ return fw_speed ;
764
790
}
765
791
766
- static u16 bnxt_get_fw_auto_link_speeds (u32 advertising )
792
+ u16 bnxt_get_fw_auto_link_speeds (u32 advertising )
767
793
{
768
794
u16 fw_speed_mask = 0 ;
769
795
@@ -823,6 +849,8 @@ static int bnxt_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
823
849
*/
824
850
set_pause = true;
825
851
} else {
852
+ u16 fw_speed ;
853
+
826
854
/* TODO: currently don't support half duplex */
827
855
if (cmd -> duplex == DUPLEX_HALF ) {
828
856
netdev_err (dev , "HALF DUPLEX is not supported!\n" );
@@ -833,14 +861,19 @@ static int bnxt_set_settings(struct net_device *dev, struct ethtool_cmd *cmd)
833
861
if (cmd -> duplex == DUPLEX_UNKNOWN )
834
862
cmd -> duplex = DUPLEX_FULL ;
835
863
speed = ethtool_cmd_speed (cmd );
836
- link_info -> req_link_speed = bnxt_get_fw_speed (dev , speed );
864
+ fw_speed = bnxt_get_fw_speed (dev , speed );
865
+ if (!fw_speed ) {
866
+ rc = - EINVAL ;
867
+ goto set_setting_exit ;
868
+ }
869
+ link_info -> req_link_speed = fw_speed ;
837
870
link_info -> req_duplex = BNXT_LINK_DUPLEX_FULL ;
838
871
link_info -> autoneg = 0 ;
839
872
link_info -> advertising = 0 ;
840
873
}
841
874
842
875
if (netif_running (dev ))
843
- rc = bnxt_hwrm_set_link_setting (bp , set_pause );
876
+ rc = bnxt_hwrm_set_link_setting (bp , set_pause , false );
844
877
845
878
set_setting_exit :
846
879
return rc ;
@@ -874,25 +907,23 @@ static int bnxt_set_pauseparam(struct net_device *dev,
874
907
return - EINVAL ;
875
908
876
909
link_info -> autoneg |= BNXT_AUTONEG_FLOW_CTRL ;
877
- link_info -> req_flow_ctrl |= BNXT_LINK_PAUSE_BOTH ;
910
+ if (bp -> hwrm_spec_code >= 0x10201 )
911
+ link_info -> req_flow_ctrl =
912
+ PORT_PHY_CFG_REQ_AUTO_PAUSE_AUTONEG_PAUSE ;
878
913
} else {
879
914
/* when transition from auto pause to force pause,
880
915
* force a link change
881
916
*/
882
917
if (link_info -> autoneg & BNXT_AUTONEG_FLOW_CTRL )
883
918
link_info -> force_link_chng = true;
884
919
link_info -> autoneg &= ~BNXT_AUTONEG_FLOW_CTRL ;
885
- link_info -> req_flow_ctrl &= ~ BNXT_LINK_PAUSE_BOTH ;
920
+ link_info -> req_flow_ctrl = 0 ;
886
921
}
887
922
if (epause -> rx_pause )
888
923
link_info -> req_flow_ctrl |= BNXT_LINK_PAUSE_RX ;
889
- else
890
- link_info -> req_flow_ctrl &= ~BNXT_LINK_PAUSE_RX ;
891
924
892
925
if (epause -> tx_pause )
893
926
link_info -> req_flow_ctrl |= BNXT_LINK_PAUSE_TX ;
894
- else
895
- link_info -> req_flow_ctrl &= ~BNXT_LINK_PAUSE_TX ;
896
927
897
928
if (netif_running (dev ))
898
929
rc = bnxt_hwrm_set_pause (bp );
@@ -1381,6 +1412,80 @@ static int bnxt_set_eeprom(struct net_device *dev,
1381
1412
eeprom -> len );
1382
1413
}
1383
1414
1415
+ static int bnxt_set_eee (struct net_device * dev , struct ethtool_eee * edata )
1416
+ {
1417
+ struct bnxt * bp = netdev_priv (dev );
1418
+ struct ethtool_eee * eee = & bp -> eee ;
1419
+ struct bnxt_link_info * link_info = & bp -> link_info ;
1420
+ u32 advertising =
1421
+ _bnxt_fw_to_ethtool_adv_spds (link_info -> advertising , 0 );
1422
+ int rc = 0 ;
1423
+
1424
+ if (BNXT_VF (bp ))
1425
+ return 0 ;
1426
+
1427
+ if (!(bp -> flags & BNXT_FLAG_EEE_CAP ))
1428
+ return - EOPNOTSUPP ;
1429
+
1430
+ if (!edata -> eee_enabled )
1431
+ goto eee_ok ;
1432
+
1433
+ if (!(link_info -> autoneg & BNXT_AUTONEG_SPEED )) {
1434
+ netdev_warn (dev , "EEE requires autoneg\n" );
1435
+ return - EINVAL ;
1436
+ }
1437
+ if (edata -> tx_lpi_enabled ) {
1438
+ if (bp -> lpi_tmr_hi && (edata -> tx_lpi_timer > bp -> lpi_tmr_hi ||
1439
+ edata -> tx_lpi_timer < bp -> lpi_tmr_lo )) {
1440
+ netdev_warn (dev , "Valid LPI timer range is %d and %d microsecs\n" ,
1441
+ bp -> lpi_tmr_lo , bp -> lpi_tmr_hi );
1442
+ return - EINVAL ;
1443
+ } else if (!bp -> lpi_tmr_hi ) {
1444
+ edata -> tx_lpi_timer = eee -> tx_lpi_timer ;
1445
+ }
1446
+ }
1447
+ if (!edata -> advertised ) {
1448
+ edata -> advertised = advertising & eee -> supported ;
1449
+ } else if (edata -> advertised & ~advertising ) {
1450
+ netdev_warn (dev , "EEE advertised %x must be a subset of autoneg advertised speeds %x\n" ,
1451
+ edata -> advertised , advertising );
1452
+ return - EINVAL ;
1453
+ }
1454
+
1455
+ eee -> advertised = edata -> advertised ;
1456
+ eee -> tx_lpi_enabled = edata -> tx_lpi_enabled ;
1457
+ eee -> tx_lpi_timer = edata -> tx_lpi_timer ;
1458
+ eee_ok :
1459
+ eee -> eee_enabled = edata -> eee_enabled ;
1460
+
1461
+ if (netif_running (dev ))
1462
+ rc = bnxt_hwrm_set_link_setting (bp , false, true);
1463
+
1464
+ return rc ;
1465
+ }
1466
+
1467
+ static int bnxt_get_eee (struct net_device * dev , struct ethtool_eee * edata )
1468
+ {
1469
+ struct bnxt * bp = netdev_priv (dev );
1470
+
1471
+ if (!(bp -> flags & BNXT_FLAG_EEE_CAP ))
1472
+ return - EOPNOTSUPP ;
1473
+
1474
+ * edata = bp -> eee ;
1475
+ if (!bp -> eee .eee_enabled ) {
1476
+ /* Preserve tx_lpi_timer so that the last value will be used
1477
+ * by default when it is re-enabled.
1478
+ */
1479
+ edata -> advertised = 0 ;
1480
+ edata -> tx_lpi_enabled = 0 ;
1481
+ }
1482
+
1483
+ if (!bp -> eee .eee_active )
1484
+ edata -> lp_advertised = 0 ;
1485
+
1486
+ return 0 ;
1487
+ }
1488
+
1384
1489
const struct ethtool_ops bnxt_ethtool_ops = {
1385
1490
.get_settings = bnxt_get_settings ,
1386
1491
.set_settings = bnxt_set_settings ,
@@ -1409,4 +1514,6 @@ const struct ethtool_ops bnxt_ethtool_ops = {
1409
1514
.get_eeprom = bnxt_get_eeprom ,
1410
1515
.set_eeprom = bnxt_set_eeprom ,
1411
1516
.get_link = bnxt_get_link ,
1517
+ .get_eee = bnxt_get_eee ,
1518
+ .set_eee = bnxt_set_eee ,
1412
1519
};
0 commit comments