diff options
| -rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_ptp.c | 9 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/i40e/i40e_register.h | 10 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/ice/ice_dpll.c | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/ice/ice_ethtool.c | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/ice/ice_fw_update.c | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c | 73 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_e610.h | 1 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c | 244 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 30 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_type.h | 2 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_type_e610.h | 32 | ||||
| -rw-r--r-- | drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c | 2 | ||||
| -rw-r--r-- | include/linux/net/intel/libie/adminq.h | 1 |
13 files changed, 337 insertions, 73 deletions
diff --git a/drivers/net/ethernet/intel/i40e/i40e_ptp.c b/drivers/net/ethernet/intel/i40e/i40e_ptp.c index 404a716db8da..7bcea7d9720f 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ptp.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ptp.c @@ -24,9 +24,6 @@ #define I40E_PTP_1GB_INCVAL_MULT 20 #define I40E_ISGN 0x80000000 -#define I40E_PRTTSYN_CTL1_TSYNTYPE_V1 BIT(I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT) -#define I40E_PRTTSYN_CTL1_TSYNTYPE_V2 (2 << \ - I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT) #define I40E_SUBDEV_ID_25G_PTP_PIN 0xB enum i40e_ptp_pin { @@ -1219,7 +1216,7 @@ static int i40e_ptp_set_timestamp_mode(struct i40e_pf *pf, pf->ptp_rx = true; tsyntype = I40E_PRTTSYN_CTL1_V1MESSTYPE0_MASK | I40E_PRTTSYN_CTL1_TSYNTYPE_V1 | - I40E_PRTTSYN_CTL1_UDP_ENA_MASK; + I40E_PRTTSYN_CTL1_UDP_ENA_319; config->rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; break; case HWTSTAMP_FILTER_PTP_V2_EVENT: @@ -1236,9 +1233,9 @@ static int i40e_ptp_set_timestamp_mode(struct i40e_pf *pf, case HWTSTAMP_FILTER_PTP_V2_L2_DELAY_REQ: pf->ptp_rx = true; tsyntype = I40E_PRTTSYN_CTL1_V2MESSTYPE0_MASK | - I40E_PRTTSYN_CTL1_TSYNTYPE_V2; + I40E_PRTTSYN_CTL1_TSYNTYPE_V2_EVENT; if (test_bit(I40E_HW_CAP_PTP_L4, pf->hw.caps)) { - tsyntype |= I40E_PRTTSYN_CTL1_UDP_ENA_MASK; + tsyntype |= I40E_PRTTSYN_CTL1_UDP_ENA_319; config->rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; } else { config->rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT; diff --git a/drivers/net/ethernet/intel/i40e/i40e_register.h b/drivers/net/ethernet/intel/i40e/i40e_register.h index 432afbb64201..d426d83e0214 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_register.h +++ b/drivers/net/ethernet/intel/i40e/i40e_register.h @@ -788,8 +788,18 @@ #define I40E_PRTTSYN_CTL1_V2MESSTYPE0_SHIFT 16 #define I40E_PRTTSYN_CTL1_V2MESSTYPE0_MASK I40E_MASK(0xF, I40E_PRTTSYN_CTL1_V2MESSTYPE0_SHIFT) #define I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT 24 +#define I40E_PRTTSYN_CTL1_TSYNTYPE_MASK I40E_MASK(0x3, I40E_PRTTSYN_CTL1_TSYNTYPE_SHIFT) +/* Timestamp UDP v1 packets */ +#define I40E_PRTTSYN_CTL1_TSYNTYPE_V1 \ + FIELD_PREP(I40E_PRTTSYN_CTL1_TSYNTYPE_MASK, 1) +/* Timestamp L2 and UDP v2 packets with message type < 8 */ +#define I40E_PRTTSYN_CTL1_TSYNTYPE_V2_EVENT \ + FIELD_PREP(I40E_PRTTSYN_CTL1_TSYNTYPE_MASK, 3) #define I40E_PRTTSYN_CTL1_UDP_ENA_SHIFT 26 #define I40E_PRTTSYN_CTL1_UDP_ENA_MASK I40E_MASK(0x3, I40E_PRTTSYN_CTL1_UDP_ENA_SHIFT) +/* Timestamp UDP packets on port 319 */ +#define I40E_PRTTSYN_CTL1_UDP_ENA_319 \ + FIELD_PREP(I40E_PRTTSYN_CTL1_UDP_ENA_MASK, 1) #define I40E_PRTTSYN_CTL1_TSYNENA_SHIFT 31 #define I40E_PRTTSYN_CTL1_TSYNENA_MASK I40E_MASK(0x1, I40E_PRTTSYN_CTL1_TSYNENA_SHIFT) #define I40E_PRTTSYN_INC_H 0x001E4060 /* Reset: GLOBR */ diff --git a/drivers/net/ethernet/intel/ice/ice_dpll.c b/drivers/net/ethernet/intel/ice/ice_dpll.c index 27b460926bac..a00da99dd19f 100644 --- a/drivers/net/ethernet/intel/ice/ice_dpll.c +++ b/drivers/net/ethernet/intel/ice/ice_dpll.c @@ -3632,7 +3632,7 @@ static int ice_dpll_init_fwnode_pins(struct ice_pf *pf, struct ice_dpll_pin *pins, int start_idx) { - char pin_name[8]; + char pin_name[16]; int i, ret; pf->dplls.wq = create_singlethread_workqueue("ice_dpll_wq"); diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index f28416a707d7..236d293aba98 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -1251,7 +1251,7 @@ static int ice_lbtest_receive_frames(struct ice_rx_ring *rx_ring) rx_buf = &rx_ring->rx_fqes[i]; page = __netmem_to_page(rx_buf->netmem); received_buf = page_address(page) + rx_buf->offset + - page->pp->p.offset; + pp_page_to_nmdesc(page)->pp->p.offset; if (ice_lbtest_check_frame(received_buf)) valid_frames++; diff --git a/drivers/net/ethernet/intel/ice/ice_fw_update.c b/drivers/net/ethernet/intel/ice/ice_fw_update.c index c143e546dd8c..36314610927b 100644 --- a/drivers/net/ethernet/intel/ice/ice_fw_update.c +++ b/drivers/net/ethernet/intel/ice/ice_fw_update.c @@ -726,7 +726,7 @@ static int ice_finalize_update(struct pldmfw *context) switch (priv->reset_level) { case ICE_AQC_NVM_EMPR_FLAG: devlink_flash_update_status_notify(devlink, - "Activate new firmware by devlink reload", + "Activate new firmware by devlink reload action fw_activate", NULL, 0, 0); break; case ICE_AQC_NVM_PERST_FLAG: diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c index 52f73142ff75..665a9813e251 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c @@ -628,6 +628,9 @@ static bool ixgbe_parse_e610_caps(struct ixgbe_hw *hw, (phys_id & IXGBE_EXT_TOPO_DEV_IMG_PROG_EN) != 0; break; } + case LIBIE_AQC_CAPS_EEE: + caps->eee_support = (u8)number; + break; default: /* Not one of the recognized common capabilities */ return false; @@ -1073,6 +1076,7 @@ void ixgbe_copy_phy_caps_to_cfg(struct ixgbe_aci_cmd_get_phy_caps_data *caps, cfg->link_fec_opt = caps->link_fec_options; cfg->module_compliance_enforcement = caps->module_compliance_enforcement; + cfg->eee_entry_delay = caps->eee_entry_delay; } /** @@ -1093,11 +1097,16 @@ int ixgbe_aci_set_phy_cfg(struct ixgbe_hw *hw, { struct ixgbe_aci_cmd_set_phy_cfg *cmd; struct libie_aq_desc desc; + bool use_buff_eee_field; + u16 buf_size; int err; if (!cfg) return -EINVAL; + /* If FW supports EEE, we have to use buffer with EEE field. */ + use_buff_eee_field = hw->dev_caps.common_cap.eee_support; + cmd = libie_aq_raw(&desc); /* Ensure that only valid bits of cfg->caps can be turned on. */ cfg->caps &= IXGBE_ACI_PHY_ENA_VALID_MASK; @@ -1106,7 +1115,17 @@ int ixgbe_aci_set_phy_cfg(struct ixgbe_hw *hw, cmd->lport_num = hw->bus.func; desc.flags |= cpu_to_le16(LIBIE_AQ_FLAG_RD); - err = ixgbe_aci_send_cmd(hw, &desc, cfg, sizeof(*cfg)); + if (use_buff_eee_field) + buf_size = sizeof(*cfg); + else + /* Buffer w/o eee_entry_delay field is 2B smaller. */ + buf_size = sizeof(*cfg) - sizeof(u16); + + err = ixgbe_aci_send_cmd(hw, &desc, cfg, buf_size); + + /* 1.40 config format is compatible with pre-1.40, just extends + * it at the end. + */ if (!err) hw->phy.curr_user_phy_cfg = *cfg; @@ -1386,6 +1405,7 @@ int ixgbe_aci_get_link_info(struct ixgbe_hw *hw, bool ena_lse, li->topo_media_conflict = link_data.topo_media_conflict; li->pacing = link_data.cfg & (IXGBE_ACI_CFG_PACING_M | IXGBE_ACI_CFG_PACING_TYPE_M); + li->eee_status = link_data.eee_status; /* Update fc info. */ tx_pause = !!(link_data.an_info & IXGBE_ACI_LINK_PAUSE_TX); @@ -1980,15 +2000,59 @@ int ixgbe_identify_phy_e610(struct ixgbe_hw *hw) /* Set PHY ID */ memcpy(&hw->phy.id, pcaps.phy_id_oui, sizeof(u32)); - hw->phy.eee_speeds_supported = IXGBE_LINK_SPEED_10_FULL | - IXGBE_LINK_SPEED_100_FULL | - IXGBE_LINK_SPEED_1GB_FULL; + /* E610 supports EEE only for speeds above 1G */ + if (hw->device_id == IXGBE_DEV_ID_E610_2_5G_T) + hw->phy.eee_speeds_supported = IXGBE_LINK_SPEED_2_5GB_FULL; + else + hw->phy.eee_speeds_supported = IXGBE_LINK_SPEED_2_5GB_FULL | + IXGBE_LINK_SPEED_5GB_FULL | + IXGBE_LINK_SPEED_10GB_FULL; + hw->phy.eee_speeds_advertised = hw->phy.eee_speeds_supported; return 0; } /** + * ixgbe_setup_eee_e610 - Enable/disable EEE support + * @hw: pointer to the HW structure + * @enable_eee: boolean flag to enable EEE + * + * Enable/disable EEE based on @enable_eee. + * + * Return: the exit code of the operation. + */ +int ixgbe_setup_eee_e610(struct ixgbe_hw *hw, bool enable_eee) +{ + struct ixgbe_aci_cmd_get_phy_caps_data phy_caps = {}; + struct ixgbe_aci_cmd_set_phy_cfg_data phy_cfg = {}; + u16 eee_cap = 0; + int err; + + err = ixgbe_aci_get_phy_caps(hw, false, + IXGBE_ACI_REPORT_ACTIVE_CFG, &phy_caps); + if (err) + return err; + + ixgbe_copy_phy_caps_to_cfg(&phy_caps, &phy_cfg); + phy_cfg.caps |= (IXGBE_ACI_PHY_ENA_LINK | + IXGBE_ACI_PHY_ENA_AUTO_LINK_UPDT); + + if (enable_eee) { + if (hw->phy.eee_speeds_advertised & IXGBE_LINK_SPEED_2_5GB_FULL) + eee_cap |= IXGBE_ACI_PHY_EEE_EN_2_5GBASE_T; + if (hw->phy.eee_speeds_advertised & IXGBE_LINK_SPEED_5GB_FULL) + eee_cap |= IXGBE_ACI_PHY_EEE_EN_5GBASE_T; + if (hw->phy.eee_speeds_advertised & IXGBE_LINK_SPEED_10GB_FULL) + eee_cap |= IXGBE_ACI_PHY_EEE_EN_10GBASE_T; + } + + phy_cfg.eee_cap = cpu_to_le16(eee_cap); + + return ixgbe_aci_set_phy_cfg(hw, &phy_cfg); +} + +/** * ixgbe_identify_module_e610 - Identify SFP module type * @hw: pointer to hardware structure * @@ -4001,6 +4065,7 @@ static const struct ixgbe_mac_operations mac_ops_e610 = { .fw_rollback_mode = ixgbe_fw_rollback_mode_e610, .get_nvm_ver = ixgbe_get_active_nvm_ver, .get_link_capabilities = ixgbe_get_link_capabilities_e610, + .setup_eee = ixgbe_setup_eee_e610, .get_bus_info = ixgbe_get_bus_info_generic, .acquire_swfw_sync = ixgbe_acquire_swfw_sync_X540, .release_swfw_sync = ixgbe_release_swfw_sync_X540, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.h index 11916b979d28..2cb76a3d30ae 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_e610.h @@ -55,6 +55,7 @@ int ixgbe_init_phy_ops_e610(struct ixgbe_hw *hw); int ixgbe_identify_phy_e610(struct ixgbe_hw *hw); int ixgbe_identify_module_e610(struct ixgbe_hw *hw); int ixgbe_setup_phy_link_e610(struct ixgbe_hw *hw); +int ixgbe_setup_eee_e610(struct ixgbe_hw *hw, bool enable_eee); int ixgbe_set_phy_power_e610(struct ixgbe_hw *hw, bool on); int ixgbe_enter_lplu_e610(struct ixgbe_hw *hw); int ixgbe_init_eeprom_params_e610(struct ixgbe_hw *hw); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c index ba049b3a9609..6990fe53f049 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c @@ -12,6 +12,7 @@ #include <linux/ethtool.h> #include <linux/vmalloc.h> #include <linux/highmem.h> +#include <linux/string_choices.h> #include <linux/uaccess.h> #include "ixgbe.h" @@ -3540,7 +3541,8 @@ static const struct { { IXGBE_LINK_SPEED_10_FULL, ETHTOOL_LINK_MODE_10baseT_Full_BIT }, { IXGBE_LINK_SPEED_100_FULL, ETHTOOL_LINK_MODE_100baseT_Full_BIT }, { IXGBE_LINK_SPEED_1GB_FULL, ETHTOOL_LINK_MODE_1000baseT_Full_BIT }, - { IXGBE_LINK_SPEED_2_5GB_FULL, ETHTOOL_LINK_MODE_2500baseX_Full_BIT }, + { IXGBE_LINK_SPEED_2_5GB_FULL, ETHTOOL_LINK_MODE_2500baseT_Full_BIT }, + { IXGBE_LINK_SPEED_5GB_FULL, ETHTOOL_LINK_MODE_5000baseT_Full_BIT }, { IXGBE_LINK_SPEED_10GB_FULL, ETHTOOL_LINK_MODE_10000baseT_Full_BIT }, }; @@ -3556,6 +3558,185 @@ static const struct { { FW_PHY_ACT_UD_2_10G_KR_EEE, ETHTOOL_LINK_MODE_10000baseKR_Full_BIT}, }; +static const struct { + u16 eee_cap_bit; + u32 link_mode; +} ixgbe_eee_cap_map[] = { + { IXGBE_ACI_PHY_EEE_EN_100BASE_TX, ETHTOOL_LINK_MODE_100baseT_Full_BIT }, + { IXGBE_ACI_PHY_EEE_EN_1000BASE_T, ETHTOOL_LINK_MODE_1000baseT_Full_BIT }, + { IXGBE_ACI_PHY_EEE_EN_10GBASE_T, ETHTOOL_LINK_MODE_10000baseT_Full_BIT }, + { IXGBE_ACI_PHY_EEE_EN_5GBASE_T, ETHTOOL_LINK_MODE_5000baseT_Full_BIT }, + { IXGBE_ACI_PHY_EEE_EN_2_5GBASE_T, ETHTOOL_LINK_MODE_2500baseT_Full_BIT }, +}; + +static int ixgbe_validate_keee(struct net_device *netdev, + struct ethtool_keee *keee_requested) +{ + struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev); + struct ethtool_keee keee_stored = {}; + int err; + + if (!(adapter->flags2 & IXGBE_FLAG2_EEE_CAPABLE)) + return -EOPNOTSUPP; + + err = netdev->ethtool_ops->get_eee(netdev, &keee_stored); + if (err) + return err; + + if (keee_stored.tx_lpi_enabled != keee_requested->tx_lpi_enabled) { + e_err(drv, "Setting EEE tx-lpi is not supported\n"); + return -EINVAL; + } + + if (keee_stored.tx_lpi_timer != keee_requested->tx_lpi_timer) { + e_err(drv, + "Setting EEE Tx LPI timer is not supported\n"); + return -EINVAL; + } + + if (!linkmode_equal(keee_stored.advertised, + keee_requested->advertised)) { + e_err(drv, + "Setting EEE advertised speeds is not supported\n"); + return -EINVAL; + } + + /* -EALREADY here is for internal use only, must be converted into + * early bail out with 0 by caller + */ + if (keee_stored.eee_enabled == keee_requested->eee_enabled) + return -EALREADY; + + return 0; +} + +/** + * ixgbe_is_eee_link_speed_supported_e610 - Check if EEE can be enabled + * @adapter: pointer to the adapter struct + * + * Check whether current link configuration is capable of enabling EEE feature. + * + * E610 specific function - for other adapters supporting EEE there might be + * no such limitation. + * + * Return: true if EEE can be enabled, false otherwise. + */ +static bool +ixgbe_is_eee_link_speed_supported_e610(struct ixgbe_adapter *adapter) +{ + switch (adapter->link_speed) { + case IXGBE_LINK_SPEED_10GB_FULL: + case IXGBE_LINK_SPEED_2_5GB_FULL: + case IXGBE_LINK_SPEED_5GB_FULL: + return true; + case IXGBE_LINK_SPEED_100_FULL: + case IXGBE_LINK_SPEED_1GB_FULL: + e_dev_info("Energy Efficient Ethernet (EEE) feature is not supported on link speeds equal to or below 1Gbps. EEE is supported on speeds above 1Gbps.\n"); + fallthrough; + default: + return false; + } +} + +static int ixgbe_get_eee_e610(struct net_device *netdev, + struct ethtool_keee *kedata) +{ + struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev); + struct ixgbe_aci_cmd_get_phy_caps_data pcaps; + struct ixgbe_hw *hw = &adapter->hw; + struct ixgbe_link_status link; + u16 eee_cap; + int err; + + linkmode_zero(kedata->lp_advertised); + linkmode_zero(kedata->supported); + linkmode_zero(kedata->advertised); + + err = ixgbe_aci_get_link_info(hw, true, &link); + if (err) + return err; + + err = ixgbe_aci_get_phy_caps(hw, false, IXGBE_ACI_REPORT_ACTIVE_CFG, + &pcaps); + if (err) + return err; + + kedata->eee_active = link.eee_status & IXGBE_ACI_LINK_EEE_ACTIVE; + kedata->eee_enabled = link.eee_status & IXGBE_ACI_LINK_EEE_ENABLED; + + /* for E610 devices EEE enablement implies TX LPI enablement */ + kedata->tx_lpi_enabled = kedata->eee_enabled; + + if (kedata->eee_enabled) + kedata->tx_lpi_timer = le16_to_cpu(pcaps.eee_entry_delay); + + eee_cap = le16_to_cpu(pcaps.eee_cap); + + for (int i = 0; i < ARRAY_SIZE(ixgbe_eee_cap_map); i++) { + if (eee_cap & ixgbe_eee_cap_map[i].eee_cap_bit) + linkmode_set_bit(ixgbe_eee_cap_map[i].link_mode, + kedata->lp_advertised); + } + + for (int i = 0; i < ARRAY_SIZE(ixgbe_ls_map); i++) { + if (hw->phy.eee_speeds_supported & + ixgbe_ls_map[i].mac_speed) + linkmode_set_bit(ixgbe_ls_map[i].link_mode, + kedata->supported); + + if (hw->phy.eee_speeds_advertised & + ixgbe_ls_map[i].mac_speed) + linkmode_set_bit(ixgbe_ls_map[i].link_mode, + kedata->advertised); + } + + return 0; +} + +static int ixgbe_set_eee_e610(struct net_device *netdev, + struct ethtool_keee *kedata) +{ + struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev); + struct ixgbe_hw *hw = &adapter->hw; + int err; + + err = ixgbe_validate_keee(netdev, kedata); + + if (err == -EALREADY) { + return 0; + } else if (err) { + if (err == -EOPNOTSUPP) + e_dev_info("Energy Efficient Ethernet (EEE) feature is currently not supported on this device, please update the device NVM to the latest and try again\n"); + return err; + } + + if (!(ixgbe_is_eee_link_speed_supported_e610(adapter)) && + kedata->eee_enabled) + return -EOPNOTSUPP; + + hw->phy.eee_speeds_advertised = kedata->eee_enabled ? + hw->phy.eee_speeds_supported : 0; + + err = hw->mac.ops.setup_eee(hw, kedata->eee_enabled); + if (err) { + e_dev_err("Setting EEE %s failed.\n", + str_on_off(kedata->eee_enabled)); + return err; + } + + if (kedata->eee_enabled) + adapter->flags2 |= IXGBE_FLAG2_EEE_ENABLED; + else + adapter->flags2 &= ~IXGBE_FLAG2_EEE_ENABLED; + + if (netif_running(netdev)) + ixgbe_reinit_locked(adapter); + else + ixgbe_reset(adapter); + + return 0; +} + static int ixgbe_get_eee_fw(struct ixgbe_adapter *adapter, struct ethtool_keee *edata) { @@ -3614,53 +3795,28 @@ static int ixgbe_set_eee(struct net_device *netdev, struct ethtool_keee *edata) { struct ixgbe_adapter *adapter = ixgbe_from_netdev(netdev); struct ixgbe_hw *hw = &adapter->hw; - struct ethtool_keee eee_data; int ret_val; - if (!(adapter->flags2 & IXGBE_FLAG2_EEE_CAPABLE)) - return -EOPNOTSUPP; - - memset(&eee_data, 0, sizeof(struct ethtool_keee)); - - ret_val = ixgbe_get_eee(netdev, &eee_data); - if (ret_val) + ret_val = ixgbe_validate_keee(netdev, edata); + if (ret_val == -EALREADY) + return 0; + else if (ret_val) return ret_val; - if (eee_data.eee_enabled && !edata->eee_enabled) { - if (eee_data.tx_lpi_enabled != edata->tx_lpi_enabled) { - e_err(drv, "Setting EEE tx-lpi is not supported\n"); - return -EINVAL; - } - - if (eee_data.tx_lpi_timer != edata->tx_lpi_timer) { - e_err(drv, - "Setting EEE Tx LPI timer is not supported\n"); - return -EINVAL; - } - - if (!linkmode_equal(eee_data.advertised, edata->advertised)) { - e_err(drv, - "Setting EEE advertised speeds is not supported\n"); - return -EINVAL; - } + if (edata->eee_enabled) { + adapter->flags2 |= IXGBE_FLAG2_EEE_ENABLED; + hw->phy.eee_speeds_advertised = + hw->phy.eee_speeds_supported; + } else { + adapter->flags2 &= ~IXGBE_FLAG2_EEE_ENABLED; + hw->phy.eee_speeds_advertised = 0; } - if (eee_data.eee_enabled != edata->eee_enabled) { - if (edata->eee_enabled) { - adapter->flags2 |= IXGBE_FLAG2_EEE_ENABLED; - hw->phy.eee_speeds_advertised = - hw->phy.eee_speeds_supported; - } else { - adapter->flags2 &= ~IXGBE_FLAG2_EEE_ENABLED; - hw->phy.eee_speeds_advertised = 0; - } - - /* reset link */ - if (netif_running(netdev)) - ixgbe_reinit_locked(adapter); - else - ixgbe_reset(adapter); - } + /* reset link */ + if (netif_running(netdev)) + ixgbe_reinit_locked(adapter); + else + ixgbe_reset(adapter); return 0; } @@ -3807,8 +3963,8 @@ static const struct ethtool_ops ixgbe_ethtool_ops_e610 = { .set_rxfh = ixgbe_set_rxfh, .get_rxfh_fields = ixgbe_get_rxfh_fields, .set_rxfh_fields = ixgbe_set_rxfh_fields, - .get_eee = ixgbe_get_eee, - .set_eee = ixgbe_set_eee, + .get_eee = ixgbe_get_eee_e610, + .set_eee = ixgbe_set_eee_e610, .get_channels = ixgbe_get_channels, .set_channels = ixgbe_set_channels, .get_priv_flags = ixgbe_get_priv_flags, diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 2646ee6f295f..9e1fb7383975 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -6758,6 +6758,7 @@ void ixgbe_down(struct ixgbe_adapter *adapter) /** * ixgbe_set_eee_capable - helper function to determine EEE support on X550 + * and E610 * @adapter: board private structure */ static void ixgbe_set_eee_capable(struct ixgbe_adapter *adapter) @@ -6774,6 +6775,20 @@ static void ixgbe_set_eee_capable(struct ixgbe_adapter *adapter) break; adapter->flags2 |= IXGBE_FLAG2_EEE_ENABLED; break; + case IXGBE_DEV_ID_E610_BACKPLANE: + case IXGBE_DEV_ID_E610_SFP: + case IXGBE_DEV_ID_E610_10G_T: + case IXGBE_DEV_ID_E610_2_5G_T: + if (hw->dev_caps.common_cap.eee_support && + hw->phy.eee_speeds_supported) { + adapter->flags2 |= IXGBE_FLAG2_EEE_CAPABLE; + /* For E610 adapters EEE should be enabled by default + * if the feature is supported by FW. + */ + adapter->flags2 |= IXGBE_FLAG2_EEE_ENABLED; + break; + } + fallthrough; default: adapter->flags2 &= ~IXGBE_FLAG2_EEE_CAPABLE; adapter->flags2 &= ~IXGBE_FLAG2_EEE_ENABLED; @@ -8082,6 +8097,7 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter) struct net_device *netdev = adapter->netdev; struct ixgbe_hw *hw = &adapter->hw; u32 link_speed = adapter->link_speed; + struct ethtool_keee keee = {}; const char *speed_str; bool flow_rx, flow_tx; @@ -8122,6 +8138,8 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter) if (test_bit(__IXGBE_PTP_RUNNING, &adapter->state)) ixgbe_ptp_start_cyclecounter(adapter); + netdev->ethtool_ops->get_eee(netdev, &keee); + switch (link_speed) { case IXGBE_LINK_SPEED_10GB_FULL: speed_str = "10 Gbps"; @@ -8145,10 +8163,11 @@ static void ixgbe_watchdog_link_is_up(struct ixgbe_adapter *adapter) speed_str = "unknown speed"; break; } - e_info(drv, "NIC Link is Up %s, Flow Control: %s\n", speed_str, + e_info(drv, "NIC Link is Up %s, Flow Control: %s, EEE: %s\n", speed_str, ((flow_rx && flow_tx) ? "RX/TX" : (flow_rx ? "RX" : - (flow_tx ? "TX" : "None")))); + (flow_tx ? "TX" : "None"))), + str_on_off(keee.eee_enabled)); netif_carrier_on(netdev); ixgbe_check_vf_rate_limit(adapter); @@ -12003,6 +12022,13 @@ skip_sriov: if (err) goto err_netdev; + if (hw->mac.type == ixgbe_mac_e610 && + (adapter->flags2 & IXGBE_FLAG2_EEE_CAPABLE)) { + bool eee_enable = adapter->flags2 & IXGBE_FLAG2_EEE_ENABLED; + + hw->mac.ops.setup_eee(hw, eee_enable); + } + ixgbe_devlink_init_regions(adapter); devl_register(adapter->devlink); devl_unlock(adapter->devlink); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h index 61f2ef67defd..a461b6542f96 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type.h @@ -2798,6 +2798,7 @@ struct ixgbe_hic_hdr2_rsp { }; union ixgbe_hic_hdr2 { + u32 buf[1]; struct ixgbe_hic_hdr2_req req; struct ixgbe_hic_hdr2_rsp rsp; }; @@ -3524,6 +3525,7 @@ struct ixgbe_mac_operations { int (*get_link_capabilities)(struct ixgbe_hw *, ixgbe_link_speed *, bool *); void (*set_rate_select_speed)(struct ixgbe_hw *, ixgbe_link_speed); + int (*setup_eee)(struct ixgbe_hw *hw, bool enable_eee); /* Packet Buffer Manipulation */ void (*set_rxpba)(struct ixgbe_hw *, int, u32, int); diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_type_e610.h b/drivers/net/ethernet/intel/ixgbe/ixgbe_type_e610.h index ff8d640a50b1..959cacecae49 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_type_e610.h +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_type_e610.h @@ -323,10 +323,8 @@ struct ixgbe_aci_cmd_get_phy_caps_data { #define IXGBE_ACI_PHY_EEE_EN_100BASE_TX BIT(0) #define IXGBE_ACI_PHY_EEE_EN_1000BASE_T BIT(1) #define IXGBE_ACI_PHY_EEE_EN_10GBASE_T BIT(2) -#define IXGBE_ACI_PHY_EEE_EN_1000BASE_KX BIT(3) -#define IXGBE_ACI_PHY_EEE_EN_10GBASE_KR BIT(4) -#define IXGBE_ACI_PHY_EEE_EN_25GBASE_KR BIT(5) -#define IXGBE_ACI_PHY_EEE_EN_10BASE_T BIT(11) +#define IXGBE_ACI_PHY_EEE_EN_5GBASE_T BIT(11) +#define IXGBE_ACI_PHY_EEE_EN_2_5GBASE_T BIT(12) __le16 eeer_value; u8 phy_id_oui[4]; /* PHY/Module ID connected on the port */ u8 phy_fw_ver[8]; @@ -356,7 +354,9 @@ struct ixgbe_aci_cmd_get_phy_caps_data { #define IXGBE_ACI_MOD_TYPE_BYTE2_SFP_PLUS 0xA0 #define IXGBE_ACI_MOD_TYPE_BYTE2_QSFP_PLUS 0x86 u8 qualified_module_count; - u8 rsvd2[7]; /* Bytes 47:41 reserved */ + u8 rsvd2; + __le16 eee_entry_delay; + u8 rsvd3[4]; #define IXGBE_ACI_QUAL_MOD_COUNT_MAX 16 struct { u8 v_oui[3]; @@ -382,6 +382,15 @@ struct ixgbe_aci_cmd_set_phy_cfg_data { __le64 phy_type_low; /* Use values from IXGBE_PHY_TYPE_LOW_* */ __le64 phy_type_high; /* Use values from IXGBE_PHY_TYPE_HIGH_* */ u8 caps; + u8 low_power_ctrl_an; + __le16 eee_cap; /* Value from ixgbe_aci_get_phy_caps */ + __le16 eeer_value; /* Use defines from ixgbe_aci_get_phy_caps */ + u8 link_fec_opt; /* Use defines from ixgbe_aci_get_phy_caps */ + u8 module_compliance_enforcement; + __le16 eee_entry_delay; +} __packed; + +/* Set PHY config capabilities (@caps) defines */ #define IXGBE_ACI_PHY_ENA_VALID_MASK 0xef #define IXGBE_ACI_PHY_ENA_TX_PAUSE_ABILITY BIT(0) #define IXGBE_ACI_PHY_ENA_RX_PAUSE_ABILITY BIT(1) @@ -390,12 +399,6 @@ struct ixgbe_aci_cmd_set_phy_cfg_data { #define IXGBE_ACI_PHY_ENA_AUTO_LINK_UPDT BIT(5) #define IXGBE_ACI_PHY_ENA_LESM BIT(6) #define IXGBE_ACI_PHY_ENA_AUTO_FEC BIT(7) - u8 low_power_ctrl_an; - __le16 eee_cap; /* Value from ixgbe_aci_get_phy_caps */ - __le16 eeer_value; /* Use defines from ixgbe_aci_get_phy_caps */ - u8 link_fec_opt; /* Use defines from ixgbe_aci_get_phy_caps */ - u8 module_compliance_enforcement; -}; /* Restart AN command data structure (direct 0x0605) * Also used for response, with only the lport_num field present. @@ -509,8 +512,9 @@ struct ixgbe_aci_cmd_get_link_status_data { #define IXGBE_ACI_LINK_SPEED_200GB BIT(11) #define IXGBE_ACI_LINK_SPEED_UNKNOWN BIT(15) __le16 reserved3; - u8 ext_fec_status; -#define IXGBE_ACI_LINK_RS_272_FEC_EN BIT(0) /* RS 272 FEC enabled */ + u8 eee_status; +#define IXGBE_ACI_LINK_EEE_ENABLED BIT(2) +#define IXGBE_ACI_LINK_EEE_ACTIVE BIT(3) u8 reserved4; __le64 phy_type_low; /* Use values from ICE_PHY_TYPE_LOW_* */ __le64 phy_type_high; /* Use values from ICE_PHY_TYPE_HIGH_* */ @@ -812,6 +816,7 @@ struct ixgbe_link_status { * of ixgbe_aci_get_phy_caps structure */ u8 module_type[IXGBE_ACI_MODULE_TYPE_TOTAL_BYTE]; + u8 eee_status; }; /* Common HW capabilities for SW use */ @@ -891,6 +896,7 @@ struct ixgbe_hw_caps { u8 apm_wol_support; u8 acpi_prog_mthd; u8 proxy_support; + u8 eee_support; bool nvm_update_pending_nvm; bool nvm_update_pending_orom; bool nvm_update_pending_netlist; diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c index 76d2fa3ef518..4a0ccbf448a2 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c @@ -1228,7 +1228,7 @@ static int ixgbe_update_flash_X550(struct ixgbe_hw *hw) buffer.req.buf_lenl = FW_SHADOW_RAM_DUMP_LEN; buffer.req.checksum = FW_DEFAULT_CHECKSUM; - status = ixgbe_host_interface_command(hw, &buffer, sizeof(buffer), + status = ixgbe_host_interface_command(hw, buffer.buf, sizeof(buffer), IXGBE_HI_COMMAND_TIMEOUT, false); return status; } diff --git a/include/linux/net/intel/libie/adminq.h b/include/linux/net/intel/libie/adminq.h index ab13bd777a28..839114d8975a 100644 --- a/include/linux/net/intel/libie/adminq.h +++ b/include/linux/net/intel/libie/adminq.h @@ -196,6 +196,7 @@ LIBIE_CHECK_STRUCT_LEN(16, libie_aqc_list_caps); #define LIBIE_AQC_BIT_ROCEV2_LAG BIT(0) #define LIBIE_AQC_BIT_SRIOV_LAG BIT(1) #define LIBIE_AQC_BIT_SRIOV_AA_LAG BIT(2) +#define LIBIE_AQC_CAPS_EEE 0x009B #define LIBIE_AQC_CAPS_FLEX10 0x00F1 #define LIBIE_AQC_CAPS_CEM 0x00F2 |
