aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-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