e1000e: provide family-specific PHY power up/down operations

The different families (80003es2lan, 8257x, ICHx/PCH) supported by the
driver each have their own conditions when the PHY can be powered down.
This patch rewrites the PHY power up/down code to fit with the family-
specific style used in the driver.  All pre-existing calls to power up or
down the PHY remain untouched.  A new call to power down the PHY when
removing the driver when the interface is down replaces the current call
to reset the PHY in order to reduce power consumption.

Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Bruce Allan 2009-12-01 15:47:22 +00:00 committed by David S. Miller
parent eb656d4552
commit 17f208deb9
7 changed files with 122 additions and 39 deletions

View file

@ -2641,18 +2641,8 @@ static void e1000_configure(struct e1000_adapter *adapter)
**/
void e1000e_power_up_phy(struct e1000_adapter *adapter)
{
u16 mii_reg = 0;
/* Just clear the power down bit to wake the phy back up */
if (adapter->hw.phy.media_type == e1000_media_type_copper) {
/*
* According to the manual, the phy will retain its
* settings across a power-down/up cycle
*/
e1e_rphy(&adapter->hw, PHY_CONTROL, &mii_reg);
mii_reg &= ~MII_CR_POWER_DOWN;
e1e_wphy(&adapter->hw, PHY_CONTROL, mii_reg);
}
if (adapter->hw.phy.ops.power_up)
adapter->hw.phy.ops.power_up(&adapter->hw);
adapter->hw.mac.ops.setup_link(&adapter->hw);
}
@ -2660,35 +2650,17 @@ void e1000e_power_up_phy(struct e1000_adapter *adapter)
/**
* e1000_power_down_phy - Power down the PHY
*
* Power down the PHY so no link is implied when interface is down
* The PHY cannot be powered down is management or WoL is active
* Power down the PHY so no link is implied when interface is down.
* The PHY cannot be powered down if management or WoL is active.
*/
static void e1000_power_down_phy(struct e1000_adapter *adapter)
{
struct e1000_hw *hw = &adapter->hw;
u16 mii_reg;
/* WoL is enabled */
if (adapter->wol)
return;
/* non-copper PHY? */
if (adapter->hw.phy.media_type != e1000_media_type_copper)
return;
/* reset is blocked because of a SoL/IDER session */
if (e1000e_check_mng_mode(hw) || e1000_check_reset_block(hw))
return;
/* manageability (AMT) is enabled */
if (er32(MANC) & E1000_MANC_SMBUS_EN)
return;
/* power down the PHY */
e1e_rphy(hw, PHY_CONTROL, &mii_reg);
mii_reg |= MII_CR_POWER_DOWN;
e1e_wphy(hw, PHY_CONTROL, mii_reg);
mdelay(1);
if (adapter->hw.phy.ops.power_down)
adapter->hw.phy.ops.power_down(&adapter->hw);
}
/**
@ -5294,17 +5266,17 @@ static void __devexit e1000_remove(struct pci_dev *pdev)
cancel_work_sync(&adapter->print_hang_task);
flush_scheduled_work();
if (!(netdev->flags & IFF_UP))
e1000_power_down_phy(adapter);
unregister_netdev(netdev);
/*
* Release control of h/w to f/w. If f/w is AMT enabled, this
* would have already happened in close and is redundant.
*/
e1000_release_hw_control(adapter);
unregister_netdev(netdev);
if (!e1000_check_reset_block(&adapter->hw))
e1000_phy_hw_reset(&adapter->hw);
e1000e_reset_interrupt_capability(adapter);
kfree(adapter->tx_ring);
kfree(adapter->rx_ring);