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

Commit a84216e6 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6: (21 commits)
  mac80211: check interface is down before type change
  cfg80211: fix NULL ptr deref
  libertas if_usb: Fix crash on 64-bit machines
  mac80211: fix reason code output endianness
  mac80211: fix addba timer
  ath9k: fix misplaced semicolon on rate control
  b43: Fix DMA TX bounce buffer copying
  mac80211: fix BSS leak
  rt73usb.c : more ids
  ipw2200: fix oops on missing firmware
  gre: Fix dev_addr clobbering for gretap
  sky2: set carrier off in probe
  net: fix sk_forward_alloc corruption
  pcnet_cs: add cis of PreMax PE-200 ethernet pcmcia card
  r8169: Fix card drop incoming VLAN tagged MTU byte large jumbo frames
  ibmtr: possible Read buffer overflow?
  net: Fix RPF to work with policy routing
  net: fix kmemcheck annotations
  e1000e: rework disable K1 at 1000Mbps for 82577/82578
  e1000e: config PHY via software after resets
  ...
parents 1836d959 bcfe3c20
Loading
Loading
Loading
Loading
+19 −7
Original line number Original line Diff line number Diff line
@@ -1427,19 +1427,31 @@ static int e100_phy_init(struct nic *nic)
	} else
	} else
		DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id);
		DPRINTK(HW, DEBUG, "phy_addr = %d\n", nic->mii.phy_id);


	/* Isolate all the PHY ids */
	for (addr = 0; addr < 32; addr++)
		mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE);
	/* Select the discovered PHY */
	bmcr &= ~BMCR_ISOLATE;
	mdio_write(netdev, nic->mii.phy_id, MII_BMCR, bmcr);

	/* Get phy ID */
	/* Get phy ID */
	id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1);
	id_lo = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID1);
	id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2);
	id_hi = mdio_read(netdev, nic->mii.phy_id, MII_PHYSID2);
	nic->phy = (u32)id_hi << 16 | (u32)id_lo;
	nic->phy = (u32)id_hi << 16 | (u32)id_lo;
	DPRINTK(HW, DEBUG, "phy ID = 0x%08X\n", nic->phy);
	DPRINTK(HW, DEBUG, "phy ID = 0x%08X\n", nic->phy);


	/* Select the phy and isolate the rest */
	for (addr = 0; addr < 32; addr++) {
		if (addr != nic->mii.phy_id) {
			mdio_write(netdev, addr, MII_BMCR, BMCR_ISOLATE);
		} else if (nic->phy != phy_82552_v) {
			bmcr = mdio_read(netdev, addr, MII_BMCR);
			mdio_write(netdev, addr, MII_BMCR,
				bmcr & ~BMCR_ISOLATE);
		}
	}
	/*
	 * Workaround for 82552:
	 * Clear the ISOLATE bit on selected phy_id last (mirrored on all
	 * other phy_id's) using bmcr value from addr discovery loop above.
	 */
	if (nic->phy == phy_82552_v)
		mdio_write(netdev, nic->mii.phy_id, MII_BMCR,
			bmcr & ~BMCR_ISOLATE);

	/* Handle National tx phys */
	/* Handle National tx phys */
