aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2026-05-02 19:12:47 -0700
committerJakub Kicinski <kuba@kernel.org>2026-05-02 19:12:47 -0700
commit98878ed91b68a3150126fccef125ee7b1bb86ab2 (patch)
tree06a93bd49440b56af46a3a50e1189e36ec00383c
parentMerge branch 'net-dsa-yt921x-add-port-police-support' (diff)
parentice: dpll: Fix compilation warning (diff)
Merge branch 'intel-wired-lan-updates-2024-04-30-ixgbe-i40e-ice'davem/net-next
Jacob Keller says: ==================== Intel Wired LAN Updates 2024-04-30 (ixgbe, i40e, ice) This series includes updates to support Energy-Efficient Ethernet (EEE) on E610 devices in the ixgbe driver, support for an unmanaged DPLL output on E830, as well as some other minor cleanups and improvements across ixgbe, i40e, and ice. Jedrzej begins with the first six patches preparing the ixgbe driver to support EEE, adding a EEE capability flag, updating the supported EEE speeds, updating the ACI command structures with the fields related to EEE, moving the EEE config validation out for re-use, and finally implementing the EEE support for E610 hardware. Aleksandr fixes the ixgbe_update_flash_X550() logic to prevent unaligned access in ixgbe_host_interface_command(). Note: this has no functional change on x86, and is being sent through net-next as it is considered a minor cleanup. Jacob (hi!) modifies the i40e driver to only timestamp PTP event packets, instead of timestamping every V2 event frame. This avoids wasting the limited number of timestamp slots for frames which the PTP protocol does not care about. Jacob also extends the devlink flash notification message reporting that users can activate the new firmware via devlink reload to explicitly indicate the required "fw_activate" action. Byungchul Park fixes the ice_lbtest_receive_frames() function to use netmem_desc instead of the page structure. Przemyslaw Korba fixes a truncation warning in ice_dpll_init_fwnode_pins() by increasing the allowed length of the pin_name string on the stack to 16. Ivan Vecera adds some bounds checking to ice_dpll_rclk_state_on_pin_get/set() and moves the CGU register macros to be under the header guard ifdef in ice_dpll.h ==================== Link: https://patch.msgid.link/20260430-jk-iwl-net-next-2026-04-30-v1-0-6f27ae1cd073@intel.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_ptp.c9
-rw-r--r--drivers/net/ethernet/intel/i40e/i40e_register.h10
-rw-r--r--drivers/net/ethernet/intel/ice/ice_dpll.c2
-rw-r--r--drivers/net/ethernet/intel/ice/ice_ethtool.c2
-rw-r--r--drivers/net/ethernet/intel/ice/ice_fw_update.c2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_e610.c73
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_e610.h1
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_ethtool.c244
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c30
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_type.h2
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_type_e610.h32
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_x550.c2
-rw-r--r--include/linux/net/intel/libie/adminq.h1
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