Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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_set_eee_i350(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_EMC_INTERNAL_DATA		0x00
+3 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@
#include <linux/i2c.h>
#include <linux/i2c-algo-bit.h>
#include <linux/pci.h>
#include <linux/mdio.h>

struct igb_adapter;

@@ -455,6 +456,7 @@ struct igb_adapter {
	unsigned long link_check_timeout;
	int copper_tries;
	struct e1000_info ei;
	u16 eee_advert;
};

#define IGB_FLAG_HAS_MSI		(1 << 0)
@@ -471,6 +473,7 @@ struct igb_adapter {
#define IGB_FLAG_MAS_CAPABLE		(1 << 11)
#define IGB_FLAG_MAS_ENABLE		(1 << 12)
#define IGB_FLAG_HAS_MSIX		(1 << 13)
#define IGB_FLAG_EEE			(1 << 14)

/* Media Auto Sense */
#define IGB_MAS_ENABLE_0		0X0001
+29 −16
Original line number Diff line number Diff line
@@ -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 e1000_hw *hw = &adapter->hw;
	u32 ipcnfg, eeer, ret_val;
	u32 ret_val;
	u16 phy_data;

	if ((hw->mac.type < e1000_i350) ||
@@ -2596,16 +2596,25 @@ static int igb_get_eee(struct net_device *netdev, struct ethtool_eee *edata)

	edata->supported = (SUPPORTED_1000baseT_Full |
			    SUPPORTED_100baseT_Full);
	if (!hw->dev_spec._82575.eee_disable)
		edata->advertised =
			mmd_eee_adv_to_ethtool_adv_t(adapter->eee_advert);

	/* The IPCNFG and EEER registers are not supported on I354. */
	if (hw->mac.type == e1000_i354) {
		igb_get_eee_status_i354(hw, (bool *)&edata->eee_active);
	} else {
		u32 eeer;

	ipcnfg = rd32(E1000_IPCNFG);
		eeer = rd32(E1000_EEER);

		/* EEE status on negotiated link */
	if (ipcnfg & E1000_IPCNFG_EEE_1G_AN)
		edata->advertised = ADVERTISED_1000baseT_Full;
		if (eeer & E1000_EEER_EEE_NEG)
			edata->eee_active = true;

	if (ipcnfg & E1000_IPCNFG_EEE_100M_AN)
		edata->advertised |= ADVERTISED_100baseT_Full;
		if (eeer & E1000_EEER_TX_LPI_EN)
			edata->tx_lpi_enabled = true;
	}

	/* EEE Link Partner Advertised */
	switch (hw->mac.type) {
@@ -2616,8 +2625,8 @@ static int igb_get_eee(struct net_device *netdev, struct ethtool_eee *edata)
			return -ENODATA;

		edata->lp_advertised = mmd_eee_adv_to_ethtool_adv_t(phy_data);

		break;
	case e1000_i354:
	case e1000_i210:
	case e1000_i211:
		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)
		break;
	}

	if (eeer & E1000_EEER_EEE_NEG)
		edata->eee_active = true;

	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;

	/* Report correct negotiated EEE status for devices that
@@ -2686,9 +2693,10 @@ static int igb_set_eee(struct net_device *netdev,
			return -EINVAL;
		}

		if (eee_curr.advertised != edata->advertised) {
		if (edata->advertised &
		    ~(ADVERTISE_100_FULL | ADVERTISE_1000_FULL)) {
			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;
		}

@@ -2698,9 +2706,14 @@ static int igb_set_eee(struct net_device *netdev,
			return -EINVAL;
		}

	adapter->eee_advert = ethtool_adv_to_mmd_eee_adv_t(edata->advertised);
	if (hw->dev_spec._82575.eee_disable != !edata->eee_enabled) {
		hw->dev_spec._82575.eee_disable = !edata->eee_enabled;
		adapter->flags |= IGB_FLAG_EEE;
		if (hw->mac.type == e1000_i350)
			igb_set_eee_i350(hw);
		else
			igb_set_eee_i354(hw);

		/* reset link */
		if (netif_running(netdev))
+55 −14
Original line number Diff line number Diff line
@@ -1726,6 +1726,10 @@ int igb_up(struct igb_adapter *adapter)
	hw->mac.get_link_status = 1;
	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;
}

@@ -1974,6 +1978,21 @@ void igb_reset(struct igb_adapter *adapter)
		}
	}
#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))
		igb_power_down_link(adapter);

@@ -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_MSI) ? "MSI" : "legacy",
		adapter->num_rx_queues, adapter->num_tx_queues);
	if (hw->phy.media_type == e1000_media_type_copper) {
		switch (hw->mac.type) {
		case e1000_i350:
		case e1000_i210:
		case e1000_i211:
		igb_set_eee_i350(hw);
			/* Enable EEE for internal copper PHY devices */
			err = igb_set_eee_i350(hw);
			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 (hw->phy.media_type == e1000_media_type_copper) {
			if ((rd32(E1000_CTRL_EXT) &
			    E1000_CTRL_EXT_LINK_MODE_SGMII))
				igb_set_eee_i354(hw);
			    E1000_CTRL_EXT_LINK_MODE_SGMII)) {
				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;
		}

	}
	pm_runtime_put_noidle(&pdev->dev);
	return 0;

@@ -4158,6 +4190,15 @@ static void igb_watchdog_task(struct work_struct *work)
			       (ctrl & E1000_CTRL_RFCE) ?  "RX" :
			       (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 */
			igb_check_downshift(hw);
			if (phy->speed_downgraded)