#define NCS_PHY_MODEL_MASK	0xFFF0FFFF
#define NCS_PHY_MODEL_MASK	0xFFF0FFFF
	if ((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) {
	if ((nic->phy & NCS_PHY_MODEL_MASK) == phy_nsc_tx) {
+2 −0
Original line number Original line Diff line number Diff line
@@ -76,6 +76,7 @@
/* Extended Device Control */
/* Extended Device Control */
#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Definable Pin 7 */
#define E1000_CTRL_EXT_SDP7_DATA 0x00000080 /* Value of SW Definable Pin 7 */
#define E1000_CTRL_EXT_EE_RST    0x00002000 /* Reinitialize from EEPROM */
#define E1000_CTRL_EXT_EE_RST    0x00002000 /* Reinitialize from EEPROM */
#define E1000_CTRL_EXT_SPD_BYPS  0x00008000 /* Speed Select Bypass */
#define E1000_CTRL_EXT_RO_DIS    0x00020000 /* Relaxed Ordering disable */
#define E1000_CTRL_EXT_RO_DIS    0x00020000 /* Relaxed Ordering disable */
#define E1000_CTRL_EXT_DMA_DYN_CLK_EN 0x00080000 /* DMA Dynamic Clock Gating */
#define E1000_CTRL_EXT_DMA_DYN_CLK_EN 0x00080000 /* DMA Dynamic Clock Gating */
#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
#define E1000_CTRL_EXT_LINK_MODE_MASK 0x00C00000
@@ -347,6 +348,7 @@
/* Extended Configuration Control and Size */
/* Extended Configuration Control and Size */
#define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP      0x00000020
#define E1000_EXTCNF_CTRL_MDIO_SW_OWNERSHIP      0x00000020
#define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE       0x00000001
#define E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE       0x00000001
#define E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE       0x00000008
#define E1000_EXTCNF_CTRL_SWFLAG                 0x00000020
#define E1000_EXTCNF_CTRL_SWFLAG                 0x00000020
#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK   0x00FF0000
#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK   0x00FF0000
#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT          16
#define E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT          16
+14 −0
Original line number Original line Diff line number Diff line
@@ -141,6 +141,20 @@ struct e1000_info;
#define HV_TNCRS_UPPER		PHY_REG(778, 29) /* Transmit with no CRS */
#define HV_TNCRS_UPPER		PHY_REG(778, 29) /* Transmit with no CRS */
#define HV_TNCRS_LOWER		PHY_REG(778, 30)
#define HV_TNCRS_LOWER		PHY_REG(778, 30)


/* BM PHY Copper Specific Status */
#define BM_CS_STATUS                      17
#define BM_CS_STATUS_LINK_UP              0x0400
#define BM_CS_STATUS_RESOLVED             0x0800
#define BM_CS_STATUS_SPEED_MASK           0xC000
#define BM_CS_STATUS_SPEED_1000           0x8000

/* 82577 Mobile Phy Status Register */
#define HV_M_STATUS                       26
#define HV_M_STATUS_AUTONEG_COMPLETE      0x1000
#define HV_M_STATUS_SPEED_MASK            0x0300
#define HV_M_STATUS_SPEED_1000            0x0200
#define HV_M_STATUS_LINK_UP               0x0040

enum e1000_boards {
enum e1000_boards {
	board_82571,
	board_82571,
	board_82572,
	board_82572,
+1 −0
Original line number Original line Diff line number Diff line
@@ -903,6 +903,7 @@ struct e1000_shadow_ram {
struct e1000_dev_spec_ich8lan {
struct e1000_dev_spec_ich8lan {
	bool kmrn_lock_loss_workaround_enabled;
	bool kmrn_lock_loss_workaround_enabled;
	struct e1000_shadow_ram shadow_ram[E1000_ICH8_SHADOW_RAM_WORDS];
	struct e1000_shadow_ram shadow_ram[E1000_ICH8_SHADOW_RAM_WORDS];
	bool nvm_k1_enabled;
};
};


struct e1000_hw {
struct e1000_hw {
+387 −95
Original line number Original line Diff line number Diff line
@@ -124,11 +124,25 @@


#define SW_FLAG_TIMEOUT    1000 /* SW Semaphore flag timeout in milliseconds */
#define SW_FLAG_TIMEOUT    1000 /* SW Semaphore flag timeout in milliseconds */


/* SMBus Address Phy Register */
#define HV_SMB_ADDR            PHY_REG(768, 26)
#define HV_SMB_ADDR_PEC_EN     0x0200
#define HV_SMB_ADDR_VALID      0x0080

/* Strapping Option Register - RO */
#define E1000_STRAP                     0x0000C
#define E1000_STRAP_SMBUS_ADDRESS_MASK  0x00FE0000
#define E1000_STRAP_SMBUS_ADDRESS_SHIFT 17

/* OEM Bits Phy Register */
/* OEM Bits Phy Register */
#define HV_OEM_BITS            PHY_REG(768, 25)
#define HV_OEM_BITS            PHY_REG(768, 25)
#define HV_OEM_BITS_LPLU       0x0004 /* Low Power Link Up */
#define HV_OEM_BITS_LPLU       0x0004 /* Low Power Link Up */
#define HV_OEM_BITS_GBE_DIS    0x0040 /* Gigabit Disable */
#define HV_OEM_BITS_RESTART_AN 0x0400 /* Restart Auto-negotiation */
#define HV_OEM_BITS_RESTART_AN 0x0400 /* Restart Auto-negotiation */


#define E1000_NVM_K1_CONFIG 0x1B /* NVM K1 Config Word */
#define E1000_NVM_K1_ENABLE 0x1  /* NVM Enable K1 bit */

/* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */
/* ICH GbE Flash Hardware Sequencing Flash Status Register bit breakdown */
/* Offset 04h HSFSTS */
/* Offset 04h HSFSTS */
union ich8_hws_flash_status {
union ich8_hws_flash_status {
@@ -208,6 +222,9 @@ static s32 e1000_cleanup_led_pchlan(struct e1000_hw *hw);
static s32 e1000_led_on_pchlan(struct e1000_hw *hw);
static s32 e1000_led_on_pchlan(struct e1000_hw *hw);
static s32 e1000_led_off_pchlan(struct e1000_hw *hw);
static s32 e1000_led_off_pchlan(struct e1000_hw *hw);
static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active);
static s32 e1000_set_lplu_state_pchlan(struct e1000_hw *hw, bool active);
static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw);
static s32  e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link);
static s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable);


static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg)
static inline u16 __er16flash(struct e1000_hw *hw, unsigned long reg)
{
{
@@ -483,14 +500,6 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
		goto out;
		goto out;
	}
	}


	if (hw->mac.type == e1000_pchlan) {
		ret_val = e1000e_write_kmrn_reg(hw,
		                                   E1000_KMRNCTRLSTA_K1_CONFIG,
		                                   E1000_KMRNCTRLSTA_K1_ENABLE);
		if (ret_val)
			goto out;
	}

	/*
	/*
	 * First we want to see if the MII Status Register reports
	 * First we want to see if the MII Status Register reports
	 * link.  If so, then we want to get the current speed/duplex
	 * link.  If so, then we want to get the current speed/duplex
@@ -500,6 +509,12 @@ static s32 e1000_check_for_copper_link_ich8lan(struct e1000_hw *hw)
	if (ret_val)
	if (ret_val)
		goto out;
		goto out;


	if (hw->mac.type == e1000_pchlan) {
		ret_val = e1000_k1_gig_workaround_hv(hw, link);
		if (ret_val)
			goto out;
	}

	if (!link)
	if (!link)
		goto out; /* No link detected */
		goto out; /* No link detected */


@@ -793,6 +808,326 @@ static s32 e1000_phy_force_speed_duplex_ich8lan(struct e1000_hw *hw)
	return 0;
	return 0;
}
}


/**
 *  e1000_sw_lcd_config_ich8lan - SW-based LCD Configuration
 *  @hw:   pointer to the HW structure
 *
 *  SW should configure the LCD from the NVM extended configuration region
 *  as a workaround for certain parts.
 **/
static s32 e1000_sw_lcd_config_ich8lan(struct e1000_hw *hw)
{
	struct e1000_phy_info *phy = &hw->phy;
	u32 i, data, cnf_size, cnf_base_addr, sw_cfg_mask;
	s32 ret_val;
	u16 word_addr, reg_data, reg_addr, phy_page = 0;

	ret_val = hw->phy.ops.acquire_phy(hw);
	if (ret_val)
		return ret_val;

	/*
	 * Initialize the PHY from the NVM on ICH platforms.  This
	 * is needed due to an issue where the NVM configuration is
	 * not properly autoloaded after power transitions.
	 * Therefore, after each PHY reset, we will load the
	 * configuration data out of the NVM manually.
	 */
	if ((hw->mac.type == e1000_ich8lan && phy->type == e1000_phy_igp_3) ||
		(hw->mac.type == e1000_pchlan)) {
		struct e1000_adapter *adapter = hw->adapter;

		/* Check if SW needs to configure the PHY */
		if ((adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M_AMT) ||
		    (adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M) ||
		    (hw->mac.type == e1000_pchlan))
			sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;
		else
			sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG;

		data = er32(FEXTNVM);
		if (!(data & sw_cfg_mask))
			goto out;

		/* Wait for basic configuration completes before proceeding */
		e1000_lan_init_done_ich8lan(hw);

		/*
		 * Make sure HW does not configure LCD from PHY
		 * extended configuration before SW configuration
		 */
		data = er32(EXTCNF_CTRL);
		if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)
			goto out;

		cnf_size = er32(EXTCNF_SIZE);
		cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK;
		cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT;
		if (!cnf_size)
			goto out;

		cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK;
		cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;

		if (!(data & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE) &&
		    (hw->mac.type == e1000_pchlan)) {
			/*
			 * HW configures the SMBus address and LEDs when the
			 * OEM and LCD Write Enable bits are set in the NVM.
			 * When both NVM bits are cleared, SW will configure
			 * them instead.
			 */
			data = er32(STRAP);
			data &= E1000_STRAP_SMBUS_ADDRESS_MASK;
			reg_data = data >> E1000_STRAP_SMBUS_ADDRESS_SHIFT;
			reg_data |= HV_SMB_ADDR_PEC_EN | HV_SMB_ADDR_VALID;
			ret_val = e1000_write_phy_reg_hv_locked(hw, HV_SMB_ADDR,
			                                        reg_data);
			if (ret_val)
				goto out;

			data = er32(LEDCTL);
			ret_val = e1000_write_phy_reg_hv_locked(hw,
			                                        HV_LED_CONFIG,
			                                        (u16)data);
			if (ret_val)
				goto out;
		}
		/* Configure LCD from extended configuration region. */

		/* cnf_base_addr is in DWORD */
		word_addr = (u16)(cnf_base_addr << 1);

		for (i = 0; i < cnf_size; i++) {
			ret_val = e1000_read_nvm(hw, (word_addr + i * 2), 1,
			                           &reg_data);
			if (ret_val)
				goto out;

			ret_val = e1000_read_nvm(hw, (word_addr + i * 2 + 1),
			                           1, &reg_addr);
			if (ret_val)
				goto out;

			/* Save off the PHY page for future writes. */
			if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) {
				phy_page = reg_data;
				continue;
			}

			reg_addr &= PHY_REG_MASK;
			reg_addr |= phy_page;

			ret_val = phy->ops.write_phy_reg_locked(hw,
			                                    (u32)reg_addr,
			                                    reg_data);
			if (ret_val)
				goto out;
		}
	}

out:
	hw->phy.ops.release_phy(hw);
	return ret_val;
}

/**
 *  e1000_k1_gig_workaround_hv - K1 Si workaround
 *  @hw:   pointer to the HW structure
 *  @link: link up bool flag
 *
 *  If K1 is enabled for 1Gbps, the MAC might stall when transitioning
 *  from a lower speed.  This workaround disables K1 whenever link is at 1Gig
 *  If link is down, the function will restore the default K1 setting located
 *  in the NVM.
 **/
static s32 e1000_k1_gig_workaround_hv(struct e1000_hw *hw, bool link)
{
	s32 ret_val = 0;
	u16 status_reg = 0;
	bool k1_enable = hw->dev_spec.ich8lan.nvm_k1_enabled;

	if (hw->mac.type != e1000_pchlan)
		goto out;

	/* Wrap the whole flow with the sw flag */
	ret_val = hw->phy.ops.acquire_phy(hw);
	if (ret_val)
		goto out;

	/* Disable K1 when link is 1Gbps, otherwise use the NVM setting */
	if (link) {
		if (hw->phy.type == e1000_phy_82578) {
			ret_val = hw->phy.ops.read_phy_reg_locked(hw,
			                                          BM_CS_STATUS,
			                                          &status_reg);
			if (ret_val)
				goto release;

			status_reg &= BM_CS_STATUS_LINK_UP |
			              BM_CS_STATUS_RESOLVED |
			              BM_CS_STATUS_SPEED_MASK;

			if (status_reg == (BM_CS_STATUS_LINK_UP |
			                   BM_CS_STATUS_RESOLVED |
			                   BM_CS_STATUS_SPEED_1000))
				k1_enable = false;
		}

		if (hw->phy.type == e1000_phy_82577) {
			ret_val = hw->phy.ops.read_phy_reg_locked(hw,
			                                          HV_M_STATUS,
			                                          &status_reg);
			if (ret_val)
				goto release;

			status_reg &= HV_M_STATUS_LINK_UP |
			              HV_M_STATUS_AUTONEG_COMPLETE |
			              HV_M_STATUS_SPEED_MASK;

			if (status_reg == (HV_M_STATUS_LINK_UP |
			                   HV_M_STATUS_AUTONEG_COMPLETE |
			                   HV_M_STATUS_SPEED_1000))
				k1_enable = false;
		}

		/* Link stall fix for link up */
		ret_val = hw->phy.ops.write_phy_reg_locked(hw, PHY_REG(770, 19),
		                                           0x0100);
		if (ret_val)
			goto release;

	} else {
		/* Link stall fix for link down */
		ret_val = hw->phy.ops.write_phy_reg_locked(hw, PHY_REG(770, 19),
		                                           0x4100);
		if (ret_val)
			goto release;
	}

	ret_val = e1000_configure_k1_ich8lan(hw, k1_enable);

release:
	hw->phy.ops.release_phy(hw);
out:
	return ret_val;
}

/**
 *  e1000_configure_k1_ich8lan - Configure K1 power state
 *  @hw: pointer to the HW structure
 *  @enable: K1 state to configure
 *
 *  Configure the K1 power state based on the provided parameter.
 *  Assumes semaphore already acquired.
 *
 *  Success returns 0, Failure returns -E1000_ERR_PHY (-2)
 **/
static s32 e1000_configure_k1_ich8lan(struct e1000_hw *hw, bool k1_enable)
{
	s32 ret_val = 0;
	u32 ctrl_reg = 0;
	u32 ctrl_ext = 0;
	u32 reg = 0;
	u16 kmrn_reg = 0;

	ret_val = e1000e_read_kmrn_reg_locked(hw,
	                                     E1000_KMRNCTRLSTA_K1_CONFIG,
	                                     &kmrn_reg);
	if (ret_val)
		goto out;

	if (k1_enable)
		kmrn_reg |= E1000_KMRNCTRLSTA_K1_ENABLE;
	else
		kmrn_reg &= ~E1000_KMRNCTRLSTA_K1_ENABLE;

	ret_val = e1000e_write_kmrn_reg_locked(hw,
	                                      E1000_KMRNCTRLSTA_K1_CONFIG,
	                                      kmrn_reg);
	if (ret_val)
		goto out;

	udelay(20);
	ctrl_ext = er32(CTRL_EXT);
	ctrl_reg = er32(CTRL);

	reg = ctrl_reg & ~(E1000_CTRL_SPD_1000 | E1000_CTRL_SPD_100);
	reg |= E1000_CTRL_FRCSPD;
	ew32(CTRL, reg);

	ew32(CTRL_EXT, ctrl_ext | E1000_CTRL_EXT_SPD_BYPS);
	udelay(20);
	ew32(CTRL, ctrl_reg);
	ew32(CTRL_EXT, ctrl_ext);
	udelay(20);

out:
	return ret_val;
}

/**
 *  e1000_oem_bits_config_ich8lan - SW-based LCD Configuration
 *  @hw:       pointer to the HW structure
 *  @d0_state: boolean if entering d0 or d3 device state
 *
 *  SW will configure Gbe Disable and LPLU based on the NVM. The four bits are
 *  collectively called OEM bits.  The OEM Write Enable bit and SW Config bit
 *  in NVM determines whether HW should configure LPLU and Gbe Disable.
 **/
static s32 e1000_oem_bits_config_ich8lan(struct e1000_hw *hw, bool d0_state)
{
	s32 ret_val = 0;
	u32 mac_reg;
	u16 oem_reg;

	if (hw->mac.type != e1000_pchlan)
		return ret_val;

	ret_val = hw->phy.ops.acquire_phy(hw);
	if (ret_val)
		return ret_val;

	mac_reg = er32(EXTCNF_CTRL);
	if (mac_reg & E1000_EXTCNF_CTRL_OEM_WRITE_ENABLE)
		goto out;

	mac_reg = er32(FEXTNVM);
	if (!(mac_reg & E1000_FEXTNVM_SW_CONFIG_ICH8M))
		goto out;

	mac_reg = er32(PHY_CTRL);

	ret_val = hw->phy.ops.read_phy_reg_locked(hw, HV_OEM_BITS, &oem_reg);
	if (ret_val)
		goto out;

	oem_reg &= ~(HV_OEM_BITS_GBE_DIS | HV_OEM_BITS_LPLU);

	if (d0_state) {
		if (mac_reg & E1000_PHY_CTRL_GBE_DISABLE)
			oem_reg |= HV_OEM_BITS_GBE_DIS;

		if (mac_reg & E1000_PHY_CTRL_D0A_LPLU)
			oem_reg |= HV_OEM_BITS_LPLU;
	} else {
		if (mac_reg & E1000_PHY_CTRL_NOND0A_GBE_DISABLE)
			oem_reg |= HV_OEM_BITS_GBE_DIS;

		if (mac_reg & E1000_PHY_CTRL_NOND0A_LPLU)
			oem_reg |= HV_OEM_BITS_LPLU;
	}
	/* Restart auto-neg to activate the bits */
	oem_reg |= HV_OEM_BITS_RESTART_AN;
	ret_val = hw->phy.ops.write_phy_reg_locked(hw, HV_OEM_BITS, oem_reg);

out:
	hw->phy.ops.release_phy(hw);

	return ret_val;
}


/**
/**
 *  e1000_hv_phy_workarounds_ich8lan - A series of Phy workarounds to be
 *  e1000_hv_phy_workarounds_ich8lan - A series of Phy workarounds to be
 *  done after every PHY reset.
 *  done after every PHY reset.
@@ -833,10 +1168,20 @@ static s32 e1000_hv_phy_workarounds_ich8lan(struct e1000_hw *hw)
	ret_val = hw->phy.ops.acquire_phy(hw);
	ret_val = hw->phy.ops.acquire_phy(hw);
	if (ret_val)
	if (ret_val)
		return ret_val;
		return ret_val;

	hw->phy.addr = 1;
	hw->phy.addr = 1;
	e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0);
	ret_val = e1000e_write_phy_reg_mdic(hw, IGP01E1000_PHY_PAGE_SELECT, 0);
	if (ret_val)
		goto out;
	hw->phy.ops.release_phy(hw);
	hw->phy.ops.release_phy(hw);


	/*
	 * Configure the K1 Si workaround during phy reset assuming there is
	 * link so that it disables K1 if link is in 1Gbps.
	 */
	ret_val = e1000_k1_gig_workaround_hv(hw, true);

out:
	return ret_val;
	return ret_val;
}
}


