ixgbe: Add ethtool support to enable 2.5 and 5.0 Gbps support
authorRadoslaw Tyl <radoslawx.tyl@intel.com>
Fri, 26 Jun 2020 13:28:14 +0000 (15:28 +0200)
committerTony Nguyen <anthony.l.nguyen@intel.com>
Wed, 1 Jul 2020 22:04:54 +0000 (15:04 -0700)
Added full support for new version Ethtool API. New API allow use
2500Gbase-T and 5000base-T supported and advertised link speed modes.

Signed-off-by: Radoslaw Tyl <radoslawx.tyl@intel.com>
Tested-by: Andrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c

index fd67849527667b11e344da941cb9837d712066b2..6725d892336e3ed9acc91773741c149438efc7b9 100644 (file)
@@ -142,32 +142,71 @@ static const char ixgbe_priv_flags_strings[][ETH_GSTRING_LEN] = {
 
 #define IXGBE_PRIV_FLAGS_STR_LEN ARRAY_SIZE(ixgbe_priv_flags_strings)
 
-/* currently supported speeds for 10G */
-#define ADVRTSD_MSK_10G (SUPPORTED_10000baseT_Full | \
-                        SUPPORTED_10000baseKX4_Full | \
-                        SUPPORTED_10000baseKR_Full)
-
 #define ixgbe_isbackplane(type) ((type) == ixgbe_media_type_backplane)
 
-static u32 ixgbe_get_supported_10gtypes(struct ixgbe_hw *hw)
+static void ixgbe_set_supported_10gtypes(struct ixgbe_hw *hw,
+                                        struct ethtool_link_ksettings *cmd)
 {
-       if (!ixgbe_isbackplane(hw->phy.media_type))
-               return SUPPORTED_10000baseT_Full;
+       if (!ixgbe_isbackplane(hw->phy.media_type)) {
+               ethtool_link_ksettings_add_link_mode(cmd, supported,
+                                                    10000baseT_Full);
+               return;
+       }
 
        switch (hw->device_id) {
        case IXGBE_DEV_ID_82598:
        case IXGBE_DEV_ID_82599_KX4:
        case IXGBE_DEV_ID_82599_KX4_MEZZ:
        case IXGBE_DEV_ID_X550EM_X_KX4:
-               return SUPPORTED_10000baseKX4_Full;
+               ethtool_link_ksettings_add_link_mode
+                       (cmd, supported, 10000baseKX4_Full);
+               break;
        case IXGBE_DEV_ID_82598_BX:
        case IXGBE_DEV_ID_82599_KR:
        case IXGBE_DEV_ID_X550EM_X_KR:
        case IXGBE_DEV_ID_X550EM_X_XFI:
-               return SUPPORTED_10000baseKR_Full;
+               ethtool_link_ksettings_add_link_mode
+                       (cmd, supported, 10000baseKR_Full);
+               break;
        default:
-               return SUPPORTED_10000baseKX4_Full |
-                      SUPPORTED_10000baseKR_Full;
+               ethtool_link_ksettings_add_link_mode
+                       (cmd, supported, 10000baseKX4_Full);
+               ethtool_link_ksettings_add_link_mode
+                       (cmd, supported, 10000baseKR_Full);
+               break;
+       }
+}
+
+static void ixgbe_set_advertising_10gtypes(struct ixgbe_hw *hw,
+                                          struct ethtool_link_ksettings *cmd)
+{
+       if (!ixgbe_isbackplane(hw->phy.media_type)) {
+               ethtool_link_ksettings_add_link_mode(cmd, advertising,
+                                                    10000baseT_Full);
+               return;
+       }
+
+       switch (hw->device_id) {
+       case IXGBE_DEV_ID_82598:
+       case IXGBE_DEV_ID_82599_KX4:
+       case IXGBE_DEV_ID_82599_KX4_MEZZ:
+       case IXGBE_DEV_ID_X550EM_X_KX4:
+               ethtool_link_ksettings_add_link_mode
+                       (cmd, advertising, 10000baseKX4_Full);
+               break;
+       case IXGBE_DEV_ID_82598_BX:
+       case IXGBE_DEV_ID_82599_KR:
+       case IXGBE_DEV_ID_X550EM_X_KR:
+       case IXGBE_DEV_ID_X550EM_X_XFI:
+               ethtool_link_ksettings_add_link_mode
+                       (cmd, advertising, 10000baseKR_Full);
+               break;
+       default:
+               ethtool_link_ksettings_add_link_mode
+                       (cmd, advertising, 10000baseKX4_Full);
+               ethtool_link_ksettings_add_link_mode
+                       (cmd, advertising, 10000baseKR_Full);
+               break;
        }
 }
 
