diff options
Diffstat (limited to 'drivers/net/ethernet/intel/e1000e/ich8lan.c')
| -rw-r--r-- | drivers/net/ethernet/intel/e1000e/ich8lan.c | 571 | 
1 files changed, 466 insertions, 105 deletions
diff --git a/drivers/net/ethernet/intel/e1000e/ich8lan.c b/drivers/net/ethernet/intel/e1000e/ich8lan.c index af08188d7e6..8894ab8ed6b 100644 --- a/drivers/net/ethernet/intel/e1000e/ich8lan.c +++ b/drivers/net/ethernet/intel/e1000e/ich8lan.c @@ -1,30 +1,23 @@ -/******************************************************************************* - -  Intel PRO/1000 Linux driver -  Copyright(c) 1999 - 2013 Intel Corporation. - -  This program is free software; you can redistribute it and/or modify it -  under the terms and conditions of the GNU General Public License, -  version 2, as published by the Free Software Foundation. - -  This program is distributed in the hope it will be useful, but WITHOUT -  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for -  more details. - -  You should have received a copy of the GNU General Public License along with -  this program; if not, write to the Free Software Foundation, Inc., -  51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - -  The full GNU General Public License is included in this distribution in -  the file called "COPYING". - -  Contact Information: -  Linux NICS <linux.nics@intel.com> -  e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> -  Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 - -*******************************************************************************/ +/* Intel PRO/1000 Linux driver + * Copyright(c) 1999 - 2014 Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for + * more details. + * + * The full GNU General Public License is included in this distribution in + * the file called "COPYING". + * + * Contact Information: + * Linux NICS <linux.nics@intel.com> + * e1000-devel Mailing List <e1000-devel@lists.sourceforge.net> + * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497 + */  /* 82562G 10/100 Network Connection   * 82562G-2 10/100 Network Connection @@ -53,6 +46,14 @@   * 82578DC Gigabit Network Connection   * 82579LM Gigabit Network Connection   * 82579V Gigabit Network Connection + * Ethernet Connection I217-LM + * Ethernet Connection I217-V + * Ethernet Connection I218-V + * Ethernet Connection I218-LM + * Ethernet Connection (2) I218-LM + * Ethernet Connection (2) I218-V + * Ethernet Connection (3) I218-LM + * Ethernet Connection (3) I218-V   */  #include "e1000.h" @@ -138,11 +139,14 @@ static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link);  static s32 e1000_set_mdio_slow_mode_hv(struct e1000_hw *hw);  static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw);  static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw); -static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index); -static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index); +static int e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index); +static int e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index); +static u32 e1000_rar_get_count_pch_lpt(struct e1000_hw *hw);  static s32 e1000_k1_workaround_lv(struct e1000_hw *hw);  static void e1000_gate_hw_phy_config_ich8lan(struct e1000_hw *hw, bool gate); +static s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force);  static s32 e1000_setup_copper_link_pch_lpt(struct e1000_hw *hw); +static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state);  static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg)  { @@ -183,7 +187,7 @@ static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw)  {  	u16 phy_reg = 0;  	u32 phy_id = 0; -	s32 ret_val; +	s32 ret_val = 0;  	u16 retry_count;  	u32 mac_reg = 0; @@ -214,11 +218,13 @@ static bool e1000_phy_is_accessible_pchlan(struct e1000_hw *hw)  	/* In case the PHY needs to be in mdio slow mode,  	 * set slow mode and try to get the PHY id again.  	 */ -	hw->phy.ops.release(hw); -	ret_val = e1000_set_mdio_slow_mode_hv(hw); -	if (!ret_val) -		ret_val = e1000e_get_phy_id(hw); -	hw->phy.ops.acquire(hw); +	if (hw->mac.type < e1000_pch_lpt) { +		hw->phy.ops.release(hw); +		ret_val = e1000_set_mdio_slow_mode_hv(hw); +		if (!ret_val) +			ret_val = e1000e_get_phy_id(hw); +		hw->phy.ops.acquire(hw); +	}  	if (ret_val)  		return false; @@ -239,6 +245,47 @@ out:  }  /** + *  e1000_toggle_lanphypc_pch_lpt - toggle the LANPHYPC pin value + *  @hw: pointer to the HW structure + * + *  Toggling the LANPHYPC pin value fully power-cycles the PHY and is + *  used to reset the PHY to a quiescent state when necessary. + **/ +static void e1000_toggle_lanphypc_pch_lpt(struct e1000_hw *hw) +{ +	u32 mac_reg; + +	/* Set Phy Config Counter to 50msec */ +	mac_reg = er32(FEXTNVM3); +	mac_reg &= ~E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK; +	mac_reg |= E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC; +	ew32(FEXTNVM3, mac_reg); + +	/* Toggle LANPHYPC Value bit */ +	mac_reg = er32(CTRL); +	mac_reg |= E1000_CTRL_LANPHYPC_OVERRIDE; +	mac_reg &= ~E1000_CTRL_LANPHYPC_VALUE; +	ew32(CTRL, mac_reg); +	e1e_flush(); +	usleep_range(10, 20); +	mac_reg &= ~E1000_CTRL_LANPHYPC_OVERRIDE; +	ew32(CTRL, mac_reg); +	e1e_flush(); + +	if (hw->mac.type < e1000_pch_lpt) { +		msleep(50); +	} else { +		u16 count = 20; + +		do { +			usleep_range(5000, 10000); +		} while (!(er32(CTRL_EXT) & E1000_CTRL_EXT_LPCD) && count--); + +		msleep(30); +	} +} + +/**   *  e1000_init_phy_workarounds_pchlan - PHY initialization workarounds   *  @hw: pointer to the HW structure   * @@ -247,6 +294,7 @@ out:   **/  static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)  { +	struct e1000_adapter *adapter = hw->adapter;  	u32 mac_reg, fwsm = er32(FWSM);  	s32 ret_val; @@ -255,6 +303,12 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)  	 */  	e1000_gate_hw_phy_config_ich8lan(hw, true); +	/* It is not possible to be certain of the current state of ULP +	 * so forcibly disable it. +	 */ +	hw->dev_spec.ich8lan.ulp_state = e1000_ulp_state_unknown; +	e1000_disable_ulp_lpt_lp(hw, true); +  	ret_val = hw->phy.ops.acquire(hw);  	if (ret_val) {  		e_dbg("Failed to initialize PHY flow\n"); @@ -300,33 +354,9 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)  			break;  		} -		e_dbg("Toggling LANPHYPC\n"); - -		/* Set Phy Config Counter to 50msec */ -		mac_reg = er32(FEXTNVM3); -		mac_reg &= ~E1000_FEXTNVM3_PHY_CFG_COUNTER_MASK; -		mac_reg |= E1000_FEXTNVM3_PHY_CFG_COUNTER_50MSEC; -		ew32(FEXTNVM3, mac_reg); -  		/* Toggle LANPHYPC Value bit */ -		mac_reg = er32(CTRL); -		mac_reg |= E1000_CTRL_LANPHYPC_OVERRIDE; -		mac_reg &= ~E1000_CTRL_LANPHYPC_VALUE; -		ew32(CTRL, mac_reg); -		e1e_flush(); -		usleep_range(10, 20); -		mac_reg &= ~E1000_CTRL_LANPHYPC_OVERRIDE; -		ew32(CTRL, mac_reg); -		e1e_flush(); -		if (hw->mac.type < e1000_pch_lpt) { -			msleep(50); -		} else { -			u16 count = 20; -			do { -				usleep_range(5000, 10000); -			} while (!(er32(CTRL_EXT) & -				   E1000_CTRL_EXT_LPCD) && count--); -			usleep_range(30000, 60000); +		e1000_toggle_lanphypc_pch_lpt(hw); +		if (hw->mac.type >= e1000_pch_lpt) {  			if (e1000_phy_is_accessible_pchlan(hw))  				break; @@ -349,12 +379,31 @@ static s32 e1000_init_phy_workarounds_pchlan(struct e1000_hw *hw)  	hw->phy.ops.release(hw);  	if (!ret_val) { + +		/* Check to see if able to reset PHY.  Print error if not */ +		if (hw->phy.ops.check_reset_block(hw)) { +			e_err("Reset blocked by ME\n"); +			goto out; +		} +  		/* Reset the PHY before any access to it.  Doing so, ensures  		 * that the PHY is in a known good state before we read/write  		 * PHY registers.  The generic reset is sufficient here,  		 * because we haven't determined the PHY type yet.  		 */  		ret_val = e1000e_phy_hw_reset_generic(hw); +		if (ret_val) +			goto out; + +		/* On a successful reset, possibly need to wait for the PHY +		 * to quiesce to an accessible state before returning control +		 * to the calling function.  If the PHY does not quiesce, then +		 * return E1000E_BLK_PHY_RESET, as this is the condition that +		 *  the PHY is in. +		 */ +		ret_val = hw->phy.ops.check_reset_block(hw); +		if (ret_val) +			e_err("ME blocked access to PHY after reset\n");  	}  out: @@ -656,6 +705,7 @@ static s32 e1000_init_mac_params_ich8lan(struct e1000_hw *hw)  		mac->ops.rar_set = e1000_rar_set_pch_lpt;  		mac->ops.setup_physical_interface =  		    e1000_setup_copper_link_pch_lpt; +		mac->ops.rar_get_count = e1000_rar_get_count_pch_lpt;  	}  	/* Enable PCS Lock-loss workaround for ICH8 */ @@ -724,8 +774,14 @@ s32 e1000_write_emi_reg_locked(struct e1000_hw *hw, u16 addr, u16 data)   *  Enable/disable EEE based on setting in dev_spec structure, the duplex of   *  the link and the EEE capabilities of the link partner.  The LPI Control   *  register bits will remain set only if/when link is up. + * + *  EEE LPI must not be asserted earlier than one second after link is up. + *  On 82579, EEE LPI should not be enabled until such time otherwise there + *  can be link issues with some switches.  Other devices can have EEE LPI + *  enabled immediately upon link up since they have a timer in hardware which + *  prevents LPI from being asserted too early.   **/ -static s32 e1000_set_eee_pchlan(struct e1000_hw *hw) +s32 e1000_set_eee_pchlan(struct e1000_hw *hw)  {  	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;  	s32 ret_val; @@ -790,6 +846,17 @@ static s32 e1000_set_eee_pchlan(struct e1000_hw *hw)  		}  	} +	if (hw->phy.type == e1000_phy_82579) { +		ret_val = e1000_read_emi_reg_locked(hw, I82579_LPI_PLL_SHUT, +						    &data); +		if (ret_val) +			goto release; + +		data &= ~I82579_LPI_100_PLL_SHUT; +		ret_val = e1000_write_emi_reg_locked(hw, I82579_LPI_PLL_SHUT, +						     data); +	} +  	/* R/Clr IEEE MMD 3.1 bits 11:10 - Tx/Rx LPI Received */  	ret_val = e1000_read_emi_reg_locked(hw, pcs_status, &data);  	if (ret_val) @@ -979,6 +1046,253 @@ static s32 e1000_platform_pm_pch_lpt(struct e1000_hw *hw, bool link)  }  /** + *  e1000_enable_ulp_lpt_lp - configure Ultra Low Power mode for LynxPoint-LP + *  @hw: pointer to the HW structure + *  @to_sx: boolean indicating a system power state transition to Sx + * + *  When link is down, configure ULP mode to significantly reduce the power + *  to the PHY.  If on a Manageability Engine (ME) enabled system, tell the + *  ME firmware to start the ULP configuration.  If not on an ME enabled + *  system, configure the ULP mode by software. + */ +s32 e1000_enable_ulp_lpt_lp(struct e1000_hw *hw, bool to_sx) +{ +	u32 mac_reg; +	s32 ret_val = 0; +	u16 phy_reg; + +	if ((hw->mac.type < e1000_pch_lpt) || +	    (hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPT_I217_LM) || +	    (hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPT_I217_V) || +	    (hw->adapter->pdev->device == E1000_DEV_ID_PCH_I218_LM2) || +	    (hw->adapter->pdev->device == E1000_DEV_ID_PCH_I218_V2) || +	    (hw->dev_spec.ich8lan.ulp_state == e1000_ulp_state_on)) +		return 0; + +	if (er32(FWSM) & E1000_ICH_FWSM_FW_VALID) { +		/* Request ME configure ULP mode in the PHY */ +		mac_reg = er32(H2ME); +		mac_reg |= E1000_H2ME_ULP | E1000_H2ME_ENFORCE_SETTINGS; +		ew32(H2ME, mac_reg); + +		goto out; +	} + +	if (!to_sx) { +		int i = 0; + +		/* Poll up to 5 seconds for Cable Disconnected indication */ +		while (!(er32(FEXT) & E1000_FEXT_PHY_CABLE_DISCONNECTED)) { +			/* Bail if link is re-acquired */ +			if (er32(STATUS) & E1000_STATUS_LU) +				return -E1000_ERR_PHY; + +			if (i++ == 100) +				break; + +			msleep(50); +		} +		e_dbg("CABLE_DISCONNECTED %s set after %dmsec\n", +		      (er32(FEXT) & +		       E1000_FEXT_PHY_CABLE_DISCONNECTED) ? "" : "not", i * 50); +	} + +	ret_val = hw->phy.ops.acquire(hw); +	if (ret_val) +		goto out; + +	/* Force SMBus mode in PHY */ +	ret_val = e1000_read_phy_reg_hv_locked(hw, CV_SMB_CTRL, &phy_reg); +	if (ret_val) +		goto release; +	phy_reg |= CV_SMB_CTRL_FORCE_SMBUS; +	e1000_write_phy_reg_hv_locked(hw, CV_SMB_CTRL, phy_reg); + +	/* Force SMBus mode in MAC */ +	mac_reg = er32(CTRL_EXT); +	mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS; +	ew32(CTRL_EXT, mac_reg); + +	/* Set Inband ULP Exit, Reset to SMBus mode and +	 * Disable SMBus Release on PERST# in PHY +	 */ +	ret_val = e1000_read_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, &phy_reg); +	if (ret_val) +		goto release; +	phy_reg |= (I218_ULP_CONFIG1_RESET_TO_SMBUS | +		    I218_ULP_CONFIG1_DISABLE_SMB_PERST); +	if (to_sx) { +		if (er32(WUFC) & E1000_WUFC_LNKC) +			phy_reg |= I218_ULP_CONFIG1_WOL_HOST; + +		phy_reg |= I218_ULP_CONFIG1_STICKY_ULP; +	} else { +		phy_reg |= I218_ULP_CONFIG1_INBAND_EXIT; +	} +	e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); + +	/* Set Disable SMBus Release on PERST# in MAC */ +	mac_reg = er32(FEXTNVM7); +	mac_reg |= E1000_FEXTNVM7_DISABLE_SMB_PERST; +	ew32(FEXTNVM7, mac_reg); + +	/* Commit ULP changes in PHY by starting auto ULP configuration */ +	phy_reg |= I218_ULP_CONFIG1_START; +	e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); +release: +	hw->phy.ops.release(hw); +out: +	if (ret_val) +		e_dbg("Error in ULP enable flow: %d\n", ret_val); +	else +		hw->dev_spec.ich8lan.ulp_state = e1000_ulp_state_on; + +	return ret_val; +} + +/** + *  e1000_disable_ulp_lpt_lp - unconfigure Ultra Low Power mode for LynxPoint-LP + *  @hw: pointer to the HW structure + *  @force: boolean indicating whether or not to force disabling ULP + * + *  Un-configure ULP mode when link is up, the system is transitioned from + *  Sx or the driver is unloaded.  If on a Manageability Engine (ME) enabled + *  system, poll for an indication from ME that ULP has been un-configured. + *  If not on an ME enabled system, un-configure the ULP mode by software. + * + *  During nominal operation, this function is called when link is acquired + *  to disable ULP mode (force=false); otherwise, for example when unloading + *  the driver or during Sx->S0 transitions, this is called with force=true + *  to forcibly disable ULP. + */ +static s32 e1000_disable_ulp_lpt_lp(struct e1000_hw *hw, bool force) +{ +	s32 ret_val = 0; +	u32 mac_reg; +	u16 phy_reg; +	int i = 0; + +	if ((hw->mac.type < e1000_pch_lpt) || +	    (hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPT_I217_LM) || +	    (hw->adapter->pdev->device == E1000_DEV_ID_PCH_LPT_I217_V) || +	    (hw->adapter->pdev->device == E1000_DEV_ID_PCH_I218_LM2) || +	    (hw->adapter->pdev->device == E1000_DEV_ID_PCH_I218_V2) || +	    (hw->dev_spec.ich8lan.ulp_state == e1000_ulp_state_off)) +		return 0; + +	if (er32(FWSM) & E1000_ICH_FWSM_FW_VALID) { +		if (force) { +			/* Request ME un-configure ULP mode in the PHY */ +			mac_reg = er32(H2ME); +			mac_reg &= ~E1000_H2ME_ULP; +			mac_reg |= E1000_H2ME_ENFORCE_SETTINGS; +			ew32(H2ME, mac_reg); +		} + +		/* Poll up to 100msec for ME to clear ULP_CFG_DONE */ +		while (er32(FWSM) & E1000_FWSM_ULP_CFG_DONE) { +			if (i++ == 10) { +				ret_val = -E1000_ERR_PHY; +				goto out; +			} + +			usleep_range(10000, 20000); +		} +		e_dbg("ULP_CONFIG_DONE cleared after %dmsec\n", i * 10); + +		if (force) { +			mac_reg = er32(H2ME); +			mac_reg &= ~E1000_H2ME_ENFORCE_SETTINGS; +			ew32(H2ME, mac_reg); +		} else { +			/* Clear H2ME.ULP after ME ULP configuration */ +			mac_reg = er32(H2ME); +			mac_reg &= ~E1000_H2ME_ULP; +			ew32(H2ME, mac_reg); +		} + +		goto out; +	} + +	ret_val = hw->phy.ops.acquire(hw); +	if (ret_val) +		goto out; + +	if (force) +		/* Toggle LANPHYPC Value bit */ +		e1000_toggle_lanphypc_pch_lpt(hw); + +	/* Unforce SMBus mode in PHY */ +	ret_val = e1000_read_phy_reg_hv_locked(hw, CV_SMB_CTRL, &phy_reg); +	if (ret_val) { +		/* The MAC might be in PCIe mode, so temporarily force to +		 * SMBus mode in order to access the PHY. +		 */ +		mac_reg = er32(CTRL_EXT); +		mac_reg |= E1000_CTRL_EXT_FORCE_SMBUS; +		ew32(CTRL_EXT, mac_reg); + +		msleep(50); + +		ret_val = e1000_read_phy_reg_hv_locked(hw, CV_SMB_CTRL, +						       &phy_reg); +		if (ret_val) +			goto release; +	} +	phy_reg &= ~CV_SMB_CTRL_FORCE_SMBUS; +	e1000_write_phy_reg_hv_locked(hw, CV_SMB_CTRL, phy_reg); + +	/* Unforce SMBus mode in MAC */ +	mac_reg = er32(CTRL_EXT); +	mac_reg &= ~E1000_CTRL_EXT_FORCE_SMBUS; +	ew32(CTRL_EXT, mac_reg); + +	/* When ULP mode was previously entered, K1 was disabled by the +	 * hardware.  Re-Enable K1 in the PHY when exiting ULP. +	 */ +	ret_val = e1000_read_phy_reg_hv_locked(hw, HV_PM_CTRL, &phy_reg); +	if (ret_val) +		goto release; +	phy_reg |= HV_PM_CTRL_K1_ENABLE; +	e1000_write_phy_reg_hv_locked(hw, HV_PM_CTRL, phy_reg); + +	/* Clear ULP enabled configuration */ +	ret_val = e1000_read_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, &phy_reg); +	if (ret_val) +		goto release; +	phy_reg &= ~(I218_ULP_CONFIG1_IND | +		     I218_ULP_CONFIG1_STICKY_ULP | +		     I218_ULP_CONFIG1_RESET_TO_SMBUS | +		     I218_ULP_CONFIG1_WOL_HOST | +		     I218_ULP_CONFIG1_INBAND_EXIT | +		     I218_ULP_CONFIG1_DISABLE_SMB_PERST); +	e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); + +	/* Commit ULP changes by starting auto ULP configuration */ +	phy_reg |= I218_ULP_CONFIG1_START; +	e1000_write_phy_reg_hv_locked(hw, I218_ULP_CONFIG1, phy_reg); + +	/* Clear Disable SMBus Release on PERST# in MAC */ +	mac_reg = er32(FEXTNVM7); +	mac_reg &= ~E1000_FEXTNVM7_DISABLE_SMB_PERST; +	ew32(FEXTNVM7, mac_reg); + +release: +	hw->phy.ops.release(hw); +	if (force) { +		e1000_phy_hw_reset(hw); +		msleep(50); +	} +out: +	if (ret_val) +		e_dbg("Error in ULP disable flow: %d\n", ret_val); +	else +		hw->dev_spec.ich8lan.ulp_state = e1000_ulp_state_off; + +	return ret_val; +} + +/**   *  e1000_check_for_copper_link_ich8lan - Check for link (Copper)   *  @hw: pointer to the HW structure   * @@ -1015,14 +1329,18 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)  			return ret_val;  	} -	/* When connected at 10Mbps half-duplex, 82579 parts are excessively +	/* When connected at 10Mbps half-duplex, some parts are excessively  	 * aggressive resulting in many collisions. To avoid this, increase  	 * the IPG and reduce Rx latency in the PHY.  	 */ -	if ((hw->mac.type == e1000_pch2lan) && link) { +	if (((hw->mac.type == e1000_pch2lan) || +	     (hw->mac.type == e1000_pch_lpt)) && link) {  		u32 reg; +  		reg = er32(STATUS);  		if (!(reg & (E1000_STATUS_FD | E1000_STATUS_SPEED_MASK))) { +			u16 emi_addr; +  			reg = er32(TIPG);  			reg &= ~E1000_TIPG_IPGT_MASK;  			reg |= 0xFF; @@ -1033,8 +1351,12 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)  			if (ret_val)  				return ret_val; -			ret_val = -			    e1000_write_emi_reg_locked(hw, I82579_RX_CONFIG, 0); +			if (hw->mac.type == e1000_pch2lan) +				emi_addr = I82579_RX_CONFIG; +			else +				emi_addr = I217_RX_CONFIG; + +			ret_val = e1000_write_emi_reg_locked(hw, emi_addr, 0);  			hw->phy.ops.release(hw); @@ -1106,9 +1428,11 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)  	e1000e_check_downshift(hw);  	/* Enable/Disable EEE after link up */ -	ret_val = e1000_set_eee_pchlan(hw); -	if (ret_val) -		return ret_val; +	if (hw->phy.type > e1000_phy_82579) { +		ret_val = e1000_set_eee_pchlan(hw); +		if (ret_val) +			return ret_val; +	}  	/* If we are forcing speed/duplex, then we simply return since  	 * we have already determined whether we have link or not. @@ -1313,9 +1637,9 @@ static bool e1000_check_mng_mode_ich8lan(struct e1000_hw *hw)  	u32 fwsm;  	fwsm = er32(FWSM); -	return ((fwsm & E1000_ICH_FWSM_FW_VALID) && +	return (fwsm & E1000_ICH_FWSM_FW_VALID) &&  		((fwsm & E1000_FWSM_MODE_MASK) == -		 (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT))); +		 (E1000_ICH_MNG_IAMT_MODE << E1000_FWSM_MODE_SHIFT));  }  /** @@ -1346,7 +1670,7 @@ static bool e1000_check_mng_mode_pchlan(struct e1000_hw *hw)   *  contain the MAC address but RAR[1-6] are reserved for manageability (ME).   *  Use SHRA[0-3] in place of those reserved for ME.   **/ -static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index) +static int e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index)  {  	u32 rar_low, rar_high; @@ -1368,10 +1692,13 @@ static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index)  		e1e_flush();  		ew32(RAH(index), rar_high);  		e1e_flush(); -		return; +		return 0;  	} -	if (index < hw->mac.rar_entry_count) { +	/* RAR[1-6] are owned by manageability.  Skip those and program the +	 * next address into the SHRA register array. +	 */ +	if (index < (u32)(hw->mac.rar_entry_count)) {  		s32 ret_val;  		ret_val = e1000_acquire_swflag_ich8lan(hw); @@ -1388,7 +1715,7 @@ static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index)  		/* verify the register updates */  		if ((er32(SHRAL(index - 1)) == rar_low) &&  		    (er32(SHRAH(index - 1)) == rar_high)) -			return; +			return 0;  		e_dbg("SHRA[%d] might be locked by ME - FWSM=0x%8.8x\n",  		      (index - 1), er32(FWSM)); @@ -1396,6 +1723,43 @@ static void e1000_rar_set_pch2lan(struct e1000_hw *hw, u8 *addr, u32 index)  out:  	e_dbg("Failed to write receive address at index %d\n", index); +	return -E1000_ERR_CONFIG; +} + +/** + *  e1000_rar_get_count_pch_lpt - Get the number of available SHRA + *  @hw: pointer to the HW structure + * + *  Get the number of available receive registers that the Host can + *  program. SHRA[0-10] are the shared receive address registers + *  that are shared between the Host and manageability engine (ME). + *  ME can reserve any number of addresses and the host needs to be + *  able to tell how many available registers it has access to. + **/ +static u32 e1000_rar_get_count_pch_lpt(struct e1000_hw *hw) +{ +	u32 wlock_mac; +	u32 num_entries; + +	wlock_mac = er32(FWSM) & E1000_FWSM_WLOCK_MAC_MASK; +	wlock_mac >>= E1000_FWSM_WLOCK_MAC_SHIFT; + +	switch (wlock_mac) { +	case 0: +		/* All SHRA[0..10] and RAR[0] available */ +		num_entries = hw->mac.rar_entry_count; +		break; +	case 1: +		/* Only RAR[0] available */ +		num_entries = 1; +		break; +	default: +		/* SHRA[0..(wlock_mac - 1)] available + RAR[0] */ +		num_entries = wlock_mac + 1; +		break; +	} + +	return num_entries;  }  /** @@ -1409,7 +1773,7 @@ out:   *  contain the MAC address. SHRA[0-10] are the shared receive address   *  registers that are shared between the Host and manageability engine (ME).   **/ -static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index) +static int e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index)  {  	u32 rar_low, rar_high;  	u32 wlock_mac; @@ -1431,7 +1795,7 @@ static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index)  		e1e_flush();  		ew32(RAH(index), rar_high);  		e1e_flush(); -		return; +		return 0;  	}  	/* The manageability engine (ME) can lock certain SHRAR registers that @@ -1463,12 +1827,13 @@ static void e1000_rar_set_pch_lpt(struct e1000_hw *hw, u8 *addr, u32 index)  			/* verify the register updates */  			if ((er32(SHRAL_PCH_LPT(index - 1)) == rar_low) &&  			    (er32(SHRAH_PCH_LPT(index - 1)) == rar_high)) -				return; +				return 0;  		}  	}  out:  	e_dbg("Failed to write receive address at index %d\n", index); +	return -E1000_ERR_CONFIG;  }  /** @@ -1481,11 +1846,13 @@ out:   **/  static s32 e1000_check_reset_block_ich8lan(struct e1000_hw *hw)  { -	u32 fwsm; +	bool blocked = false; +	int i = 0; -	fwsm = er32(FWSM); - -	return (fwsm & E1000_ICH_FWSM_RSPCIPHY) ? 0 : E1000_BLK_PHY_RESET; +	while ((blocked = !(er32(FWSM) & E1000_ICH_FWSM_RSPCIPHY)) && +	       (i++ < 10)) +		usleep_range(10000, 20000); +	return blocked ? E1000_BLK_PHY_RESET : 0;  }  /** @@ -1962,8 +2329,8 @@ void e1000_copy_rx_addrs_to_phy_ich8lan(struct e1000_hw *hw)  	if (ret_val)  		goto release; -	/* Copy both RAL/H (rar_entry_count) and SHRAL/H (+4) to PHY */ -	for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) { +	/* Copy both RAL/H (rar_entry_count) and SHRAL/H to PHY */ +	for (i = 0; i < (hw->mac.rar_entry_count); i++) {  		mac_reg = er32(RAL(i));  		hw->phy.ops.write_reg_page(hw, BM_RAR_L(i),  					   (u16)(mac_reg & 0xFFFF)); @@ -2007,10 +2374,10 @@ s32 e1000_lv_jumbo_workaround_ich8lan(struct e1000_hw *hw, bool enable)  		return ret_val;  	if (enable) { -		/* Write Rx addresses (rar_entry_count for RAL/H, +4 for +		/* Write Rx addresses (rar_entry_count for RAL/H, and  		 * SHRAL/H) and initial CRC values to the MAC  		 */ -		for (i = 0; i < (hw->mac.rar_entry_count + 4); i++) { +		for (i = 0; i < hw->mac.rar_entry_count; i++) {  			u8 mac_addr[ETH_ALEN] = { 0 };  			u32 addr_high, addr_low; @@ -2187,51 +2554,44 @@ release:   *  e1000_k1_gig_workaround_lv - K1 Si workaround   *  @hw:   pointer to the HW structure   * - *  Workaround to set the K1 beacon duration for 82579 parts + *  Workaround to set the K1 beacon duration for 82579 parts in 10Mbps + *  Disable K1 in 1000Mbps and 100Mbps   **/  static s32 e1000_k1_workaround_lv(struct e1000_hw *hw)  {  	s32 ret_val = 0;  	u16 status_reg = 0; -	u32 mac_reg; -	u16 phy_reg;  	if (hw->mac.type != e1000_pch2lan)  		return 0; -	/* Set K1 beacon duration based on 1Gbps speed or otherwise */ +	/* Set K1 beacon duration based on 10Mbs speed */  	ret_val = e1e_rphy(hw, HV_M_STATUS, &status_reg);  	if (ret_val)  		return ret_val;  	if ((status_reg & (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE))  	    == (HV_M_STATUS_LINK_UP | HV_M_STATUS_AUTONEG_COMPLETE)) { -		mac_reg = er32(FEXTNVM4); -		mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK; - -		ret_val = e1e_rphy(hw, I82579_LPI_CTRL, &phy_reg); -		if (ret_val) -			return ret_val; - -		if (status_reg & HV_M_STATUS_SPEED_1000) { +		if (status_reg & +		    (HV_M_STATUS_SPEED_1000 | HV_M_STATUS_SPEED_100)) {  			u16 pm_phy_reg; -			mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC; -			phy_reg &= ~I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT; -			/* LV 1G Packet drop issue wa  */ +			/* LV 1G/100 Packet drop issue wa  */  			ret_val = e1e_rphy(hw, HV_PM_CTRL, &pm_phy_reg);  			if (ret_val)  				return ret_val; -			pm_phy_reg &= ~HV_PM_CTRL_PLL_STOP_IN_K1_GIGA; +			pm_phy_reg &= ~HV_PM_CTRL_K1_ENABLE;  			ret_val = e1e_wphy(hw, HV_PM_CTRL, pm_phy_reg);  			if (ret_val)  				return ret_val;  		} else { +			u32 mac_reg; + +			mac_reg = er32(FEXTNVM4); +			mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK;  			mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_16USEC; -			phy_reg |= I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT; +			ew32(FEXTNVM4, mac_reg);  		} -		ew32(FEXTNVM4, mac_reg); -		ret_val = e1e_wphy(hw, I82579_LPI_CTRL, phy_reg);  	}  	return ret_val; @@ -4657,6 +5017,7 @@ static const struct e1000_mac_operations ich8_mac_ops = {  	/* id_led_init dependent on mac type */  	.config_collision_dist	= e1000e_config_collision_dist_generic,  	.rar_set		= e1000e_rar_set_generic, +	.rar_get_count		= e1000e_rar_get_count_generic,  };  static const struct e1000_phy_operations ich8_phy_ops = {  | 
