diff options
Diffstat (limited to 'drivers/net/e1000e/ich8lan.c')
| -rw-r--r-- | drivers/net/e1000e/ich8lan.c | 65 | 
1 files changed, 52 insertions, 13 deletions
diff --git a/drivers/net/e1000e/ich8lan.c b/drivers/net/e1000e/ich8lan.c index 4e36978b8fd..54add27c8f7 100644 --- a/drivers/net/e1000e/ich8lan.c +++ b/drivers/net/e1000e/ich8lan.c @@ -137,8 +137,9 @@  #define HV_PM_CTRL		PHY_REG(770, 17)  /* PHY Low Power Idle Control */ -#define I82579_LPI_CTRL			PHY_REG(772, 20) -#define I82579_LPI_CTRL_ENABLE_MASK	0x6000 +#define I82579_LPI_CTRL				PHY_REG(772, 20) +#define I82579_LPI_CTRL_ENABLE_MASK		0x6000 +#define I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT	0x80  /* EMI Registers */  #define I82579_EMI_ADDR         0x10 @@ -163,6 +164,11 @@  #define HV_KMRN_MODE_CTRL      PHY_REG(769, 16)  #define HV_KMRN_MDIO_SLOW      0x0400 +/* KMRN FIFO Control and Status */ +#define HV_KMRN_FIFO_CTRLSTA                  PHY_REG(770, 16) +#define HV_KMRN_FIFO_CTRLSTA_PREAMBLE_MASK    0x7000 +#define HV_KMRN_FIFO_CTRLSTA_PREAMBLE_SHIFT   12 +  /* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */  /* Offset 04h HSFSTS */  union ich8_hws_flash_status { @@ -657,6 +663,7 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)  	struct e1000_mac_info *mac = &hw->mac;  	s32 ret_val;  	bool link; +	u16 phy_reg;  	/*  	 * We only want to go out to the PHY registers to see if Auto-Neg @@ -689,16 +696,35 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)  	mac->get_link_status = false; -	if (hw->phy.type == e1000_phy_82578) { -		ret_val = e1000_link_stall_workaround_hv(hw); -		if (ret_val) -			goto out; -	} - -	if (hw->mac.type == e1000_pch2lan) { +	switch (hw->mac.type) { +	case e1000_pch2lan:  		ret_val = e1000_k1_workaround_lv(hw);  		if (ret_val)  			goto out; +		/* fall-thru */ +	case e1000_pchlan: +		if (hw->phy.type == e1000_phy_82578) { +			ret_val = e1000_link_stall_workaround_hv(hw); +			if (ret_val) +				goto out; +		} + +		/* +		 * Workaround for PCHx parts in half-duplex: +		 * Set the number of preambles removed from the packet +		 * when it is passed from the PHY to the MAC to prevent +		 * the MAC from misinterpreting the packet type. +		 */ +		e1e_rphy(hw, HV_KMRN_FIFO_CTRLSTA, &phy_reg); +		phy_reg &= ~HV_KMRN_FIFO_CTRLSTA_PREAMBLE_MASK; + +		if ((er32(STATUS) & E1000_STATUS_FD) != E1000_STATUS_FD) +			phy_reg |= (1 << HV_KMRN_FIFO_CTRLSTA_PREAMBLE_SHIFT); + +		e1e_wphy(hw, HV_KMRN_FIFO_CTRLSTA, phy_reg); +		break; +	default: +		break;  	}  	/* @@ -788,6 +814,11 @@ static s32 e1000_get_variants_ich8lan(struct e1000_adapter *adapter)  	    (adapter->hw.phy.type == e1000_phy_igp_3))  		adapter->flags |= FLAG_LSC_GIG_SPEED_DROP; +	/* Enable workaround for 82579 w/ ME enabled */ +	if ((adapter->hw.mac.type == e1000_pch2lan) && +	    (er32(FWSM) & E1000_ICH_FWSM_FW_VALID)) +		adapter->flags2 |= FLAG2_PCIM2PCI_ARBITER_WA; +  	/* Disable EEE by default until IEEE802.3az spec is finalized */  	if (adapter->flags2 & FLAG2_HAS_EEE)  		adapter->hw.dev_spec.ich8lan.eee_disable = true; @@ -1355,7 +1386,7 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)  			return ret_val;  		/* Preamble tuning for SSC */ -		ret_val = e1e_wphy(hw, PHY_REG(770, 16), 0xA204); +		ret_val = e1e_wphy(hw, HV_KMRN_FIFO_CTRLSTA, 0xA204);  		if (ret_val)  			return ret_val;  	} @@ -1645,6 +1676,7 @@ 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)  		goto out; @@ -1659,12 +1691,19 @@ static s32 e1000_k1_workaround_lv(struct e1000_hw *hw)  		mac_reg = er32(FEXTNVM4);  		mac_reg &= ~E1000_FEXTNVM4_BEACON_DURATION_MASK; -		if (status_reg & HV_M_STATUS_SPEED_1000) +		ret_val = e1e_rphy(hw, I82579_LPI_CTRL, &phy_reg); +		if (ret_val) +			goto out; + +		if (status_reg & HV_M_STATUS_SPEED_1000) {  			mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_8USEC; -		else +			phy_reg &= ~I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT; +		} else {  			mac_reg |= E1000_FEXTNVM4_BEACON_DURATION_16USEC; - +			phy_reg |= I82579_LPI_CTRL_FORCE_PLL_LOCK_COUNT; +		}  		ew32(FEXTNVM4, mac_reg); +		ret_val = e1e_wphy(hw, I82579_LPI_CTRL, phy_reg);  	}  out:  |