Commit a296d665 authored by Radoslaw Tyl's avatar Radoslaw Tyl Committed by Tony Nguyen

ixgbe: Add ethtool support to enable 2.5 and 5.0 Gbps support

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: default avatarRadoslaw Tyl <radoslawx.tyl@intel.com>
Tested-by: default avatarAndrew Bowers <andrewx.bowers@intel.com>
Signed-off-by: default avatarTony Nguyen <anthony.l.nguyen@intel.com>
parent bb0967c0
...@@ -142,32 +142,71 @@ static const char ixgbe_priv_flags_strings[][ETH_GSTRING_LEN] = { ...@@ -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) #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) #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)) if (!ixgbe_isbackplane(hw->phy.media_type)) {
return SUPPORTED_10000baseT_Full; ethtool_link_ksettings_add_link_mode(cmd, supported,
10000baseT_Full);
return;
}
switch (hw->device_id) { switch (hw->device_id) {
case IXGBE_DEV_ID_82598: case IXGBE_DEV_ID_82598:
case IXGBE_DEV_ID_82599_KX4: case IXGBE_DEV_ID_82599_KX4:
case IXGBE_DEV_ID_82599_KX4_MEZZ: case IXGBE_DEV_ID_82599_KX4_MEZZ:
case IXGBE_DEV_ID_X550EM_X_KX4: 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_82598_BX:
case IXGBE_DEV_ID_82599_KR: case IXGBE_DEV_ID_82599_KR:
case IXGBE_DEV_ID_X550EM_X_KR: case IXGBE_DEV_ID_X550EM_X_KR:
case IXGBE_DEV_ID_X550EM_X_XFI: case IXGBE_DEV_ID_X550EM_X_XFI:
return SUPPORTED_10000baseKR_Full; ethtool_link_ksettings_add_link_mode
(cmd, supported, 10000baseKR_Full);
break;
default: default:
return SUPPORTED_10000baseKX4_Full | ethtool_link_ksettings_add_link_mode
SUPPORTED_10000baseKR_Full; (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, ...@@ -178,52 +217,88 @@ static int ixgbe_get_link_ksettings(struct net_device *netdev,
struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_hw *hw = &adapter->hw;
ixgbe_link_speed supported_link; ixgbe_link_speed supported_link;
bool autoneg = false; bool autoneg = false;
u32 supported, advertising;
ethtool_convert_link_mode_to_legacy_u32(&supported, ethtool_link_ksettings_zero_link_mode(cmd, supported);
cmd->link_modes.supported); ethtool_link_ksettings_zero_link_mode(cmd, advertising);
hw->mac.ops.get_link_capabilities(hw, &supported_link, &autoneg); hw->mac.ops.get_link_capabilities(hw, &supported_link, &autoneg);
/* set the supported link speeds */ /* set the supported link speeds */
if (supported_link & IXGBE_LINK_SPEED_10GB_FULL) if (supported_link & IXGBE_LINK_SPEED_10GB_FULL) {
supported |= ixgbe_get_supported_10gtypes(hw); ixgbe_set_supported_10gtypes(hw, cmd);
if (supported_link & IXGBE_LINK_SPEED_1GB_FULL) ixgbe_set_advertising_10gtypes(hw, cmd);
supported |= (ixgbe_isbackplane(hw->phy.media_type)) ? }
SUPPORTED_1000baseKX_Full : if (supported_link & IXGBE_LINK_SPEED_5GB_FULL)
SUPPORTED_1000baseT_Full; ethtool_link_ksettings_add_link_mode(cmd, supported,
if (supported_link & IXGBE_LINK_SPEED_100_FULL) 5000baseT_Full);
supported |= SUPPORTED_100baseT_Full;
if (supported_link & IXGBE_LINK_SPEED_10_FULL) if (supported_link & IXGBE_LINK_SPEED_2_5GB_FULL)
supported |= SUPPORTED_10baseT_Full; ethtool_link_ksettings_add_link_mode(cmd, supported,
2500baseT_Full);
/* default advertised speed if phy.autoneg_advertised isn't set */
advertising = supported; 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 */ /* set the advertised speeds */
if (hw->phy.autoneg_advertised) { 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) 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) 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) 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 (hw->phy.autoneg_advertised & IXGBE_LINK_SPEED_1GB_FULL) {
if (supported & SUPPORTED_1000baseKX_Full) if (ethtool_link_ksettings_test_link_mode
advertising |= ADVERTISED_1000baseKX_Full; (cmd, supported, 1000baseKX_Full))
ethtool_link_ksettings_add_link_mode
(cmd, advertising, 1000baseKX_Full);
else 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 { } else {
if (hw->phy.multispeed_fiber && !autoneg) { if (hw->phy.multispeed_fiber && !autoneg) {
if (supported_link & IXGBE_LINK_SPEED_10GB_FULL) if (supported_link & IXGBE_LINK_SPEED_10GB_FULL)
advertising = ADVERTISED_10000baseT_Full; ethtool_link_ksettings_add_link_mode
(cmd, advertising, 10000baseT_Full);
} }
} }
if (autoneg) { if (autoneg) {
supported |= SUPPORTED_Autoneg; ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg);
advertising |= ADVERTISED_Autoneg; ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg);
cmd->base.autoneg = AUTONEG_ENABLE; cmd->base.autoneg = AUTONEG_ENABLE;
} else } else
cmd->base.autoneg = AUTONEG_DISABLE; cmd->base.autoneg = AUTONEG_DISABLE;
...@@ -235,13 +310,13 @@ static int ixgbe_get_link_ksettings(struct net_device *netdev, ...@@ -235,13 +310,13 @@ static int ixgbe_get_link_ksettings(struct net_device *netdev,
case ixgbe_phy_x550em_ext_t: case ixgbe_phy_x550em_ext_t:
case ixgbe_phy_fw: case ixgbe_phy_fw:
case ixgbe_phy_cu_unknown: case ixgbe_phy_cu_unknown:
supported |= SUPPORTED_TP; ethtool_link_ksettings_add_link_mode(cmd, supported, TP);
advertising |= ADVERTISED_TP; ethtool_link_ksettings_add_link_mode(cmd, advertising, TP);
cmd->base.port = PORT_TP; cmd->base.port = PORT_TP;
break; break;
case ixgbe_phy_qt: case ixgbe_phy_qt:
supported |= SUPPORTED_FIBRE; ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
advertising |= ADVERTISED_FIBRE; ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE);
cmd->base.port = PORT_FIBRE; cmd->base.port = PORT_FIBRE;
break; break;
case ixgbe_phy_nl: case ixgbe_phy_nl:
...@@ -260,8 +335,10 @@ static int ixgbe_get_link_ksettings(struct net_device *netdev, ...@@ -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:
case ixgbe_sfp_type_da_cu_core0: case ixgbe_sfp_type_da_cu_core0:
case ixgbe_sfp_type_da_cu_core1: case ixgbe_sfp_type_da_cu_core1:
supported |= SUPPORTED_FIBRE; ethtool_link_ksettings_add_link_mode(cmd, supported,
advertising |= ADVERTISED_FIBRE; FIBRE);
ethtool_link_ksettings_add_link_mode(cmd, advertising,
FIBRE);
cmd->base.port = PORT_DA; cmd->base.port = PORT_DA;
break; break;
case ixgbe_sfp_type_sr: case ixgbe_sfp_type_sr:
...@@ -272,61 +349,76 @@ static int ixgbe_get_link_ksettings(struct net_device *netdev, ...@@ -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_sx_core1:
case ixgbe_sfp_type_1g_lx_core0: case ixgbe_sfp_type_1g_lx_core0:
case ixgbe_sfp_type_1g_lx_core1: case ixgbe_sfp_type_1g_lx_core1:
supported |= SUPPORTED_FIBRE; ethtool_link_ksettings_add_link_mode(cmd, supported,
advertising |= ADVERTISED_FIBRE; FIBRE);
ethtool_link_ksettings_add_link_mode(cmd, advertising,
FIBRE);
cmd->base.port = PORT_FIBRE; cmd->base.port = PORT_FIBRE;
break; break;
case ixgbe_sfp_type_not_present: case ixgbe_sfp_type_not_present:
supported |= SUPPORTED_FIBRE; ethtool_link_ksettings_add_link_mode(cmd, supported,
advertising |= ADVERTISED_FIBRE; FIBRE);
ethtool_link_ksettings_add_link_mode(cmd, advertising,
FIBRE);
cmd->base.port = PORT_NONE; cmd->base.port = PORT_NONE;
break; break;
case ixgbe_sfp_type_1g_cu_core0: case ixgbe_sfp_type_1g_cu_core0:
case ixgbe_sfp_type_1g_cu_core1: case ixgbe_sfp_type_1g_cu_core1:
supported |= SUPPORTED_TP; ethtool_link_ksettings_add_link_mode(cmd, supported,
advertising |= ADVERTISED_TP; TP);
ethtool_link_ksettings_add_link_mode(cmd, advertising,
TP);
cmd->base.port = PORT_TP; cmd->base.port = PORT_TP;
break; break;
case ixgbe_sfp_type_unknown: case ixgbe_sfp_type_unknown:
default: default:
supported |= SUPPORTED_FIBRE; ethtool_link_ksettings_add_link_mode(cmd, supported,
advertising |= ADVERTISED_FIBRE; FIBRE);
ethtool_link_ksettings_add_link_mode(cmd, advertising,
FIBRE);
cmd->base.port = PORT_OTHER; cmd->base.port = PORT_OTHER;
break; break;
} }
break; break;
case ixgbe_phy_xaui: case ixgbe_phy_xaui:
supported |= SUPPORTED_FIBRE; ethtool_link_ksettings_add_link_mode(cmd, supported,
advertising |= ADVERTISED_FIBRE; FIBRE);
ethtool_link_ksettings_add_link_mode(cmd, advertising,
FIBRE);
cmd->base.port = PORT_NONE; cmd->base.port = PORT_NONE;
break; break;
case ixgbe_phy_unknown: case ixgbe_phy_unknown:
case ixgbe_phy_generic: case ixgbe_phy_generic:
case ixgbe_phy_sfp_unsupported: case ixgbe_phy_sfp_unsupported:
default: default:
supported |= SUPPORTED_FIBRE; ethtool_link_ksettings_add_link_mode(cmd, supported,
advertising |= ADVERTISED_FIBRE; FIBRE);
ethtool_link_ksettings_add_link_mode(cmd, advertising,
FIBRE);
cmd->base.port = PORT_OTHER; cmd->base.port = PORT_OTHER;
break; break;
} }
/* Indicate pause support */ /* Indicate pause support */
supported |= SUPPORTED_Pause; ethtool_link_ksettings_add_link_mode(cmd, supported, Pause);
switch (hw->fc.requested_mode) { switch (hw->fc.requested_mode) {
case ixgbe_fc_full: case ixgbe_fc_full:
advertising |= ADVERTISED_Pause; ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause);
break; break;
case ixgbe_fc_rx_pause: case ixgbe_fc_rx_pause:
advertising |= ADVERTISED_Pause | ethtool_link_ksettings_add_link_mode(cmd, advertising, Pause);
ADVERTISED_Asym_Pause; ethtool_link_ksettings_add_link_mode(cmd, advertising,
Asym_Pause);
break; break;
case ixgbe_fc_tx_pause: case ixgbe_fc_tx_pause:
advertising |= ADVERTISED_Asym_Pause; ethtool_link_ksettings_add_link_mode(cmd, advertising,
Asym_Pause);
break; break;
default: default:
advertising &= ~(ADVERTISED_Pause | ethtool_link_ksettings_del_link_mode(cmd, advertising, Pause);
ADVERTISED_Asym_Pause); ethtool_link_ksettings_del_link_mode(cmd, advertising,
Asym_Pause);
} }
if (netif_carrier_ok(netdev)) { if (netif_carrier_ok(netdev)) {
...@@ -358,11 +450,6 @@ static int ixgbe_get_link_ksettings(struct net_device *netdev, ...@@ -358,11 +450,6 @@ static int ixgbe_get_link_ksettings(struct net_device *netdev,
cmd->base.duplex = DUPLEX_UNKNOWN; 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; return 0;
} }
...@@ -373,12 +460,6 @@ static int ixgbe_set_link_ksettings(struct net_device *netdev, ...@@ -373,12 +460,6 @@ static int ixgbe_set_link_ksettings(struct net_device *netdev,
struct ixgbe_hw *hw = &adapter->hw; struct ixgbe_hw *hw = &adapter->hw;
u32 advertised, old; u32 advertised, old;
s32 err = 0; 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) || if ((hw->phy.media_type == ixgbe_media_type_copper) ||
(hw->phy.multispeed_fiber)) { (hw->phy.multispeed_fiber)) {
...@@ -386,29 +467,41 @@ static int ixgbe_set_link_ksettings(struct net_device *netdev, ...@@ -386,29 +467,41 @@ static int ixgbe_set_link_ksettings(struct net_device *netdev,
* this function does not support duplex forcing, but can * this function does not support duplex forcing, but can
* limit the advertising of the adapter to the specified speed * 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; return -EINVAL;
/* only allow one speed at a time if no autoneg */ /* only allow one speed at a time if no autoneg */
if (!cmd->base.autoneg && hw->phy.multispeed_fiber) { if (!cmd->base.autoneg && hw->phy.multispeed_fiber) {
if (advertising == if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
(ADVERTISED_10000baseT_Full | 10000baseT_Full) &&
ADVERTISED_1000baseT_Full)) ethtool_link_ksettings_test_link_mode(cmd, advertising,
1000baseT_Full))
return -EINVAL; return -EINVAL;
} }
old = hw->phy.autoneg_advertised; old = hw->phy.autoneg_advertised;
advertised = 0; advertised = 0;
if (advertising & ADVERTISED_10000baseT_Full) if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
10000baseT_Full))
advertised |= IXGBE_LINK_SPEED_10GB_FULL; advertised |= IXGBE_LINK_SPEED_10GB_FULL;
if (ethtool_link_ksettings_test_link_mode(cmd, advertising,
if (advertising & ADVERTISED_1000baseT_Full) 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; 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; 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; advertised |= IXGBE_LINK_SPEED_10_FULL;
if (old == advertised) if (old == advertised)
...@@ -429,7 +522,8 @@ static int ixgbe_set_link_ksettings(struct net_device *netdev, ...@@ -429,7 +522,8 @@ static int ixgbe_set_link_ksettings(struct net_device *netdev,
u32 speed = cmd->base.speed; u32 speed = cmd->base.speed;
if ((cmd->base.autoneg == AUTONEG_ENABLE) || 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)) (speed + cmd->base.duplex != SPEED_10000 + DUPLEX_FULL))
return -EINVAL; return -EINVAL;
} }
......
...@@ -5501,9 +5501,13 @@ static int ixgbe_non_sfp_link_config(struct ixgbe_hw *hw) ...@@ -5501,9 +5501,13 @@ static int ixgbe_non_sfp_link_config(struct ixgbe_hw *hw)
return ret; return ret;
speed = hw->phy.autoneg_advertised; 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, ret = hw->mac.ops.get_link_capabilities(hw, &speed,
&autoneg); &autoneg);
speed &= ~(IXGBE_LINK_SPEED_5GB_FULL |
IXGBE_LINK_SPEED_2_5GB_FULL);
}
if (ret) if (ret)
return ret; return ret;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment