aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Nunley <nicholasx.d.nunley@intel.com>2010-02-16 20:01:59 -0500
committerDavid S. Miller <davem@davemloft.net>2010-02-17 16:21:33 -0500
commit88a268c1a11a2e94b7c55a8cfe97892d845887c8 (patch)
treeb748dcd6491b17376c984145c2dca02165d92547
parent53c992fa8497286f24f279ebec5a8c7a58d4e68c (diff)
igb: Power down link when interface is down
This changes the behavior of the driver to power down the link when the associated interface is down, unless management is enabled. Signed-off-by: Nicholas Nunley <nicholasx.d.nunley@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/igb/e1000_82575.c44
-rw-r--r--drivers/net/igb/e1000_82575.h2
-rw-r--r--drivers/net/igb/e1000_defines.h1
-rw-r--r--drivers/net/igb/e1000_phy.c35
-rw-r--r--drivers/net/igb/e1000_phy.h2
-rw-r--r--drivers/net/igb/igb.h1
-rw-r--r--drivers/net/igb/igb_ethtool.c16
-rw-r--r--drivers/net/igb/igb_main.c39
8 files changed, 129 insertions, 11 deletions
diff --git a/drivers/net/igb/e1000_82575.c b/drivers/net/igb/e1000_82575.c
index 59817bcc7169..9d7fa2fb85ea 100644
--- a/drivers/net/igb/e1000_82575.c
+++ b/drivers/net/igb/e1000_82575.c
@@ -727,6 +727,34 @@ static s32 igb_check_for_link_82575(struct e1000_hw *hw)
727} 727}
728 728
729/** 729/**
730 * igb_power_up_serdes_link_82575 - Power up the serdes link after shutdown
731 * @hw: pointer to the HW structure
732 **/
733void igb_power_up_serdes_link_82575(struct e1000_hw *hw)
734{
735 u32 reg;
736
737
738 if ((hw->phy.media_type != e1000_media_type_internal_serdes) &&
739 !igb_sgmii_active_82575(hw))
740 return;
741
742 /* Enable PCS to turn on link */
743 reg = rd32(E1000_PCS_CFG0);
744 reg |= E1000_PCS_CFG_PCS_EN;
745 wr32(E1000_PCS_CFG0, reg);
746
747 /* Power up the laser */
748 reg = rd32(E1000_CTRL_EXT);
749 reg &= ~E1000_CTRL_EXT_SDP3_DATA;
750 wr32(E1000_CTRL_EXT, reg);
751
752 /* flush the write to verify completion */
753 wrfl();
754 msleep(1);
755}
756
757/**
730 * igb_get_pcs_speed_and_duplex_82575 - Retrieve current speed/duplex 758 * igb_get_pcs_speed_and_duplex_82575 - Retrieve current speed/duplex
731 * @hw: pointer to the HW structure 759 * @hw: pointer to the HW structure
732 * @speed: stores the current speed 760 * @speed: stores the current speed
@@ -1166,6 +1194,22 @@ out:
1166} 1194}
1167 1195
1168/** 1196/**
1197 * igb_power_down_phy_copper_82575 - Remove link during PHY power down
1198 * @hw: pointer to the HW structure
1199 *
1200 * In the case of a PHY power down to save power, or to turn off link during a
1201 * driver unload, or wake on lan is not enabled, remove the link.
1202 **/
1203void igb_power_down_phy_copper_82575(struct e1000_hw *hw)
1204{
1205 /* If the management interface is not enabled, then power down */
1206 if (!(igb_enable_mng_pass_thru(hw) || igb_check_reset_block(hw)))
1207 igb_power_down_phy_copper(hw);
1208
1209 return;
1210}
1211
1212/**
1169 * igb_clear_hw_cntrs_82575 - Clear device specific hardware counters 1213 * igb_clear_hw_cntrs_82575 - Clear device specific hardware counters
1170 * @hw: pointer to the HW structure 1214 * @hw: pointer to the HW structure
1171 * 1215 *
diff --git a/drivers/net/igb/e1000_82575.h b/drivers/net/igb/e1000_82575.h
index bb53083ec61f..fbe1c99c193c 100644
--- a/drivers/net/igb/e1000_82575.h
+++ b/drivers/net/igb/e1000_82575.h
@@ -29,6 +29,8 @@
29#define _E1000_82575_H_ 29#define _E1000_82575_H_
30 30
31extern void igb_shutdown_serdes_link_82575(struct e1000_hw *hw); 31extern void igb_shutdown_serdes_link_82575(struct e1000_hw *hw);
32extern void igb_power_up_serdes_link_82575(struct e1000_hw *hw);
33extern void igb_power_down_phy_copper_82575(struct e1000_hw *hw);
32extern void igb_rx_fifo_flush_82575(struct e1000_hw *hw); 34extern void igb_rx_fifo_flush_82575(struct e1000_hw *hw);
33 35
34#define ID_LED_DEFAULT_82575_SERDES ((ID_LED_DEF1_DEF2 << 12) | \ 36#define ID_LED_DEFAULT_82575_SERDES ((ID_LED_DEF1_DEF2 << 12) | \
diff --git a/drivers/net/igb/e1000_defines.h b/drivers/net/igb/e1000_defines.h
index 6e036ae3138f..c01715070764 100644
--- a/drivers/net/igb/e1000_defines.h
+++ b/drivers/net/igb/e1000_defines.h
@@ -481,6 +481,7 @@
481/* PHY Control Register */ 481/* PHY Control Register */
482#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */ 482#define MII_CR_FULL_DUPLEX 0x0100 /* FDX =1, half duplex =0 */
483#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */ 483#define MII_CR_RESTART_AUTO_NEG 0x0200 /* Restart auto negotiation */
484#define MII_CR_POWER_DOWN 0x0800 /* Power down */
484#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */ 485#define MII_CR_AUTO_NEG_EN 0x1000 /* Auto Neg Enable */
485#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */ 486#define MII_CR_LOOPBACK 0x4000 /* 0 = normal, 1 = loopback */
486#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */ 487#define MII_CR_RESET 0x8000 /* 0 = normal, 1 = PHY reset */
diff --git a/drivers/net/igb/e1000_phy.c b/drivers/net/igb/e1000_phy.c
index 3670a66401b8..cf1f32300923 100644
--- a/drivers/net/igb/e1000_phy.c
+++ b/drivers/net/igb/e1000_phy.c
@@ -1931,6 +1931,41 @@ s32 igb_phy_init_script_igp3(struct e1000_hw *hw)
1931} 1931}
1932 1932
1933/** 1933/**
1934 * igb_power_up_phy_copper - Restore copper link in case of PHY power down
1935 * @hw: pointer to the HW structure
1936 *
1937 * In the case of a PHY power down to save power, or to turn off link during a
1938 * driver unload, restore the link to previous settings.
1939 **/
1940void igb_power_up_phy_copper(struct e1000_hw *hw)
1941{
1942 u16 mii_reg = 0;
1943
1944 /* The PHY will retain its settings across a power down/up cycle */
1945 hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
1946 mii_reg &= ~MII_CR_POWER_DOWN;
1947 hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
1948}
1949
1950/**
1951 * igb_power_down_phy_copper - Power down copper PHY
1952 * @hw: pointer to the HW structure
1953 *
1954 * Power down PHY to save power when interface is down and wake on lan
1955 * is not enabled.
1956 **/
1957void igb_power_down_phy_copper(struct e1000_hw *hw)
1958{
1959 u16 mii_reg = 0;
1960
1961 /* The PHY will retain its settings across a power down/up cycle */
1962 hw->phy.ops.read_reg(hw, PHY_CONTROL, &mii_reg);
1963 mii_reg |= MII_CR_POWER_DOWN;
1964 hw->phy.ops.write_reg(hw, PHY_CONTROL, mii_reg);
1965 msleep(1);
1966}
1967
1968/**
1934 * igb_check_polarity_82580 - Checks the polarity. 1969 * igb_check_polarity_82580 - Checks the polarity.
1935 * @hw: pointer to the HW structure 1970 * @hw: pointer to the HW structure
1936 * 1971 *
diff --git a/drivers/net/igb/e1000_phy.h b/drivers/net/igb/e1000_phy.h
index 555eb54bb6ed..565a6dbb3714 100644
--- a/drivers/net/igb/e1000_phy.h
+++ b/drivers/net/igb/e1000_phy.h
@@ -60,6 +60,8 @@ s32 igb_setup_copper_link(struct e1000_hw *hw);
60s32 igb_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data); 60s32 igb_write_phy_reg_igp(struct e1000_hw *hw, u32 offset, u16 data);
61s32 igb_phy_has_link(struct e1000_hw *hw, u32 iterations, 61s32 igb_phy_has_link(struct e1000_hw *hw, u32 iterations,
62 u32 usec_interval, bool *success); 62 u32 usec_interval, bool *success);
63void igb_power_up_phy_copper(struct e1000_hw *hw);
64void igb_power_down_phy_copper(struct e1000_hw *hw);
63s32 igb_phy_init_script_igp3(struct e1000_hw *hw); 65s32 igb_phy_init_script_igp3(struct e1000_hw *hw);
64s32 igb_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data); 66s32 igb_read_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 *data);
65s32 igb_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data); 67s32 igb_write_phy_reg_mdic(struct e1000_hw *hw, u32 offset, u16 data);
diff --git a/drivers/net/igb/igb.h b/drivers/net/igb/igb.h
index 452a4dee87f8..0e0800dc801d 100644
--- a/drivers/net/igb/igb.h
+++ b/drivers/net/igb/igb.h
@@ -358,6 +358,7 @@ extern void igb_alloc_rx_buffers_adv(struct igb_ring *, int);
358extern void igb_update_stats(struct igb_adapter *); 358extern void igb_update_stats(struct igb_adapter *);
359extern bool igb_has_link(struct igb_adapter *adapter); 359extern bool igb_has_link(struct igb_adapter *adapter);
360extern void igb_set_ethtool_ops(struct net_device *); 360extern void igb_set_ethtool_ops(struct net_device *);
361extern void igb_power_up_link(struct igb_adapter *);
361 362
362static inline s32 igb_reset_phy(struct e1000_hw *hw) 363static inline s32 igb_reset_phy(struct e1000_hw *hw)
363{ 364{
diff --git a/drivers/net/igb/igb_ethtool.c b/drivers/net/igb/igb_ethtool.c
index 4eea03b428c4..485288303f32 100644
--- a/drivers/net/igb/igb_ethtool.c
+++ b/drivers/net/igb/igb_ethtool.c
@@ -1722,6 +1722,9 @@ static void igb_diag_test(struct net_device *netdev,
1722 1722
1723 dev_info(&adapter->pdev->dev, "offline testing starting\n"); 1723 dev_info(&adapter->pdev->dev, "offline testing starting\n");
1724 1724
1725 /* power up link for link test */
1726 igb_power_up_link(adapter);
1727
1725 /* Link test performed before hardware reset so autoneg doesn't 1728 /* Link test performed before hardware reset so autoneg doesn't
1726 * interfere with test result */ 1729 * interfere with test result */
1727 if (igb_link_test(adapter, &data[4])) 1730 if (igb_link_test(adapter, &data[4]))
@@ -1745,6 +1748,8 @@ static void igb_diag_test(struct net_device *netdev,
1745 eth_test->flags |= ETH_TEST_FL_FAILED; 1748 eth_test->flags |= ETH_TEST_FL_FAILED;
1746 1749
1747 igb_reset(adapter); 1750 igb_reset(adapter);
1751 /* power up link for loopback test */
1752 igb_power_up_link(adapter);
1748 if (igb_loopback_test(adapter, &data[3])) 1753 if (igb_loopback_test(adapter, &data[3]))
1749 eth_test->flags |= ETH_TEST_FL_FAILED; 1754 eth_test->flags |= ETH_TEST_FL_FAILED;
1750 1755
@@ -1763,9 +1768,14 @@ static void igb_diag_test(struct net_device *netdev,
1763 dev_open(netdev); 1768 dev_open(netdev);
1764 } else { 1769 } else {
1765 dev_info(&adapter->pdev->dev, "online testing starting\n"); 1770 dev_info(&adapter->pdev->dev, "online testing starting\n");
1766 /* Online tests */ 1771
1767 if (igb_link_test(adapter, &data[4])) 1772 /* PHY is powered down when interface is down */
1768 eth_test->flags |= ETH_TEST_FL_FAILED; 1773 if (!netif_carrier_ok(netdev)) {
1774 data[4] = 0;
1775 } else {
1776 if (igb_link_test(adapter, &data[4]))
1777 eth_test->flags |= ETH_TEST_FL_FAILED;
1778 }
1769 1779
1770 /* Online tests aren't run; pass by default */ 1780 /* Online tests aren't run; pass by default */
1771 data[0] = 0; 1781 data[0] = 0;
diff --git a/drivers/net/igb/igb_main.c b/drivers/net/igb/igb_main.c
index e40319e2ec25..0427e7c10295 100644
--- a/drivers/net/igb/igb_main.c
+++ b/drivers/net/igb/igb_main.c
@@ -1114,6 +1114,29 @@ static void igb_configure(struct igb_adapter *adapter)
1114 adapter->tx_queue_len = netdev->tx_queue_len; 1114 adapter->tx_queue_len = netdev->tx_queue_len;
1115} 1115}
1116 1116
1117/**
1118 * igb_power_up_link - Power up the phy/serdes link
1119 * @adapter: address of board private structure
1120 **/
1121void igb_power_up_link(struct igb_adapter *adapter)
1122{
1123 if (adapter->hw.phy.media_type == e1000_media_type_copper)
1124 igb_power_up_phy_copper(&adapter->hw);
1125 else
1126 igb_power_up_serdes_link_82575(&adapter->hw);
1127}
1128
1129/**
1130 * igb_power_down_link - Power down the phy/serdes link
1131 * @adapter: address of board private structure
1132 */
1133static void igb_power_down_link(struct igb_adapter *adapter)
1134{
1135 if (adapter->hw.phy.media_type == e1000_media_type_copper)
1136 igb_power_down_phy_copper_82575(&adapter->hw);
1137 else
1138 igb_shutdown_serdes_link_82575(&adapter->hw);
1139}
1117 1140
1118/** 1141/**
1119 * igb_up - Open the interface and prepare it to handle traffic 1142 * igb_up - Open the interface and prepare it to handle traffic
@@ -1335,6 +1358,9 @@ void igb_reset(struct igb_adapter *adapter)
1335 wr32(E1000_PCIEMISC, 1358 wr32(E1000_PCIEMISC,
1336 reg & ~E1000_PCIEMISC_LX_DECISION); 1359 reg & ~E1000_PCIEMISC_LX_DECISION);
1337 } 1360 }
1361 if (!netif_running(adapter->netdev))
1362 igb_power_down_link(adapter);
1363
1338 igb_update_mng_vlan(adapter); 1364 igb_update_mng_vlan(adapter);
1339 1365
1340 /* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */ 1366 /* Enable h/w to recognize an 802.1Q VLAN Ethernet packet */
@@ -1717,9 +1743,6 @@ static void __devexit igb_remove(struct pci_dev *pdev)
1717 1743
1718 unregister_netdev(netdev); 1744 unregister_netdev(netdev);
1719 1745
1720 if (!igb_check_reset_block(hw))
1721 igb_reset_phy(hw);
1722
1723 igb_clear_interrupt_scheme(adapter); 1746 igb_clear_interrupt_scheme(adapter);
1724 1747
1725#ifdef CONFIG_PCI_IOV 1748#ifdef CONFIG_PCI_IOV
@@ -1995,7 +2018,7 @@ static int igb_open(struct net_device *netdev)
1995 if (err) 2018 if (err)
1996 goto err_setup_rx; 2019 goto err_setup_rx;
1997 2020
1998 /* e1000_power_up_phy(adapter); */ 2021 igb_power_up_link(adapter);
1999 2022
2000 /* before we allocate an interrupt, we must be ready to handle it. 2023 /* before we allocate an interrupt, we must be ready to handle it.
2001 * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt 2024 * Setting DEBUG_SHIRQ in the kernel makes it fire an interrupt
@@ -2037,7 +2060,7 @@ static int igb_open(struct net_device *netdev)
2037 2060
2038err_req_irq: 2061err_req_irq:
2039 igb_release_hw_control(adapter); 2062 igb_release_hw_control(adapter);
2040 /* e1000_power_down_phy(adapter); */ 2063 igb_power_down_link(adapter);
2041 igb_free_all_rx_resources(adapter); 2064 igb_free_all_rx_resources(adapter);
2042err_setup_rx: 2065err_setup_rx:
2043 igb_free_all_tx_resources(adapter); 2066 igb_free_all_tx_resources(adapter);
@@ -5820,7 +5843,9 @@ static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake)
5820 5843
5821 *enable_wake = wufc || adapter->en_mng_pt; 5844 *enable_wake = wufc || adapter->en_mng_pt;
5822 if (!*enable_wake) 5845 if (!*enable_wake)
5823 igb_shutdown_serdes_link_82575(hw); 5846 igb_power_down_link(adapter);
5847 else
5848 igb_power_up_link(adapter);
5824 5849
5825 /* Release control of h/w to f/w. If f/w is AMT enabled, this 5850 /* Release control of h/w to f/w. If f/w is AMT enabled, this
5826 * would have already happened in close and is redundant. */ 5851 * would have already happened in close and is redundant. */
@@ -5877,8 +5902,6 @@ static int igb_resume(struct pci_dev *pdev)
5877 return -ENOMEM; 5902 return -ENOMEM;
5878 } 5903 }
5879 5904
5880 /* e1000_power_up_phy(adapter); */
5881
5882 igb_reset(adapter); 5905 igb_reset(adapter);
5883 5906
5884 /* let the f/w know that the h/w is now under the control of the 5907 /* let the f/w know that the h/w is now under the control of the