Commit f4c01e96 authored by Carolyn Wyborny's avatar Carolyn Wyborny Committed by Jeff Kirsher

igb: Fix for devices using ethtool for EEE settings

This patch fixes a problem where using ethtool for EEE setting was not
working correctly.  This patch also fixes a problem where
the function that checks for EEE status on i354 devices was not being
called and was causing warnings with static analysis tools.
Reported-by: default avatarRashika Kheria <rashika.kheria@gmail.com>
Reported-by: default avatarJosh Triplett <josh@joshtriplett.org>
Reported-by: default avatarStephen Hemminger <stephen@networkplumber.org>
Signed-off-by: default avatarCarolyn Wyborny <carolyn.wyborny@intel.com>
Tested-by: default avatarJeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 42bdf083
...@@ -265,6 +265,7 @@ u16 igb_rxpbs_adjust_82580(u32 data); ...@@ -265,6 +265,7 @@ u16 igb_rxpbs_adjust_82580(u32 data);
s32 igb_read_emi_reg(struct e1000_hw *, u16 addr, u16 *data); s32 igb_read_emi_reg(struct e1000_hw *, u16 addr, u16 *data);
s32 igb_set_eee_i350(struct e1000_hw *); s32 igb_set_eee_i350(struct e1000_hw *);
s32 igb_set_eee_i354(struct e1000_hw *); s32 igb_set_eee_i354(struct e1000_hw *);
s32 igb_get_eee_status_i354(struct e1000_hw *hw, bool *status);
#define E1000_I2C_THERMAL_SENSOR_ADDR 0xF8 #define E1000_I2C_THERMAL_SENSOR_ADDR 0xF8
#define E1000_EMC_INTERNAL_DATA 0x00 #define E1000_EMC_INTERNAL_DATA 0x00
......
...@@ -41,6 +41,7 @@ ...@@ -41,6 +41,7 @@
#include <linux/i2c.h> #include <linux/i2c.h>
#include <linux/i2c-algo-bit.h> #include <linux/i2c-algo-bit.h>
#include <linux/pci.h> #include <linux/pci.h>
#include <linux/mdio.h>
struct igb_adapter; struct igb_adapter;
...@@ -455,6 +456,7 @@ struct igb_adapter { ...@@ -455,6 +456,7 @@ struct igb_adapter {
unsigned long link_check_timeout; unsigned long link_check_timeout;
int copper_tries; int copper_tries;
struct e1000_info ei; struct e1000_info ei;
u16 eee_advert;
}; };
#define IGB_FLAG_HAS_MSI (1 << 0) #define IGB_FLAG_HAS_MSI (1 << 0)
...@@ -471,6 +473,7 @@ struct igb_adapter { ...@@ -471,6 +473,7 @@ struct igb_adapter {
#define IGB_FLAG_MAS_CAPABLE (1 << 11) #define IGB_FLAG_MAS_CAPABLE (1 << 11)
#define IGB_FLAG_MAS_ENABLE (1 << 12) #define IGB_FLAG_MAS_ENABLE (1 << 12)
#define IGB_FLAG_HAS_MSIX (1 << 13) #define IGB_FLAG_HAS_MSIX (1 << 13)
#define IGB_FLAG_EEE (1 << 14)
/* Media Auto Sense */ /* Media Auto Sense */
#define IGB_MAS_ENABLE_0 0X0001 #define IGB_MAS_ENABLE_0 0X0001
......
...@@ -2587,7 +2587,7 @@ static int igb_get_eee(struct net_device *netdev, struct ethtool_eee *edata) ...@@ -2587,7 +2587,7 @@ static int igb_get_eee(struct net_device *netdev, struct ethtool_eee *edata)
{ {
struct igb_adapter *adapter = netdev_priv(netdev); struct igb_adapter *adapter = netdev_priv(netdev);
struct e1000_hw *hw = &adapter->hw; struct e1000_hw *hw = &adapter->hw;
u32 ipcnfg, eeer, ret_val; u32 ret_val;
u16 phy_data; u16 phy_data;
if ((hw->mac.type < e1000_i350) || if ((hw->mac.type < e1000_i350) ||
...@@ -2596,16 +2596,25 @@ static int igb_get_eee(struct net_device *netdev, struct ethtool_eee *edata) ...@@ -2596,16 +2596,25 @@ static int igb_get_eee(struct net_device *netdev, struct ethtool_eee *edata)
edata->supported = (SUPPORTED_1000baseT_Full | edata->supported = (SUPPORTED_1000baseT_Full |
SUPPORTED_100baseT_Full); SUPPORTED_100baseT_Full);
if (!hw->dev_spec._82575.eee_disable)
edata->advertised =
mmd_eee_adv_to_ethtool_adv_t(adapter->eee_advert);
ipcnfg = rd32(E1000_IPCNFG); /* The IPCNFG and EEER registers are not supported on I354. */
eeer = rd32(E1000_EEER); if (hw->mac.type == e1000_i354) {
igb_get_eee_status_i354(hw, (bool *)&edata->eee_active);
} else {
u32 eeer;
eeer = rd32(E1000_EEER);
/* EEE status on negotiated link */ /* EEE status on negotiated link */
if (ipcnfg & E1000_IPCNFG_EEE_1G_AN) if (eeer & E1000_EEER_EEE_NEG)
edata->advertised = ADVERTISED_1000baseT_Full; edata->eee_active = true;
if (ipcnfg & E1000_IPCNFG_EEE_100M_AN) if (eeer & E1000_EEER_TX_LPI_EN)
edata->advertised |= ADVERTISED_100baseT_Full; edata->tx_lpi_enabled = true;
}
/* EEE Link Partner Advertised */ /* EEE Link Partner Advertised */
switch (hw->mac.type) { switch (hw->mac.type) {
...@@ -2616,8 +2625,8 @@ static int igb_get_eee(struct net_device *netdev, struct ethtool_eee *edata) ...@@ -2616,8 +2625,8 @@ static int igb_get_eee(struct net_device *netdev, struct ethtool_eee *edata)
return -ENODATA; return -ENODATA;
edata->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(phy_data); edata->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(phy_data);
break; break;
case e1000_i354:
case e1000_i210: case e1000_i210:
case e1000_i211: case e1000_i211:
ret_val = igb_read_xmdio_reg(hw, E1000_EEE_LP_ADV_ADDR_I210, ret_val = igb_read_xmdio_reg(hw, E1000_EEE_LP_ADV_ADDR_I210,
...@@ -2633,12 +2642,10 @@ static int igb_get_eee(struct net_device *netdev, struct ethtool_eee *edata) ...@@ -2633,12 +2642,10 @@ static int igb_get_eee(struct net_device *netdev, struct ethtool_eee *edata)
break; break;
} }
if (eeer & E1000_EEER_EEE_NEG)
edata->eee_active = true;
edata->eee_enabled = !hw->dev_spec._82575.eee_disable; edata->eee_enabled = !hw->dev_spec._82575.eee_disable;
if (eeer & E1000_EEER_TX_LPI_EN) if ((hw->mac.type == e1000_i354) &&
(edata->eee_enabled))
edata->tx_lpi_enabled = true; edata->tx_lpi_enabled = true;
/* Report correct negotiated EEE status for devices that /* Report correct negotiated EEE status for devices that
...@@ -2686,9 +2693,10 @@ static int igb_set_eee(struct net_device *netdev, ...@@ -2686,9 +2693,10 @@ static int igb_set_eee(struct net_device *netdev,
return -EINVAL; return -EINVAL;
} }
if (eee_curr.advertised != edata->advertised) { if (edata->advertised &
~(ADVERTISE_100_FULL | ADVERTISE_1000_FULL)) {
dev_err(&adapter->pdev->dev, dev_err(&adapter->pdev->dev,
"Setting EEE Advertisement is not supported\n"); "EEE Advertisement supports only 100Tx and or 100T full duplex\n");
return -EINVAL; return -EINVAL;
} }
...@@ -2698,9 +2706,14 @@ static int igb_set_eee(struct net_device *netdev, ...@@ -2698,9 +2706,14 @@ static int igb_set_eee(struct net_device *netdev,
return -EINVAL; return -EINVAL;
} }
adapter->eee_advert = ethtool_adv_to_mmd_eee_adv_t(edata->advertised);
if (hw->dev_spec._82575.eee_disable != !edata->eee_enabled) { if (hw->dev_spec._82575.eee_disable != !edata->eee_enabled) {
hw->dev_spec._82575.eee_disable = !edata->eee_enabled; hw->dev_spec._82575.eee_disable = !edata->eee_enabled;
igb_set_eee_i350(hw); adapter->flags |= IGB_FLAG_EEE;
if (hw->mac.type == e1000_i350)
igb_set_eee_i350(hw);
else
igb_set_eee_i354(hw);
/* reset link */ /* reset link */
if (netif_running(netdev)) if (netif_running(netdev))
......
...@@ -1726,6 +1726,10 @@ int igb_up(struct igb_adapter *adapter) ...@@ -1726,6 +1726,10 @@ int igb_up(struct igb_adapter *adapter)
hw->mac.get_link_status = 1; hw->mac.get_link_status = 1;
schedule_work(&adapter->watchdog_task); schedule_work(&adapter->watchdog_task);
if ((adapter->flags & IGB_FLAG_EEE) &&
(!hw->dev_spec._82575.eee_disable))
adapter->eee_advert = MDIO_EEE_100TX | MDIO_EEE_1000T;
return 0; return 0;
} }
...@@ -1974,6 +1978,21 @@ void igb_reset(struct igb_adapter *adapter) ...@@ -1974,6 +1978,21 @@ void igb_reset(struct igb_adapter *adapter)
} }
} }
#endif #endif
/*Re-establish EEE setting */
if (hw->phy.media_type == e1000_media_type_copper) {
switch (mac->type) {
case e1000_i350:
case e1000_i210:
case e1000_i211:
igb_set_eee_i350(hw);
break;
case e1000_i354:
igb_set_eee_i354(hw);
break;
default:
break;
}
}
if (!netif_running(adapter->netdev)) if (!netif_running(adapter->netdev))
igb_power_down_link(adapter); igb_power_down_link(adapter);
...@@ -2560,23 +2579,36 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent) ...@@ -2560,23 +2579,36 @@ static int igb_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
(adapter->flags & IGB_FLAG_HAS_MSIX) ? "MSI-X" : (adapter->flags & IGB_FLAG_HAS_MSIX) ? "MSI-X" :
(adapter->flags & IGB_FLAG_HAS_MSI) ? "MSI" : "legacy", (adapter->flags & IGB_FLAG_HAS_MSI) ? "MSI" : "legacy",
adapter->num_rx_queues, adapter->num_tx_queues); adapter->num_rx_queues, adapter->num_tx_queues);
switch (hw->mac.type) { if (hw->phy.media_type == e1000_media_type_copper) {
case e1000_i350: switch (hw->mac.type) {
case e1000_i210: case e1000_i350:
case e1000_i211: case e1000_i210:
igb_set_eee_i350(hw); case e1000_i211:
break; /* Enable EEE for internal copper PHY devices */
case e1000_i354: err = igb_set_eee_i350(hw);
if (hw->phy.media_type == e1000_media_type_copper) { if ((!err) &&
(!hw->dev_spec._82575.eee_disable)) {
adapter->eee_advert =
MDIO_EEE_100TX | MDIO_EEE_1000T;
adapter->flags |= IGB_FLAG_EEE;
}
break;
case e1000_i354:
if ((rd32(E1000_CTRL_EXT) & if ((rd32(E1000_CTRL_EXT) &
E1000_CTRL_EXT_LINK_MODE_SGMII)) E1000_CTRL_EXT_LINK_MODE_SGMII)) {
igb_set_eee_i354(hw); err = igb_set_eee_i354(hw);
if ((!err) &&
(!hw->dev_spec._82575.eee_disable)) {
adapter->eee_advert =
MDIO_EEE_100TX | MDIO_EEE_1000T;
adapter->flags |= IGB_FLAG_EEE;
}
}
break;
default:
break;
} }
break;
default:
break;
} }
pm_runtime_put_noidle(&pdev->dev); pm_runtime_put_noidle(&pdev->dev);
return 0; return 0;
...@@ -4158,6 +4190,15 @@ static void igb_watchdog_task(struct work_struct *work) ...@@ -4158,6 +4190,15 @@ static void igb_watchdog_task(struct work_struct *work)
(ctrl & E1000_CTRL_RFCE) ? "RX" : (ctrl & E1000_CTRL_RFCE) ? "RX" :
(ctrl & E1000_CTRL_TFCE) ? "TX" : "None"); (ctrl & E1000_CTRL_TFCE) ? "TX" : "None");
/* disable EEE if enabled */
if ((adapter->flags & IGB_FLAG_EEE) &&
(adapter->link_duplex == HALF_DUPLEX)) {
dev_info(&adapter->pdev->dev,
"EEE Disabled: unsupported at half duplex. Re-enable using ethtool when at full duplex.\n");
adapter->hw.dev_spec._82575.eee_disable = true;
adapter->flags &= ~IGB_FLAG_EEE;
}
/* check if SmartSpeed worked */ /* check if SmartSpeed worked */
igb_check_downshift(hw); igb_check_downshift(hw);
if (phy->speed_downgraded) if (phy->speed_downgraded)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment