Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 184261
b: refs/heads/master
c: 88a268c
h: refs/heads/master
i:
  184259: cb1bf61
v: v3
  • Loading branch information
Nick Nunley authored and David S. Miller committed Feb 17, 2010
1 parent 0632785 commit 48a129a
Show file tree
Hide file tree
Showing 9 changed files with 130 additions and 12 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 53c992fa8497286f24f279ebec5a8c7a58d4e68c
refs/heads/master: 88a268c1a11a2e94b7c55a8cfe97892d845887c8
44 changes: 44 additions & 0 deletions trunk/drivers/net/igb/e1000_82575.c
Original file line number Diff line number Diff line change
Expand Up @@ -726,6 +726,34 @@ static s32 igb_check_for_link_82575(struct e1000_hw *hw)
return ret_val;
}

/**
* igb_power_up_serdes_link_82575 - Power up the serdes link after shutdown
* @hw: pointer to the HW structure
**/
void igb_power_up_serdes_link_82575(struct e1000_hw *hw)
{
u32 reg;


if ((hw->phy.media_type != e1000_media_type_internal_serdes) &&
!igb_sgmii_active_82575(hw))
return;

/* Enable PCS to turn on link */
reg = rd32(E1000_PCS_CFG0);
reg |= E1000_PCS_CFG_PCS_EN;
wr32(E1000_PCS_CFG0, reg);

/* Power up the laser */
reg = rd32(E1000_CTRL_EXT);
reg &= ~E1000_CTRL_EXT_SDP3_DATA;
wr32(E1000_CTRL_EXT, reg);

/* flush the write to verify completion */
wrfl();
msleep(1);
}

/**
* igb_get_pcs_speed_and_duplex_82575 - Retrieve current speed/duplex
* @hw: pointer to the HW structure
Expand Down Expand Up @@ -1165,6 +1193,22 @@ static s32 igb_read_mac_addr_82575(struct e1000_hw *hw)
return ret_val;
}

/**
* igb_power_down_phy_copper_82575 - Remove link during PHY power down
* @hw: pointer to the HW structure
*
* In the case of a PHY power down to save power, or to turn off link during a
* driver unload, or wake on lan is not enabled, remove the link.
**/
void igb_power_down_phy_copper_82575(struct e1000_hw *hw)
{
/* If the management interface is not enabled, then power down */
if (!(igb_enable_mng_pass_thru(hw) || igb_check_reset_block(hw)))
igb_power_down_phy_copper(hw);

return;
}

/**
* igb_clear_hw_cntrs_82575 - Clear device specific hardware counters
* @hw: pointer to the HW structure
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/net/igb/e1000_82575.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#define _E1000_82575_H_

extern void igb_shutdown_serdes_link_82575(struct e1000_hw *hw);
extern void igb_power_up_serdes_link_82575(struct e1000_hw *hw);
extern void igb_power_down_phy_copper_82575(struct e1000_hw *hw);
extern void igb_rx_fifo_flush_82575(struct e1000_hw *hw);

#define ID_LED_DEFAULT_82575_SERDES ((ID_LED_DEF1_DEF2 << 12) | \
Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/net/igb/e1000_defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -481,6 +481,7 @@
/* PHY Control Register */
#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */
#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */
#define MII_CR_POWER_DOWN 0x0800 /* Power down */
#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */
#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */
#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */
Expand Down
35 changes: 35 additions & 0 deletions trunk/drivers/net/igb/e1000_phy.c
Original file line number Diff line number Diff line change
Expand Up @@ -1930,6 +1930,41 @@ s32 igb_phy_init_script_igp3(struct e1000_hw *hw)
return 0;
}

/**
* igb_power_up_phy_copper - Restore copper link in case of PHY power down
* @hw: pointer to the HW structure
*
* In the case of a PHY power down to save power, or to turn off link during a
* driver unload, restore the link to previous settings.
**/
void igb_power_up_phy_copper(struct e1000_hw *hw)
{
u16 mii_reg = 0;

/* The PHY will retain its settings across a power down/up cycle */
hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
mii_reg &= ~MII_CR_POWER_DOWN;
hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
}

/**
* igb_power_down_phy_copper - Power down copper PHY
* @hw: pointer to the HW structure
*
* Power down PHY to save power when interface is down and wake on lan
* is not enabled.
**/
void igb_power_down_phy_copper(struct e1000_hw *hw)
{
u16 mii_reg = 0;

/* The PHY will retain its settings across a power down/up cycle */
hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
mii_reg |= MII_CR_POWER_DOWN;
hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
msleep(1);
}