@@ -178,52 +217,88 @@ static int ixgbe_get_link_ksettings(struct net_device *netdev,
        struct ixgbe_hw *hw = &adapter->hw;
        ixgbe_link_speed supported_link;
        bool autoneg = false;
-       u32 supported, advertising;
 
-       ethtool_convert_link_mode_to_legacy_u32(&supported,
-                                               cmd->link_modes.supported);
+       ethtool_link_ksettings_zero_link_mode(cmd, supported);
+       ethtool_link_ksettings_zero_link_mode(cmd, advertising);
 
        hw->mac.ops.get_link_capabilities(hw, &supported_link, &autoneg);
 
        /* set the supported link speeds */
-       if (supported_link & IXGBE_LINK_SPEED_10GB_FULL)
-               supported |= ixgbe_get_supported_10gtypes(hw);
-       if (supported_link & IXGBE_LINK_SPEED_1GB_FULL)
-               supported |= (ixgbe_isbackplane(hw->phy.media_type)) ?
-                                  SUPPORTED_1000baseKX_Full :
-                                  SUPPORTED_1000baseT_Full;
-       if (supported_link & IXGBE_LINK_SPEED_100_FULL)
-               supported |= SUPPORTED_100baseT_Full;
-       if (supported_link & IXGBE_LINK_SPEED_10_FULL)
-               supported |= SUPPORTED_10baseT_Full;
-
-       /* default advertised speed if phy.autoneg_advertised isn't set */
-       advertising = supported;
+       if (supported_link & IXGBE_LINK_SPEED_10GB_FULL) {
+               ixgbe_set_supported_10gtypes(hw, cmd);
+               ixgbe_set_advertising_10gtypes(hw, cmd);
+       }
+       if (supported_link & IXGBE_LINK_SPEED_5GB_FULL)
+               ethtool_link_ksettings_add_link_mode(cmd, supported,
+                                                    5000baseT_Full);
+
+       if (supported_link & IXGBE_LINK_SPEED_2_5GB_FULL)
+               ethtool_link_ksettings_add_link_mode(cmd, supported,
+                                                    2500baseT_Full);
+
+       if (supported_link & IXGBE_LINK_SPEED_1GB_FULL) {
+               if (ixgbe_isbackplane(hw->phy.media_type)) {
+                       ethtool_link_ksettings_add_link_mode(cmd, supported,
+                                                            1000baseKX_Full);
+                       ethtool_link_ksettings_add_link_mode(cmd, advertising,
+                                                            1000baseKX_Full);
+               } else {
+                       ethtool_link_ksettings_add_link_mode(cmd, supported,
+                                                            1000baseT_Full);
+                       ethtool_link_ksettings_add_link_mode(cmd, advertising,
+                                                            1000baseT_Full);
+               }
+       }
+       if (supported_link & IXGBE_LINK_SPEED_100_FULL) {
+               ethtool_link_ksettings_add_link_mode(cmd, supported,
+                                                    100baseT_Full);
+               ethtool_link_ksettings_add_link_mode(cmd, advertising,
+                                                    100baseT_Full);
+       }
+       if (supported_link & IXGBE_LINK_SPEED_10_FULL) {
+               ethtool_link_ksettings_add_link_mode(cmd, supported,
+                                                    10baseT_Full);
+               ethtool_link_ksettings_add_link_mode(cmd, advertising,
+                                                    10baseT_Full);
+       }
+
        /* set the advertised speeds */
        if (hw->phy.autoneg_advertised) {
-               advertising = 0;
+               ethtool_link_ksettings_zero_link_mode(cmd, advertising);
                if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10_FULL)
-                       advertising |= ADVERTISED_10baseT_Full;
+                       ethtool_link_ksettings_add_link_mode(cmd, advertising,
+                                                            10baseT_Full);
                if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_100_FULL)
