diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index 266e1dc5e786..eb017763646d 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -130,7 +130,8 @@ /* BW rate limiting */ #define I40E_BW_CREDIT_DIVISOR 50 /* 50Mbps per BW credit */ -#define I40E_MAX_BW_INACTIVE_ACCUM 4 /* accumulate 4 credits max */ +#define I40E_BW_MBPS_DIVISOR 125000 /* rate / (1000000 / 8) Mbps */ +#define I40E_MAX_BW_INACTIVE_ACCUM 4 /* accumulate 4 credits max */ /* driver state flags */ enum i40e_state_t { diff --git a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h index a8f65aed5421..6a5db1b33fa2 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40e/i40e_adminq_cmd.h @@ -1771,6 +1771,8 @@ enum i40e_aq_phy_type { I40E_PHY_TYPE_25GBASE_CR = 0x20, I40E_PHY_TYPE_25GBASE_SR = 0x21, I40E_PHY_TYPE_25GBASE_LR = 0x22, + I40E_PHY_TYPE_25GBASE_AOC = 0x23, + I40E_PHY_TYPE_25GBASE_ACC = 0x24, I40E_PHY_TYPE_MAX, I40E_PHY_TYPE_NOT_SUPPORTED_HIGH_TEMP = 0xFD, I40E_PHY_TYPE_EMPTY = 0xFE, @@ -1831,6 +1833,8 @@ struct i40e_aq_get_phy_abilities_resp { #define I40E_AQ_PHY_TYPE_EXT_25G_CR 0X02 #define I40E_AQ_PHY_TYPE_EXT_25G_SR 0x04 #define I40E_AQ_PHY_TYPE_EXT_25G_LR 0x08 +#define I40E_AQ_PHY_TYPE_EXT_25G_AOC 0x10 +#define I40E_AQ_PHY_TYPE_EXT_25G_ACC 0x20 u8 fec_cfg_curr_mod_ext_info; #define I40E_AQ_ENABLE_FEC_KR 0x01 #define I40E_AQ_ENABLE_FEC_RS 0x02 diff --git a/drivers/net/ethernet/intel/i40e/i40e_common.c b/drivers/net/ethernet/intel/i40e/i40e_common.c index aeb497258f20..8d0ee006606b 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_common.c +++ b/drivers/net/ethernet/intel/i40e/i40e_common.c @@ -1180,6 +1180,8 @@ static enum i40e_media_type i40e_get_media_type(struct i40e_hw *hw) case I40E_PHY_TYPE_40GBASE_AOC: case I40E_PHY_TYPE_10GBASE_AOC: case I40E_PHY_TYPE_25GBASE_CR: + case I40E_PHY_TYPE_25GBASE_AOC: + case I40E_PHY_TYPE_25GBASE_ACC: media = I40E_MEDIA_TYPE_DA; break; case I40E_PHY_TYPE_1000BASE_KX: diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 72d5f2cdf419..9eb618799a30 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -253,428 +253,557 @@ static void i40e_partition_setting_complaint(struct i40e_pf *pf) /** * i40e_phy_type_to_ethtool - convert the phy_types to ethtool link modes - * @phy_types: PHY types to convert - * @supported: pointer to the ethtool supported variable to fill in - * @advertising: pointer to the ethtool advertising variable to fill in + * @pf: PF struct with phy_types + * @ks: ethtool link ksettings struct to fill out * **/ -static void i40e_phy_type_to_ethtool(struct i40e_pf *pf, u32 *supported, - u32 *advertising) +static void i40e_phy_type_to_ethtool(struct i40e_pf *pf, + struct ethtool_link_ksettings *ks) { struct i40e_link_status *hw_link_info = &pf->hw.phy.link_info; u64 phy_types = pf->hw.phy.phy_types; - *supported = 0x0; - *advertising = 0x0; + ethtool_link_ksettings_zero_link_mode(ks, supported); + ethtool_link_ksettings_zero_link_mode(ks, advertising); if (phy_types & I40E_CAP_PHY_TYPE_SGMII) { - *supported |= SUPPORTED_Autoneg | - SUPPORTED_1000baseT_Full; - *advertising |= ADVERTISED_Autoneg; + ethtool_link_ksettings_add_link_mode(ks, supported, + 1000baseT_Full); if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB) - *advertising |= ADVERTISED_1000baseT_Full; + ethtool_link_ksettings_add_link_mode(ks, advertising, + 1000baseT_Full); if (pf->hw_features & I40E_HW_100M_SGMII_CAPABLE) { - *supported |= SUPPORTED_100baseT_Full; - *advertising |= ADVERTISED_100baseT_Full; + ethtool_link_ksettings_add_link_mode(ks, supported, + 100baseT_Full); + ethtool_link_ksettings_add_link_mode(ks, advertising, + 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) - *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) { - *supported |= SUPPORTED_Autoneg | - SUPPORTED_10000baseT_Full; - *advertising |= ADVERTISED_Autoneg; + phy_types & I40E_CAP_PHY_TYPE_10GBASE_AOC) { + ethtool_link_ksettings_add_link_mode(ks, supported, + 10000baseT_Full); if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB) - *advertising |= ADVERTISED_10000baseT_Full; + ethtool_link_ksettings_add_link_mode(ks, advertising, + 10000baseT_Full); + } + if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_T) { + ethtool_link_ksettings_add_link_mode(ks, supported, + 10000baseT_Full); + if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB) + ethtool_link_ksettings_add_link_mode(ks, advertising, + 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) - *supported |= SUPPORTED_40000baseCR4_Full; + ethtool_link_ksettings_add_link_mode(ks, supported, + 40000baseCR4_Full); if (phy_types & I40E_CAP_PHY_TYPE_40GBASE_CR4_CU || phy_types & I40E_CAP_PHY_TYPE_40GBASE_CR4) { - *supported |= SUPPORTED_Autoneg | - SUPPORTED_40000baseCR4_Full; - *advertising |= ADVERTISED_Autoneg; + ethtool_link_ksettings_add_link_mode(ks, supported, + 40000baseCR4_Full); if (hw_link_info->requested_speeds & I40E_LINK_SPEED_40GB) - *advertising |= ADVERTISED_40000baseCR4_Full; + ethtool_link_ksettings_add_link_mode(ks, advertising, + 40000baseCR4_Full); } if (phy_types & I40E_CAP_PHY_TYPE_100BASE_TX) { - *supported |= SUPPORTED_Autoneg | - SUPPORTED_100baseT_Full; - *advertising |= ADVERTISED_Autoneg; + ethtool_link_ksettings_add_link_mode(ks, supported, + 100baseT_Full); if (hw_link_info->requested_speeds & I40E_LINK_SPEED_100MB) - *advertising |= ADVERTISED_100baseT_Full; + ethtool_link_ksettings_add_link_mode(ks, advertising, + 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) { - *supported |= SUPPORTED_Autoneg | - SUPPORTED_1000baseT_Full; - *advertising |= ADVERTISED_Autoneg; + if (phy_types & I40E_CAP_PHY_TYPE_1000BASE_T) { + ethtool_link_ksettings_add_link_mode(ks, supported, + 1000baseT_Full); if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB) - *advertising |= ADVERTISED_1000baseT_Full; + ethtool_link_ksettings_add_link_mode(ks, advertising, + 1000baseT_Full); } if (phy_types & I40E_CAP_PHY_TYPE_40GBASE_SR4) - *supported |= SUPPORTED_40000baseSR4_Full; + ethtool_link_ksettings_add_link_mode(ks, supported, + 40000baseSR4_Full); if (phy_types & I40E_CAP_PHY_TYPE_40GBASE_LR4) - *supported |= SUPPORTED_40000baseLR4_Full; + ethtool_link_ksettings_add_link_mode(ks, supported, + 40000baseLR4_Full); if (phy_types & I40E_CAP_PHY_TYPE_40GBASE_KR4) { - *supported |= SUPPORTED_40000baseKR4_Full | - SUPPORTED_Autoneg; - *advertising |= ADVERTISED_40000baseKR4_Full | - ADVERTISED_Autoneg; + ethtool_link_ksettings_add_link_mode(ks, supported, + 40000baseLR4_Full); + ethtool_link_ksettings_add_link_mode(ks, advertising, + 40000baseLR4_Full); } if (phy_types & I40E_CAP_PHY_TYPE_20GBASE_KR2) { - *supported |= SUPPORTED_20000baseKR2_Full | - SUPPORTED_Autoneg; - *advertising |= ADVERTISED_Autoneg; + ethtool_link_ksettings_add_link_mode(ks, supported, + 20000baseKR2_Full); if (hw_link_info->requested_speeds & I40E_LINK_SPEED_20GB) - *advertising |= ADVERTISED_20000baseKR2_Full; - } - if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_KR) { - if (!(pf->hw_features & I40E_HW_HAVE_CRT_RETIMER)) - *supported |= SUPPORTED_10000baseKR_Full | - SUPPORTED_Autoneg; - *advertising |= ADVERTISED_Autoneg; - if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB) - if (!(pf->hw_features & I40E_HW_HAVE_CRT_RETIMER)) - *advertising |= ADVERTISED_10000baseKR_Full; + ethtool_link_ksettings_add_link_mode(ks, advertising, + 20000baseKR2_Full); } if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_KX4) { - *supported |= SUPPORTED_10000baseKX4_Full | - SUPPORTED_Autoneg; - *advertising |= ADVERTISED_Autoneg; + ethtool_link_ksettings_add_link_mode(ks, supported, + 10000baseKX4_Full); if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB) - *advertising |= ADVERTISED_10000baseKX4_Full; + ethtool_link_ksettings_add_link_mode(ks, advertising, + 10000baseKX4_Full); } - if (phy_types & I40E_CAP_PHY_TYPE_1000BASE_KX) { - if (!(pf->hw_features & I40E_HW_HAVE_CRT_RETIMER)) - *supported |= SUPPORTED_1000baseKX_Full | - SUPPORTED_Autoneg; - *advertising |= ADVERTISED_Autoneg; + if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_KR && + !(pf->hw_features & I40E_HW_HAVE_CRT_RETIMER)) { + ethtool_link_ksettings_add_link_mode(ks, supported, + 10000baseKR_Full); + if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB) + ethtool_link_ksettings_add_link_mode(ks, advertising, + 10000baseKR_Full); + } + if (phy_types & I40E_CAP_PHY_TYPE_1000BASE_KX && + !(pf->hw_features & I40E_HW_HAVE_CRT_RETIMER)) { + ethtool_link_ksettings_add_link_mode(ks, supported, + 1000baseKX_Full); if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB) - if (!(pf->hw_features & I40E_HW_HAVE_CRT_RETIMER)) - *advertising |= ADVERTISED_1000baseKX_Full; + ethtool_link_ksettings_add_link_mode(ks, advertising, + 1000baseKX_Full); } - if (phy_types & I40E_CAP_PHY_TYPE_25GBASE_KR || - phy_types & I40E_CAP_PHY_TYPE_25GBASE_CR || - phy_types & I40E_CAP_PHY_TYPE_25GBASE_SR || + /* need to add 25G PHY types */ + if (phy_types & I40E_CAP_PHY_TYPE_25GBASE_KR) { + ethtool_link_ksettings_add_link_mode(ks, supported, + 25000baseKR_Full); + if (hw_link_info->requested_speeds & I40E_LINK_SPEED_25GB) + ethtool_link_ksettings_add_link_mode(ks, advertising, + 25000baseKR_Full); + } + if (phy_types & I40E_CAP_PHY_TYPE_25GBASE_CR) { + ethtool_link_ksettings_add_link_mode(ks, supported, + 25000baseCR_Full); + if (hw_link_info->requested_speeds & I40E_LINK_SPEED_25GB) + ethtool_link_ksettings_add_link_mode(ks, advertising, + 25000baseCR_Full); + } + if (phy_types & I40E_CAP_PHY_TYPE_25GBASE_SR || phy_types & I40E_CAP_PHY_TYPE_25GBASE_LR) { - *supported |= SUPPORTED_Autoneg; - *advertising |= ADVERTISED_Autoneg; + ethtool_link_ksettings_add_link_mode(ks, supported, + 25000baseSR_Full); + if (hw_link_info->requested_speeds & I40E_LINK_SPEED_25GB) + ethtool_link_ksettings_add_link_mode(ks, advertising, + 25000baseSR_Full); + } + if (phy_types & I40E_CAP_PHY_TYPE_25GBASE_AOC || + phy_types & I40E_CAP_PHY_TYPE_25GBASE_ACC) { + ethtool_link_ksettings_add_link_mode(ks, supported, + 25000baseCR_Full); + if (hw_link_info->requested_speeds & I40E_LINK_SPEED_25GB) + ethtool_link_ksettings_add_link_mode(ks, advertising, + 25000baseCR_Full); + } + /* need to add new 10G PHY types */ + if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_CR1 || + phy_types & I40E_CAP_PHY_TYPE_10GBASE_CR1_CU) { + ethtool_link_ksettings_add_link_mode(ks, supported, + 10000baseCR_Full); + if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB) + ethtool_link_ksettings_add_link_mode(ks, advertising, + 10000baseCR_Full); + } + if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_SR) { + ethtool_link_ksettings_add_link_mode(ks, supported, + 10000baseSR_Full); + if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB) + ethtool_link_ksettings_add_link_mode(ks, advertising, + 10000baseSR_Full); + } + if (phy_types & I40E_CAP_PHY_TYPE_10GBASE_LR) { + ethtool_link_ksettings_add_link_mode(ks, supported, + 10000baseLR_Full); + if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB) + ethtool_link_ksettings_add_link_mode(ks, advertising, + 10000baseLR_Full); + } + if (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) { + ethtool_link_ksettings_add_link_mode(ks, supported, + 1000baseX_Full); + if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB) + ethtool_link_ksettings_add_link_mode(ks, advertising, + 1000baseX_Full); + } + /* Autoneg PHY types */ + if (phy_types & I40E_CAP_PHY_TYPE_SGMII || + phy_types & I40E_CAP_PHY_TYPE_40GBASE_KR4 || + phy_types & I40E_CAP_PHY_TYPE_40GBASE_CR4_CU || + phy_types & I40E_CAP_PHY_TYPE_40GBASE_CR4 || + phy_types & I40E_CAP_PHY_TYPE_25GBASE_SR || + phy_types & I40E_CAP_PHY_TYPE_25GBASE_LR || + phy_types & I40E_CAP_PHY_TYPE_25GBASE_KR || + phy_types & I40E_CAP_PHY_TYPE_25GBASE_CR || + phy_types & I40E_CAP_PHY_TYPE_20GBASE_KR2 || + phy_types & I40E_CAP_PHY_TYPE_10GBASE_T || + phy_types & I40E_CAP_PHY_TYPE_10GBASE_SR || + phy_types & I40E_CAP_PHY_TYPE_10GBASE_LR || + phy_types & I40E_CAP_PHY_TYPE_10GBASE_KX4 || + phy_types & I40E_CAP_PHY_TYPE_10GBASE_KR || + phy_types & I40E_CAP_PHY_TYPE_10GBASE_CR1_CU || + phy_types & I40E_CAP_PHY_TYPE_10GBASE_CR1 || + phy_types & I40E_CAP_PHY_TYPE_1000BASE_T_OPTICAL || + 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_KX || + phy_types & I40E_CAP_PHY_TYPE_100BASE_TX) { + ethtool_link_ksettings_add_link_mode(ks, supported, + Autoneg); + ethtool_link_ksettings_add_link_mode(ks, advertising, + Autoneg); } } /** * i40e_get_settings_link_up - Get the Link settings for when link is up * @hw: hw structure - * @ecmd: ethtool command to fill in + * @ks: ethtool ksettings to fill in * @netdev: network interface device structure - * + * @pf: pointer to physical function struct **/ static void i40e_get_settings_link_up(struct i40e_hw *hw, - struct ethtool_link_ksettings *cmd, + struct ethtool_link_ksettings *ks, struct net_device *netdev, struct i40e_pf *pf) { struct i40e_link_status *hw_link_info = &hw->phy.link_info; + struct ethtool_link_ksettings cap_ksettings; u32 link_speed = hw_link_info->link_speed; - u32 e_advertising = 0x0; - u32 e_supported = 0x0; - 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); /* Initialize supported and advertised settings based on phy settings */ switch (hw_link_info->phy_type) { case I40E_PHY_TYPE_40GBASE_CR4: case I40E_PHY_TYPE_40GBASE_CR4_CU: - supported = SUPPORTED_Autoneg | - SUPPORTED_40000baseCR4_Full; - advertising = ADVERTISED_Autoneg | - ADVERTISED_40000baseCR4_Full; + ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); + ethtool_link_ksettings_add_link_mode(ks, supported, + 40000baseCR4_Full); + ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); + ethtool_link_ksettings_add_link_mode(ks, advertising, + 40000baseCR4_Full); break; case I40E_PHY_TYPE_XLAUI: case I40E_PHY_TYPE_XLPPI: case I40E_PHY_TYPE_40GBASE_AOC: - supported = SUPPORTED_40000baseCR4_Full; + ethtool_link_ksettings_add_link_mode(ks, supported, + 40000baseCR4_Full); break; case I40E_PHY_TYPE_40GBASE_SR4: - supported = SUPPORTED_40000baseSR4_Full; + ethtool_link_ksettings_add_link_mode(ks, supported, + 40000baseSR4_Full); break; case I40E_PHY_TYPE_40GBASE_LR4: - supported = SUPPORTED_40000baseLR4_Full; + ethtool_link_ksettings_add_link_mode(ks, supported, + 40000baseLR4_Full); break; + case I40E_PHY_TYPE_25GBASE_SR: + case I40E_PHY_TYPE_25GBASE_LR: case I40E_PHY_TYPE_10GBASE_SR: case I40E_PHY_TYPE_10GBASE_LR: case I40E_PHY_TYPE_1000BASE_SX: case I40E_PHY_TYPE_1000BASE_LX: - supported = SUPPORTED_10000baseT_Full; + ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); + ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); + ethtool_link_ksettings_add_link_mode(ks, supported, + 25000baseSR_Full); + ethtool_link_ksettings_add_link_mode(ks, advertising, + 25000baseSR_Full); + ethtool_link_ksettings_add_link_mode(ks, supported, + 10000baseSR_Full); + ethtool_link_ksettings_add_link_mode(ks, advertising, + 10000baseSR_Full); + ethtool_link_ksettings_add_link_mode(ks, supported, + 10000baseLR_Full); + ethtool_link_ksettings_add_link_mode(ks, advertising, + 10000baseLR_Full); + ethtool_link_ksettings_add_link_mode(ks, supported, + 1000baseX_Full); + ethtool_link_ksettings_add_link_mode(ks, advertising, + 1000baseX_Full); + ethtool_link_ksettings_add_link_mode(ks, 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) { - supported |= SUPPORTED_1000baseT_Full; + ethtool_link_ksettings_add_link_mode(ks, supported, + 1000baseT_Full); if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB) - advertising |= ADVERTISED_1000baseT_Full; + ethtool_link_ksettings_add_link_mode( + ks, advertising, 1000baseT_Full); } if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB) - advertising |= ADVERTISED_10000baseT_Full; + ethtool_link_ksettings_add_link_mode(ks, advertising, + 10000baseT_Full); break; case I40E_PHY_TYPE_10GBASE_T: case I40E_PHY_TYPE_1000BASE_T: case I40E_PHY_TYPE_100BASE_TX: - supported = SUPPORTED_Autoneg | - SUPPORTED_10000baseT_Full | - SUPPORTED_1000baseT_Full | - SUPPORTED_100baseT_Full; - advertising = ADVERTISED_Autoneg; + ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); + ethtool_link_ksettings_add_link_mode(ks, supported, + 10000baseT_Full); + ethtool_link_ksettings_add_link_mode(ks, supported, + 1000baseT_Full); + ethtool_link_ksettings_add_link_mode(ks, supported, + 100baseT_Full); + ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB) - advertising |= ADVERTISED_10000baseT_Full; + ethtool_link_ksettings_add_link_mode(ks, advertising, + 10000baseT_Full); if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB) - advertising |= ADVERTISED_1000baseT_Full; + ethtool_link_ksettings_add_link_mode(ks, advertising, + 1000baseT_Full); if (hw_link_info->requested_speeds & I40E_LINK_SPEED_100MB) - advertising |= ADVERTISED_100baseT_Full; + ethtool_link_ksettings_add_link_mode(ks, advertising, + 100baseT_Full); break; case I40E_PHY_TYPE_1000BASE_T_OPTICAL: - supported = SUPPORTED_Autoneg | - SUPPORTED_1000baseT_Full; - advertising = ADVERTISED_Autoneg | - ADVERTISED_1000baseT_Full; + ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); + ethtool_link_ksettings_add_link_mode(ks, supported, + 1000baseT_Full); + ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); + ethtool_link_ksettings_add_link_mode(ks, advertising, + 1000baseT_Full); break; case I40E_PHY_TYPE_10GBASE_CR1_CU: case I40E_PHY_TYPE_10GBASE_CR1: - supported = SUPPORTED_Autoneg | - SUPPORTED_10000baseT_Full; - advertising = ADVERTISED_Autoneg | - ADVERTISED_10000baseT_Full; + ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); + ethtool_link_ksettings_add_link_mode(ks, supported, + 10000baseT_Full); + ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); + ethtool_link_ksettings_add_link_mode(ks, advertising, + 10000baseT_Full); break; case I40E_PHY_TYPE_XAUI: case I40E_PHY_TYPE_XFI: case I40E_PHY_TYPE_SFI: case I40E_PHY_TYPE_10GBASE_SFPP_CU: case I40E_PHY_TYPE_10GBASE_AOC: - supported = SUPPORTED_10000baseT_Full; - advertising = SUPPORTED_10000baseT_Full; + ethtool_link_ksettings_add_link_mode(ks, supported, + 10000baseT_Full); + if (hw_link_info->requested_speeds & I40E_LINK_SPEED_10GB) + ethtool_link_ksettings_add_link_mode(ks, advertising, + 10000baseT_Full); break; case I40E_PHY_TYPE_SGMII: - supported = SUPPORTED_Autoneg | - SUPPORTED_1000baseT_Full; + ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); + ethtool_link_ksettings_add_link_mode(ks, supported, + 1000baseT_Full); if (hw_link_info->requested_speeds & I40E_LINK_SPEED_1GB) - advertising |= ADVERTISED_1000baseT_Full; + ethtool_link_ksettings_add_link_mode(ks, advertising, + 1000baseT_Full); if (pf->hw_features & I40E_HW_100M_SGMII_CAPABLE) { - supported |= SUPPORTED_100baseT_Full; + ethtool_link_ksettings_add_link_mode(ks, supported, + 100baseT_Full); if (hw_link_info->requested_speeds & I40E_LINK_SPEED_100MB) - advertising |= ADVERTISED_100baseT_Full; + ethtool_link_ksettings_add_link_mode( + ks, advertising, 100baseT_Full); } break; case I40E_PHY_TYPE_40GBASE_KR4: + case I40E_PHY_TYPE_25GBASE_KR: case I40E_PHY_TYPE_20GBASE_KR2: case I40E_PHY_TYPE_10GBASE_KR: case I40E_PHY_TYPE_10GBASE_KX4: case I40E_PHY_TYPE_1000BASE_KX: - supported |= SUPPORTED_40000baseKR4_Full | - SUPPORTED_20000baseKR2_Full | - SUPPORTED_10000baseKR_Full | - SUPPORTED_10000baseKX4_Full | - SUPPORTED_1000baseKX_Full | - SUPPORTED_Autoneg; - advertising |= ADVERTISED_40000baseKR4_Full | - ADVERTISED_20000baseKR2_Full | - ADVERTISED_10000baseKR_Full | - ADVERTISED_10000baseKX4_Full | - ADVERTISED_1000baseKX_Full | - ADVERTISED_Autoneg; + ethtool_link_ksettings_add_link_mode(ks, supported, + 40000baseKR4_Full); + ethtool_link_ksettings_add_link_mode(ks, supported, + 25000baseKR_Full); + ethtool_link_ksettings_add_link_mode(ks, supported, + 20000baseKR2_Full); + ethtool_link_ksettings_add_link_mode(ks, supported, + 10000baseKR_Full); + ethtool_link_ksettings_add_link_mode(ks, supported, + 10000baseKX4_Full); + ethtool_link_ksettings_add_link_mode(ks, supported, + 1000baseKX_Full); + ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); + ethtool_link_ksettings_add_link_mode(ks, advertising, + 40000baseKR4_Full); + ethtool_link_ksettings_add_link_mode(ks, advertising, + 25000baseKR_Full); + ethtool_link_ksettings_add_link_mode(ks, advertising, + 20000baseKR2_Full); + ethtool_link_ksettings_add_link_mode(ks, advertising, + 10000baseKR_Full); + ethtool_link_ksettings_add_link_mode(ks, advertising, + 10000baseKX4_Full); + ethtool_link_ksettings_add_link_mode(ks, advertising, + 1000baseKX_Full); + ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); break; - case I40E_PHY_TYPE_25GBASE_KR: case I40E_PHY_TYPE_25GBASE_CR: - case I40E_PHY_TYPE_25GBASE_SR: - case I40E_PHY_TYPE_25GBASE_LR: - supported = SUPPORTED_Autoneg; - advertising = ADVERTISED_Autoneg; - /* TODO: add speeds when ethtool is ready to support*/ + ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); + ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); + ethtool_link_ksettings_add_link_mode(ks, supported, + 25000baseCR_Full); + ethtool_link_ksettings_add_link_mode(ks, advertising, + 25000baseCR_Full); + break; + case I40E_PHY_TYPE_25GBASE_AOC: + case I40E_PHY_TYPE_25GBASE_ACC: + ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); + ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); + ethtool_link_ksettings_add_link_mode(ks, supported, + 25000baseCR_Full); + + ethtool_link_ksettings_add_link_mode(ks, advertising, + 25000baseCR_Full); + ethtool_link_ksettings_add_link_mode(ks, supported, + 10000baseCR_Full); + ethtool_link_ksettings_add_link_mode(ks, advertising, + 10000baseCR_Full); 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", + netdev_info(netdev, + "WARNING: Link is up but PHY type 0x%x is not recognized.\n", hw_link_info->phy_type); } /* Now that we've worked out everything that could be supported by the - * current PHY type, get what is supported by the NVM and them to - * get what is truly supported + * current PHY type, get what is supported by the NVM and intersect + * them to get what is truly supported */ - i40e_phy_type_to_ethtool(pf, &e_supported, - &e_advertising); - - supported = supported & e_supported; - advertising = advertising & e_advertising; + memset(&cap_ksettings, 0, sizeof(struct ethtool_link_ksettings)); + i40e_phy_type_to_ethtool(pf, &cap_ksettings); + ethtool_intersect_link_masks(ks, &cap_ksettings); /* Set speed and duplex */ switch (link_speed) { case I40E_LINK_SPEED_40GB: - cmd->base.speed = SPEED_40000; + ks->base.speed = SPEED_40000; break; case I40E_LINK_SPEED_25GB: -#ifdef SPEED_25000 - cmd->base.speed = SPEED_25000; -#else - netdev_info(netdev, - "Speed is 25G, display not supported by this version of ethtool.\n"); -#endif + ks->base.speed = SPEED_25000; break; case I40E_LINK_SPEED_20GB: - cmd->base.speed = SPEED_20000; + ks->base.speed = SPEED_20000; break; case I40E_LINK_SPEED_10GB: - cmd->base.speed = SPEED_10000; + ks->base.speed = SPEED_10000; break; case I40E_LINK_SPEED_1GB: - cmd->base.speed = SPEED_1000; + ks->base.speed = SPEED_1000; break; case I40E_LINK_SPEED_100MB: - cmd->base.speed = SPEED_100; + ks->base.speed = SPEED_100; break; default: break; } - cmd->base.duplex = DUPLEX_FULL; - - ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, - supported); - ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising, - advertising); + ks->base.duplex = DUPLEX_FULL; } /** * i40e_get_settings_link_down - Get the Link settings for when link is down * @hw: hw structure - * @ecmd: ethtool command to fill in + * @ks: ethtool ksettings to fill in + * @pf: pointer to physical function struct * * Reports link settings that can be determined when link is down **/ static void i40e_get_settings_link_down(struct i40e_hw *hw, - struct ethtool_link_ksettings *cmd, + struct ethtool_link_ksettings *ks, struct i40e_pf *pf) { - u32 supported, advertising; - /* link is down and the driver needs to fall back on * supported phy types to figure out what info to display */ - i40e_phy_type_to_ethtool(pf, &supported, &advertising); - - ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, - supported); - ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.advertising, - advertising); + i40e_phy_type_to_ethtool(pf, ks); /* With no link speed and duplex are unknown */ - cmd->base.speed = SPEED_UNKNOWN; - cmd->base.duplex = DUPLEX_UNKNOWN; + ks->base.speed = SPEED_UNKNOWN; + ks->base.duplex = DUPLEX_UNKNOWN; } /** - * i40e_get_settings - Get Link Speed and Duplex settings + * i40e_get_link_ksettings - Get Link Speed and Duplex settings * @netdev: network interface device structure - * @ecmd: ethtool command + * @ks: ethtool ksettings * * Reports speed/duplex settings based on media_type **/ static int i40e_get_link_ksettings(struct net_device *netdev, - struct ethtool_link_ksettings *cmd) + struct ethtool_link_ksettings *ks) { struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_pf *pf = np->vsi->back; struct i40e_hw *hw = &pf->hw; struct i40e_link_status *hw_link_info = &hw->phy.link_info; bool link_up = hw_link_info->link_info & I40E_AQ_LINK_UP; - u32 advertising; + + ethtool_link_ksettings_zero_link_mode(ks, supported); + ethtool_link_ksettings_zero_link_mode(ks, advertising); if (link_up) - i40e_get_settings_link_up(hw, cmd, netdev, pf); + i40e_get_settings_link_up(hw, ks, netdev, pf); else - i40e_get_settings_link_down(hw, cmd, pf); + i40e_get_settings_link_down(hw, ks, pf); /* Now set the settings that don't rely on link being up/down */ /* Set autoneg settings */ - cmd->base.autoneg = ((hw_link_info->an_info & I40E_AQ_AN_COMPLETED) ? - AUTONEG_ENABLE : AUTONEG_DISABLE); + ks->base.autoneg = ((hw_link_info->an_info & I40E_AQ_AN_COMPLETED) ? + AUTONEG_ENABLE : AUTONEG_DISABLE); + /* Set media type settings */ switch (hw->phy.media_type) { case I40E_MEDIA_TYPE_BACKPLANE: - ethtool_link_ksettings_add_link_mode(cmd, supported, - Autoneg); - ethtool_link_ksettings_add_link_mode(cmd, supported, + ethtool_link_ksettings_add_link_mode(ks, supported, Autoneg); + ethtool_link_ksettings_add_link_mode(ks, supported, Backplane); + ethtool_link_ksettings_add_link_mode(ks, advertising, Autoneg); + ethtool_link_ksettings_add_link_mode(ks, advertising, Backplane); - ethtool_link_ksettings_add_link_mode(cmd, advertising, - Autoneg); - ethtool_link_ksettings_add_link_mode(cmd, advertising, - Backplane); - cmd->base.port = PORT_NONE; + ks->base.port = PORT_NONE; break; case I40E_MEDIA_TYPE_BASET: - ethtool_link_ksettings_add_link_mode(cmd, supported, TP); - ethtool_link_ksettings_add_link_mode(cmd, advertising, TP); - cmd->base.port = PORT_TP; + ethtool_link_ksettings_add_link_mode(ks, supported, TP); + ethtool_link_ksettings_add_link_mode(ks, advertising, TP); + ks->base.port = PORT_TP; break; case I40E_MEDIA_TYPE_DA: case I40E_MEDIA_TYPE_CX4: - ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE); - ethtool_link_ksettings_add_link_mode(cmd, advertising, FIBRE); - cmd->base.port = PORT_DA; + ethtool_link_ksettings_add_link_mode(ks, supported, FIBRE); + ethtool_link_ksettings_add_link_mode(ks, advertising, FIBRE); + ks->base.port = PORT_DA; break; case I40E_MEDIA_TYPE_FIBER: - ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE); - cmd->base.port = PORT_FIBRE; + ethtool_link_ksettings_add_link_mode(ks, supported, FIBRE); + ks->base.port = PORT_FIBRE; break; case I40E_MEDIA_TYPE_UNKNOWN: default: - cmd->base.port = PORT_OTHER; + ks->base.port = PORT_OTHER; break; } /* Set flow control settings */ - ethtool_link_ksettings_add_link_mode(cmd, supported, Pause); + ethtool_link_ksettings_add_link_mode(ks, supported, Pause); switch (hw->fc.requested_mode) { case I40E_FC_FULL: - ethtool_link_ksettings_add_link_mode(cmd, advertising, - Pause); + ethtool_link_ksettings_add_link_mode(ks, advertising, Pause); break; case I40E_FC_TX_PAUSE: - ethtool_link_ksettings_add_link_mode(cmd, advertising, + ethtool_link_ksettings_add_link_mode(ks, advertising, Asym_Pause); break; case I40E_FC_RX_PAUSE: - ethtool_link_ksettings_add_link_mode(cmd, advertising, - Pause); - ethtool_link_ksettings_add_link_mode(cmd, advertising, + ethtool_link_ksettings_add_link_mode(ks, advertising, Pause); + ethtool_link_ksettings_add_link_mode(ks, advertising, Asym_Pause); break; default: - ethtool_convert_link_mode_to_legacy_u32( - &advertising, cmd->link_modes.advertising); - - advertising &= ~(ADVERTISED_Pause | ADVERTISED_Asym_Pause); - - ethtool_convert_legacy_u32_to_link_mode( - cmd->link_modes.advertising, advertising); + ethtool_link_ksettings_del_link_mode(ks, advertising, Pause); + ethtool_link_ksettings_del_link_mode(ks, advertising, + Asym_Pause); break; } @@ -682,30 +811,28 @@ static int i40e_get_link_ksettings(struct net_device *netdev, } /** - * i40e_set_settings - Set Speed and Duplex + * i40e_set_link_ksettings - Set Speed and Duplex * @netdev: network interface device structure - * @ecmd: ethtool command + * @ks: ethtool ksettings * * Set speed/duplex per media_types advertised/forced **/ static int i40e_set_link_ksettings(struct net_device *netdev, - const struct ethtool_link_ksettings *cmd) + const struct ethtool_link_ksettings *ks) { struct i40e_netdev_priv *np = netdev_priv(netdev); struct i40e_aq_get_phy_abilities_resp abilities; + struct ethtool_link_ksettings safe_ks; + struct ethtool_link_ksettings copy_ks; struct i40e_aq_set_phy_config config; struct i40e_pf *pf = np->vsi->back; struct i40e_vsi *vsi = np->vsi; struct i40e_hw *hw = &pf->hw; - struct ethtool_link_ksettings safe_cmd; - struct ethtool_link_ksettings copy_cmd; + bool autoneg_changed = false; i40e_status status = 0; - bool change = false; int timeout = 50; int err = 0; - u32 autoneg; - u32 advertise; - u32 tmp; + u8 autoneg; /* Changing port settings is not supported if this isn't the * port's controlling PF @@ -714,17 +841,14 @@ static int i40e_set_link_ksettings(struct net_device *netdev, i40e_partition_setting_complaint(pf); return -EOPNOTSUPP; } - if (vsi != pf->vsi[pf->lan_vsi]) return -EOPNOTSUPP; - if (hw->phy.media_type != I40E_MEDIA_TYPE_BASET && hw->phy.media_type != I40E_MEDIA_TYPE_FIBER && hw->phy.media_type != I40E_MEDIA_TYPE_BACKPLANE && hw->phy.media_type != I40E_MEDIA_TYPE_DA && 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 || @@ -733,31 +857,37 @@ static int i40e_set_link_ksettings(struct net_device *netdev, return -EOPNOTSUPP; } - /* copy the cmd to copy_cmd to avoid modifying the origin */ - memcpy(©_cmd, cmd, sizeof(struct ethtool_link_ksettings)); + /* copy the ksettings to copy_ks to avoid modifying the origin */ + memcpy(©_ks, ks, sizeof(struct ethtool_link_ksettings)); + + /* save autoneg out of ksettings */ + autoneg = copy_ks.base.autoneg; + + memset(&safe_ks, 0, sizeof(safe_ks)); + /* Get link modes supported by hardware and check against modes + * requested by the user. Return an error if unsupported mode was set. + */ + i40e_phy_type_to_ethtool(pf, &safe_ks); + if (!bitmap_subset(copy_ks.link_modes.advertising, + safe_ks.link_modes.supported, + __ETHTOOL_LINK_MODE_MASK_NBITS)) + return -EINVAL; /* get our own copy of the bits to check against */ - memset(&safe_cmd, 0, sizeof(struct ethtool_link_ksettings)); - i40e_get_link_ksettings(netdev, &safe_cmd); + memset(&safe_ks, 0, sizeof(struct ethtool_link_ksettings)); + safe_ks.base.cmd = copy_ks.base.cmd; + safe_ks.base.link_mode_masks_nwords = + copy_ks.base.link_mode_masks_nwords; + i40e_get_link_ksettings(netdev, &safe_ks); - /* save autoneg and speed out of cmd */ - autoneg = cmd->base.autoneg; - ethtool_convert_link_mode_to_legacy_u32(&advertise, - cmd->link_modes.advertising); + /* set autoneg back to what it currently is */ + copy_ks.base.autoneg = safe_ks.base.autoneg; - /* set autoneg and speed back to what they currently are */ - copy_cmd.base.autoneg = safe_cmd.base.autoneg; - ethtool_convert_link_mode_to_legacy_u32( - &tmp, safe_cmd.link_modes.advertising); - ethtool_convert_legacy_u32_to_link_mode( - copy_cmd.link_modes.advertising, tmp); - - copy_cmd.base.cmd = safe_cmd.base.cmd; - - /* If copy_cmd and safe_cmd are not the same now, then they are - * trying to set something that we do not support + /* If copy_ks.base and safe_ks.base are not the same now, then they are + * trying to set something that we do not support. */ - if (memcmp(©_cmd, &safe_cmd, sizeof(struct ethtool_link_ksettings))) + if (memcmp(©_ks.base, &safe_ks.base, + sizeof(struct ethtool_link_settings))) return -EOPNOTSUPP; while (test_and_set_bit(__I40E_CONFIG_BUSY, pf->state)) { @@ -786,8 +916,9 @@ static int i40e_set_link_ksettings(struct net_device *netdev, /* If autoneg was not already enabled */ if (!(hw->phy.link_info.an_info & I40E_AQ_AN_COMPLETED)) { /* If autoneg is not supported, return error */ - if (!ethtool_link_ksettings_test_link_mode( - &safe_cmd, supported, Autoneg)) { + if (!ethtool_link_ksettings_test_link_mode(&safe_ks, + supported, + Autoneg)) { netdev_info(netdev, "Autoneg not supported on this phy\n"); err = -EINVAL; goto done; @@ -795,7 +926,7 @@ static int i40e_set_link_ksettings(struct net_device *netdev, /* Autoneg is allowed to change */ config.abilities = abilities.abilities | I40E_AQ_PHY_ENABLE_AN; - change = true; + autoneg_changed = true; } } else { /* If autoneg is currently enabled */ @@ -803,8 +934,9 @@ static int i40e_set_link_ksettings(struct net_device *netdev, /* If autoneg is supported 10GBASE_T is the only PHY * that can disable it, so otherwise return error */ - if (ethtool_link_ksettings_test_link_mode( - &safe_cmd, supported, Autoneg) && + if (ethtool_link_ksettings_test_link_mode(&safe_ks, + supported, + Autoneg) && hw->phy.link_info.phy_type != I40E_PHY_TYPE_10GBASE_T) { netdev_info(netdev, "Autoneg cannot be disabled on this phy\n"); @@ -814,32 +946,49 @@ static int i40e_set_link_ksettings(struct net_device *netdev, /* Autoneg is allowed to change */ config.abilities = abilities.abilities & ~I40E_AQ_PHY_ENABLE_AN; - change = true; + autoneg_changed = true; } } - ethtool_convert_link_mode_to_legacy_u32(&tmp, - safe_cmd.link_modes.supported); - if (advertise & ~tmp) { - err = -EINVAL; - goto done; - } - - if (advertise & ADVERTISED_100baseT_Full) + if (ethtool_link_ksettings_test_link_mode(ks, advertising, + 100baseT_Full)) config.link_speed |= I40E_LINK_SPEED_100MB; - if (advertise & ADVERTISED_1000baseT_Full || - advertise & ADVERTISED_1000baseKX_Full) + if (ethtool_link_ksettings_test_link_mode(ks, advertising, + 1000baseT_Full) || + ethtool_link_ksettings_test_link_mode(ks, advertising, + 1000baseX_Full) || + ethtool_link_ksettings_test_link_mode(ks, advertising, + 1000baseKX_Full)) config.link_speed |= I40E_LINK_SPEED_1GB; - if (advertise & ADVERTISED_10000baseT_Full || - advertise & ADVERTISED_10000baseKX4_Full || - advertise & ADVERTISED_10000baseKR_Full) + if (ethtool_link_ksettings_test_link_mode(ks, advertising, + 10000baseT_Full) || + ethtool_link_ksettings_test_link_mode(ks, advertising, + 10000baseKX4_Full) || + ethtool_link_ksettings_test_link_mode(ks, advertising, + 10000baseKR_Full) || + ethtool_link_ksettings_test_link_mode(ks, advertising, + 10000baseCR_Full) || + ethtool_link_ksettings_test_link_mode(ks, advertising, + 10000baseSR_Full)) config.link_speed |= I40E_LINK_SPEED_10GB; - if (advertise & ADVERTISED_20000baseKR2_Full) + if (ethtool_link_ksettings_test_link_mode(ks, advertising, + 20000baseKR2_Full)) config.link_speed |= I40E_LINK_SPEED_20GB; - if (advertise & ADVERTISED_40000baseKR4_Full || - advertise & ADVERTISED_40000baseCR4_Full || - advertise & ADVERTISED_40000baseSR4_Full || - advertise & ADVERTISED_40000baseLR4_Full) + if (ethtool_link_ksettings_test_link_mode(ks, advertising, + 25000baseCR_Full) || + ethtool_link_ksettings_test_link_mode(ks, advertising, + 25000baseKR_Full) || + ethtool_link_ksettings_test_link_mode(ks, advertising, + 25000baseSR_Full)) + config.link_speed |= I40E_LINK_SPEED_25GB; + if (ethtool_link_ksettings_test_link_mode(ks, advertising, + 40000baseKR4_Full) || + ethtool_link_ksettings_test_link_mode(ks, advertising, + 40000baseCR4_Full) || + ethtool_link_ksettings_test_link_mode(ks, advertising, + 40000baseSR4_Full) || + ethtool_link_ksettings_test_link_mode(ks, advertising, + 40000baseLR4_Full)) config.link_speed |= I40E_LINK_SPEED_40GB; /* If speed didn't get set, set it to what it currently is. @@ -848,8 +997,7 @@ static int i40e_set_link_ksettings(struct net_device *netdev, */ if (!config.link_speed) config.link_speed = abilities.link_speed; - - if (change || (abilities.link_speed != config.link_speed)) { + if (autoneg_changed || abilities.link_speed != config.link_speed) { /* copy over the rest of the abilities */ config.phy_type = abilities.phy_type; config.phy_type_ext = abilities.phy_type_ext; @@ -876,7 +1024,8 @@ static int i40e_set_link_ksettings(struct net_device *netdev, /* make the aq call */ status = i40e_aq_set_phy_config(hw, &config, NULL); if (status) { - netdev_info(netdev, "Set phy config failed, err %s aq_err %s\n", + netdev_info(netdev, + "Set phy config failed, err %s aq_err %s\n", i40e_stat_str(hw, status), i40e_aq_str(hw, hw->aq.asq_last_status)); err = -EAGAIN; @@ -885,7 +1034,8 @@ static int i40e_set_link_ksettings(struct net_device *netdev, status = i40e_update_link_info(hw); if (status) - netdev_dbg(netdev, "Updating link info failed with err %s aq_err %s\n", + netdev_dbg(netdev, + "Updating link info failed with err %s aq_err %s\n", i40e_stat_str(hw, status), i40e_aq_str(hw, hw->aq.asq_last_status)); @@ -2076,14 +2226,13 @@ static int __i40e_get_coalesce(struct net_device *netdev, ec->tx_max_coalesced_frames_irq = vsi->work_limit; ec->rx_max_coalesced_frames_irq = vsi->work_limit; - /* rx and tx usecs has per queue value. If user doesn't specify the queue, - * return queue 0's value to represent. + /* rx and tx usecs has per queue value. If user doesn't specify the + * queue, return queue 0's value to represent. */ - if (queue < 0) { + if (queue < 0) queue = 0; - } else if (queue >= vsi->num_queue_pairs) { + else if (queue >= vsi->num_queue_pairs) return -EINVAL; - } rx_ring = vsi->rx_rings[queue]; tx_ring = vsi->tx_rings[queue]; @@ -2097,7 +2246,6 @@ static int __i40e_get_coalesce(struct net_device *netdev, ec->rx_coalesce_usecs = rx_ring->rx_itr_setting & ~I40E_ITR_DYNAMIC; ec->tx_coalesce_usecs = tx_ring->tx_itr_setting & ~I40E_ITR_DYNAMIC; - /* we use the _usecs_high to store/set the interrupt rate limit * that the hardware supports, that almost but not quite * fits the original intent of the ethtool variable, @@ -2147,7 +2295,6 @@ static int i40e_get_per_queue_coalesce(struct net_device *netdev, u32 queue, * * Change the ITR settings for a specific queue. **/ - static void i40e_set_itr_per_queue(struct i40e_vsi *vsi, struct ethtool_coalesce *ec, int queue) @@ -2269,8 +2416,8 @@ static int __i40e_set_coalesce(struct net_device *netdev, vsi->int_rate_limit); } - /* rx and tx usecs has per queue value. If user doesn't specify the queue, - * apply to all queues. + /* rx and tx usecs has per queue value. If user doesn't specify the + * queue, apply to all queues. */ if (queue < 0) { for (i = 0; i < vsi->num_queue_pairs; i++) @@ -3970,6 +4117,16 @@ static u32 i40e_get_rxfh_indir_size(struct net_device *netdev) return I40E_HLUT_ARRAY_SIZE; } +/** + * i40e_get_rxfh - get the rx flow hash indirection table + * @netdev: network interface device structure + * @indir: indirection table + * @key: hash key + * @hfunc: hash function + * + * Reads the indirection table directly from the hardware. Returns 0 on + * success. + **/ static int i40e_get_rxfh(struct net_device *netdev, u32 *indir, u8 *key, u8 *hfunc) { diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 39989147b30b..54ff34faca37 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -5442,6 +5442,7 @@ int i40e_get_link_speed(struct i40e_vsi *vsi) int i40e_set_bw_limit(struct i40e_vsi *vsi, u16 seid, u64 max_tx_rate) { struct i40e_pf *pf = vsi->back; + u64 credits = 0; int speed = 0; int ret = 0; @@ -5459,8 +5460,9 @@ int i40e_set_bw_limit(struct i40e_vsi *vsi, u16 seid, u64 max_tx_rate) } /* Tx rate credits are in values of 50Mbps, 0 is disabled */ - ret = i40e_aq_config_vsi_bw_limit(&pf->hw, seid, - max_tx_rate / I40E_BW_CREDIT_DIVISOR, + credits = max_tx_rate; + do_div(credits, I40E_BW_CREDIT_DIVISOR); + ret = i40e_aq_config_vsi_bw_limit(&pf->hw, seid, credits, I40E_MAX_BW_INACTIVE_ACCUM, NULL); if (ret) dev_err(&pf->pdev->dev, @@ -6063,13 +6065,17 @@ int i40e_create_queue_channel(struct i40e_vsi *vsi, /* configure VSI for BW limit */ if (ch->max_tx_rate) { + u64 credits = ch->max_tx_rate; + if (i40e_set_bw_limit(vsi, ch->seid, ch->max_tx_rate)) return -EINVAL; + do_div(credits, I40E_BW_CREDIT_DIVISOR); dev_dbg(&pf->pdev->dev, "Set tx rate of %llu Mbps (count of 50Mbps %llu) for vsi->seid %u\n", ch->max_tx_rate, - ch->max_tx_rate / I40E_BW_CREDIT_DIVISOR, ch->seid); + credits, + ch->seid); } /* in case of VF, this will be main SRIOV VSI */ @@ -6090,6 +6096,7 @@ int i40e_create_queue_channel(struct i40e_vsi *vsi, static int i40e_configure_queue_channels(struct i40e_vsi *vsi) { struct i40e_channel *ch; + u64 max_rate = 0; int ret = 0, i; /* Create app vsi with the TCs. Main VSI with TC0 is already set up */ @@ -6110,8 +6117,9 @@ static int i40e_configure_queue_channels(struct i40e_vsi *vsi) /* Bandwidth limit through tc interface is in bytes/s, * change to Mbit/s */ - ch->max_tx_rate = - vsi->mqprio_qopt.max_rate[i] / (1000000 / 8); + max_rate = vsi->mqprio_qopt.max_rate[i]; + do_div(max_rate, I40E_BW_MBPS_DIVISOR); + ch->max_tx_rate = max_rate; list_add_tail(&ch->list, &vsi->ch_list); @@ -6540,6 +6548,7 @@ static int i40e_validate_mqprio_qopt(struct i40e_vsi *vsi, struct tc_mqprio_qopt_offload *mqprio_qopt) { u64 sum_max_rate = 0; + u64 max_rate = 0; int i; if (mqprio_qopt->qopt.offset[0] != 0 || @@ -6554,7 +6563,9 @@ static int i40e_validate_mqprio_qopt(struct i40e_vsi *vsi, "Invalid min tx rate (greater than 0) specified\n"); return -EINVAL; } - sum_max_rate += (mqprio_qopt->max_rate[i] / (1000000 / 8)); + max_rate = mqprio_qopt->max_rate[i]; + do_div(max_rate, I40E_BW_MBPS_DIVISOR); + sum_max_rate += max_rate; if (i >= mqprio_qopt->qopt.num_tc - 1) break; @@ -6698,14 +6709,18 @@ config_tc: if (pf->flags & I40E_FLAG_TC_MQPRIO) { if (vsi->mqprio_qopt.max_rate[0]) { - u64 max_tx_rate = vsi->mqprio_qopt.max_rate[0] / - (1000000 / 8); + u64 max_tx_rate = vsi->mqprio_qopt.max_rate[0]; + + do_div(max_tx_rate, I40E_BW_MBPS_DIVISOR); ret = i40e_set_bw_limit(vsi, vsi->seid, max_tx_rate); if (!ret) { + u64 credits = max_tx_rate; + + do_div(credits, I40E_BW_CREDIT_DIVISOR); dev_dbg(&vsi->back->pdev->dev, "Set tx rate of %llu Mbps (count of 50Mbps %llu) for vsi->seid %u\n", max_tx_rate, - max_tx_rate / I40E_BW_CREDIT_DIVISOR, + credits, vsi->seid); } else { need_reset = true; @@ -8166,14 +8181,17 @@ static int i40e_rebuild_channels(struct i40e_vsi *vsi) return ret; } if (ch->max_tx_rate) { + u64 credits = ch->max_tx_rate; + if (i40e_set_bw_limit(vsi, ch->seid, ch->max_tx_rate)) return -EINVAL; + do_div(credits, I40E_BW_CREDIT_DIVISOR); dev_dbg(&vsi->back->pdev->dev, "Set tx rate of %llu Mbps (count of 50Mbps %llu) for vsi->seid %u\n", ch->max_tx_rate, - ch->max_tx_rate / I40E_BW_CREDIT_DIVISOR, + credits, ch->seid); } } @@ -8446,17 +8464,21 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired) } if (vsi->mqprio_qopt.max_rate[0]) { - u64 max_tx_rate = vsi->mqprio_qopt.max_rate[0] / (1000000 / 8); + u64 max_tx_rate = vsi->mqprio_qopt.max_rate[0]; + u64 credits = 0; + do_div(max_tx_rate, I40E_BW_MBPS_DIVISOR); ret = i40e_set_bw_limit(vsi, vsi->seid, max_tx_rate); - if (!ret) - dev_dbg(&vsi->back->pdev->dev, - "Set tx rate of %llu Mbps (count of 50Mbps %llu) for vsi->seid %u\n", - max_tx_rate, - max_tx_rate / I40E_BW_CREDIT_DIVISOR, - vsi->seid); - else + if (ret) goto end_unlock; + + credits = max_tx_rate; + do_div(credits, I40E_BW_CREDIT_DIVISOR); + dev_dbg(&vsi->back->pdev->dev, + "Set tx rate of %llu Mbps (count of 50Mbps %llu) for vsi->seid %u\n", + max_tx_rate, + credits, + vsi->seid); } /* PF Main VSI is rebuild by now, go ahead and rebuild channel VSIs diff --git a/drivers/net/ethernet/intel/i40e/i40e_type.h b/drivers/net/ethernet/intel/i40e/i40e_type.h index 0410fcbdbb94..17a99b53acd9 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_type.h +++ b/drivers/net/ethernet/intel/i40e/i40e_type.h @@ -271,6 +271,10 @@ struct i40e_phy_info { I40E_PHY_TYPE_OFFSET) #define I40E_CAP_PHY_TYPE_25GBASE_LR BIT_ULL(I40E_PHY_TYPE_25GBASE_LR + \ I40E_PHY_TYPE_OFFSET) +#define I40E_CAP_PHY_TYPE_25GBASE_AOC BIT_ULL(I40E_PHY_TYPE_25GBASE_AOC + \ + I40E_PHY_TYPE_OFFSET) +#define I40E_CAP_PHY_TYPE_25GBASE_ACC BIT_ULL(I40E_PHY_TYPE_25GBASE_ACC + \ + I40E_PHY_TYPE_OFFSET) #define I40E_HW_CAP_MAX_GPIO 30 /* Capabilities of a PF or a VF or the whole device */ struct i40e_hw_capabilities { diff --git a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h index 60c892f559b9..463e331a70a9 100644 --- a/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h +++ b/drivers/net/ethernet/intel/i40evf/i40e_adminq_cmd.h @@ -1767,6 +1767,8 @@ enum i40e_aq_phy_type { I40E_PHY_TYPE_25GBASE_CR = 0x20, I40E_PHY_TYPE_25GBASE_SR = 0x21, I40E_PHY_TYPE_25GBASE_LR = 0x22, + I40E_PHY_TYPE_25GBASE_AOC = 0x23, + I40E_PHY_TYPE_25GBASE_ACC = 0x24, I40E_PHY_TYPE_MAX, I40E_PHY_TYPE_NOT_SUPPORTED_HIGH_TEMP = 0xFD, I40E_PHY_TYPE_EMPTY = 0xFE, @@ -1827,6 +1829,8 @@ struct i40e_aq_get_phy_abilities_resp { #define I40E_AQ_PHY_TYPE_EXT_25G_CR 0X02 #define I40E_AQ_PHY_TYPE_EXT_25G_SR 0x04 #define I40E_AQ_PHY_TYPE_EXT_25G_LR 0x08 +#define I40E_AQ_PHY_TYPE_EXT_25G_AOC 0x10 +#define I40E_AQ_PHY_TYPE_EXT_25G_ACC 0x20 u8 fec_cfg_curr_mod_ext_info; #define I40E_AQ_ENABLE_FEC_KR 0x01 #define I40E_AQ_ENABLE_FEC_RS 0x02 diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 4587a4c36923..c77fa3529e15 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -163,6 +163,16 @@ extern int __ethtool_get_link_ksettings(struct net_device *dev, struct ethtool_link_ksettings *link_ksettings); +/** + * ethtool_intersect_link_masks - Given two link masks, AND them together + * @dst: first mask and where result is stored + * @src: second mask to intersect with + * + * Given two link mode masks, AND them together and save the result in dst. + */ +void ethtool_intersect_link_masks(struct ethtool_link_ksettings *dst, + struct ethtool_link_ksettings *src); + void ethtool_convert_legacy_u32_to_link_mode(unsigned long *dst, u32 legacy_u32); diff --git a/net/core/ethtool.c b/net/core/ethtool.c index 3228411ada0f..0c406306792a 100644 --- a/net/core/ethtool.c +++ b/net/core/ethtool.c @@ -403,6 +403,22 @@ static int __ethtool_set_flags(struct net_device *dev, u32 data) return 0; } +/* Given two link masks, AND them together and save the result in dst. */ +void ethtool_intersect_link_masks(struct ethtool_link_ksettings *dst, + struct ethtool_link_ksettings *src) +{ + unsigned int size = BITS_TO_LONGS(__ETHTOOL_LINK_MODE_MASK_NBITS); + unsigned int idx = 0; + + for (; idx < size; idx++) { + dst->link_modes.supported[idx] &= + src->link_modes.supported[idx]; + dst->link_modes.advertising[idx] &= + src->link_modes.advertising[idx]; + } +} +EXPORT_SYMBOL(ethtool_intersect_link_masks); + void ethtool_convert_legacy_u32_to_link_mode(unsigned long *dst, u32 legacy_u32) {