/**
* igb_check_polarity_82580 - Checks the polarity.
* @hw: pointer to the HW structure
Expand Down
2 changes: 2 additions & 0 deletions trunk/drivers/net/igb/e1000_phy.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ s32 igb_setup_copper_link(struct e1000_hw *hw);
s32 igb_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data);
s32 igb_phy_has_link(struct e1000_hw *hw, u32 iterations,
u32 usec_interval, bool *success);
void igb_power_up_phy_copper(struct e1000_hw *hw);
void igb_power_down_phy_copper(struct e1000_hw *hw);
s32 igb_phy_init_script_igp3(struct e1000_hw *hw);
s32 igb_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data);
s32 igb_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data);
Expand Down
1 change: 1 addition & 0 deletions trunk/drivers/net/igb/igb.h
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,7 @@ extern void igb_alloc_rx_buffers_adv(struct igb_ring *, int);
extern void igb_update_stats(struct igb_adapter *);
extern bool igb_has_link(struct igb_adapter *adapter);
extern void igb_set_ethtool_ops(struct net_device *);
extern void igb_power_up_link(struct igb_adapter *);

static inline s32 igb_reset_phy(struct e1000_hw *hw)
{
Expand Down
16 changes: 13 additions & 3 deletions trunk/drivers/net/igb/igb_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -1722,6 +1722,9 @@ static void igb_diag_test(struct net_device *netdev,

dev_info(&adapter->pdev->dev, "offline testing starting\n");

/* power up link for link test */
igb_power_up_link(adapter);

/* Link test performed before hardware reset so autoneg doesn't
* interfere with test result */
if (igb_link_test(adapter, &data[4]))
Expand All @@ -1745,6 +1748,8 @@ static void igb_diag_test(struct net_device *netdev,
eth_test->flags |= ETH_TEST_FL_FAILED;

igb_reset(adapter);
/* power up link for loopback test */
igb_power_up_link(adapter);
if (igb_loopback_test(adapter, &data[3]))
eth_test->flags |= ETH_TEST_FL_FAILED;

Expand All @@ -1763,9 +1768,14 @@ static void igb_diag_test(struct net_device *netdev,
dev_open(netdev);
} else {
dev_info(&adapter->pdev->dev, "online testing starting\n");
/* Online tests */
if (igb_link_test(adapter, &data[4]))
eth_test->flags |= ETH_TEST_FL_FAILED;

/* PHY is powered down when interface is down */
if (!netif_carrier_ok(netdev)) {
data[4] = 0;
} else {
if (igb_link_test(adapter, &data[4]))
eth_test->flags |= ETH_TEST_FL_FAILED;
}

/* Online tests aren't run; pass by default */
data[0] = 0;
Expand Down
39 changes: 31 additions & 8 deletions trunk/drivers/net/igb/igb_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -1114,6 +1114,29 @@ static void igb_configure(struct igb_adapter *adapter)
adapter->tx_queue_len = netdev->tx_queue_len;
}

/**
* igb_power_up_link - Power up the phy/serdes link
* @adapter: address of board private structure
**/
void igb_power_up_link(struct igb_adapter *adapter)
{
if (adapter->hw.phy.media_type == e1000_media_type_copper)
igb_power_up_phy_copper(&adapter->hw);
else
igb_power_up_serdes_link_82575(&adapter->hw);
}

/**
* igb_power_down_link - Power down the phy/serdes link
* @adapter: address of board private structure
*/
static void igb_power_down_link(struct igb_adapter *adapter)
{
if (adapter->hw.phy.media_type == e1000_media_type_copper)
igb_power_down_phy_copper_82575(&adapter->hw);
else
igb_shutdown_serdes_link_82575(&adapter->hw);
}

/**
* igb_up - Open the interface and prepare it to handle traffic
Expand Down Expand Up @@ -1335,6 +1358,9 @@ void igb_reset(struct igb_adapter *adapter)
wr32(E1000_PCIEMISC,
reg & ~E1000_PCIEMISC_LX_DECISION);
}
if (!netif_running(adapter->netdev))
igb_power_down_link(adapter);

igb_update_mng_vlan(adapter);

/* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */
Expand Down Expand Up @@ -1717,9 +1743,6 @@ static void __devexit igb_remove(struct pci_dev *pdev)

unregister_netdev(netdev);

if (!igb_check_reset_block(hw))
igb_reset_phy(hw);

igb_clear_interrupt_scheme(adapter);

#ifdef CONFIG_PCI_IOV
Expand Down Expand Up @@ -1995,7 +2018,7 @@ static int igb_open(struct net_device *netdev)
if (err)
goto err_setup_rx;

/* e1000_power_up_phy(adapter); */
igb_power_up_link(adapter);

/* before we allocate an interrupt, we must be ready to handle it.
* Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt
Expand Down Expand Up @@ -2037,7 +2060,7 @@ static int igb_open(struct net_device *netdev)

err_req_irq:
igb_release_hw_control(adapter);
/* e1000_power_down_phy(adapter); */
igb_power_down_link(adapter);
igb_free_all_rx_resources(adapter);
err_setup_rx:
igb_free_all_tx_resources(adapter);
Expand Down Expand Up @@ -5820,7 +5843,9 @@ static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake)

*enable_wake = wufc || adapter->en_mng_pt;
if (!*enable_wake)
igb_shutdown_serdes_link_82575(hw);
igb_power_down_link(adapter);
else
igb_power_up_link(adapter);

/* Release control of h/w to f/w. If f/w is AMT enabled, this
* would have already happened in close and is redundant. */
Expand Down Expand Up @@ -5877,8 +5902,6 @@ static int igb_resume(struct pci_dev *pdev)
return -ENOMEM;
}

/* e1000_power_up_phy(adapter); */

igb_reset(adapter);

/* let the f/w know that the h/w is now under the control of the
Expand Down

0 comments on commit 48a129a

Please sign in to comment.