-                       advertising |= ADVERTISED_100baseT_Full;
+                       ethtool_link_ksettings_add_link_mode(cmd, advertising,
+                                                            100baseT_Full);
                if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_10GB_FULL)
-                       advertising |= supported & ADVRTSD_MSK_10G;
+                       ixgbe_set_advertising_10gtypes(hw, cmd);
                if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) {
-                       if (supported & SUPPORTED_1000baseKX_Full)
-                               advertising |= ADVERTISED_1000baseKX_Full;
+                       if (ethtool_link_ksettings_test_link_mode
+                               (cmd, supported, 1000baseKX_Full))
+                               ethtool_link_ksettings_add_link_mode
+                                       (cmd, advertising, 1000baseKX_Full);
                        else
-                               advertising |= ADVERTISED_1000baseT_Full;
+                               ethtool_link_ksettings_add_link_mode
+                                       (cmd, advertising, 1000baseT_Full);
                }
+               if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_5GB_FULL)
+                       ethtool_link_ksettings_add_link_mode(cmd, advertising,
+                                                            5000baseT_Full);
+               if (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_2_5GB_FULL)
+                       ethtool_link_ksettings_add_link_mode(cmd, advertising,
+                                                            2500baseT_Full);
        } else {
                if (hw->phy.multispeed_fiber && !autoneg) {
                        if (supported_link & IXGBE_LINK_SPEED_10GB_FULL)
-                               advertising = ADVERTISED_10000baseT_Full;
+                               ethtool_link_ksettings_add_link_mode
+                                       (cmd, advertising, 10000baseT_Full);
                }
        }
 
        if (autoneg) {
-               supported |= SUPPORTED_Autoneg;
-               advertising |= ADVERTISED_Autoneg;
+               ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg);
+               ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg);
                cmd->base.autoneg = AUTONEG_ENABLE;
        } else
                cmd->base.autoneg = AUTONEG_DISABLE;
@@ -235,13 +310,13 @@ static int ixgbe_get_link_ksettings(struct net_device *netdev,
        case ixgbe_phy_x550em_ext_t:
        case ixgbe_phy_fw:
        case ixgbe_phy_cu_unknown:
-               supported |= SUPPORTED_TP;
-               advertising |= ADVERTISED_TP;
+               ethtool_link_ksettings_add_link_mode(cmd, supported, TP);
+               ethtool_link_ksettings_add_link_mode(cmd, advertising, TP);
                cmd->base.port = PORT_TP;
                break;
        case ixgbe_phy_qt:
-               supported |= SUPPORTED_FIBRE;
-               advertising |= ADVERTISED_FIBRE;
+               ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
+               ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE);
                cmd->base.port = PORT_FIBRE;
                break;
        case ixgbe_phy_nl:
