diff mbox series

[v3,10/11] igc: Add setup link functionality

Message ID 20180624084525.10374-1-sasha.neftin@intel.com
State RFC
Headers show
Series None | expand

Commit Message

Sasha Neftin June 24, 2018, 8:45 a.m. UTC
Add link establishment methods
Add auto negotiation methods
Add read MAC address method

Sasha Neftin (v2):
minor cosmetic changes

Sasha Neftin (v3):
removed not addressed methods

Signed-off-by: Sasha Neftin <sasha.neftin@intel.com>
---
 drivers/net/ethernet/intel/igc/e1000_base.c    |  41 +++
 drivers/net/ethernet/intel/igc/e1000_defines.h |  45 ++++
 drivers/net/ethernet/intel/igc/e1000_mac.c     | 272 +++++++++++++++++++-
 drivers/net/ethernet/intel/igc/e1000_mac.h     |   2 +
 drivers/net/ethernet/intel/igc/e1000_phy.c     | 332 ++++++++++++++++++++++++-
 drivers/net/ethernet/intel/igc/e1000_phy.h     |   1 +
 drivers/net/ethernet/intel/igc/igc.h           |   1 +
 drivers/net/ethernet/intel/igc/igc_main.c      |  35 ++-
 8 files changed, 725 insertions(+), 4 deletions(-)

Comments