@@ -882,11 +1227,8 @@ static void e1000_lan_init_done_ich8lan(struct e1000_hw *hw)
 **/
 **/
static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
{
{
	struct e1000_phy_info *phy = &hw->phy;
	s32 ret_val = 0;
	u32 i;
	u16 reg;
	u32 data, cnf_size, cnf_base_addr, sw_cfg_mask;
	s32 ret_val;
	u16 reg, word_addr, reg_data, reg_addr, phy_page = 0;


	ret_val = e1000e_phy_hw_reset_generic(hw);
	ret_val = e1000e_phy_hw_reset_generic(hw);
	if (ret_val)
	if (ret_val)
@@ -905,81 +1247,16 @@ static s32 e1000_phy_hw_reset_ich8lan(struct e1000_hw *hw)
	if (hw->mac.type == e1000_pchlan)
	if (hw->mac.type == e1000_pchlan)
		e1e_rphy(hw, BM_WUC, &reg);
		e1e_rphy(hw, BM_WUC, &reg);


	/*
	/* Configure the LCD with the extended configuration region in NVM */
	 * Initialize the PHY from the NVM on ICH platforms.  This
	ret_val = e1000_sw_lcd_config_ich8lan(hw);
	 * is needed due to an issue where the NVM configuration is
	 * not properly autoloaded after power transitions.
	 * Therefore, after each PHY reset, we will load the
	 * configuration data out of the NVM manually.
	 */
	if (hw->mac.type == e1000_ich8lan && phy->type == e1000_phy_igp_3) {
		struct e1000_adapter *adapter = hw->adapter;

		/* Check if SW needs configure the PHY */
		if ((adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M_AMT) ||
		    (adapter->pdev->device == E1000_DEV_ID_ICH8_IGP_M))
			sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG_ICH8M;
		else
			sw_cfg_mask = E1000_FEXTNVM_SW_CONFIG;

		data = er32(FEXTNVM);
		if (!(data & sw_cfg_mask))
			return 0;

		/* Wait for basic configuration completes before proceeding */
		e1000_lan_init_done_ich8lan(hw);

		/*
		 * Make sure HW does not configure LCD from PHY
		 * extended configuration before SW configuration
		 */
		data = er32(EXTCNF_CTRL);
		if (data & E1000_EXTCNF_CTRL_LCD_WRITE_ENABLE)
			return 0;

		cnf_size = er32(EXTCNF_SIZE);
		cnf_size &= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_MASK;
		cnf_size >>= E1000_EXTCNF_SIZE_EXT_PCIE_LENGTH_SHIFT;
		if (!cnf_size)
			return 0;

		cnf_base_addr = data & E1000_EXTCNF_CTRL_EXT_CNF_POINTER_MASK;
		cnf_base_addr >>= E1000_EXTCNF_CTRL_EXT_CNF_POINTER_SHIFT;

		/* Configure LCD from extended configuration region. */

		/* cnf_base_addr is in DWORD */
		word_addr = (u16)(cnf_base_addr << 1);

		for (i = 0; i < cnf_size; i++) {
			ret_val = e1000_read_nvm(hw,
						(word_addr + i * 2),
						1,
						&reg_data);
			if (ret_val)
				return ret_val;

			ret_val = e1000_read_nvm(hw,
						(word_addr + i * 2 + 1),
						1,
						&reg_addr);
	if (ret_val)
	if (ret_val)
				return ret_val;
		goto out;

			/* Save off the PHY page for future writes. */
			if (reg_addr == IGP01E1000_PHY_PAGE_SELECT) {
				phy_page = reg_data;
				continue;
			}

			reg_addr |= phy_page;


			ret_val = e1e_wphy(hw, (u32)reg_addr, reg_data);
	/* Configure the LCD with the OEM bits in NVM */
			if (ret_val)
	if (hw->mac.type == e1000_pchlan)
				return ret_val;
		ret_val = e1000_oem_bits_config_ich8lan(hw, true);
		}
	}


out:
	return 0;
	return 0;
}
}