@@ -260,8 +335,10 @@ static int ixgbe_get_link_ksettings(struct net_device *netdev,
                case ixgbe_sfp_type_da_cu:
                case ixgbe_sfp_type_da_cu_core0:
                case ixgbe_sfp_type_da_cu_core1:
-                       supported |= SUPPORTED_FIBRE;
-                       advertising |= ADVERTISED_FIBRE;
+                       ethtool_link_ksettings_add_link_mode(cmd, supported,
+                                                            FIBRE);
+                       ethtool_link_ksettings_add_link_mode(cmd, advertising,
+                                                            FIBRE);
                        cmd->base.port = PORT_DA;
                        break;
                case ixgbe_sfp_type_sr:
@@ -272,61 +349,76 @@ static int ixgbe_get_link_ksettings(struct net_device *netdev,
                case ixgbe_sfp_type_1g_sx_core1:
                case ixgbe_sfp_type_1g_lx_core0:
                case ixgbe_sfp_type_1g_lx_core1:
-                       supported |= SUPPORTED_FIBRE;
-                       advertising |= ADVERTISED_FIBRE;
+                       ethtool_link_ksettings_add_link_mode(cmd, supported,
+                                                            FIBRE);
+                       ethtool_link_ksettings_add_link_mode(cmd, advertising,
+                                                            FIBRE);
                        cmd->base.port = PORT_FIBRE;
                        break;
                case ixgbe_sfp_type_not_present:
-                       supported |= SUPPORTED_FIBRE;
-                       advertising |= ADVERTISED_FIBRE;
+                       ethtool_link_ksettings_add_link_mode(cmd, supported,
+                                                            FIBRE);
+                       ethtool_link_ksettings_add_link_mode(cmd, advertising,
+                                                            FIBRE);
                        cmd->base.port = PORT_NONE;
                        break;
                case ixgbe_sfp_type_1g_cu_core0:
                case ixgbe_sfp_type_1g_cu_core1:
-                       supported |= SUPPORTED_TP;
-                       advertising |= ADVERTISED_TP;
+                       ethtool_link_ksettings_add_link_mode(cmd, supported,
+                                                            TP);
+                       ethtool_link_ksettings_add_link_mode(cmd, advertising,
+                                                            TP);
                        cmd->base.port = PORT_TP;
                        break;
                case ixgbe_sfp_type_unknown:
                default:
-                       supported |= SUPPORTED_FIBRE;
-                       advertising |= ADVERTISED_FIBRE;
+                       ethtool_link_ksettings_add_link_mode(cmd, supported,
+                                                            FIBRE);
+                       ethtool_link_ksettings_add_link_mode(cmd, advertising,
+                                                            FIBRE);
                        cmd->base.port = PORT_OTHER;
                        break;
                }
                break;
        case ixgbe_phy_xaui:
-               supported |= SUPPORTED_FIBRE;
-               advertising |= ADVERTISED_FIBRE;
+               ethtool_link_ksettings_add_link_mode(cmd, supported,
+                                                    FIBRE);
+               ethtool_link_ksettings_add_link_mode(cmd, advertising,
+                                                    FIBRE);
                cmd->base.port = PORT_NONE;
                break;
        case ixgbe_phy_unknown:
        case ixgbe_phy_generic:
        case ixgbe_phy_sfp_unsupported:
        default:
-               supported |= SUPPORTED_FIBRE;
-               advertising |= ADVERTISED_FIBRE;
+               ethtool_link_ksettings_add_link_mode(cmd, supported,
+                                                    FIBRE);
+               ethtool_link_ksettings_add_link_mode(cmd, advertising,
+                                                    FIBRE);
                cmd->base.port = PORT_OTHER;
                break;
        }
 
        /* Indicate pause support */
-       supported |= SUPPORTED_Pause;
+       ethtool_link_ksettings_add_link_mode(cmd, supported, Pause);
 
        switch (hw->fc.requested_mode) {
        case ixgbe_fc_full:
-               advertising |= ADVERTISED_Pause;
+               ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause);
                break;
        case ixgbe_fc_rx_pause:
-               advertising |= ADVERTISED_Pause |
-                                    ADVERTISED_Asym_Pause;
+               ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause);
+               ethtool_link_ksettings_add_link_mode(cmd, advertising,
+                                                    Asym_Pause);
                break;
        case ixgbe_fc_tx_pause:
-               advertising |= ADVERTISED_Asym_Pause;
+               ethtool_link_ksettings_add_link_mode(cmd, advertising,
+                                                    Asym_Pause);
                break;
        default:
-               advertising &= ~(ADVERTISED_Pause |
-                                      ADVERTISED_Asym_Pause);
+               ethtool_link_ksettings_del_link_mode(cmd, advertising, Pause);
+               ethtool_link_ksettings_del_link_mode(cmd, advertising,
+                                                    Asym_Pause);
        }
 
        if (netif_carrier_ok(netdev)) {
@@ -358,11 +450,6 @@ static int ixgbe_get_link_ksettings(struct net_device *netdev,
                cmd->base.duplex = DUPLEX_UNKNOWN;
        }
 
-       ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported,
-                                               supported);
-       ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising,
-                                               advertising);
-
        return 0;
 }
 