Shannon Nelson June 29, 2018, 3:03 p.m. UTC | #1
On 6/24/2018 1:45 AM, Sasha Neftin wrote:
> Add link establishment methods
> Add auto negotiation methods
> Add read MAC address method
> 
> Sasha Neftin (v2):
> minor cosmetic changes
> 
> Sasha Neftin (v3):
> removed not addressed methods
> 
> Signed-off-by: Sasha Neftin <sasha.neftin@intel.com>
> ---
>   drivers/net/ethernet/intel/igc/e1000_base.c    |  41 +++
>   drivers/net/ethernet/intel/igc/e1000_defines.h |  45 ++++
>   drivers/net/ethernet/intel/igc/e1000_mac.c     | 272 +++++++++++++++++++-
>   drivers/net/ethernet/intel/igc/e1000_mac.h     |   2 +
>   drivers/net/ethernet/intel/igc/e1000_phy.c     | 332 ++++++++++++++++++++++++-
>   drivers/net/ethernet/intel/igc/e1000_phy.h     |   1 +
>   drivers/net/ethernet/intel/igc/igc.h           |   1 +
>   drivers/net/ethernet/intel/igc/igc_main.c      |  35 ++-
>   8 files changed, 725 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/net/ethernet/intel/igc/e1000_base.c b/drivers/net/ethernet/intel/igc/e1000_base.c
> index 8b35e1d6c32e..6405506ff7b8 100644
> --- a/drivers/net/ethernet/intel/igc/e1000_base.c
> +++ b/drivers/net/ethernet/intel/igc/e1000_base.c
> @@ -17,6 +17,7 @@ static void igc_release_phy_base(struct e1000_hw *);
>   static s32 igc_get_phy_id_base(struct e1000_hw *);
>   static s32 igc_init_hw_base(struct e1000_hw *);
>   static s32 igc_reset_hw_base(struct e1000_hw *);
> +static s32 igc_setup_copper_link_base(struct e1000_hw *);
>   static s32 igc_set_pcie_completion_timeout(struct e1000_hw *hw);
>   static s32 igc_read_mac_addr_base(struct e1000_hw *hw);
>   
> @@ -97,6 +98,9 @@ static s32 igc_init_mac_params_base(struct e1000_hw *hw)
>   	if (mac->type == e1000_i225)
>   		dev_spec->clear_semaphore_once = true;
>   
> +	/* physical interface link setup */
> +	mac->ops.setup_physical_interface = igc_setup_copper_link_base;
> +
>   	return 0;
>   }
>   
> @@ -139,6 +143,8 @@ static s32 igc_init_phy_params_base(struct e1000_hw *hw)
>   	if (ret_val)
>   		return ret_val;
>   
> +	igc_check_for_link_base(hw);
> +
>   	/* Verify phy id and set remaining function pointers */
>   	switch (phy->id) {
>   	case I225_I_PHY_ID:
> @@ -155,10 +161,22 @@ static s32 igc_init_phy_params_base(struct e1000_hw *hw)
>   
>   static s32 igc_get_invariants_base(struct e1000_hw *hw)
>   {
> +	struct e1000_mac_info *mac = &hw->mac;
>   	s32 ret_val = 0;
>   	u32 ctrl_ext = 0;
>   	u32 link_mode = 0;
>   
> +	switch (hw->device_id) {
> +	case E1000_DEV_ID_I225_LM:
> +	case E1000_DEV_ID_I225_V:
> +		mac->type = e1000_i225;
> +		break;
> +	default:
> +		return -E1000_ERR_MAC_INIT;
> +	}
> +
> +	hw->phy.media_type = e1000_media_type_copper;
> +
>   	ctrl_ext = rd32(E1000_CTRL_EXT);
>   	link_mode = ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK;
>   
> @@ -289,6 +307,29 @@ static s32 igc_init_hw_base(struct e1000_hw *hw)
>   }
>   
>   /**
> + *  igc_setup_copper_link_base - Configure copper link settings
> + *  @hw: pointer to the HW structure
> + *
> + *  Configures the link for auto-neg or forced speed and duplex.  Then we check
> + *  for link, once link is established calls to configure collision distance
> + *  and flow control are called.
> + **/
> +static s32 igc_setup_copper_link_base(struct e1000_hw *hw)
> +{
> +	s32  ret_val = 0;
> +	u32 ctrl;
> +
> +	ctrl = rd32(E1000_CTRL);
> +	ctrl |= E1000_CTRL_SLU;
> +	ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
> +	wr32(E1000_CTRL, ctrl);
> +
> +	ret_val = igc_setup_copper_link(hw);
> +
> +	return ret_val;
> +}
> +
> +/**
>    *  igc_read_mac_addr_base - Read device MAC address
>    *  @hw: pointer to the HW structure
>    **/
> diff --git a/drivers/net/ethernet/intel/igc/e1000_defines.h b/drivers/net/ethernet/intel/igc/e1000_defines.h
> index 40276ae76c9f..24c24c197d6b 100644
> --- a/drivers/net/ethernet/intel/igc/e1000_defines.h
> +++ b/drivers/net/ethernet/intel/igc/e1000_defines.h
> @@ -33,6 +33,11 @@
>   /* Physical Func Reset Done Indication */
>   #define E1000_CTRL_EXT_LINK_MODE_MASK	0x00C00000
>   
> +/* Loop limit on how long we wait for auto-negotiation to complete */
> +#define COPPER_LINK_UP_LIMIT		10
> +#define PHY_AUTO_NEG_LIMIT		45
> +#define PHY_FORCE_LIMIT			20
> +
>   /* Number of 100 microseconds we wait for PCI Express master disable */
>   #define MASTER_DISABLE_TIMEOUT		800
>   /*Blocks new Master requests */
> @@ -74,6 +79,12 @@
>   #define E1000_CTRL_RST		0x04000000  /* Global reset */
>   
>   #define E1000_CTRL_PHY_RST	0x80000000  /* PHY Reset */
> +#define E1000_CTRL_SLU		0x00000040  /* Set link up (Force Link) */
> +#define E1000_CTRL_FRCSPD	0x00000800  /* Force Speed */
> +#define E1000_CTRL_FRCDPX	0x00001000  /* Force Duplex */
> +
> +#define E1000_CTRL_RFCE		0x08000000  /* Receive Flow Control enable */
> +#define E1000_CTRL_TFCE		0x10000000  /* Transmit flow control enable */
>   
>   /* PBA constants */
>   #define E1000_PBA_34K			0x0022
> @@ -89,6 +100,40 @@
>   #define E1000_SWFW_PHY2_SM	0x20
>   #define E1000_SWFW_PHY3_SM	0x40
>   
> +/* PHY 1000 MII Register/Bit Definitions */
> +/* PHY Registers defined by IEEE */
> +#define PHY_CONTROL		0x00 /* Control Register */
> +#define PHY_STATUS		0x01 /* Status Register */
> +#define PHY_ID1			0x02 /* Phy Id Reg (word 1) */
> +#define PHY_ID2			0x03 /* Phy Id Reg (word 2) */
> +#define PHY_AUTONEG_ADV		0x04 /* Autoneg Advertisement */
> +#define PHY_LP_ABILITY		0x05 /* Link Partner Ability (Base Page) */
> +#define PHY_1000T_CTRL		0x09 /* 1000Base-T Control Reg */
> +#define PHY_1000T_STATUS	0x0A /* 1000Base-T Status Reg */
> +
> +/* Autoneg Advertisement Register */
> +#define NWAY_AR_10T_HD_CAPS	0x0020   /* 10T   Half Duplex Capable */
> +#define NWAY_AR_10T_FD_CAPS	0x0040   /* 10T   Full Duplex Capable */
> +#define NWAY_AR_100TX_HD_CAPS	0x0080   /* 100TX Half Duplex Capable */
> +#define NWAY_AR_100TX_FD_CAPS	0x0100   /* 100TX Full Duplex Capable */
> +#define NWAY_AR_PAUSE		0x0400   /* Pause operation desired */
> +#define NWAY_AR_ASM_DIR		0x0800   /* Asymmetric Pause Direction bit */
> +
> +/* Link Partner Ability Register (Base Page) */
> +#define NWAY_LPAR_PAUSE		0x0400 /* LP Pause operation desired */
> +#define NWAY_LPAR_ASM_DIR	0x0800 /* LP Asymmetric Pause Direction bit */
> +
> +/* 1000BASE-T Control Register */
> +#define CR_1000T_ASYM_PAUSE	0x0080 /* Advertise asymmetric pause bit */
> +#define CR_1000T_HD_CAPS	0x0100 /* Advertise 1000T HD capability */
> +#define CR_1000T_FD_CAPS	0x0200 /* Advertise 1000T FD capability  */
> +
> +/* PHY GPY 211 registers */
> +#define STANDARD_AN_REG_MASK	0x0007 /* MMD */
> +#define ANEG_MULTIGBT_AN_CTRL	0x0020 /* MULTI GBT AN Control Register */
> +#define MMD_DEVADDR_SHIFT	16     /* Shift MMD to higher bits */
> +#define CR_2500T_FD_CAPS	0x0080 /* Advertise 2500T FD capability */
> +

If these are specific to this device, please use an IGC_ prefix. 
Otherwise, they look like something that should be defined globally for 
other drivers to use.

>   /* NVM Control */
>   #define E1000_EECD_SK		0x00000001 /* NVM Clock */
>   #define E1000_EECD_CS		0x00000002 /* NVM Chip Select */
> diff --git a/drivers/net/ethernet/intel/igc/e1000_mac.c b/drivers/net/ethernet/intel/igc/e1000_mac.c
> index fe483211f66f..3f60810adc19 100644
> --- a/drivers/net/ethernet/intel/igc/e1000_mac.c
> +++ b/drivers/net/ethernet/intel/igc/e1000_mac.c
> @@ -141,6 +141,8 @@ s32 igc_setup_link(struct e1000_hw *hw)
>   	/* In the case of the phy reset being blocked, we already have a link.
>   	 * We do not need to set it up again.
>   	 */
> +	if (igc_check_reset_block(hw))
> +		goto out;
>   
>   	/* If requested flow control is set to default, set flow control
>   	 * based on the EEPROM flow control settings.
> @@ -192,10 +194,74 @@ s32 igc_setup_link(struct e1000_hw *hw)
>    **/
>   static s32 igc_set_default_fc(struct e1000_hw *hw)
>   {
> +	hw->fc.requested_mode = e1000_fc_full;
>   	return 0;
>   }
>   
>   /**
> + *  igc_force_mac_fc - Force the MAC's flow control settings
> + *  @hw: pointer to the HW structure
> + *
> + *  Force the MAC's flow control settings.  Sets the TFCE and RFCE bits in the
> + *  device control register to reflect the adapter settings.  TFCE and RFCE
> + *  need to be explicitly set by software when a copper PHY is used because
> + *  autonegotiation is managed by the PHY rather than the MAC.  Software must
> + *  also configure these bits when link is forced on a fiber connection.
> + **/
> +s32 igc_force_mac_fc(struct e1000_hw *hw)
> +{
> +	u32 ctrl;
> +	s32 ret_val = 0;
> +
> +	ctrl = rd32(E1000_CTRL);
> +
> +	/* Because we didn't get link via the internal auto-negotiation
> +	 * mechanism (we either forced link or we got link via PHY
> +	 * auto-neg), we have to manually enable/disable transmit an
> +	 * receive flow control.
> +	 *
> +	 * The "Case" statement below enables/disable flow control
> +	 * according to the "hw->fc.current_mode" parameter.
> +	 *
> +	 * The possible values of the "fc" parameter are:
> +	 *      0:  Flow control is completely disabled
> +	 *      1:  Rx flow control is enabled (we can receive pause
> +	 *          frames but not send pause frames).
> +	 *      2:  Tx flow control is enabled (we can send pause frames
> +	 *          frames but we do not receive pause frames).
> +	 *      3:  Both Rx and TX flow control (symmetric) is enabled.
> +	 *  other:  No other values should be possible at this point.
> +	 */
> +	hw_dbg("hw->fc.current_mode = %u\n", hw->fc.current_mode);
> +
> +	switch (hw->fc.current_mode) {
> +	case e1000_fc_none:
> +		ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE));
> +		break;
> +	case e1000_fc_rx_pause:
> +		ctrl &= (~E1000_CTRL_TFCE);
> +		ctrl |= E1000_CTRL_RFCE;
> +		break;
> +	case e1000_fc_tx_pause:
> +		ctrl &= (~E1000_CTRL_RFCE);
> +		ctrl |= E1000_CTRL_TFCE;
> +		break;
> +	case e1000_fc_full:
> +		ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE);
> +		break;
> +	default:
> +		hw_dbg("Flow control param set incorrectly\n");
> +		ret_val = -E1000_ERR_CONFIG;
> +		goto out;
> +	}
> +
> +	wr32(E1000_CTRL, ctrl);
> +
> +out:
> +	return ret_val;
> +}
> +
> +/**
>    *  igc_set_fc_watermarks - Set flow control high/low watermarks
>    *  @hw: pointer to the HW structure
>    *
> @@ -423,7 +489,7 @@ s32 igc_check_for_copper_link(struct e1000_hw *hw)
>   	 * settings because we may have had to re-autoneg with a
>   	 * different link partner.
>   	 */
> -	/* TODO ret_val = igc_config_fc_after_link_up(hw); */
> +	ret_val = igc_config_fc_after_link_up(hw);
>   	if (ret_val)
>   		hw_dbg("Error configuring flow control\n");
>   
> @@ -453,6 +519,210 @@ void igc_config_collision_dist(struct e1000_hw *hw)
>   }
>   
>   /**
> + *  igc_config_fc_after_link_up - Configures flow control after link
> + *  @hw: pointer to the HW structure
> + *
> + *  Checks the status of auto-negotiation after link up to ensure that the
> + *  speed and duplex were not forced.  If the link needed to be forced, then
> + *  flow control needs to be forced also.  If auto-negotiation is enabled
> + *  and did not fail, then we configure flow control based on our link
> + *  partner.
> + **/
> +s32 igc_config_fc_after_link_up(struct e1000_hw *hw)
> +{
> +	struct e1000_mac_info *mac = &hw->mac;
> +	s32 ret_val = 0;
> +	u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg;
> +	u16 speed, duplex;
> +
> +	/* Check for the case where we have fiber media and auto-neg failed
> +	 * so we had to force link.  In this case, we need to force the
> +	 * configuration of the MAC to match the "fc" parameter.
> +	 */
> +	if (mac->autoneg_failed) {
> +		if (hw->phy.media_type == e1000_media_type_copper)
> +			ret_val = igc_force_mac_fc(hw);
> +	}
> +
> +	if (ret_val) {
> +		hw_dbg("Error forcing flow control settings\n");
> +		goto out;
> +	}
> +
> +	/* Check for the case where we have copper media and auto-neg is
> +	 * enabled.  In this case, we need to check and see if Auto-Neg
> +	 * has completed, and if so, how the PHY and link partner has
> +	 * flow control configured.
> +	 */
> +	if (hw->phy.media_type == e1000_media_type_copper && mac->autoneg) {
> +		/* Read the MII Status Register and check to see if AutoNeg
> +		 * has completed.  We read this twice because this reg has
> +		 * some "sticky" (latched) bits.
> +		 */
> +		ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS,
> +					       &mii_status_reg);
> +		if (ret_val)
> +			goto out;
> +		ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS,
> +					       &mii_status_reg);
> +		if (ret_val)
> +			goto out;
> +
> +		if (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) {
> +			hw_dbg("Copper PHY and Auto Neg has not completed.\n");
> +			goto out;
> +		}
> +
> +		/* The AutoNeg process has completed, so we now need to
> +		 * read both the Auto Negotiation Advertisement
> +		 * Register (Address 4) and the Auto_Negotiation Base
> +		 * Page Ability Register (Address 5) to determine how
> +		 * flow control was negotiated.
> +		 */
> +		ret_val = hw->phy.ops.read_reg(hw, PHY_AUTONEG_ADV,
> +					       &mii_nway_adv_reg);
> +		if (ret_val)
> +			goto out;
> +		ret_val = hw->phy.ops.read_reg(hw, PHY_LP_ABILITY,
> +					       &mii_nway_lp_ability_reg);
> +		if (ret_val)
> +			goto out;
> +		/* Two bits in the Auto Negotiation Advertisement Register
> +		 * (Address 4) and two bits in the Auto Negotiation Base
> +		 * Page Ability Register (Address 5) determine flow control
> +		 * for both the PHY and the link partner.  The following
> +		 * table, taken out of the IEEE 802.3ab/D6.0 dated March 25,
> +		 * 1999, describes these PAUSE resolution bits and how flow
> +		 * control is determined based upon these settings.
> +		 * NOTE:  DC = Don't Care
> +		 *
> +		 *   LOCAL DEVICE  |   LINK PARTNER
> +		 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution
> +		 *-------|---------|-------|---------|--------------------
> +		 *   0   |    0    |  DC   |   DC    | e1000_fc_none
> +		 *   0   |    1    |   0   |   DC    | e1000_fc_none
> +		 *   0   |    1    |   1   |    0    | e1000_fc_none
> +		 *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
> +		 *   1   |    0    |   0   |   DC    | e1000_fc_none
> +		 *   1   |   DC    |   1   |   DC    | e1000_fc_full
> +		 *   1   |    1    |   0   |    0    | e1000_fc_none
> +		 *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
> +		 *
> +		 * Are both PAUSE bits set to 1?  If so, this implies
> +		 * Symmetric Flow Control is enabled at both ends.  The
> +		 * ASM_DIR bits are irrelevant per the spec.
> +		 *
> +		 * For Symmetric Flow Control:
> +		 *
> +		 *   LOCAL DEVICE  |   LINK PARTNER
> +		 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
> +		 *-------|---------|-------|---------|--------------------
> +		 *   1   |   DC    |   1   |   DC    | E1000_fc_full
> +		 *
> +		 */
> +		if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
> +		    (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) {
> +			/* Now we need to check if the user selected RX ONLY
> +			 * of pause frames.  In this case, we had to advertise
> +			 * FULL flow control because we could not advertise RX
> +			 * ONLY. Hence, we must now check to see if we need to
> +			 * turn OFF  the TRANSMISSION of PAUSE frames.
> +			 */
> +			if (hw->fc.requested_mode == e1000_fc_full) {
> +				hw->fc.current_mode = e1000_fc_full;
> +				hw_dbg("Flow Control = FULL.\n");
> +			} else {
> +				hw->fc.current_mode = e1000_fc_rx_pause;
> +				hw_dbg("Flow Control = RX PAUSE frames only.\n");
> +			}
> +		}
> +
> +		/* For receiving PAUSE frames ONLY.
> +		 *
> +		 *   LOCAL DEVICE  |   LINK PARTNER
> +		 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
> +		 *-------|---------|-------|---------|--------------------
> +		 *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
> +		 */
> +		else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) &&
> +			 (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
> +			 (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
> +			 (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
> +			hw->fc.current_mode = e1000_fc_tx_pause;
> +			hw_dbg("Flow Control = TX PAUSE frames only.\n");
> +		}
> +		/* For transmitting PAUSE frames ONLY.
> +		 *
> +		 *   LOCAL DEVICE  |   LINK PARTNER
> +		 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
> +		 *-------|---------|-------|---------|--------------------
> +		 *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
> +		 */
> +		else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
> +			 (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
> +			 !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
> +			 (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
> +			hw->fc.current_mode = e1000_fc_rx_pause;
> +			hw_dbg("Flow Control = RX PAUSE frames only.\n");
> +		}
> +		/* Per the IEEE spec, at this point flow control should be
> +		 * disabled.  However, we want to consider that we could
> +		 * be connected to a legacy switch that doesn't advertise
> +		 * desired flow control, but can be forced on the link
> +		 * partner.  So if we advertised no flow control, that is
> +		 * what we will resolve to.  If we advertised some kind of
> +		 * receive capability (Rx Pause Only or Full Flow Control)
> +		 * and the link partner advertised none, we will configure
> +		 * ourselves to enable Rx Flow Control only.  We can do
> +		 * this safely for two reasons:  If the link partner really
> +		 * didn't want flow control enabled, and we enable Rx, no
> +		 * harm done since we won't be receiving any PAUSE frames
> +		 * anyway.  If the intent on the link partner was to have
> +		 * flow control enabled, then by us enabling RX only, we
> +		 * can at least receive pause frames and process them.
> +		 * This is a good idea because in most cases, since we are
> +		 * predominantly a server NIC, more times than not we will
> +		 * be asked to delay transmission of packets than asking
> +		 * our link partner to pause transmission of frames.
> +		 */
> +		else if ((hw->fc.requested_mode == e1000_fc_none) ||
> +			 (hw->fc.requested_mode == e1000_fc_tx_pause) ||
> +			 (hw->fc.strict_ieee)) {
> +			hw->fc.current_mode = e1000_fc_none;
> +			hw_dbg("Flow Control = NONE.\n");
> +		} else {
> +			hw->fc.current_mode = e1000_fc_rx_pause;
> +			hw_dbg("Flow Control = RX PAUSE frames only.\n");
> +		}
> +
> +		/* Now we need to do one last check...  If we auto-
> +		 * negotiated to HALF DUPLEX, flow control should not be
> +		 * enabled per IEEE 802.3 spec.
> +		 */
> +		ret_val = hw->mac.ops.get_speed_and_duplex(hw, &speed, &duplex);
> +		if (ret_val) {
> +			hw_dbg("Error getting link speed and duplex\n");
> +			goto out;
> +		}
> +
> +		if (duplex == HALF_DUPLEX)
> +			hw->fc.current_mode = e1000_fc_none;
> +
> +		/* Now we call a subroutine to actually force the MAC
> +		 * controller to use the correct flow control settings.
> +		 */
> +		ret_val = igc_force_mac_fc(hw);
> +		if (ret_val) {
> +			hw_dbg("Error forcing flow control settings\n");
> +			goto out;
> +		}
> +	}
> +
> +out:
> +	return 0;
> +}
> +
> +/**
>    *  igc_get_auto_rd_done - Check for auto read completion
>    *  @hw: pointer to the HW structure
>    *
> diff --git a/drivers/net/ethernet/intel/igc/e1000_mac.h b/drivers/net/ethernet/intel/igc/e1000_mac.h
> index 0f17a8443125..0b32f21ce168 100644
> --- a/drivers/net/ethernet/intel/igc/e1000_mac.h
> +++ b/drivers/net/ethernet/intel/igc/e1000_mac.h
> @@ -14,6 +14,8 @@
>   
>   /* forward declaration */
>   s32 igc_check_for_copper_link(struct e1000_hw *hw);
> +s32 igc_config_fc_after_link_up(struct e1000_hw *hw);
> +s32 igc_force_mac_fc(struct e1000_hw *hw);
>   
>   s32 igc_disable_pcie_master(struct e1000_hw *hw);
>   void igc_init_rx_addrs(struct e1000_hw *hw, u16 rar_count);
> diff --git a/drivers/net/ethernet/intel/igc/e1000_phy.c b/drivers/net/ethernet/intel/igc/e1000_phy.c
> index c95efc4145e8..4f130402225f 100644
> --- a/drivers/net/ethernet/intel/igc/e1000_phy.c
> +++ b/drivers/net/ethernet/intel/igc/e1000_phy.c
> @@ -3,6 +3,10 @@
>   
>   #include "e1000_phy.h"
>   
> +/* forward declaration */
> +static s32  igc_phy_setup_autoneg(struct e1000_hw *hw);
> +static s32  igc_wait_autoneg(struct e1000_hw *hw);
> +
>   /**
>    *  igc_check_reset_block - Check if PHY reset is blocked
>    *  @hw: pointer to the HW structure
> @@ -206,7 +210,333 @@ s32 igc_phy_hw_reset(struct e1000_hw *hw)
>   
>   	phy->ops.release(hw);
>   
> -	ret_val = phy->ops.get_cfg_done(hw);
> +out:
> +	return ret_val;
> +}
> +
> +/**
> + *  igc_copper_link_autoneg - Setup/Enable autoneg for copper link
> + *  @hw: pointer to the HW structure
> + *
> + *  Performs initial bounds checking on autoneg advertisement parameter, then
> + *  configure to advertise the full capability.  Setup the PHY to autoneg
> + *  and restart the negotiation process between the link partner.  If
> + *  autoneg_wait_to_complete, then wait for autoneg to complete before exiting.
> + **/
> +static s32 igc_copper_link_autoneg(struct e1000_hw *hw)
> +{
> +	struct e1000_phy_info *phy = &hw->phy;
> +	s32 ret_val;
> +	u16 phy_ctrl;
> +
> +	/* Perform some bounds checking on the autoneg advertisement
> +	 * parameter.
> +	 */
> +	phy->autoneg_advertised &= phy->autoneg_mask;
> +
> +	/* If autoneg_advertised is zero, we assume it was not defaulted
> +	 * by the calling code so we set to advertise full capability.
> +	 */
> +	if (phy->autoneg_advertised == 0)
> +		phy->autoneg_advertised = phy->autoneg_mask;
> +
> +	hw_dbg("Reconfiguring auto-neg advertisement params\n");
> +	ret_val = igc_phy_setup_autoneg(hw);
> +	if (ret_val) {
> +		hw_dbg("Error Setting up Auto-Negotiation\n");
> +		goto out;
> +	}
> +	hw_dbg("Restarting Auto-Neg\n");
> +
> +	/* Restart auto-negotiation by setting the Auto Neg Enable bit and
> +	 * the Auto Neg Restart bit in the PHY control register.
> +	 */
> +	ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl);
> +	if (ret_val)
> +		goto out;
> +
> +	phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
> +	ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl);
> +	if (ret_val)
> +		goto out;
> +
> +	/* Does the user want to wait for Auto-Neg to complete here, or
> +	 * check at a later time (for example, callback routine).
> +	 */
> +	if (phy->autoneg_wait_to_complete) {
> +		ret_val = igc_wait_autoneg(hw);
> +		if (ret_val) {
> +			hw_dbg("Error while waiting for autoneg to complete\n");
> +			goto out;
> +		}
> +	}
> +
> +	hw->mac.get_link_status = true;
> +
> +out:
> +	return ret_val;
> +}
> +
> +/**
> + *  igc_wait_autoneg - Wait for auto-neg completion
> + *  @hw: pointer to the HW structure
> + *
> + *  Waits for auto-negotiation to complete or for the auto-negotiation time
> + *  limit to expire, which ever happens first.
> + **/
> +static s32 igc_wait_autoneg(struct e1000_hw *hw)
> +{
> +	s32 ret_val = 0;
> +	u16 i, phy_status;
> +
> +	/* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */
> +	for (i = PHY_AUTO_NEG_LIMIT; i > 0; i--) {
> +		ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
> +		if (ret_val)
> +			break;
> +		ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
> +		if (ret_val)
> +			break;
> +		if (phy_status & MII_SR_AUTONEG_COMPLETE)
> +			break;
> +		msleep(100);
> +	}
> +
> +	/* PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation
> +	 * has completed.
> +	 */

Should you return an error value if the wait time expired?

> +	return ret_val;
> +}
> +
> +/**
> + *  igc_phy_setup_autoneg - Configure PHY for auto-negotiation
> + *  @hw: pointer to the HW structure
> + *
> + *  Reads the MII auto-neg advertisement register and/or the 1000T control
> + *  register and if the PHY is already setup for auto-negotiation, then
> + *  return successful.  Otherwise, setup advertisement and flow control to
> + *  the appropriate values for the wanted auto-negotiation.
> + **/
> +static s32 igc_phy_setup_autoneg(struct e1000_hw *hw)
> +{
> +	struct e1000_phy_info *phy = &hw->phy;
> +	s32 ret_val;
> +	u16 mii_autoneg_adv_reg;
> +	u16 mii_1000t_ctrl_reg = 0;
> +	u16 aneg_multigbt_an_ctrl = 0;
> +
> +	phy->autoneg_advertised &= phy->autoneg_mask;
> +
> +	/* Read the MII Auto-Neg Advertisement Register (Address 4). */
> +	ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg);
> +	if (ret_val)
> +		return ret_val;
> +
> +	if (phy->autoneg_mask & ADVERTISE_1000_FULL) {
> +		/* Read the MII 1000Base-T Control Register (Address 9). */
> +		ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL,
> +					    &mii_1000t_ctrl_reg);
> +		if (ret_val)
> +			return ret_val;
> +	}
> +
> +	if ((phy->autoneg_mask & ADVERTISE_2500_FULL) &&
> +	    hw->phy.id == I225_I_PHY_ID) {
> +		/* Read the MULTI GBT AN Control Register - reg 7.32 */
> +		ret_val = phy->ops.read_reg(hw, (STANDARD_AN_REG_MASK <<
> +					    MMD_DEVADDR_SHIFT) |
> +					    ANEG_MULTIGBT_AN_CTRL,
> +					    &aneg_multigbt_an_ctrl);
> +
> +		if (ret_val)
> +			return ret_val;
> +	}
> +
> +	/* Need to parse both autoneg_advertised and fc and set up
> +	 * the appropriate PHY registers.  First we will parse for
> +	 * autoneg_advertised software override.  Since we can advertise
> +	 * a plethora of combinations, we need to check each bit
> +	 * individually.
> +	 */
> +
> +	/* First we clear all the 10/100 mb speed bits in the Auto-Neg
> +	 * Advertisement Register (Address 4) and the 1000 mb speed bits in
> +	 * the  1000Base-T Control Register (Address 9).
> +	 */
> +	mii_autoneg_adv_reg &= ~(NWAY_AR_100TX_FD_CAPS |
> +				 NWAY_AR_100TX_HD_CAPS |
> +				 NWAY_AR_10T_FD_CAPS   |
> +				 NWAY_AR_10T_HD_CAPS);
> +	mii_1000t_ctrl_reg &= ~(CR_1000T_HD_CAPS | CR_1000T_FD_CAPS);
> +
> +	hw_dbg("autoneg_advertised %x\n", phy->autoneg_advertised);
> +
> +	/* Do we want to advertise 10 Mb Half Duplex? */
> +	if (phy->autoneg_advertised & ADVERTISE_10_HALF) {
> +		hw_dbg("Advertise 10mb Half duplex\n");
> +		mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS;
> +	}
> +
> +	/* Do we want to advertise 10 Mb Full Duplex? */
> +	if (phy->autoneg_advertised & ADVERTISE_10_FULL) {
> +		hw_dbg("Advertise 10mb Full duplex\n");
> +		mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS;
> +	}
> +
> +	/* Do we want to advertise 100 Mb Half Duplex? */
> +	if (phy->autoneg_advertised & ADVERTISE_100_HALF) {
> +		hw_dbg("Advertise 100mb Half duplex\n");
> +		mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS;
> +	}
> +
> +	/* Do we want to advertise 100 Mb Full Duplex? */
> +	if (phy->autoneg_advertised & ADVERTISE_100_FULL) {
> +		hw_dbg("Advertise 100mb Full duplex\n");
> +		mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS;
> +	}
> +
> +	/* We do not allow the Phy to advertise 1000 Mb Half Duplex */
> +	if (phy->autoneg_advertised & ADVERTISE_1000_HALF)
> +		hw_dbg("Advertise 1000mb Half duplex request denied!\n");
> +
> +	/* Do we want to advertise 1000 Mb Full Duplex? */
> +	if (phy->autoneg_advertised & ADVERTISE_1000_FULL) {
> +		hw_dbg("Advertise 1000mb Full duplex\n");
> +		mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
> +	}
> +
> +	/* We do not allow the Phy to advertise 2500 Mb Half Duplex */
> +	if (phy->autoneg_advertised & ADVERTISE_2500_HALF)
> +		hw_dbg("Advertise 2500mb Half duplex request denied!\n");
> +
> +	/* Do we want to advertise 2500 Mb Full Duplex? */
> +	if (phy->autoneg_advertised & ADVERTISE_2500_FULL) {
> +		hw_dbg("Advertise 2500mb Full duplex\n");
> +		aneg_multigbt_an_ctrl |= CR_2500T_FD_CAPS;
> +	}
> +
> +	/* Check for a software override of the flow control settings, and
> +	 * setup the PHY advertisement registers accordingly.  If
> +	 * auto-negotiation is enabled, then software will have to set the
> +	 * "PAUSE" bits to the correct value in the Auto-Negotiation
> +	 * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto-
> +	 * negotiation.
> +	 *
> +	 * The possible values of the "fc" parameter are:
> +	 *      0:  Flow control is completely disabled
> +	 *      1:  Rx flow control is enabled (we can receive pause frames
> +	 *          but not send pause frames).
> +	 *      2:  Tx flow control is enabled (we can send pause frames
> +	 *          but we do not support receiving pause frames).
> +	 *      3:  Both Rx and Tx flow control (symmetric) are enabled.
> +	 *  other:  No software override.  The flow control configuration
> +	 *          in the EEPROM is used.
> +	 */
> +	switch (hw->fc.current_mode) {
> +	case e1000_fc_none:
> +		/* Flow control (Rx & Tx) is completely disabled by a
> +		 * software over-ride.
> +		 */
> +		mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
> +		break;
> +	case e1000_fc_rx_pause:
> +		/* Rx Flow control is enabled, and Tx Flow control is
> +		 * disabled, by a software over-ride.
> +		 *
> +		 * Since there really isn't a way to advertise that we are
> +		 * capable of Rx Pause ONLY, we will advertise that we
> +		 * support both symmetric and asymmetric Rx PAUSE.  Later
> +		 * (in e1000_config_fc_after_link_up) we will disable the
> +		 * hw's ability to send PAUSE frames.
> +		 */
> +		mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
> +		break;
> +	case e1000_fc_tx_pause:
> +		/* Tx Flow control is enabled, and Rx Flow control is
> +		 * disabled, by a software over-ride.
> +		 */
> +		mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;
> +		mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;
> +		break;
> +	case e1000_fc_full:
> +		/* Flow control (both Rx and Tx) is enabled by a software
> +		 * over-ride.
> +		 */
> +		mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
> +		break;
> +	default:
> +		hw_dbg("Flow control param set incorrectly\n");
> +		return -E1000_ERR_CONFIG;
> +	}
> +
> +	ret_val = phy->ops.write_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg);
> +	if (ret_val)
> +		return ret_val;
> +
> +	hw_dbg("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
> +
> +	if (phy->autoneg_mask & ADVERTISE_1000_FULL)
> +		ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL,
> +					     mii_1000t_ctrl_reg);
> +
> +	if ((phy->autoneg_mask & ADVERTISE_2500_FULL) &&
> +	    hw->phy.id == I225_I_PHY_ID)
> +		ret_val = phy->ops.write_reg(hw,
> +					     (STANDARD_AN_REG_MASK <<
> +					     MMD_DEVADDR_SHIFT) |
> +					     ANEG_MULTIGBT_AN_CTRL,
> +					     aneg_multigbt_an_ctrl);
> +
> +	return ret_val;
> +}
> +
> +/**
> + *  igc_setup_copper_link - Configure copper link settings
> + *  @hw: pointer to the HW structure
> + *
> + *  Calls the appropriate function to configure the link for auto-neg or forced
> + *  speed and duplex.  Then we check for link, once link is established calls
> + *  to configure collision distance and flow control are called.  If link is
> + *  not established, we return -E1000_ERR_PHY (-2).
> + **/
> +s32 igc_setup_copper_link(struct e1000_hw *hw)
> +{
> +	s32 ret_val = 0;
> +	bool link;
> +
> +	if (hw->mac.autoneg) {
> +		/* Setup autoneg and flow control advertisement and perform
> +		 * autonegotiation.
> +		 */
> +		ret_val = igc_copper_link_autoneg(hw);
> +		if (ret_val)
> +			goto out;
> +	} else {
> +		/* PHY will be set to 10H, 10F, 100H or 100F
> +		 * depending on user settings.
> +		 */
> +		hw_dbg("Forcing Speed and Duplex\n");
> +		ret_val = hw->phy.ops.force_speed_duplex(hw);
> +		if (ret_val) {
> +			hw_dbg("Error Forcing Speed and Duplex\n");
> +			goto out;
> +		}
> +	}
> +
> +	/* Check link status. Wait up to 100 microseconds for link to become
> +	 * valid.
> +	 */
> +	ret_val = igc_phy_has_link(hw, COPPER_LINK_UP_LIMIT, 10, &link);
> +	if (ret_val)
> +		goto out;
> +
> +	if (link) {
> +		hw_dbg("Valid link established!!!\n");
> +		igc_config_collision_dist(hw);
> +		ret_val = igc_config_fc_after_link_up(hw);
> +	} else {
> +		hw_dbg("Unable to establish link!!!\n");
> +	}
>   
>   out:
>   	return ret_val;
> diff --git a/drivers/net/ethernet/intel/igc/e1000_phy.h b/drivers/net/ethernet/intel/igc/e1000_phy.h
> index d04dfd0be7fd..3fddb1269ea2 100644
> --- a/drivers/net/ethernet/intel/igc/e1000_phy.h
> +++ b/drivers/net/ethernet/intel/igc/e1000_phy.h
> @@ -12,6 +12,7 @@ s32  igc_get_phy_id(struct e1000_hw *hw);
>   s32  igc_phy_has_link(struct e1000_hw *hw, u32 iterations,
>   		      u32 usec_interval, bool *success);
>   s32 igc_check_downshift(struct e1000_hw *hw);
> +s32 igc_setup_copper_link(struct e1000_hw *hw);
>   void igc_power_up_phy_copper(struct e1000_hw *hw);
>   void igc_power_down_phy_copper(struct e1000_hw *hw);
>   
> diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h
> index 91df0a14c3a5..99bc2344b7ff 100644
> --- a/drivers/net/ethernet/intel/igc/igc.h
> +++ b/drivers/net/ethernet/intel/igc/igc.h
> @@ -320,6 +320,7 @@ struct igc_adapter {
>   	struct work_struct reset_task;
>   	struct work_struct watchdog_task;
>   	struct work_struct dma_err_task;
> +	bool fc_autoneg;
>   
>   	u8  tx_timeout_factor;
>   
> diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
> index 21aed91454d4..563612910b3f 100644
> --- a/drivers/net/ethernet/intel/igc/igc_main.c
> +++ b/drivers/net/ethernet/intel/igc/igc_main.c
> @@ -3194,7 +3194,6 @@ static int __igc_open(struct net_device *netdev, bool resuming)
>   
>   	/* start the watchdog. */
>   	hw->mac.get_link_status = 1;
> -	schedule_work(&adapter->watchdog_task);
>   
>   	return E1000_SUCCESS;
>   
> @@ -3452,6 +3451,25 @@ static int igc_probe(struct pci_dev *pdev,
>   	netdev->min_mtu = ETH_MIN_MTU;
>   	netdev->max_mtu = MAX_STD_JUMBO_FRAME_SIZE;
>   
> +	/* before reading the NVM, reset the controller to put the device in a
> +	 * known good starting state
> +	 */
> +	hw->mac.ops.reset_hw(hw);
> +
> +	if (eth_platform_get_mac_address(&pdev->dev, hw->mac.addr)) {
> +		/* copy the MAC address out of the NVM */
> +		if (hw->mac.ops.read_mac_addr(hw))
> +			dev_err(&pdev->dev, "NVM Read Error\n");
> +	}
> +
> +	memcpy(netdev->dev_addr, hw->mac.addr, netdev->addr_len);
> +
> +	if (!is_valid_ether_addr(netdev->dev_addr)) {
> +		dev_err(&pdev->dev, "Invalid MAC Address\n");
> +		err = -EIO;
> +		goto err_eeprom;
> +	}
> +
>   	/* configure RXPBSIZE and TXPBSIZE */
>   	wr32(E1000_RXPBS, I225_RXPBSIZE_DEFAULT);
>   	wr32(E1000_TXPBS, I225_TXPBSIZE_DEFAULT);
> @@ -3460,6 +3478,14 @@ static int igc_probe(struct pci_dev *pdev,
>   
>   	INIT_WORK(&adapter->reset_task, igc_reset_task);
>   
> +	/* Initialize link properties that are user-changeable */
> +	adapter->fc_autoneg = true;
> +	hw->mac.autoneg = true;
> +	hw->phy.autoneg_advertised = 0x2f;
> +
> +	hw->fc.requested_mode = e1000_fc_default;
> +	hw->fc.current_mode = e1000_fc_default;
> +
>   	/* reset the hardware with the new settings */
>   	igc_reset(adapter);
>   
> @@ -3496,6 +3522,12 @@ static int igc_probe(struct pci_dev *pdev,
>   
>   err_register:
>   	igc_release_hw_control(adapter);
> +err_eeprom:
> +	if (!igc_check_reset_block(hw))
> +		igc_reset_phy(hw);
> +
> +	if (hw->flash_address)
> +		iounmap(hw->flash_address);
>   err_sw_init:
>   	igc_clear_interrupt_scheme(adapter);
>   	iounmap(adapter->io_addr);
> @@ -3530,7 +3562,6 @@ static void igc_remove(struct pci_dev *pdev)
>   	del_timer_sync(&adapter->watchdog_timer);
>   
>   	cancel_work_sync(&adapter->reset_task);
> -	cancel_work_sync(&adapter->watchdog_task);

Why are you removing this?  Yes, I see that it got put back in patch 
11/11, but why take it out in the first place?

>   
>   	/* Release control of h/w to f/w.  If f/w is AMT enabled, this
>   	 * would have already happened in close and is redundant.
>
Sasha Neftin July 4, 2018, 3:19 p.m. UTC | #2
On 6/29/2018 18:03, Shannon Nelson wrote:
> On 6/24/2018 1:45 AM, Sasha Neftin wrote:
>> Add link establishment methods
>> Add auto negotiation methods
>> Add read MAC address method
>>
>> Sasha Neftin (v2):
>> minor cosmetic changes
>>
>> Sasha Neftin (v3):
>> removed not addressed methods
>>
>> Signed-off-by: Sasha Neftin <sasha.neftin@intel.com>
>> ---
>>   drivers/net/ethernet/intel/igc/e1000_base.c    |  41 +++
>>   drivers/net/ethernet/intel/igc/e1000_defines.h |  45 ++++
>>   drivers/net/ethernet/intel/igc/e1000_mac.c     | 272 
>> +++++++++++++++++++-
>>   drivers/net/ethernet/intel/igc/e1000_mac.h     |   2 +
>>   drivers/net/ethernet/intel/igc/e1000_phy.c     | 332 
>> ++++++++++++++++++++++++-
>>   drivers/net/ethernet/intel/igc/e1000_phy.h     |   1 +
>>   drivers/net/ethernet/intel/igc/igc.h           |   1 +
>>   drivers/net/ethernet/intel/igc/igc_main.c      |  35 ++-
>>   8 files changed, 725 insertions(+), 4 deletions(-)
>>
>> diff --git a/drivers/net/ethernet/intel/igc/e1000_base.c 
>> b/drivers/net/ethernet/intel/igc/e1000_base.c
>> index 8b35e1d6c32e..6405506ff7b8 100644
>> --- a/drivers/net/ethernet/intel/igc/e1000_base.c
>> +++ b/drivers/net/ethernet/intel/igc/e1000_base.c
>> @@ -17,6 +17,7 @@ static void igc_release_phy_base(struct e1000_hw *);
>>   static s32 igc_get_phy_id_base(struct e1000_hw *);
>>   static s32 igc_init_hw_base(struct e1000_hw *);
>>   static s32 igc_reset_hw_base(struct e1000_hw *);
>> +static s32 igc_setup_copper_link_base(struct e1000_hw *);
>>   static s32 igc_set_pcie_completion_timeout(struct e1000_hw *hw);
>>   static s32 igc_read_mac_addr_base(struct e1000_hw *hw);
>> @@ -97,6 +98,9 @@ static s32 igc_init_mac_params_base(struct e1000_hw 
>> *hw)
>>       if (mac->type == e1000_i225)
>>           dev_spec->clear_semaphore_once = true;
>> +    /* physical interface link setup */
>> +    mac->ops.setup_physical_interface = igc_setup_copper_link_base;
>> +
>>       return 0;
>>   }
>> @@ -139,6 +143,8 @@ static s32 igc_init_phy_params_base(struct 
>> e1000_hw *hw)
>>       if (ret_val)
>>           return ret_val;
>> +    igc_check_for_link_base(hw);
>> +
>>       /* Verify phy id and set remaining function pointers */
>>       switch (phy->id) {
>>       case I225_I_PHY_ID:
>> @@ -155,10 +161,22 @@ static s32 igc_init_phy_params_base(struct 
>> e1000_hw *hw)
>>   static s32 igc_get_invariants_base(struct e1000_hw *hw)
>>   {
>> +    struct e1000_mac_info *mac = &hw->mac;
>>       s32 ret_val = 0;
>>       u32 ctrl_ext = 0;
>>       u32 link_mode = 0;
>> +    switch (hw->device_id) {
>> +    case E1000_DEV_ID_I225_LM:
>> +    case E1000_DEV_ID_I225_V:
>> +        mac->type = e1000_i225;
>> +        break;
>> +    default:
>> +        return -E1000_ERR_MAC_INIT;
>> +    }
>> +
>> +    hw->phy.media_type = e1000_media_type_copper;
>> +
>>       ctrl_ext = rd32(E1000_CTRL_EXT);
>>       link_mode = ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK;
>> @@ -289,6 +307,29 @@ static s32 igc_init_hw_base(struct e1000_hw *hw)
>>   }
>>   /**
>> + *  igc_setup_copper_link_base - Configure copper link settings
>> + *  @hw: pointer to the HW structure
>> + *
>> + *  Configures the link for auto-neg or forced speed and duplex.  
>> Then we check
>> + *  for link, once link is established calls to configure collision 
>> distance
>> + *  and flow control are called.
>> + **/
>> +static s32 igc_setup_copper_link_base(struct e1000_hw *hw)
>> +{
>> +    s32  ret_val = 0;
>> +    u32 ctrl;
>> +
>> +    ctrl = rd32(E1000_CTRL);
>> +    ctrl |= E1000_CTRL_SLU;
>> +    ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
>> +    wr32(E1000_CTRL, ctrl);
>> +
>> +    ret_val = igc_setup_copper_link(hw);
>> +
>> +    return ret_val;
>> +}
>> +
>> +/**
>>    *  igc_read_mac_addr_base - Read device MAC address
>>    *  @hw: pointer to the HW structure
>>    **/
>> diff --git a/drivers/net/ethernet/intel/igc/e1000_defines.h 
>> b/drivers/net/ethernet/intel/igc/e1000_defines.h
>> index 40276ae76c9f..24c24c197d6b 100644
>> --- a/drivers/net/ethernet/intel/igc/e1000_defines.h
>> +++ b/drivers/net/ethernet/intel/igc/e1000_defines.h
>> @@ -33,6 +33,11 @@
>>   /* Physical Func Reset Done Indication */
>>   #define E1000_CTRL_EXT_LINK_MODE_MASK    0x00C00000
>> +/* Loop limit on how long we wait for auto-negotiation to complete */
>> +#define COPPER_LINK_UP_LIMIT        10
>> +#define PHY_AUTO_NEG_LIMIT        45
>> +#define PHY_FORCE_LIMIT            20
>> +
>>   /* Number of 100 microseconds we wait for PCI Express master disable */
>>   #define MASTER_DISABLE_TIMEOUT        800
>>   /*Blocks new Master requests */
>> @@ -74,6 +79,12 @@
>>   #define E1000_CTRL_RST        0x04000000  /* Global reset */
>>   #define E1000_CTRL_PHY_RST    0x80000000  /* PHY Reset */
>> +#define E1000_CTRL_SLU        0x00000040  /* Set link up (Force Link) */
>> +#define E1000_CTRL_FRCSPD    0x00000800  /* Force Speed */
>> +#define E1000_CTRL_FRCDPX    0x00001000  /* Force Duplex */
>> +
>> +#define E1000_CTRL_RFCE        0x08000000  /* Receive Flow Control 
>> enable */
>> +#define E1000_CTRL_TFCE        0x10000000  /* Transmit flow control 
>> enable */
>>   /* PBA constants */
>>   #define E1000_PBA_34K            0x0022
>> @@ -89,6 +100,40 @@
>>   #define E1000_SWFW_PHY2_SM    0x20
>>   #define E1000_SWFW_PHY3_SM    0x40
>> +/* PHY 1000 MII Register/Bit Definitions */
>> +/* PHY Registers defined by IEEE */
>> +#define PHY_CONTROL        0x00 /* Control Register */
>> +#define PHY_STATUS        0x01 /* Status Register */
>> +#define PHY_ID1            0x02 /* Phy Id Reg (word 1) */
>> +#define PHY_ID2            0x03 /* Phy Id Reg (word 2) */
>> +#define PHY_AUTONEG_ADV        0x04 /* Autoneg Advertisement */
>> +#define PHY_LP_ABILITY        0x05 /* Link Partner Ability (Base 
>> Page) */
>> +#define PHY_1000T_CTRL        0x09 /* 1000Base-T Control Reg */
>> +#define PHY_1000T_STATUS    0x0A /* 1000Base-T Status Reg */
>> +
>> +/* Autoneg Advertisement Register */
>> +#define NWAY_AR_10T_HD_CAPS    0x0020   /* 10T   Half Duplex Capable */
>> +#define NWAY_AR_10T_FD_CAPS    0x0040   /* 10T   Full Duplex Capable */
>> +#define NWAY_AR_100TX_HD_CAPS    0x0080   /* 100TX Half Duplex 
>> Capable */
>> +#define NWAY_AR_100TX_FD_CAPS    0x0100   /* 100TX Full Duplex 
>> Capable */
>> +#define NWAY_AR_PAUSE        0x0400   /* Pause operation desired */
>> +#define NWAY_AR_ASM_DIR        0x0800   /* Asymmetric Pause Direction 
>> bit */
>> +
>> +/* Link Partner Ability Register (Base Page) */
>> +#define NWAY_LPAR_PAUSE        0x0400 /* LP Pause operation desired */
>> +#define NWAY_LPAR_ASM_DIR    0x0800 /* LP Asymmetric Pause Direction 
>> bit */
>> +
>> +/* 1000BASE-T Control Register */
>> +#define CR_1000T_ASYM_PAUSE    0x0080 /* Advertise asymmetric pause 
>> bit */
>> +#define CR_1000T_HD_CAPS    0x0100 /* Advertise 1000T HD capability */
>> +#define CR_1000T_FD_CAPS    0x0200 /* Advertise 1000T FD capability  */
>> +
>> +/* PHY GPY 211 registers */
>> +#define STANDARD_AN_REG_MASK    0x0007 /* MMD */
>> +#define ANEG_MULTIGBT_AN_CTRL    0x0020 /* MULTI GBT AN Control 
>> Register */
>> +#define MMD_DEVADDR_SHIFT    16     /* Shift MMD to higher bits */
>> +#define CR_2500T_FD_CAPS    0x0080 /* Advertise 2500T FD capability */
>> +
> 
> If these are specific to this device, please use an IGC_ prefix. 
> Otherwise, they look like something that should be defined globally for 
> other drivers to use.
> 
This and all comments regard to e1000_ or igc_ prefix... I should 
consult with my colleagues and reply.
>>   /* NVM Control */
>>   #define E1000_EECD_SK        0x00000001 /* NVM Clock */
>>   #define E1000_EECD_CS        0x00000002 /* NVM Chip Select */
>> diff --git a/drivers/net/ethernet/intel/igc/e1000_mac.c 
>> b/drivers/net/ethernet/intel/igc/e1000_mac.c
>> index fe483211f66f..3f60810adc19 100644
>> --- a/drivers/net/ethernet/intel/igc/e1000_mac.c
>> +++ b/drivers/net/ethernet/intel/igc/e1000_mac.c
>> @@ -141,6 +141,8 @@ s32 igc_setup_link(struct e1000_hw *hw)
>>       /* In the case of the phy reset being blocked, we already have a 
>> link.
>>        * We do not need to set it up again.
>>        */
>> +    if (igc_check_reset_block(hw))
>> +        goto out;
>>       /* If requested flow control is set to default, set flow control
>>        * based on the EEPROM flow control settings.
>> @@ -192,10 +194,74 @@ s32 igc_setup_link(struct e1000_hw *hw)
>>    **/
>>   static s32 igc_set_default_fc(struct e1000_hw *hw)
>>   {
>> +    hw->fc.requested_mode = e1000_fc_full;
>>       return 0;
>>   }
>>   /**
>> + *  igc_force_mac_fc - Force the MAC's flow control settings
>> + *  @hw: pointer to the HW structure
>> + *
>> + *  Force the MAC's flow control settings.  Sets the TFCE and RFCE 
>> bits in the
>> + *  device control register to reflect the adapter settings.  TFCE 
>> and RFCE
>> + *  need to be explicitly set by software when a copper PHY is used 
>> because
>> + *  autonegotiation is managed by the PHY rather than the MAC.  
>> Software must
>> + *  also configure these bits when link is forced on a fiber connection.
>> + **/
>> +s32 igc_force_mac_fc(struct e1000_hw *hw)
>> +{
>> +    u32 ctrl;
>> +    s32 ret_val = 0;
>> +
>> +    ctrl = rd32(E1000_CTRL);
>> +
>> +    /* Because we didn't get link via the internal auto-negotiation
>> +     * mechanism (we either forced link or we got link via PHY
>> +     * auto-neg), we have to manually enable/disable transmit an
>> +     * receive flow control.
>> +     *
>> +     * The "Case" statement below enables/disable flow control
>> +     * according to the "hw->fc.current_mode" parameter.
>> +     *
>> +     * The possible values of the "fc" parameter are:
>> +     *      0:  Flow control is completely disabled
>> +     *      1:  Rx flow control is enabled (we can receive pause
>> +     *          frames but not send pause frames).
>> +     *      2:  Tx flow control is enabled (we can send pause frames
>> +     *          frames but we do not receive pause frames).
>> +     *      3:  Both Rx and TX flow control (symmetric) is enabled.
>> +     *  other:  No other values should be possible at this point.
>> +     */
>> +    hw_dbg("hw->fc.current_mode = %u\n", hw->fc.current_mode);
>> +
>> +    switch (hw->fc.current_mode) {
>> +    case e1000_fc_none:
>> +        ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE));
>> +        break;
>> +    case e1000_fc_rx_pause:
>> +        ctrl &= (~E1000_CTRL_TFCE);
>> +        ctrl |= E1000_CTRL_RFCE;
>> +        break;
>> +    case e1000_fc_tx_pause:
>> +        ctrl &= (~E1000_CTRL_RFCE);
>> +        ctrl |= E1000_CTRL_TFCE;
>> +        break;
>> +    case e1000_fc_full:
>> +        ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE);
>> +        break;
>> +    default:
>> +        hw_dbg("Flow control param set incorrectly\n");
>> +        ret_val = -E1000_ERR_CONFIG;
>> +        goto out;
>> +    }
>> +
>> +    wr32(E1000_CTRL, ctrl);
>> +
>> +out:
>> +    return ret_val;
>> +}
>> +
>> +/**
>>    *  igc_set_fc_watermarks - Set flow control high/low watermarks
>>    *  @hw: pointer to the HW structure
>>    *
>> @@ -423,7 +489,7 @@ s32 igc_check_for_copper_link(struct e1000_hw *hw)
>>        * settings because we may have had to re-autoneg with a
>>        * different link partner.
>>        */
>> -    /* TODO ret_val = igc_config_fc_after_link_up(hw); */
>> +    ret_val = igc_config_fc_after_link_up(hw);
>>       if (ret_val)
>>           hw_dbg("Error configuring flow control\n");
>> @@ -453,6 +519,210 @@ void igc_config_collision_dist(struct e1000_hw *hw)
>>   }
>>   /**
>> + *  igc_config_fc_after_link_up - Configures flow control after link
>> + *  @hw: pointer to the HW structure
>> + *
>> + *  Checks the status of auto-negotiation after link up to ensure 
>> that the
>> + *  speed and duplex were not forced.  If the link needed to be 
>> forced, then
>> + *  flow control needs to be forced also.  If auto-negotiation is 
>> enabled
>> + *  and did not fail, then we configure flow control based on our link
>> + *  partner.
>> + **/
>> +s32 igc_config_fc_after_link_up(struct e1000_hw *hw)
>> +{
>> +    struct e1000_mac_info *mac = &hw->mac;
>> +    s32 ret_val = 0;
>> +    u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg;
>> +    u16 speed, duplex;
>> +
>> +    /* Check for the case where we have fiber media and auto-neg failed
>> +     * so we had to force link.  In this case, we need to force the
>> +     * configuration of the MAC to match the "fc" parameter.
>> +     */
>> +    if (mac->autoneg_failed) {
>> +        if (hw->phy.media_type == e1000_media_type_copper)
>> +            ret_val = igc_force_mac_fc(hw);
>> +    }
>> +
>> +    if (ret_val) {
>> +        hw_dbg("Error forcing flow control settings\n");
>> +        goto out;
>> +    }
>> +
>> +    /* Check for the case where we have copper media and auto-neg is
>> +     * enabled.  In this case, we need to check and see if Auto-Neg
>> +     * has completed, and if so, how the PHY and link partner has
>> +     * flow control configured.
>> +     */
>> +    if (hw->phy.media_type == e1000_media_type_copper && mac->autoneg) {
>> +        /* Read the MII Status Register and check to see if AutoNeg
>> +         * has completed.  We read this twice because this reg has
>> +         * some "sticky" (latched) bits.
>> +         */
>> +        ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS,
>> +                           &mii_status_reg);
>> +        if (ret_val)
>> +            goto out;
>> +        ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS,
>> +                           &mii_status_reg);
>> +        if (ret_val)
>> +            goto out;
>> +
>> +        if (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) {
>> +            hw_dbg("Copper PHY and Auto Neg has not completed.\n");
>> +            goto out;
>> +        }
>> +
>> +        /* The AutoNeg process has completed, so we now need to
>> +         * read both the Auto Negotiation Advertisement
>> +         * Register (Address 4) and the Auto_Negotiation Base
>> +         * Page Ability Register (Address 5) to determine how
>> +         * flow control was negotiated.
>> +         */
>> +        ret_val = hw->phy.ops.read_reg(hw, PHY_AUTONEG_ADV,
>> +                           &mii_nway_adv_reg);
>> +        if (ret_val)
>> +            goto out;
>> +        ret_val = hw->phy.ops.read_reg(hw, PHY_LP_ABILITY,
>> +                           &mii_nway_lp_ability_reg);
>> +        if (ret_val)
>> +            goto out;
>> +        /* Two bits in the Auto Negotiation Advertisement Register
>> +         * (Address 4) and two bits in the Auto Negotiation Base
>> +         * Page Ability Register (Address 5) determine flow control
>> +         * for both the PHY and the link partner.  The following
>> +         * table, taken out of the IEEE 802.3ab/D6.0 dated March 25,
>> +         * 1999, describes these PAUSE resolution bits and how flow
>> +         * control is determined based upon these settings.
>> +         * NOTE:  DC = Don't Care
>> +         *
>> +         *   LOCAL DEVICE  |   LINK PARTNER
>> +         * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution
>> +         *-------|---------|-------|---------|--------------------
>> +         *   0   |    0    |  DC   |   DC    | e1000_fc_none
>> +         *   0   |    1    |   0   |   DC    | e1000_fc_none
>> +         *   0   |    1    |   1   |    0    | e1000_fc_none
>> +         *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
>> +         *   1   |    0    |   0   |   DC    | e1000_fc_none
>> +         *   1   |   DC    |   1   |   DC    | e1000_fc_full
>> +         *   1   |    1    |   0   |    0    | e1000_fc_none
>> +         *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
>> +         *
>> +         * Are both PAUSE bits set to 1?  If so, this implies
>> +         * Symmetric Flow Control is enabled at both ends.  The
>> +         * ASM_DIR bits are irrelevant per the spec.
>> +         *
>> +         * For Symmetric Flow Control:
>> +         *
>> +         *   LOCAL DEVICE  |   LINK PARTNER
>> +         * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
>> +         *-------|---------|-------|---------|--------------------
>> +         *   1   |   DC    |   1   |   DC    | E1000_fc_full
>> +         *
>> +         */
>> +        if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
>> +            (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) {
>> +            /* Now we need to check if the user selected RX ONLY
>> +             * of pause frames.  In this case, we had to advertise
>> +             * FULL flow control because we could not advertise RX
>> +             * ONLY. Hence, we must now check to see if we need to
>> +             * turn OFF  the TRANSMISSION of PAUSE frames.
>> +             */
>> +            if (hw->fc.requested_mode == e1000_fc_full) {
>> +                hw->fc.current_mode = e1000_fc_full;
>> +                hw_dbg("Flow Control = FULL.\n");
>> +            } else {
>> +                hw->fc.current_mode = e1000_fc_rx_pause;
>> +                hw_dbg("Flow Control = RX PAUSE frames only.\n");
>> +            }
>> +        }
>> +
>> +        /* For receiving PAUSE frames ONLY.
>> +         *
>> +         *   LOCAL DEVICE  |   LINK PARTNER
>> +         * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
>> +         *-------|---------|-------|---------|--------------------
>> +         *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
>> +         */
>> +        else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) &&
>> +             (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
>> +             (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
>> +             (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
>> +            hw->fc.current_mode = e1000_fc_tx_pause;
>> +            hw_dbg("Flow Control = TX PAUSE frames only.\n");
>> +        }
>> +        /* For transmitting PAUSE frames ONLY.
>> +         *
>> +         *   LOCAL DEVICE  |   LINK PARTNER
>> +         * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
>> +         *-------|---------|-------|---------|--------------------
>> +         *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
>> +         */
>> +        else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
>> +             (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
>> +             !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
>> +             (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
>> +            hw->fc.current_mode = e1000_fc_rx_pause;
>> +            hw_dbg("Flow Control = RX PAUSE frames only.\n");
>> +        }
>> +        /* Per the IEEE spec, at this point flow control should be
>> +         * disabled.  However, we want to consider that we could
>> +         * be connected to a legacy switch that doesn't advertise
>> +         * desired flow control, but can be forced on the link
>> +         * partner.  So if we advertised no flow control, that is
>> +         * what we will resolve to.  If we advertised some kind of
>> +         * receive capability (Rx Pause Only or Full Flow Control)
>> +         * and the link partner advertised none, we will configure
>> +         * ourselves to enable Rx Flow Control only.  We can do
>> +         * this safely for two reasons:  If the link partner really
>> +         * didn't want flow control enabled, and we enable Rx, no
>> +         * harm done since we won't be receiving any PAUSE frames
>> +         * anyway.  If the intent on the link partner was to have
>> +         * flow control enabled, then by us enabling RX only, we
>> +         * can at least receive pause frames and process them.
>> +         * This is a good idea because in most cases, since we are
>> +         * predominantly a server NIC, more times than not we will
>> +         * be asked to delay transmission of packets than asking
>> +         * our link partner to pause transmission of frames.
>> +         */
>> +        else if ((hw->fc.requested_mode == e1000_fc_none) ||
>> +             (hw->fc.requested_mode == e1000_fc_tx_pause) ||
>> +             (hw->fc.strict_ieee)) {
>> +            hw->fc.current_mode = e1000_fc_none;
>> +            hw_dbg("Flow Control = NONE.\n");
>> +        } else {
>> +            hw->fc.current_mode = e1000_fc_rx_pause;
>> +            hw_dbg("Flow Control = RX PAUSE frames only.\n");
>> +        }
>> +
>> +        /* Now we need to do one last check...  If we auto-
>> +         * negotiated to HALF DUPLEX, flow control should not be
>> +         * enabled per IEEE 802.3 spec.
>> +         */
>> +        ret_val = hw->mac.ops.get_speed_and_duplex(hw, &speed, &duplex);
>> +        if (ret_val) {
>> +            hw_dbg("Error getting link speed and duplex\n");
>> +            goto out;
>> +        }
>> +
>> +        if (duplex == HALF_DUPLEX)
>> +            hw->fc.current_mode = e1000_fc_none;
>> +
>> +        /* Now we call a subroutine to actually force the MAC
>> +         * controller to use the correct flow control settings.
>> +         */
>> +        ret_val = igc_force_mac_fc(hw);
>> +        if (ret_val) {
>> +            hw_dbg("Error forcing flow control settings\n");
>> +            goto out;
>> +        }
>> +    }
>> +
>> +out:
>> +    return 0;
>> +}
>> +
>> +/**
>>    *  igc_get_auto_rd_done - Check for auto read completion
>>    *  @hw: pointer to the HW structure
>>    *
>> diff --git a/drivers/net/ethernet/intel/igc/e1000_mac.h 
>> b/drivers/net/ethernet/intel/igc/e1000_mac.h
>> index 0f17a8443125..0b32f21ce168 100644
>> --- a/drivers/net/ethernet/intel/igc/e1000_mac.h
>> +++ b/drivers/net/ethernet/intel/igc/e1000_mac.h
>> @@ -14,6 +14,8 @@
>>   /* forward declaration */
>>   s32 igc_check_for_copper_link(struct e1000_hw *hw);
>> +s32 igc_config_fc_after_link_up(struct e1000_hw *hw);
>> +s32 igc_force_mac_fc(struct e1000_hw *hw);
>>   s32 igc_disable_pcie_master(struct e1000_hw *hw);
>>   void igc_init_rx_addrs(struct e1000_hw *hw, u16 rar_count);
>> diff --git a/drivers/net/ethernet/intel/igc/e1000_phy.c 
>> b/drivers/net/ethernet/intel/igc/e1000_phy.c
>> index c95efc4145e8..4f130402225f 100644
>> --- a/drivers/net/ethernet/intel/igc/e1000_phy.c
>> +++ b/drivers/net/ethernet/intel/igc/e1000_phy.c
>> @@ -3,6 +3,10 @@
>>   #include "e1000_phy.h"
>> +/* forward declaration */
>> +static s32  igc_phy_setup_autoneg(struct e1000_hw *hw);
>> +static s32  igc_wait_autoneg(struct e1000_hw *hw);
>> +
>>   /**
>>    *  igc_check_reset_block - Check if PHY reset is blocked
>>    *  @hw: pointer to the HW structure
>> @@ -206,7 +210,333 @@ s32 igc_phy_hw_reset(struct e1000_hw *hw)
>>       phy->ops.release(hw);
>> -    ret_val = phy->ops.get_cfg_done(hw);
>> +out:
>> +    return ret_val;
>> +}
>> +
>> +/**
>> + *  igc_copper_link_autoneg - Setup/Enable autoneg for copper link
>> + *  @hw: pointer to the HW structure
>> + *
>> + *  Performs initial bounds checking on autoneg advertisement 
>> parameter, then
>> + *  configure to advertise the full capability.  Setup the PHY to 
>> autoneg
>> + *  and restart the negotiation process between the link partner.  If
>> + *  autoneg_wait_to_complete, then wait for autoneg to complete 
>> before exiting.
>> + **/
>> +static s32 igc_copper_link_autoneg(struct e1000_hw *hw)
>> +{
>> +    struct e1000_phy_info *phy = &hw->phy;
>> +    s32 ret_val;
>> +    u16 phy_ctrl;
>> +
>> +    /* Perform some bounds checking on the autoneg advertisement
>> +     * parameter.
>> +     */
>> +    phy->autoneg_advertised &= phy->autoneg_mask;
>> +
>> +    /* If autoneg_advertised is zero, we assume it was not defaulted
>> +     * by the calling code so we set to advertise full capability.
>> +     */
>> +    if (phy->autoneg_advertised == 0)
>> +        phy->autoneg_advertised = phy->autoneg_mask;
>> +
>> +    hw_dbg("Reconfiguring auto-neg advertisement params\n");
>> +    ret_val = igc_phy_setup_autoneg(hw);
>> +    if (ret_val) {
>> +        hw_dbg("Error Setting up Auto-Negotiation\n");
>> +        goto out;
>> +    }
>> +    hw_dbg("Restarting Auto-Neg\n");
>> +
>> +    /* Restart auto-negotiation by setting the Auto Neg Enable bit and
>> +     * the Auto Neg Restart bit in the PHY control register.
>> +     */
>> +    ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl);
>> +    if (ret_val)
>> +        goto out;
>> +
>> +    phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
>> +    ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl);
>> +    if (ret_val)
>> +        goto out;
>> +
>> +    /* Does the user want to wait for Auto-Neg to complete here, or
>> +     * check at a later time (for example, callback routine).
>> +     */
>> +    if (phy->autoneg_wait_to_complete) {
>> +        ret_val = igc_wait_autoneg(hw);
>> +        if (ret_val) {
>> +            hw_dbg("Error while waiting for autoneg to complete\n");
>> +            goto out;
>> +        }
>> +    }
>> +
>> +    hw->mac.get_link_status = true;
>> +
>> +out:
>> +    return ret_val;
>> +}
>> +
>> +/**
>> + *  igc_wait_autoneg - Wait for auto-neg completion
>> + *  @hw: pointer to the HW structure
>> + *
>> + *  Waits for auto-negotiation to complete or for the 
>> auto-negotiation time
>> + *  limit to expire, which ever happens first.
>> + **/
>> +static s32 igc_wait_autoneg(struct e1000_hw *hw)
>> +{
>> +    s32 ret_val = 0;
>> +    u16 i, phy_status;
>> +
>> +    /* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */
>> +    for (i = PHY_AUTO_NEG_LIMIT; i > 0; i--) {
>> +        ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
>> +        if (ret_val)
>> +            break;
>> +        ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
>> +        if (ret_val)
>> +            break;
>> +        if (phy_status & MII_SR_AUTONEG_COMPLETE)
>> +            break;
>> +        msleep(100);
>> +    }
>> +
>> +    /* PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation
>> +     * has completed.
>> +     */
> 
> Should you return an error value if the wait time expired?
> 
ret_val is returned. do you mean something else?
>> +    return ret_val;
>> +}
>> +
>> +/**
>> + *  igc_phy_setup_autoneg - Configure PHY for auto-negotiation
>> + *  @hw: pointer to the HW structure
>> + *
>> + *  Reads the MII auto-neg advertisement register and/or the 1000T 
>> control
>> + *  register and if the PHY is already setup for auto-negotiation, then
>> + *  return successful.  Otherwise, setup advertisement and flow 
>> control to
>> + *  the appropriate values for the wanted auto-negotiation.
>> + **/
>> +static s32 igc_phy_setup_autoneg(struct e1000_hw *hw)
>> +{
>> +    struct e1000_phy_info *phy = &hw->phy;
>> +    s32 ret_val;
>> +    u16 mii_autoneg_adv_reg;
>> +    u16 mii_1000t_ctrl_reg = 0;
>> +    u16 aneg_multigbt_an_ctrl = 0;
>> +
>> +    phy->autoneg_advertised &= phy->autoneg_mask;
>> +
>> +    /* Read the MII Auto-Neg Advertisement Register (Address 4). */
>> +    ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, 
>> &mii_autoneg_adv_reg);
>> +    if (ret_val)
>> +        return ret_val;
>> +
>> +    if (phy->autoneg_mask & ADVERTISE_1000_FULL) {
>> +        /* Read the MII 1000Base-T Control Register (Address 9). */
>> +        ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL,
>> +                        &mii_1000t_ctrl_reg);
>> +        if (ret_val)
>> +            return ret_val;
>> +    }
>> +
>> +    if ((phy->autoneg_mask & ADVERTISE_2500_FULL) &&
>> +        hw->phy.id == I225_I_PHY_ID) {
>> +        /* Read the MULTI GBT AN Control Register - reg 7.32 */
>> +        ret_val = phy->ops.read_reg(hw, (STANDARD_AN_REG_MASK <<
>> +                        MMD_DEVADDR_SHIFT) |
>> +                        ANEG_MULTIGBT_AN_CTRL,
>> +                        &aneg_multigbt_an_ctrl);
>> +
>> +        if (ret_val)
>> +            return ret_val;
>> +    }
>> +
>> +    /* Need to parse both autoneg_advertised and fc and set up
>> +     * the appropriate PHY registers.  First we will parse for
>> +     * autoneg_advertised software override.  Since we can advertise
>> +     * a plethora of combinations, we need to check each bit
>> +     * individually.
>> +     */
>> +
>> +    /* First we clear all the 10/100 mb speed bits in the Auto-Neg
>> +     * Advertisement Register (Address 4) and the 1000 mb speed bits in
>> +     * the  1000Base-T Control Register (Address 9).
>> +     */
>> +    mii_autoneg_adv_reg &= ~(NWAY_AR_100TX_FD_CAPS |
>> +                 NWAY_AR_100TX_HD_CAPS |
>> +                 NWAY_AR_10T_FD_CAPS   |
>> +                 NWAY_AR_10T_HD_CAPS);
>> +    mii_1000t_ctrl_reg &= ~(CR_1000T_HD_CAPS | CR_1000T_FD_CAPS);
>> +
>> +    hw_dbg("autoneg_advertised %x\n", phy->autoneg_advertised);
>> +
>> +    /* Do we want to advertise 10 Mb Half Duplex? */
>> +    if (phy->autoneg_advertised & ADVERTISE_10_HALF) {
>> +        hw_dbg("Advertise 10mb Half duplex\n");
>> +        mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS;
>> +    }
>> +
>> +    /* Do we want to advertise 10 Mb Full Duplex? */
>> +    if (phy->autoneg_advertised & ADVERTISE_10_FULL) {
>> +        hw_dbg("Advertise 10mb Full duplex\n");
>> +        mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS;
>> +    }
>> +
>> +    /* Do we want to advertise 100 Mb Half Duplex? */
>> +    if (phy->autoneg_advertised & ADVERTISE_100_HALF) {
>> +        hw_dbg("Advertise 100mb Half duplex\n");
>> +        mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS;
>> +    }
>> +
>> +    /* Do we want to advertise 100 Mb Full Duplex? */
>> +    if (phy->autoneg_advertised & ADVERTISE_100_FULL) {
>> +        hw_dbg("Advertise 100mb Full duplex\n");
>> +        mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS;
>> +    }
>> +
>> +    /* We do not allow the Phy to advertise 1000 Mb Half Duplex */
>> +    if (phy->autoneg_advertised & ADVERTISE_1000_HALF)
>> +        hw_dbg("Advertise 1000mb Half duplex request denied!\n");
>> +
>> +    /* Do we want to advertise 1000 Mb Full Duplex? */
>> +    if (phy->autoneg_advertised & ADVERTISE_1000_FULL) {
>> +        hw_dbg("Advertise 1000mb Full duplex\n");
>> +        mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
>> +    }
>> +
>> +    /* We do not allow the Phy to advertise 2500 Mb Half Duplex */
>> +    if (phy->autoneg_advertised & ADVERTISE_2500_HALF)
>> +        hw_dbg("Advertise 2500mb Half duplex request denied!\n");
>> +
>> +    /* Do we want to advertise 2500 Mb Full Duplex? */
>> +    if (phy->autoneg_advertised & ADVERTISE_2500_FULL) {
>> +        hw_dbg("Advertise 2500mb Full duplex\n");
>> +        aneg_multigbt_an_ctrl |= CR_2500T_FD_CAPS;
>> +    }
>> +
>> +    /* Check for a software override of the flow control settings, and
>> +     * setup the PHY advertisement registers accordingly.  If
>> +     * auto-negotiation is enabled, then software will have to set the
>> +     * "PAUSE" bits to the correct value in the Auto-Negotiation
>> +     * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto-
>> +     * negotiation.
>> +     *
>> +     * The possible values of the "fc" parameter are:
>> +     *      0:  Flow control is completely disabled
>> +     *      1:  Rx flow control is enabled (we can receive pause frames
>> +     *          but not send pause frames).
>> +     *      2:  Tx flow control is enabled (we can send pause frames
>> +     *          but we do not support receiving pause frames).
>> +     *      3:  Both Rx and Tx flow control (symmetric) are enabled.
>> +     *  other:  No software override.  The flow control configuration
>> +     *          in the EEPROM is used.
>> +     */
>> +    switch (hw->fc.current_mode) {
>> +    case e1000_fc_none:
>> +        /* Flow control (Rx & Tx) is completely disabled by a
>> +         * software over-ride.
>> +         */
>> +        mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
>> +        break;
>> +    case e1000_fc_rx_pause:
>> +        /* Rx Flow control is enabled, and Tx Flow control is
>> +         * disabled, by a software over-ride.
>> +         *
>> +         * Since there really isn't a way to advertise that we are
>> +         * capable of Rx Pause ONLY, we will advertise that we
>> +         * support both symmetric and asymmetric Rx PAUSE.  Later
>> +         * (in e1000_config_fc_after_link_up) we will disable the
>> +         * hw's ability to send PAUSE frames.
>> +         */
>> +        mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
>> +        break;
>> +    case e1000_fc_tx_pause:
>> +        /* Tx Flow control is enabled, and Rx Flow control is
>> +         * disabled, by a software over-ride.
>> +         */
>> +        mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;
>> +        mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;
>> +        break;
>> +    case e1000_fc_full:
>> +        /* Flow control (both Rx and Tx) is enabled by a software
>> +         * over-ride.
>> +         */
>> +        mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
>> +        break;
>> +    default:
>> +        hw_dbg("Flow control param set incorrectly\n");
>> +        return -E1000_ERR_CONFIG;
>> +    }
>> +
>> +    ret_val = phy->ops.write_reg(hw, PHY_AUTONEG_ADV, 
>> mii_autoneg_adv_reg);
>> +    if (ret_val)
>> +        return ret_val;
>> +
>> +    hw_dbg("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
>> +
>> +    if (phy->autoneg_mask & ADVERTISE_1000_FULL)
>> +        ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL,
>> +                         mii_1000t_ctrl_reg);
>> +
>> +    if ((phy->autoneg_mask & ADVERTISE_2500_FULL) &&
>> +        hw->phy.id == I225_I_PHY_ID)
>> +        ret_val = phy->ops.write_reg(hw,
>> +                         (STANDARD_AN_REG_MASK <<
>> +                         MMD_DEVADDR_SHIFT) |
>> +                         ANEG_MULTIGBT_AN_CTRL,
>> +                         aneg_multigbt_an_ctrl);
>> +
>> +    return ret_val;
>> +}
>> +
>> +/**
>> + *  igc_setup_copper_link - Configure copper link settings
>> + *  @hw: pointer to the HW structure
>> + *
>> + *  Calls the appropriate function to configure the link for auto-neg 
>> or forced
>> + *  speed and duplex.  Then we check for link, once link is 
>> established calls
>> + *  to configure collision distance and flow control are called.  If 
>> link is
>> + *  not established, we return -E1000_ERR_PHY (-2).
>> + **/
>> +s32 igc_setup_copper_link(struct e1000_hw *hw)
>> +{
>> +    s32 ret_val = 0;
>> +    bool link;
>> +
>> +    if (hw->mac.autoneg) {
>> +        /* Setup autoneg and flow control advertisement and perform
>> +         * autonegotiation.
>> +         */
>> +        ret_val = igc_copper_link_autoneg(hw);
>> +        if (ret_val)
>> +            goto out;
>> +    } else {
>> +        /* PHY will be set to 10H, 10F, 100H or 100F
>> +         * depending on user settings.
>> +         */
>> +        hw_dbg("Forcing Speed and Duplex\n");
>> +        ret_val = hw->phy.ops.force_speed_duplex(hw);
>> +        if (ret_val) {
>> +            hw_dbg("Error Forcing Speed and Duplex\n");
>> +            goto out;
>> +        }
>> +    }
>> +
>> +    /* Check link status. Wait up to 100 microseconds for link to become
>> +     * valid.
>> +     */
>> +    ret_val = igc_phy_has_link(hw, COPPER_LINK_UP_LIMIT, 10, &link);
>> +    if (ret_val)
>> +        goto out;
>> +
>> +    if (link) {
>> +        hw_dbg("Valid link established!!!\n");
>> +        igc_config_collision_dist(hw);
>> +        ret_val = igc_config_fc_after_link_up(hw);
>> +    } else {
>> +        hw_dbg("Unable to establish link!!!\n");
>> +    }
>>   out:
>>       return ret_val;
>> diff --git a/drivers/net/ethernet/intel/igc/e1000_phy.h 
>> b/drivers/net/ethernet/intel/igc/e1000_phy.h
>> index d04dfd0be7fd..3fddb1269ea2 100644
>> --- a/drivers/net/ethernet/intel/igc/e1000_phy.h
>> +++ b/drivers/net/ethernet/intel/igc/e1000_phy.h
>> @@ -12,6 +12,7 @@ s32  igc_get_phy_id(struct e1000_hw *hw);
>>   s32  igc_phy_has_link(struct e1000_hw *hw, u32 iterations,
>>                 u32 usec_interval, bool *success);
>>   s32 igc_check_downshift(struct e1000_hw *hw);
>> +s32 igc_setup_copper_link(struct e1000_hw *hw);
>>   void igc_power_up_phy_copper(struct e1000_hw *hw);
>>   void igc_power_down_phy_copper(struct e1000_hw *hw);
>> diff --git a/drivers/net/ethernet/intel/igc/igc.h 
>> b/drivers/net/ethernet/intel/igc/igc.h
>> index 91df0a14c3a5..99bc2344b7ff 100644
>> --- a/drivers/net/ethernet/intel/igc/igc.h
>> +++ b/drivers/net/ethernet/intel/igc/igc.h
>> @@ -320,6 +320,7 @@ struct igc_adapter {
>>       struct work_struct reset_task;
>>       struct work_struct watchdog_task;
>>       struct work_struct dma_err_task;
>> +    bool fc_autoneg;
>>       u8  tx_timeout_factor;
>> diff --git a/drivers/net/ethernet/intel/igc/igc_main.c 
>> b/drivers/net/ethernet/intel/igc/igc_main.c
>> index 21aed91454d4..563612910b3f 100644
>> --- a/drivers/net/ethernet/intel/igc/igc_main.c
>> +++ b/drivers/net/ethernet/intel/igc/igc_main.c
>> @@ -3194,7 +3194,6 @@ static int __igc_open(struct net_device *netdev, 
>> bool resuming)
>>       /* start the watchdog. */
>>       hw->mac.get_link_status = 1;
>> -    schedule_work(&adapter->watchdog_task);
>>       return E1000_SUCCESS;
>> @@ -3452,6 +3451,25 @@ static int igc_probe(struct pci_dev *pdev,
>>       netdev->min_mtu = ETH_MIN_MTU;
>>       netdev->max_mtu = MAX_STD_JUMBO_FRAME_SIZE;
>> +    /* before reading the NVM, reset the controller to put the device 
>> in a
>> +     * known good starting state
>> +     */
>> +    hw->mac.ops.reset_hw(hw);
>> +
>> +    if (eth_platform_get_mac_address(&pdev->dev, hw->mac.addr)) {
>> +        /* copy the MAC address out of the NVM */
>> +        if (hw->mac.ops.read_mac_addr(hw))
>> +            dev_err(&pdev->dev, "NVM Read Error\n");
>> +    }
>> +
>> +    memcpy(netdev->dev_addr, hw->mac.addr, netdev->addr_len);
>> +
>> +    if (!is_valid_ether_addr(netdev->dev_addr)) {
>> +        dev_err(&pdev->dev, "Invalid MAC Address\n");
>> +        err = -EIO;
>> +        goto err_eeprom;
>> +    }
>> +
>>       /* configure RXPBSIZE and TXPBSIZE */
>>       wr32(E1000_RXPBS, I225_RXPBSIZE_DEFAULT);
>>       wr32(E1000_TXPBS, I225_TXPBSIZE_DEFAULT);
>> @@ -3460,6 +3478,14 @@ static int igc_probe(struct pci_dev *pdev,
>>       INIT_WORK(&adapter->reset_task, igc_reset_task);
>> +    /* Initialize link properties that are user-changeable */
>> +    adapter->fc_autoneg = true;
>> +    hw->mac.autoneg = true;
>> +    hw->phy.autoneg_advertised = 0x2f;
>> +
>> +    hw->fc.requested_mode = e1000_fc_default;
>> +    hw->fc.current_mode = e1000_fc_default;
>> +
>>       /* reset the hardware with the new settings */
>>       igc_reset(adapter);
>> @@ -3496,6 +3522,12 @@ static int igc_probe(struct pci_dev *pdev,
>>   err_register:
>>       igc_release_hw_control(adapter);
>> +err_eeprom:
>> +    if (!igc_check_reset_block(hw))
>> +        igc_reset_phy(hw);
>> +
>> +    if (hw->flash_address)
>> +        iounmap(hw->flash_address);
>>   err_sw_init:
>>       igc_clear_interrupt_scheme(adapter);
>>       iounmap(adapter->io_addr);
>> @@ -3530,7 +3562,6 @@ static void igc_remove(struct pci_dev *pdev)
>>       del_timer_sync(&adapter->watchdog_timer);
>>       cancel_work_sync(&adapter->reset_task);
>> -    cancel_work_sync(&adapter->watchdog_task);
> 
> Why are you removing this?  Yes, I see that it got put back in patch 
> 11/11, but why take it out in the first place?
> 
Ah... my failure. fix will be applied in v4.
>>       /* Release control of h/w to f/w.  If f/w is AMT enabled, this
>>        * would have already happened in close and is redundant.
>>
Thanks for your comments.
Shannon Nelson July 9, 2018, 4:13 p.m. UTC | #3
On 7/4/2018 8:19 AM, Neftin, Sasha wrote:
> On 6/29/2018 18:03, Shannon Nelson wrote:
>> On 6/24/2018 1:45 AM, Sasha Neftin wrote:

[...]

>>> +/**
>>> + *  igc_wait_autoneg - Wait for auto-neg completion
>>> + *  @hw: pointer to the HW structure
>>> + *
>>> + *  Waits for auto-negotiation to complete or for the 
>>> auto-negotiation time
>>> + *  limit to expire, which ever happens first.
>>> + **/
>>> +static s32 igc_wait_autoneg(struct e1000_hw *hw)
>>> +{
>>> +    s32 ret_val = 0;
>>> +    u16 i, phy_status;
>>> +
>>> +    /* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */
>>> +    for (i = PHY_AUTO_NEG_LIMIT; i > 0; i--) {
>>> +        ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
>>> +        if (ret_val)
>>> +            break;
>>> +        ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
>>> +        if (ret_val)
>>> +            break;
>>> +        if (phy_status & MII_SR_AUTONEG_COMPLETE)
>>> +            break;
>>> +        msleep(100);
>>> +    }
>>> +
>>> +    /* PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation
>>> +     * has completed.
>>> +     */
>>
>> Should you return an error value if the wait time expired?
>>
> ret_val is returned. do you mean something else?

Should some non-zero value be returned if the for-loop ran out and 
MII_SR_AUTONEG_COMPLETE was never set?

sln
diff mbox series

Patch

diff --git a/drivers/net/ethernet/intel/igc/e1000_base.c b/drivers/net/ethernet/intel/igc/e1000_base.c
index 8b35e1d6c32e..6405506ff7b8 100644
--- a/drivers/net/ethernet/intel/igc/e1000_base.c
+++ b/drivers/net/ethernet/intel/igc/e1000_base.c
@@ -17,6 +17,7 @@  static void igc_release_phy_base(struct e1000_hw *);
 static s32 igc_get_phy_id_base(struct e1000_hw *);
 static s32 igc_init_hw_base(struct e1000_hw *);
 static s32 igc_reset_hw_base(struct e1000_hw *);
+static s32 igc_setup_copper_link_base(struct e1000_hw *);
 static s32 igc_set_pcie_completion_timeout(struct e1000_hw *hw);
 static s32 igc_read_mac_addr_base(struct e1000_hw *hw);
 
@@ -97,6 +98,9 @@  static s32 igc_init_mac_params_base(struct e1000_hw *hw)
 	if (mac->type == e1000_i225)
 		dev_spec->clear_semaphore_once = true;
 
+	/* physical interface link setup */
+	mac->ops.setup_physical_interface = igc_setup_copper_link_base;
+
 	return 0;
 }
 
@@ -139,6 +143,8 @@  static s32 igc_init_phy_params_base(struct e1000_hw *hw)
 	if (ret_val)
 		return ret_val;
 
+	igc_check_for_link_base(hw);
+
 	/* Verify phy id and set remaining function pointers */
 	switch (phy->id) {
 	case I225_I_PHY_ID:
@@ -155,10 +161,22 @@  static s32 igc_init_phy_params_base(struct e1000_hw *hw)
 
 static s32 igc_get_invariants_base(struct e1000_hw *hw)
 {
+	struct e1000_mac_info *mac = &hw->mac;
 	s32 ret_val = 0;
 	u32 ctrl_ext = 0;
 	u32 link_mode = 0;
 
+	switch (hw->device_id) {
+	case E1000_DEV_ID_I225_LM:
+	case E1000_DEV_ID_I225_V:
+		mac->type = e1000_i225;
+		break;
+	default:
+		return -E1000_ERR_MAC_INIT;
+	}
+
+	hw->phy.media_type = e1000_media_type_copper;
+
 	ctrl_ext = rd32(E1000_CTRL_EXT);
 	link_mode = ctrl_ext & E1000_CTRL_EXT_LINK_MODE_MASK;
 
@@ -289,6 +307,29 @@  static s32 igc_init_hw_base(struct e1000_hw *hw)
 }
 
 /**
+ *  igc_setup_copper_link_base - Configure copper link settings
+ *  @hw: pointer to the HW structure
+ *
+ *  Configures the link for auto-neg or forced speed and duplex.  Then we check
+ *  for link, once link is established calls to configure collision distance
+ *  and flow control are called.
+ **/
+static s32 igc_setup_copper_link_base(struct e1000_hw *hw)
+{
+	s32  ret_val = 0;
+	u32 ctrl;
+
+	ctrl = rd32(E1000_CTRL);
+	ctrl |= E1000_CTRL_SLU;
+	ctrl &= ~(E1000_CTRL_FRCSPD | E1000_CTRL_FRCDPX);
+	wr32(E1000_CTRL, ctrl);
+
+	ret_val = igc_setup_copper_link(hw);
+
+	return ret_val;
+}
+
+/**
  *  igc_read_mac_addr_base - Read device MAC address
  *  @hw: pointer to the HW structure
  **/
diff --git a/drivers/net/ethernet/intel/igc/e1000_defines.h b/drivers/net/ethernet/intel/igc/e1000_defines.h
index 40276ae76c9f..24c24c197d6b 100644
--- a/drivers/net/ethernet/intel/igc/e1000_defines.h
+++ b/drivers/net/ethernet/intel/igc/e1000_defines.h
@@ -33,6 +33,11 @@ 
 /* Physical Func Reset Done Indication */
 #define E1000_CTRL_EXT_LINK_MODE_MASK	0x00C00000
 
+/* Loop limit on how long we wait for auto-negotiation to complete */
+#define COPPER_LINK_UP_LIMIT		10
+#define PHY_AUTO_NEG_LIMIT		45
+#define PHY_FORCE_LIMIT			20
+
 /* Number of 100 microseconds we wait for PCI Express master disable */
 #define MASTER_DISABLE_TIMEOUT		800
 /*Blocks new Master requests */
@@ -74,6 +79,12 @@ 
 #define E1000_CTRL_RST		0x04000000  /* Global reset */
 
 #define E1000_CTRL_PHY_RST	0x80000000  /* PHY Reset */
+#define E1000_CTRL_SLU		0x00000040  /* Set link up (Force Link) */
+#define E1000_CTRL_FRCSPD	0x00000800  /* Force Speed */
+#define E1000_CTRL_FRCDPX	0x00001000  /* Force Duplex */
+
+#define E1000_CTRL_RFCE		0x08000000  /* Receive Flow Control enable */
+#define E1000_CTRL_TFCE		0x10000000  /* Transmit flow control enable */
 
 /* PBA constants */
 #define E1000_PBA_34K			0x0022
@@ -89,6 +100,40 @@ 
 #define E1000_SWFW_PHY2_SM	0x20
 #define E1000_SWFW_PHY3_SM	0x40
 
+/* PHY 1000 MII Register/Bit Definitions */
+/* PHY Registers defined by IEEE */
+#define PHY_CONTROL		0x00 /* Control Register */
+#define PHY_STATUS		0x01 /* Status Register */
+#define PHY_ID1			0x02 /* Phy Id Reg (word 1) */
+#define PHY_ID2			0x03 /* Phy Id Reg (word 2) */
+#define PHY_AUTONEG_ADV		0x04 /* Autoneg Advertisement */
+#define PHY_LP_ABILITY		0x05 /* Link Partner Ability (Base Page) */
+#define PHY_1000T_CTRL		0x09 /* 1000Base-T Control Reg */
+#define PHY_1000T_STATUS	0x0A /* 1000Base-T Status Reg */
+
+/* Autoneg Advertisement Register */
+#define NWAY_AR_10T_HD_CAPS	0x0020   /* 10T   Half Duplex Capable */
+#define NWAY_AR_10T_FD_CAPS	0x0040   /* 10T   Full Duplex Capable */
+#define NWAY_AR_100TX_HD_CAPS	0x0080   /* 100TX Half Duplex Capable */
+#define NWAY_AR_100TX_FD_CAPS	0x0100   /* 100TX Full Duplex Capable */
+#define NWAY_AR_PAUSE		0x0400   /* Pause operation desired */
+#define NWAY_AR_ASM_DIR		0x0800   /* Asymmetric Pause Direction bit */
+
+/* Link Partner Ability Register (Base Page) */
+#define NWAY_LPAR_PAUSE		0x0400 /* LP Pause operation desired */
+#define NWAY_LPAR_ASM_DIR	0x0800 /* LP Asymmetric Pause Direction bit */
+
+/* 1000BASE-T Control Register */
+#define CR_1000T_ASYM_PAUSE	0x0080 /* Advertise asymmetric pause bit */
+#define CR_1000T_HD_CAPS	0x0100 /* Advertise 1000T HD capability */
+#define CR_1000T_FD_CAPS	0x0200 /* Advertise 1000T FD capability  */
+
+/* PHY GPY 211 registers */
+#define STANDARD_AN_REG_MASK	0x0007 /* MMD */
+#define ANEG_MULTIGBT_AN_CTRL	0x0020 /* MULTI GBT AN Control Register */
+#define MMD_DEVADDR_SHIFT	16     /* Shift MMD to higher bits */
+#define CR_2500T_FD_CAPS	0x0080 /* Advertise 2500T FD capability */
+
 /* NVM Control */
 #define E1000_EECD_SK		0x00000001 /* NVM Clock */
 #define E1000_EECD_CS		0x00000002 /* NVM Chip Select */
diff --git a/drivers/net/ethernet/intel/igc/e1000_mac.c b/drivers/net/ethernet/intel/igc/e1000_mac.c
index fe483211f66f..3f60810adc19 100644
--- a/drivers/net/ethernet/intel/igc/e1000_mac.c
+++ b/drivers/net/ethernet/intel/igc/e1000_mac.c
@@ -141,6 +141,8 @@  s32 igc_setup_link(struct e1000_hw *hw)
 	/* In the case of the phy reset being blocked, we already have a link.
 	 * We do not need to set it up again.
 	 */
+	if (igc_check_reset_block(hw))
+		goto out;
 
 	/* If requested flow control is set to default, set flow control
 	 * based on the EEPROM flow control settings.
@@ -192,10 +194,74 @@  s32 igc_setup_link(struct e1000_hw *hw)
  **/
 static s32 igc_set_default_fc(struct e1000_hw *hw)
 {
+	hw->fc.requested_mode = e1000_fc_full;
 	return 0;
 }
 
 /**
+ *  igc_force_mac_fc - Force the MAC's flow control settings
+ *  @hw: pointer to the HW structure
+ *
+ *  Force the MAC's flow control settings.  Sets the TFCE and RFCE bits in the
+ *  device control register to reflect the adapter settings.  TFCE and RFCE
+ *  need to be explicitly set by software when a copper PHY is used because
+ *  autonegotiation is managed by the PHY rather than the MAC.  Software must
+ *  also configure these bits when link is forced on a fiber connection.
+ **/
+s32 igc_force_mac_fc(struct e1000_hw *hw)
+{
+	u32 ctrl;
+	s32 ret_val = 0;
+
+	ctrl = rd32(E1000_CTRL);
+
+	/* Because we didn't get link via the internal auto-negotiation
+	 * mechanism (we either forced link or we got link via PHY
+	 * auto-neg), we have to manually enable/disable transmit an
+	 * receive flow control.
+	 *
+	 * The "Case" statement below enables/disable flow control
+	 * according to the "hw->fc.current_mode" parameter.
+	 *
+	 * The possible values of the "fc" parameter are:
+	 *      0:  Flow control is completely disabled
+	 *      1:  Rx flow control is enabled (we can receive pause
+	 *          frames but not send pause frames).
+	 *      2:  Tx flow control is enabled (we can send pause frames
+	 *          frames but we do not receive pause frames).
+	 *      3:  Both Rx and TX flow control (symmetric) is enabled.
+	 *  other:  No other values should be possible at this point.
+	 */
+	hw_dbg("hw->fc.current_mode = %u\n", hw->fc.current_mode);
+
+	switch (hw->fc.current_mode) {
+	case e1000_fc_none:
+		ctrl &= (~(E1000_CTRL_TFCE | E1000_CTRL_RFCE));
+		break;
+	case e1000_fc_rx_pause:
+		ctrl &= (~E1000_CTRL_TFCE);
+		ctrl |= E1000_CTRL_RFCE;
+		break;
+	case e1000_fc_tx_pause:
+		ctrl &= (~E1000_CTRL_RFCE);
+		ctrl |= E1000_CTRL_TFCE;
+		break;
+	case e1000_fc_full:
+		ctrl |= (E1000_CTRL_TFCE | E1000_CTRL_RFCE);
+		break;
+	default:
+		hw_dbg("Flow control param set incorrectly\n");
+		ret_val = -E1000_ERR_CONFIG;
+		goto out;
+	}
+
+	wr32(E1000_CTRL, ctrl);
+
+out:
+	return ret_val;
+}
+
+/**
  *  igc_set_fc_watermarks - Set flow control high/low watermarks
  *  @hw: pointer to the HW structure
  *
@@ -423,7 +489,7 @@  s32 igc_check_for_copper_link(struct e1000_hw *hw)
 	 * settings because we may have had to re-autoneg with a
 	 * different link partner.
 	 */
-	/* TODO ret_val = igc_config_fc_after_link_up(hw); */
+	ret_val = igc_config_fc_after_link_up(hw);
 	if (ret_val)
 		hw_dbg("Error configuring flow control\n");
 
@@ -453,6 +519,210 @@  void igc_config_collision_dist(struct e1000_hw *hw)
 }
 
 /**
+ *  igc_config_fc_after_link_up - Configures flow control after link
+ *  @hw: pointer to the HW structure
+ *
+ *  Checks the status of auto-negotiation after link up to ensure that the
+ *  speed and duplex were not forced.  If the link needed to be forced, then
+ *  flow control needs to be forced also.  If auto-negotiation is enabled
+ *  and did not fail, then we configure flow control based on our link
+ *  partner.
+ **/
+s32 igc_config_fc_after_link_up(struct e1000_hw *hw)
+{
+	struct e1000_mac_info *mac = &hw->mac;
+	s32 ret_val = 0;
+	u16 mii_status_reg, mii_nway_adv_reg, mii_nway_lp_ability_reg;
+	u16 speed, duplex;
+
+	/* Check for the case where we have fiber media and auto-neg failed
+	 * so we had to force link.  In this case, we need to force the
+	 * configuration of the MAC to match the "fc" parameter.
+	 */
+	if (mac->autoneg_failed) {
+		if (hw->phy.media_type == e1000_media_type_copper)
+			ret_val = igc_force_mac_fc(hw);
+	}
+
+	if (ret_val) {
+		hw_dbg("Error forcing flow control settings\n");
+		goto out;
+	}
+
+	/* Check for the case where we have copper media and auto-neg is
+	 * enabled.  In this case, we need to check and see if Auto-Neg
+	 * has completed, and if so, how the PHY and link partner has
+	 * flow control configured.
+	 */
+	if (hw->phy.media_type == e1000_media_type_copper && mac->autoneg) {
+		/* Read the MII Status Register and check to see if AutoNeg
+		 * has completed.  We read this twice because this reg has
+		 * some "sticky" (latched) bits.
+		 */
+		ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS,
+					       &mii_status_reg);
+		if (ret_val)
+			goto out;
+		ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS,
+					       &mii_status_reg);
+		if (ret_val)
+			goto out;
+
+		if (!(mii_status_reg & MII_SR_AUTONEG_COMPLETE)) {
+			hw_dbg("Copper PHY and Auto Neg has not completed.\n");
+			goto out;
+		}
+
+		/* The AutoNeg process has completed, so we now need to
+		 * read both the Auto Negotiation Advertisement
+		 * Register (Address 4) and the Auto_Negotiation Base
+		 * Page Ability Register (Address 5) to determine how
+		 * flow control was negotiated.
+		 */
+		ret_val = hw->phy.ops.read_reg(hw, PHY_AUTONEG_ADV,
+					       &mii_nway_adv_reg);
+		if (ret_val)
+			goto out;
+		ret_val = hw->phy.ops.read_reg(hw, PHY_LP_ABILITY,
+					       &mii_nway_lp_ability_reg);
+		if (ret_val)
+			goto out;
+		/* Two bits in the Auto Negotiation Advertisement Register
+		 * (Address 4) and two bits in the Auto Negotiation Base
+		 * Page Ability Register (Address 5) determine flow control
+		 * for both the PHY and the link partner.  The following
+		 * table, taken out of the IEEE 802.3ab/D6.0 dated March 25,
+		 * 1999, describes these PAUSE resolution bits and how flow
+		 * control is determined based upon these settings.
+		 * NOTE:  DC = Don't Care
+		 *
+		 *   LOCAL DEVICE  |   LINK PARTNER
+		 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | NIC Resolution
+		 *-------|---------|-------|---------|--------------------
+		 *   0   |    0    |  DC   |   DC    | e1000_fc_none
+		 *   0   |    1    |   0   |   DC    | e1000_fc_none
+		 *   0   |    1    |   1   |    0    | e1000_fc_none
+		 *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
+		 *   1   |    0    |   0   |   DC    | e1000_fc_none
+		 *   1   |   DC    |   1   |   DC    | e1000_fc_full
+		 *   1   |    1    |   0   |    0    | e1000_fc_none
+		 *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
+		 *
+		 * Are both PAUSE bits set to 1?  If so, this implies
+		 * Symmetric Flow Control is enabled at both ends.  The
+		 * ASM_DIR bits are irrelevant per the spec.
+		 *
+		 * For Symmetric Flow Control:
+		 *
+		 *   LOCAL DEVICE  |   LINK PARTNER
+		 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+		 *-------|---------|-------|---------|--------------------
+		 *   1   |   DC    |   1   |   DC    | E1000_fc_full
+		 *
+		 */
+		if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
+		    (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE)) {
+			/* Now we need to check if the user selected RX ONLY
+			 * of pause frames.  In this case, we had to advertise
+			 * FULL flow control because we could not advertise RX
+			 * ONLY. Hence, we must now check to see if we need to
+			 * turn OFF  the TRANSMISSION of PAUSE frames.
+			 */
+			if (hw->fc.requested_mode == e1000_fc_full) {
+				hw->fc.current_mode = e1000_fc_full;
+				hw_dbg("Flow Control = FULL.\n");
+			} else {
+				hw->fc.current_mode = e1000_fc_rx_pause;
+				hw_dbg("Flow Control = RX PAUSE frames only.\n");
+			}
+		}
+
+		/* For receiving PAUSE frames ONLY.
+		 *
+		 *   LOCAL DEVICE  |   LINK PARTNER
+		 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+		 *-------|---------|-------|---------|--------------------
+		 *   0   |    1    |   1   |    1    | e1000_fc_tx_pause
+		 */
+		else if (!(mii_nway_adv_reg & NWAY_AR_PAUSE) &&
+			 (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
+			 (mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
+			 (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
+			hw->fc.current_mode = e1000_fc_tx_pause;
+			hw_dbg("Flow Control = TX PAUSE frames only.\n");
+		}
+		/* For transmitting PAUSE frames ONLY.
+		 *
+		 *   LOCAL DEVICE  |   LINK PARTNER
+		 * PAUSE | ASM_DIR | PAUSE | ASM_DIR | Result
+		 *-------|---------|-------|---------|--------------------
+		 *   1   |    1    |   0   |    1    | e1000_fc_rx_pause
+		 */
+		else if ((mii_nway_adv_reg & NWAY_AR_PAUSE) &&
+			 (mii_nway_adv_reg & NWAY_AR_ASM_DIR) &&
+			 !(mii_nway_lp_ability_reg & NWAY_LPAR_PAUSE) &&
+			 (mii_nway_lp_ability_reg & NWAY_LPAR_ASM_DIR)) {
+			hw->fc.current_mode = e1000_fc_rx_pause;
+			hw_dbg("Flow Control = RX PAUSE frames only.\n");
+		}
+		/* Per the IEEE spec, at this point flow control should be
+		 * disabled.  However, we want to consider that we could
+		 * be connected to a legacy switch that doesn't advertise
+		 * desired flow control, but can be forced on the link
+		 * partner.  So if we advertised no flow control, that is
+		 * what we will resolve to.  If we advertised some kind of
+		 * receive capability (Rx Pause Only or Full Flow Control)
+		 * and the link partner advertised none, we will configure
+		 * ourselves to enable Rx Flow Control only.  We can do
+		 * this safely for two reasons:  If the link partner really
+		 * didn't want flow control enabled, and we enable Rx, no
+		 * harm done since we won't be receiving any PAUSE frames
+		 * anyway.  If the intent on the link partner was to have
+		 * flow control enabled, then by us enabling RX only, we
+		 * can at least receive pause frames and process them.
+		 * This is a good idea because in most cases, since we are
+		 * predominantly a server NIC, more times than not we will
+		 * be asked to delay transmission of packets than asking
+		 * our link partner to pause transmission of frames.
+		 */
+		else if ((hw->fc.requested_mode == e1000_fc_none) ||
+			 (hw->fc.requested_mode == e1000_fc_tx_pause) ||
+			 (hw->fc.strict_ieee)) {
+			hw->fc.current_mode = e1000_fc_none;
+			hw_dbg("Flow Control = NONE.\n");
+		} else {
+			hw->fc.current_mode = e1000_fc_rx_pause;
+			hw_dbg("Flow Control = RX PAUSE frames only.\n");
+		}
+
+		/* Now we need to do one last check...  If we auto-
+		 * negotiated to HALF DUPLEX, flow control should not be
+		 * enabled per IEEE 802.3 spec.
+		 */
+		ret_val = hw->mac.ops.get_speed_and_duplex(hw, &speed, &duplex);
+		if (ret_val) {
+			hw_dbg("Error getting link speed and duplex\n");
+			goto out;
+		}
+
+		if (duplex == HALF_DUPLEX)
+			hw->fc.current_mode = e1000_fc_none;
+
+		/* Now we call a subroutine to actually force the MAC
+		 * controller to use the correct flow control settings.
+		 */
+		ret_val = igc_force_mac_fc(hw);
+		if (ret_val) {
+			hw_dbg("Error forcing flow control settings\n");
+			goto out;
+		}
+	}
+
+out:
+	return 0;
+}
+
+/**
  *  igc_get_auto_rd_done - Check for auto read completion
  *  @hw: pointer to the HW structure
  *
diff --git a/drivers/net/ethernet/intel/igc/e1000_mac.h b/drivers/net/ethernet/intel/igc/e1000_mac.h
index 0f17a8443125..0b32f21ce168 100644
--- a/drivers/net/ethernet/intel/igc/e1000_mac.h
+++ b/drivers/net/ethernet/intel/igc/e1000_mac.h
@@ -14,6 +14,8 @@ 
 
 /* forward declaration */
 s32 igc_check_for_copper_link(struct e1000_hw *hw);
+s32 igc_config_fc_after_link_up(struct e1000_hw *hw);
+s32 igc_force_mac_fc(struct e1000_hw *hw);
 
 s32 igc_disable_pcie_master(struct e1000_hw *hw);
 void igc_init_rx_addrs(struct e1000_hw *hw, u16 rar_count);
diff --git a/drivers/net/ethernet/intel/igc/e1000_phy.c b/drivers/net/ethernet/intel/igc/e1000_phy.c
index c95efc4145e8..4f130402225f 100644
--- a/drivers/net/ethernet/intel/igc/e1000_phy.c
+++ b/drivers/net/ethernet/intel/igc/e1000_phy.c
@@ -3,6 +3,10 @@ 
 
 #include "e1000_phy.h"
 
+/* forward declaration */
+static s32  igc_phy_setup_autoneg(struct e1000_hw *hw);
+static s32  igc_wait_autoneg(struct e1000_hw *hw);
+
 /**
  *  igc_check_reset_block - Check if PHY reset is blocked
  *  @hw: pointer to the HW structure
@@ -206,7 +210,333 @@  s32 igc_phy_hw_reset(struct e1000_hw *hw)
 
 	phy->ops.release(hw);
 
-	ret_val = phy->ops.get_cfg_done(hw);
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_copper_link_autoneg - Setup/Enable autoneg for copper link
+ *  @hw: pointer to the HW structure
+ *
+ *  Performs initial bounds checking on autoneg advertisement parameter, then
+ *  configure to advertise the full capability.  Setup the PHY to autoneg
+ *  and restart the negotiation process between the link partner.  If
+ *  autoneg_wait_to_complete, then wait for autoneg to complete before exiting.
+ **/
+static s32 igc_copper_link_autoneg(struct e1000_hw *hw)
+{
+	struct e1000_phy_info *phy = &hw->phy;
+	s32 ret_val;
+	u16 phy_ctrl;
+
+	/* Perform some bounds checking on the autoneg advertisement
+	 * parameter.
+	 */
+	phy->autoneg_advertised &= phy->autoneg_mask;
+
+	/* If autoneg_advertised is zero, we assume it was not defaulted
+	 * by the calling code so we set to advertise full capability.
+	 */
+	if (phy->autoneg_advertised == 0)
+		phy->autoneg_advertised = phy->autoneg_mask;
+
+	hw_dbg("Reconfiguring auto-neg advertisement params\n");
+	ret_val = igc_phy_setup_autoneg(hw);
+	if (ret_val) {
+		hw_dbg("Error Setting up Auto-Negotiation\n");
+		goto out;
+	}
+	hw_dbg("Restarting Auto-Neg\n");
+
+	/* Restart auto-negotiation by setting the Auto Neg Enable bit and
+	 * the Auto Neg Restart bit in the PHY control register.
+	 */
+	ret_val = phy->ops.read_reg(hw, PHY_CONTROL, &phy_ctrl);
+	if (ret_val)
+		goto out;
+
+	phy_ctrl |= (MII_CR_AUTO_NEG_EN | MII_CR_RESTART_AUTO_NEG);
+	ret_val = phy->ops.write_reg(hw, PHY_CONTROL, phy_ctrl);
+	if (ret_val)
+		goto out;
+
+	/* Does the user want to wait for Auto-Neg to complete here, or
+	 * check at a later time (for example, callback routine).
+	 */
+	if (phy->autoneg_wait_to_complete) {
+		ret_val = igc_wait_autoneg(hw);
+		if (ret_val) {
+			hw_dbg("Error while waiting for autoneg to complete\n");
+			goto out;
+		}
+	}
+
+	hw->mac.get_link_status = true;
+
+out:
+	return ret_val;
+}
+
+/**
+ *  igc_wait_autoneg - Wait for auto-neg completion
+ *  @hw: pointer to the HW structure
+ *
+ *  Waits for auto-negotiation to complete or for the auto-negotiation time
+ *  limit to expire, which ever happens first.
+ **/
+static s32 igc_wait_autoneg(struct e1000_hw *hw)
+{
+	s32 ret_val = 0;
+	u16 i, phy_status;
+
+	/* Break after autoneg completes or PHY_AUTO_NEG_LIMIT expires. */
+	for (i = PHY_AUTO_NEG_LIMIT; i > 0; i--) {
+		ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
+		if (ret_val)
+			break;
+		ret_val = hw->phy.ops.read_reg(hw, PHY_STATUS, &phy_status);
+		if (ret_val)
+			break;
+		if (phy_status & MII_SR_AUTONEG_COMPLETE)
+			break;
+		msleep(100);
+	}
+
+	/* PHY_AUTO_NEG_TIME expiration doesn't guarantee auto-negotiation
+	 * has completed.
+	 */
+	return ret_val;
+}
+
+/**
+ *  igc_phy_setup_autoneg - Configure PHY for auto-negotiation
+ *  @hw: pointer to the HW structure
+ *
+ *  Reads the MII auto-neg advertisement register and/or the 1000T control
+ *  register and if the PHY is already setup for auto-negotiation, then
+ *  return successful.  Otherwise, setup advertisement and flow control to
+ *  the appropriate values for the wanted auto-negotiation.
+ **/
+static s32 igc_phy_setup_autoneg(struct e1000_hw *hw)
+{
+	struct e1000_phy_info *phy = &hw->phy;
+	s32 ret_val;
+	u16 mii_autoneg_adv_reg;
+	u16 mii_1000t_ctrl_reg = 0;
+	u16 aneg_multigbt_an_ctrl = 0;
+
+	phy->autoneg_advertised &= phy->autoneg_mask;
+
+	/* Read the MII Auto-Neg Advertisement Register (Address 4). */
+	ret_val = phy->ops.read_reg(hw, PHY_AUTONEG_ADV, &mii_autoneg_adv_reg);
+	if (ret_val)
+		return ret_val;
+
+	if (phy->autoneg_mask & ADVERTISE_1000_FULL) {
+		/* Read the MII 1000Base-T Control Register (Address 9). */
+		ret_val = phy->ops.read_reg(hw, PHY_1000T_CTRL,
+					    &mii_1000t_ctrl_reg);
+		if (ret_val)
+			return ret_val;
+	}
+
+	if ((phy->autoneg_mask & ADVERTISE_2500_FULL) &&
+	    hw->phy.id == I225_I_PHY_ID) {
+		/* Read the MULTI GBT AN Control Register - reg 7.32 */
+		ret_val = phy->ops.read_reg(hw, (STANDARD_AN_REG_MASK <<
+					    MMD_DEVADDR_SHIFT) |
+					    ANEG_MULTIGBT_AN_CTRL,
+					    &aneg_multigbt_an_ctrl);
+
+		if (ret_val)
+			return ret_val;
+	}
+
+	/* Need to parse both autoneg_advertised and fc and set up
+	 * the appropriate PHY registers.  First we will parse for
+	 * autoneg_advertised software override.  Since we can advertise
+	 * a plethora of combinations, we need to check each bit
+	 * individually.
+	 */
+
+	/* First we clear all the 10/100 mb speed bits in the Auto-Neg
+	 * Advertisement Register (Address 4) and the 1000 mb speed bits in
+	 * the  1000Base-T Control Register (Address 9).
+	 */
+	mii_autoneg_adv_reg &= ~(NWAY_AR_100TX_FD_CAPS |
+				 NWAY_AR_100TX_HD_CAPS |
+				 NWAY_AR_10T_FD_CAPS   |
+				 NWAY_AR_10T_HD_CAPS);
+	mii_1000t_ctrl_reg &= ~(CR_1000T_HD_CAPS | CR_1000T_FD_CAPS);
+
+	hw_dbg("autoneg_advertised %x\n", phy->autoneg_advertised);
+
+	/* Do we want to advertise 10 Mb Half Duplex? */
+	if (phy->autoneg_advertised & ADVERTISE_10_HALF) {
+		hw_dbg("Advertise 10mb Half duplex\n");
+		mii_autoneg_adv_reg |= NWAY_AR_10T_HD_CAPS;
+	}
+
+	/* Do we want to advertise 10 Mb Full Duplex? */
+	if (phy->autoneg_advertised & ADVERTISE_10_FULL) {
+		hw_dbg("Advertise 10mb Full duplex\n");
+		mii_autoneg_adv_reg |= NWAY_AR_10T_FD_CAPS;
+	}
+
+	/* Do we want to advertise 100 Mb Half Duplex? */
+	if (phy->autoneg_advertised & ADVERTISE_100_HALF) {
+		hw_dbg("Advertise 100mb Half duplex\n");
+		mii_autoneg_adv_reg |= NWAY_AR_100TX_HD_CAPS;
+	}
+
+	/* Do we want to advertise 100 Mb Full Duplex? */
+	if (phy->autoneg_advertised & ADVERTISE_100_FULL) {
+		hw_dbg("Advertise 100mb Full duplex\n");
+		mii_autoneg_adv_reg |= NWAY_AR_100TX_FD_CAPS;
+	}
+
+	/* We do not allow the Phy to advertise 1000 Mb Half Duplex */
+	if (phy->autoneg_advertised & ADVERTISE_1000_HALF)
+		hw_dbg("Advertise 1000mb Half duplex request denied!\n");
+
+	/* Do we want to advertise 1000 Mb Full Duplex? */
+	if (phy->autoneg_advertised & ADVERTISE_1000_FULL) {
+		hw_dbg("Advertise 1000mb Full duplex\n");
+		mii_1000t_ctrl_reg |= CR_1000T_FD_CAPS;
+	}
+
+	/* We do not allow the Phy to advertise 2500 Mb Half Duplex */
+	if (phy->autoneg_advertised & ADVERTISE_2500_HALF)
+		hw_dbg("Advertise 2500mb Half duplex request denied!\n");
+
+	/* Do we want to advertise 2500 Mb Full Duplex? */
+	if (phy->autoneg_advertised & ADVERTISE_2500_FULL) {
+		hw_dbg("Advertise 2500mb Full duplex\n");
+		aneg_multigbt_an_ctrl |= CR_2500T_FD_CAPS;
+	}
+
+	/* Check for a software override of the flow control settings, and
+	 * setup the PHY advertisement registers accordingly.  If
+	 * auto-negotiation is enabled, then software will have to set the
+	 * "PAUSE" bits to the correct value in the Auto-Negotiation
+	 * Advertisement Register (PHY_AUTONEG_ADV) and re-start auto-
+	 * negotiation.
+	 *
+	 * The possible values of the "fc" parameter are:
+	 *      0:  Flow control is completely disabled
+	 *      1:  Rx flow control is enabled (we can receive pause frames
+	 *          but not send pause frames).
+	 *      2:  Tx flow control is enabled (we can send pause frames
+	 *          but we do not support receiving pause frames).
+	 *      3:  Both Rx and Tx flow control (symmetric) are enabled.
+	 *  other:  No software override.  The flow control configuration
+	 *          in the EEPROM is used.
+	 */
+	switch (hw->fc.current_mode) {
+	case e1000_fc_none:
+		/* Flow control (Rx & Tx) is completely disabled by a
+		 * software over-ride.
+		 */
+		mii_autoneg_adv_reg &= ~(NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
+		break;
+	case e1000_fc_rx_pause:
+		/* Rx Flow control is enabled, and Tx Flow control is
+		 * disabled, by a software over-ride.
+		 *
+		 * Since there really isn't a way to advertise that we are
+		 * capable of Rx Pause ONLY, we will advertise that we
+		 * support both symmetric and asymmetric Rx PAUSE.  Later
+		 * (in e1000_config_fc_after_link_up) we will disable the
+		 * hw's ability to send PAUSE frames.
+		 */
+		mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
+		break;
+	case e1000_fc_tx_pause:
+		/* Tx Flow control is enabled, and Rx Flow control is
+		 * disabled, by a software over-ride.
+		 */
+		mii_autoneg_adv_reg |= NWAY_AR_ASM_DIR;
+		mii_autoneg_adv_reg &= ~NWAY_AR_PAUSE;
+		break;
+	case e1000_fc_full:
+		/* Flow control (both Rx and Tx) is enabled by a software
+		 * over-ride.
+		 */
+		mii_autoneg_adv_reg |= (NWAY_AR_ASM_DIR | NWAY_AR_PAUSE);
+		break;
+	default:
+		hw_dbg("Flow control param set incorrectly\n");
+		return -E1000_ERR_CONFIG;
+	}
+
+	ret_val = phy->ops.write_reg(hw, PHY_AUTONEG_ADV, mii_autoneg_adv_reg);
+	if (ret_val)
+		return ret_val;
+
+	hw_dbg("Auto-Neg Advertising %x\n", mii_autoneg_adv_reg);
+
+	if (phy->autoneg_mask & ADVERTISE_1000_FULL)
+		ret_val = phy->ops.write_reg(hw, PHY_1000T_CTRL,
+					     mii_1000t_ctrl_reg);
+
+	if ((phy->autoneg_mask & ADVERTISE_2500_FULL) &&
+	    hw->phy.id == I225_I_PHY_ID)
+		ret_val = phy->ops.write_reg(hw,
+					     (STANDARD_AN_REG_MASK <<
+					     MMD_DEVADDR_SHIFT) |
+					     ANEG_MULTIGBT_AN_CTRL,
+					     aneg_multigbt_an_ctrl);
+
+	return ret_val;
+}
+
+/**
+ *  igc_setup_copper_link - Configure copper link settings
+ *  @hw: pointer to the HW structure
+ *
+ *  Calls the appropriate function to configure the link for auto-neg or forced
+ *  speed and duplex.  Then we check for link, once link is established calls
+ *  to configure collision distance and flow control are called.  If link is
+ *  not established, we return -E1000_ERR_PHY (-2).
+ **/
+s32 igc_setup_copper_link(struct e1000_hw *hw)
+{
+	s32 ret_val = 0;
+	bool link;
+
+	if (hw->mac.autoneg) {
+		/* Setup autoneg and flow control advertisement and perform
+		 * autonegotiation.
+		 */
+		ret_val = igc_copper_link_autoneg(hw);
+		if (ret_val)
+			goto out;
+	} else {
+		/* PHY will be set to 10H, 10F, 100H or 100F
+		 * depending on user settings.
+		 */
+		hw_dbg("Forcing Speed and Duplex\n");
+		ret_val = hw->phy.ops.force_speed_duplex(hw);
+		if (ret_val) {
+			hw_dbg("Error Forcing Speed and Duplex\n");
+			goto out;
+		}
+	}
+
+	/* Check link status. Wait up to 100 microseconds for link to become
+	 * valid.
+	 */
+	ret_val = igc_phy_has_link(hw, COPPER_LINK_UP_LIMIT, 10, &link);
+	if (ret_val)
+		goto out;
+
+	if (link) {
+		hw_dbg("Valid link established!!!\n");
+		igc_config_collision_dist(hw);
+		ret_val = igc_config_fc_after_link_up(hw);
+	} else {
+		hw_dbg("Unable to establish link!!!\n");
+	}
 
 out:
 	return ret_val;
diff --git a/drivers/net/ethernet/intel/igc/e1000_phy.h b/drivers/net/ethernet/intel/igc/e1000_phy.h
index d04dfd0be7fd..3fddb1269ea2 100644
--- a/drivers/net/ethernet/intel/igc/e1000_phy.h
+++ b/drivers/net/ethernet/intel/igc/e1000_phy.h
@@ -12,6 +12,7 @@  s32  igc_get_phy_id(struct e1000_hw *hw);
 s32  igc_phy_has_link(struct e1000_hw *hw, u32 iterations,
 		      u32 usec_interval, bool *success);
 s32 igc_check_downshift(struct e1000_hw *hw);
+s32 igc_setup_copper_link(struct e1000_hw *hw);
 void igc_power_up_phy_copper(struct e1000_hw *hw);
 void igc_power_down_phy_copper(struct e1000_hw *hw);
 
diff --git a/drivers/net/ethernet/intel/igc/igc.h b/drivers/net/ethernet/intel/igc/igc.h
index 91df0a14c3a5..99bc2344b7ff 100644
--- a/drivers/net/ethernet/intel/igc/igc.h
+++ b/drivers/net/ethernet/intel/igc/igc.h
@@ -320,6 +320,7 @@  struct igc_adapter {
 	struct work_struct reset_task;
 	struct work_struct watchdog_task;
 	struct work_struct dma_err_task;
+	bool fc_autoneg;
 
 	u8  tx_timeout_factor;
 
diff --git a/drivers/net/ethernet/intel/igc/igc_main.c b/drivers/net/ethernet/intel/igc/igc_main.c
index 21aed91454d4..563612910b3f 100644
--- a/drivers/net/ethernet/intel/igc/igc_main.c
+++ b/drivers/net/ethernet/intel/igc/igc_main.c
@@ -3194,7 +3194,6 @@  static int __igc_open(struct net_device *netdev, bool resuming)
 
 	/* start the watchdog. */
 	hw->mac.get_link_status = 1;
-	schedule_work(&adapter->watchdog_task);
 
 	return E1000_SUCCESS;
 
@@ -3452,6 +3451,25 @@  static int igc_probe(struct pci_dev *pdev,
 	netdev->min_mtu = ETH_MIN_MTU;
 	netdev->max_mtu = MAX_STD_JUMBO_FRAME_SIZE;
 
+	/* before reading the NVM, reset the controller to put the device in a
+	 * known good starting state
+	 */
+	hw->mac.ops.reset_hw(hw);
+
+	if (eth_platform_get_mac_address(&pdev->dev, hw->mac.addr)) {
+		/* copy the MAC address out of the NVM */
+		if (hw->mac.ops.read_mac_addr(hw))
+			dev_err(&pdev->dev, "NVM Read Error\n");
+	}
+
+	memcpy(netdev->dev_addr, hw->mac.addr, netdev->addr_len);
+
+	if (!is_valid_ether_addr(netdev->dev_addr)) {
+		dev_err(&pdev->dev, "Invalid MAC Address\n");
+		err = -EIO;
+		goto err_eeprom;
+	}
+
 	/* configure RXPBSIZE and TXPBSIZE */
 	wr32(E1000_RXPBS, I225_RXPBSIZE_DEFAULT);
 	wr32(E1000_TXPBS, I225_TXPBSIZE_DEFAULT);
@@ -3460,6 +3478,14 @@  static int igc_probe(struct pci_dev *pdev,
 
 	INIT_WORK(&adapter->reset_task, igc_reset_task);
 
+	/* Initialize link properties that are user-changeable */
+	adapter->fc_autoneg = true;
+	hw->mac.autoneg = true;
+	hw->phy.autoneg_advertised = 0x2f;
+
+	hw->fc.requested_mode = e1000_fc_default;
+	hw->fc.current_mode = e1000_fc_default;
+
 	/* reset the hardware with the new settings */
 	igc_reset(adapter);
 
@@ -3496,6 +3522,12 @@  static int igc_probe(struct pci_dev *pdev,
 
 err_register:
 	igc_release_hw_control(adapter);
+err_eeprom:
+	if (!igc_check_reset_block(hw))
+		igc_reset_phy(hw);
+
+	if (hw->flash_address)
+		iounmap(hw->flash_address);
 err_sw_init:
 	igc_clear_interrupt_scheme(adapter);
 	iounmap(adapter->io_addr);
@@ -3530,7 +3562,6 @@  static void igc_remove(struct pci_dev *pdev)
 	del_timer_sync(&adapter->watchdog_timer);
 
 	cancel_work_sync(&adapter->reset_task);
-	cancel_work_sync(&adapter->watchdog_task);
 
 	/* Release control of h/w to f/w.  If f/w is AMT enabled, this
 	 * would have already happened in close and is redundant.