diff options
Diffstat (limited to 'drivers/net/ethernet/intel/i40e/i40e_ethtool.c')
-rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 205 |
1 files changed, 116 insertions, 89 deletions
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 148f61461076..831f97125c8f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -273,52 +273,28 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw, case I40E_PHY_TYPE_40GBASE_AOC: ecmd->supported = SUPPORTED_40000baseCR4_Full; break; - case I40E_PHY_TYPE_40GBASE_KR4: - ecmd->supported = SUPPORTED_Autoneg | - SUPPORTED_40000baseKR4_Full; - ecmd->advertising = ADVERTISED_Autoneg | - ADVERTISED_40000baseKR4_Full; - break; case I40E_PHY_TYPE_40GBASE_SR4: ecmd->supported = SUPPORTED_40000baseSR4_Full; break; case I40E_PHY_TYPE_40GBASE_LR4: ecmd->supported = SUPPORTED_40000baseLR4_Full; break; - case I40E_PHY_TYPE_20GBASE_KR2: - ecmd->supported = SUPPORTED_Autoneg | - SUPPORTED_20000baseKR2_Full; - ecmd->advertising = ADVERTISED_Autoneg | - ADVERTISED_20000baseKR2_Full; - break; - case I40E_PHY_TYPE_10GBASE_KX4: - ecmd->supported = SUPPORTED_Autoneg | - SUPPORTED_10000baseKX4_Full; - ecmd->advertising = ADVERTISED_Autoneg | - ADVERTISED_10000baseKX4_Full; - break; - case I40E_PHY_TYPE_10GBASE_KR: - ecmd->supported = SUPPORTED_Autoneg | - SUPPORTED_10000baseKR_Full; - ecmd->advertising = ADVERTISED_Autoneg | - ADVERTISED_10000baseKR_Full; - break; case I40E_PHY_TYPE_10GBASE_SR: case I40E_PHY_TYPE_10GBASE_LR: case I40E_PHY_TYPE_1000BASE_SX: case I40E_PHY_TYPE_1000BASE_LX: - ecmd->supported = SUPPORTED_10000baseT_Full | - SUPPORTED_1000baseT_Full; + ecmd->supported = SUPPORTED_10000baseT_Full; + if (hw_link_info->module_type[2] & + I40E_MODULE_TYPE_1000BASE_SX || + hw_link_info->module_type[2] & + I40E_MODULE_TYPE_1000BASE_LX) { + ecmd->supported |= SUPPORTED_1000baseT_Full; + if (hw_link_info->requested_speeds & + I40E_LINK_SPEED_1GB) + ecmd->advertising |= ADVERTISED_1000baseT_Full; + } if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB) ecmd->advertising |= ADVERTISED_10000baseT_Full; - if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB) - ecmd->advertising |= ADVERTISED_1000baseT_Full; - break; - case I40E_PHY_TYPE_1000BASE_KX: - ecmd->supported = SUPPORTED_Autoneg | - SUPPORTED_1000baseKX_Full; - ecmd->advertising = ADVERTISED_Autoneg | - ADVERTISED_1000baseKX_Full; break; case I40E_PHY_TYPE_10GBASE_T: case I40E_PHY_TYPE_1000BASE_T: @@ -358,6 +334,15 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw, if (hw_link_info->requested_speeds & I40E_LINK_SPEED_100MB) ecmd->advertising |= ADVERTISED_100baseT_Full; break; + /* Backplane is set based on supported phy types in get_settings + * so don't set anything here but don't warn either + */ + case I40E_PHY_TYPE_40GBASE_KR4: + case I40E_PHY_TYPE_20GBASE_KR2: + case I40E_PHY_TYPE_10GBASE_KR: + case I40E_PHY_TYPE_10GBASE_KX4: + case I40E_PHY_TYPE_1000BASE_KX: + break; default: /* if we got here and link is up something bad is afoot */ netdev_info(netdev, "WARNING: Link is up but PHY type 0x%x is not recognized.\n", @@ -397,64 +382,67 @@ static void i40e_get_settings_link_up(struct i40e_hw *hw, static void i40e_get_settings_link_down(struct i40e_hw *hw, struct ethtool_cmd *ecmd) { - struct i40e_link_status *hw_link_info = &hw->phy.link_info; + enum i40e_aq_capabilities_phy_type phy_types = hw->phy.phy_types; /* link is down and the driver needs to fall back on - * device ID to determine what kinds of info to display, - * it's mostly a guess that may change when link is up + * supported phy types to figure out what info to display */ - switch (hw->device_id) { - case I40E_DEV_ID_QSFP_A: - case I40E_DEV_ID_QSFP_B: - case I40E_DEV_ID_QSFP_C: - /* pluggable QSFP */ - ecmd->supported = SUPPORTED_40000baseSR4_Full | - SUPPORTED_40000baseCR4_Full | - SUPPORTED_40000baseLR4_Full; - ecmd->advertising = ADVERTISED_40000baseSR4_Full | - ADVERTISED_40000baseCR4_Full | - ADVERTISED_40000baseLR4_Full; - break; - case I40E_DEV_ID_KX_B: - /* backplane 40G */ - ecmd->supported = SUPPORTED_40000baseKR4_Full; - ecmd->advertising = ADVERTISED_40000baseKR4_Full; - break; - case I40E_DEV_ID_KX_C: - /* backplane 10G */ - ecmd->supported = SUPPORTED_10000baseKR_Full; - ecmd->advertising = ADVERTISED_10000baseKR_Full; - break; - case I40E_DEV_ID_10G_BASE_T: - case I40E_DEV_ID_10G_BASE_T4: - ecmd->supported = SUPPORTED_10000baseT_Full | - SUPPORTED_1000baseT_Full | - SUPPORTED_100baseT_Full; - /* Figure out what has been requested */ - if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB) - ecmd->advertising |= ADVERTISED_10000baseT_Full; - if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB) - ecmd->advertising |= ADVERTISED_1000baseT_Full; - if (hw_link_info->requested_speeds & I40E_LINK_SPEED_100MB) - ecmd->advertising |= ADVERTISED_100baseT_Full; - break; - case I40E_DEV_ID_20G_KR2: - case I40E_DEV_ID_20G_KR2_A: - /* backplane 20G */ - ecmd->supported = SUPPORTED_20000baseKR2_Full; - ecmd->advertising = ADVERTISED_20000baseKR2_Full; - break; - default: - /* all the rest are 10G/1G */ - ecmd->supported = SUPPORTED_10000baseT_Full | - SUPPORTED_1000baseT_Full; - /* Figure out what has been requested */ - if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB) - ecmd->advertising |= ADVERTISED_10000baseT_Full; - if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB) - ecmd->advertising |= ADVERTISED_1000baseT_Full; - break; + ecmd->supported = 0x0; + ecmd->advertising = 0x0; + if (phy_types & I40E_CAP_PHY_TYPE_SGMII) { + ecmd->supported |= SUPPORTED_Autoneg | + SUPPORTED_1000baseT_Full | + SUPPORTED_100baseT_Full; + ecmd->advertising |= ADVERTISED_Autoneg | + ADVERTISED_1000baseT_Full | + ADVERTISED_100baseT_Full; + } + if (phy_types & I40E_CAP_PHY_TYPE_XAUI || + phy_types & I40E_CAP_PHY_TYPE_XFI || + phy_types & I40E_CAP_PHY_TYPE_SFI || + phy_types & I40E_CAP_PHY_TYPE_10GBASE_SFPP_CU || + phy_types & I40E_CAP_PHY_TYPE_10GBASE_AOC) + ecmd->supported |= SUPPORTED_10000baseT_Full; + if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_CR1_CU || + phy_types & I40E_CAP_PHY_TYPE_10GBASE_CR1 || + phy_types & I40E_CAP_PHY_TYPE_10GBASE_T || + phy_types & I40E_CAP_PHY_TYPE_10GBASE_SR || + phy_types & I40E_CAP_PHY_TYPE_10GBASE_LR) { + ecmd->supported |= SUPPORTED_Autoneg | + SUPPORTED_10000baseT_Full; + ecmd->advertising |= ADVERTISED_Autoneg | + ADVERTISED_10000baseT_Full; + } + if (phy_types & I40E_CAP_PHY_TYPE_XLAUI || + phy_types & I40E_CAP_PHY_TYPE_XLPPI || + phy_types & I40E_CAP_PHY_TYPE_40GBASE_AOC) + ecmd->supported |= SUPPORTED_40000baseCR4_Full; + if (phy_types & I40E_CAP_PHY_TYPE_40GBASE_CR4_CU || + phy_types & I40E_CAP_PHY_TYPE_40GBASE_CR4) { + ecmd->supported |= SUPPORTED_Autoneg | + SUPPORTED_40000baseCR4_Full; + ecmd->advertising |= ADVERTISED_Autoneg | + ADVERTISED_40000baseCR4_Full; + } + if (phy_types & I40E_CAP_PHY_TYPE_100BASE_TX) { + ecmd->supported |= SUPPORTED_Autoneg | + SUPPORTED_100baseT_Full; + ecmd->advertising |= ADVERTISED_Autoneg | + ADVERTISED_100baseT_Full; + } + if (phy_types & I40E_CAP_PHY_TYPE_1000BASE_T || + phy_types & I40E_CAP_PHY_TYPE_1000BASE_SX || + phy_types & I40E_CAP_PHY_TYPE_1000BASE_LX || + phy_types & I40E_CAP_PHY_TYPE_1000BASE_T_OPTICAL) { + ecmd->supported |= SUPPORTED_Autoneg | + SUPPORTED_1000baseT_Full; + ecmd->advertising |= ADVERTISED_Autoneg | + ADVERTISED_1000baseT_Full; } + if (phy_types & I40E_CAP_PHY_TYPE_40GBASE_SR4) + ecmd->supported |= SUPPORTED_40000baseSR4_Full; + if (phy_types & I40E_CAP_PHY_TYPE_40GBASE_LR4) + ecmd->supported |= SUPPORTED_40000baseLR4_Full; /* With no link speed and duplex are unknown */ ethtool_cmd_speed_set(ecmd, SPEED_UNKNOWN); @@ -484,6 +472,37 @@ static int i40e_get_settings(struct net_device *netdev, /* Now set the settings that don't rely on link being up/down */ + /* For backplane, supported and advertised are only reliant on the + * phy types the NVM specifies are supported. + */ + if (hw->device_id == I40E_DEV_ID_KX_B || + hw->device_id == I40E_DEV_ID_KX_C || + hw->device_id == I40E_DEV_ID_20G_KR2 || + hw->device_id == I40E_DEV_ID_20G_KR2_A) { + ecmd->supported = SUPPORTED_Autoneg; + ecmd->advertising = ADVERTISED_Autoneg; + if (hw->phy.phy_types & I40E_CAP_PHY_TYPE_40GBASE_KR4) { + ecmd->supported |= SUPPORTED_40000baseKR4_Full; + ecmd->advertising |= ADVERTISED_40000baseKR4_Full; + } + if (hw->phy.phy_types & I40E_CAP_PHY_TYPE_20GBASE_KR2) { + ecmd->supported |= SUPPORTED_20000baseKR2_Full; + ecmd->advertising |= ADVERTISED_20000baseKR2_Full; + } + if (hw->phy.phy_types & I40E_CAP_PHY_TYPE_10GBASE_KR) { + ecmd->supported |= SUPPORTED_10000baseKR_Full; + ecmd->advertising |= ADVERTISED_10000baseKR_Full; + } + if (hw->phy.phy_types & I40E_CAP_PHY_TYPE_10GBASE_KX4) { + ecmd->supported |= SUPPORTED_10000baseKX4_Full; + ecmd->advertising |= ADVERTISED_10000baseKX4_Full; + } + if (hw->phy.phy_types & I40E_CAP_PHY_TYPE_1000BASE_KX) { + ecmd->supported |= SUPPORTED_1000baseKX_Full; + ecmd->advertising |= ADVERTISED_1000baseKX_Full; + } + } + /* Set autoneg settings */ ecmd->autoneg = ((hw_link_info->an_info & I40E_AQ_AN_COMPLETED) ? AUTONEG_ENABLE : AUTONEG_DISABLE); @@ -583,6 +602,14 @@ static int i40e_set_settings(struct net_device *netdev, hw->phy.link_info.link_info & I40E_AQ_LINK_UP) return -EOPNOTSUPP; + if (hw->device_id == I40E_DEV_ID_KX_B || + hw->device_id == I40E_DEV_ID_KX_C || + hw->device_id == I40E_DEV_ID_20G_KR2 || + hw->device_id == I40E_DEV_ID_20G_KR2_A) { + netdev_info(netdev, "Changing settings is not supported on backplane.\n"); + return -EOPNOTSUPP; + } + /* get our own copy of the bits to check against */ memset(&safe_ecmd, 0, sizeof(struct ethtool_cmd)); i40e_get_settings(netdev, &safe_ecmd); @@ -704,7 +731,7 @@ static int i40e_set_settings(struct net_device *netdev, return -EAGAIN; } - status = i40e_aq_get_link_info(hw, true, NULL, NULL); + status = i40e_update_link_info(hw); if (status) netdev_info(netdev, "Updating link info failed with err %s aq_err %s\n", i40e_stat_str(hw, status), |