@@ -373,12 +460,6 @@ static int ixgbe_set_link_ksettings(struct net_device *netdev,
        struct ixgbe_hw *hw = &adapter->hw;
        u32 advertised, old;
        s32 err = 0;
-       u32 supported, advertising;
-
-       ethtool_convert_link_mode_to_legacy_u32(&supported,
-                                               cmd->link_modes.supported);
-       ethtool_convert_link_mode_to_legacy_u32(&advertising,
-                                               cmd->link_modes.advertising);
 
        if ((hw->phy.media_type == ixgbe_media_type_copper) ||
            (hw->phy.multispeed_fiber)) {
@@ -386,29 +467,41 @@ static int ixgbe_set_link_ksettings(struct net_device *netdev,
                 * this function does not support duplex forcing, but can
                 * limit the advertising of the adapter to the specified speed
                 */
-               if (advertising & ~supported)
+               if (!bitmap_subset(cmd->link_modes.advertising,
+                                  cmd->link_modes.supported,
+                                  __ETHTOOL_LINK_MODE_MASK_NBITS))
                        return -EINVAL;
 
                /* only allow one speed at a time if no autoneg */
                if (!cmd->base.autoneg && hw->phy.multispeed_fiber) {
-                       if (advertising ==
-                           (ADVERTISED_10000baseT_Full |
-                            ADVERTISED_1000baseT_Full))
+                       if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
+                                                                 10000baseT_Full) &&
+                           ethtool_link_ksettings_test_link_mode(cmd, advertising,
+                                                                 1000baseT_Full))
                                return -EINVAL;
                }
 
                old = hw->phy.autoneg_advertised;
                advertised = 0;
-               if (advertising & ADVERTISED_10000baseT_Full)
+               if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
+                                                         10000baseT_Full))
                        advertised |= IXGBE_LINK_SPEED_10GB_FULL;
-
-               if (advertising & ADVERTISED_1000baseT_Full)
+               if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
+                                                         5000baseT_Full))
+                       advertised |= IXGBE_LINK_SPEED_5GB_FULL;
+               if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
+                                                         2500baseT_Full))
+                       advertised |= IXGBE_LINK_SPEED_2_5GB_FULL;
+               if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
+                                                         1000baseT_Full))
                        advertised |= IXGBE_LINK_SPEED_1GB_FULL;
 
-               if (advertising & ADVERTISED_100baseT_Full)
+               if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
+                                                         100baseT_Full))
                        advertised |= IXGBE_LINK_SPEED_100_FULL;
 
-               if (advertising & ADVERTISED_10baseT_Full)
+               if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
+                                                         10baseT_Full))
                        advertised |= IXGBE_LINK_SPEED_10_FULL;
 
                if (old == advertised)
@@ -429,7 +522,8 @@ static int ixgbe_set_link_ksettings(struct net_device *netdev,
                u32 speed = cmd->base.speed;
 
                if ((cmd->base.autoneg == AUTONEG_ENABLE) ||
-                   (advertising != ADVERTISED_10000baseT_Full) ||
+                   (!ethtool_link_ksettings_test_link_mode(cmd, advertising,
+                                                           10000baseT_Full)) ||
                    (speed + cmd->base.duplex != SPEED_10000 + DUPLEX_FULL))
                        return -EINVAL;
        }
index 4601118f88c936ac7fd505b764a70ffde84b2536..f5d3d6230786753ef1192fb0afb9e932f489fa77 100644 (file)
@@ -5501,9 +5501,13 @@ static int ixgbe_non_sfp_link_config(struct ixgbe_hw *hw)
                return ret;
 
        speed = hw->phy.autoneg_advertised;
-       if ((!speed) && (hw->mac.ops.get_link_capabilities))
+       if (!speed && hw->mac.ops.get_link_capabilities) {
                ret = hw->mac.ops.get_link_capabilities(hw, &speed,
                                                        &autoneg);
+               speed &= ~(IXGBE_LINK_SPEED_5GB_FULL |
+                          IXGBE_LINK_SPEED_2_5GB_FULL);
+       }
+
        if (ret)
                return ret;