@@ -2306,6 +2583,7 @@ static s32 e1000_get_bus_info_ich8lan(struct e1000_hw *hw)
 **/
 **/
static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
{
{
	struct e1000_dev_spec_ich8lan *dev_spec = &hw->dev_spec.ich8lan;
	u16 reg;
	u16 reg;
	u32 ctrl, icr, kab;
	u32 ctrl, icr, kab;
	s32 ret_val;
	s32 ret_val;
@@ -2341,6 +2619,18 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
		ew32(PBS, E1000_PBS_16K);
		ew32(PBS, E1000_PBS_16K);
	}
	}


	if (hw->mac.type == e1000_pchlan) {
		/* Save the NVM K1 bit setting*/
		ret_val = e1000_read_nvm(hw, E1000_NVM_K1_CONFIG, 1, &reg);
		if (ret_val)
			return ret_val;

		if (reg & E1000_NVM_K1_ENABLE)
			dev_spec->nvm_k1_enabled = true;
		else
			dev_spec->nvm_k1_enabled = false;
	}

	ctrl = er32(CTRL);
	ctrl = er32(CTRL);


	if (!e1000_check_reset_block(hw)) {
	if (!e1000_check_reset_block(hw)) {
@@ -2386,6 +2676,15 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
	if (hw->mac.type == e1000_pchlan)
	if (hw->mac.type == e1000_pchlan)
		e1e_rphy(hw, BM_WUC, &reg);
		e1e_rphy(hw, BM_WUC, &reg);


	ret_val = e1000_sw_lcd_config_ich8lan(hw);
	if (ret_val)
		goto out;

	if (hw->mac.type == e1000_pchlan) {
		ret_val = e1000_oem_bits_config_ich8lan(hw, true);
		if (ret_val)
			goto out;
	}
	/*
	/*
	 * For PCH, this write will make sure that any noise
	 * For PCH, this write will make sure that any noise
	 * will be detected as a CRC error and be dropped rather than show up
	 * will be detected as a CRC error and be dropped rather than show up
@@ -2404,6 +2703,7 @@ static s32 e1000_reset_hw_ich8lan(struct e1000_hw *hw)
	if (hw->mac.type == e1000_pchlan)
	if (hw->mac.type == e1000_pchlan)
		ret_val = e1000_hv_phy_workarounds_ich8lan(hw);
		ret_val = e1000_hv_phy_workarounds_ich8lan(hw);


out:
	return ret_val;
	return ret_val;
}
}


@@ -2708,14 +3008,6 @@ static s32 e1000_get_link_up_info_ich8lan(struct e1000_hw *hw, u16 *speed,
	if (ret_val)
	if (ret_val)
		return ret_val;
		return ret_val;


	if ((hw->mac.type == e1000_pchlan) && (*speed == SPEED_1000)) {
		ret_val = e1000e_write_kmrn_reg(hw,
		                                  E1000_KMRNCTRLSTA_K1_CONFIG,
		                                  E1000_KMRNCTRLSTA_K1_DISABLE);
		if (ret_val)
			return ret_val;
	}

	if ((hw->mac.type == e1000_ich8lan) &&
	if ((hw->mac.type == e1000_ich8lan) &&
	    (hw->phy.type == e1000_phy_igp_3) &&
	    (hw->phy.type == e1000_phy_igp_3) &&
	    (*speed == SPEED_1000)) {
	    (*speed == SPEED_1000)) {
Loading