diff options
author | Bruce Allan <bruce.w.allan@intel.com> | 2011-01-06 09:29:52 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2011-01-10 02:44:09 -0500 |
commit | 31dbe5b4ac6fca72dec946e4d0fa7f0913f1d9b1 (patch) | |
tree | 8774e4836c881a7a2c18ddb02f253b66c82aec6c /drivers/net/e1000e | |
parent | fe46f58fa61f025564a3c1e80b789885cb4b0f30 (diff) |
e1000e: power off PHY after reset when interface is down
Some Phys supported by the driver do not remain powered off across a reset
of the device when the interface is down, e.g. on 82571, but not on 82574.
This patch powers down (only when WoL is disabled) the PHY after a reset if
the interface is down and the ethtool diagnostics are not currently running.
The ethtool diagnostic function required a minor re-factor as a result, and
the e1000_[get|put]_hw_control() functions are renamed since they are no
longer static to netdev.c as they are needed by the ethtool diagnostics.
A couple minor whitespace issues were cleaned up, too.
Reported-by: Arthur Jones <ajones@riverbed.com>
Signed-off-by: Bruce Allan <bruce.w.allan@intel.com>
Tested-by: Jeff Pieper <jeffrey.e.pieper@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/e1000e')
-rw-r--r-- | drivers/net/e1000e/e1000.h | 2 | ||||
-rw-r--r-- | drivers/net/e1000e/ethtool.c | 40 | ||||
-rw-r--r-- | drivers/net/e1000e/netdev.c | 46 |
3 files changed, 53 insertions, 35 deletions
diff --git a/drivers/net/e1000e/e1000.h b/drivers/net/e1000e/e1000.h index 4b3802ae1082..5255be753746 100644 --- a/drivers/net/e1000e/e1000.h +++ b/drivers/net/e1000e/e1000.h | |||
@@ -497,6 +497,8 @@ extern void e1000e_free_tx_resources(struct e1000_adapter *adapter); | |||
497 | extern void e1000e_update_stats(struct e1000_adapter *adapter); | 497 | extern void e1000e_update_stats(struct e1000_adapter *adapter); |
498 | extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter); | 498 | extern void e1000e_set_interrupt_capability(struct e1000_adapter *adapter); |
499 | extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter); | 499 | extern void e1000e_reset_interrupt_capability(struct e1000_adapter *adapter); |
500 | extern void e1000e_get_hw_control(struct e1000_adapter *adapter); | ||
501 | extern void e1000e_release_hw_control(struct e1000_adapter *adapter); | ||
500 | extern void e1000e_disable_aspm(struct pci_dev *pdev, u16 state); | 502 | extern void e1000e_disable_aspm(struct pci_dev *pdev, u16 state); |
501 | 503 | ||
502 | extern unsigned int copybreak; | 504 | extern unsigned int copybreak; |
diff --git a/drivers/net/e1000e/ethtool.c b/drivers/net/e1000e/ethtool.c index c942ccab8bca..f8ed03dab9b1 100644 --- a/drivers/net/e1000e/ethtool.c +++ b/drivers/net/e1000e/ethtool.c | |||
@@ -1708,6 +1708,19 @@ static void e1000_diag_test(struct net_device *netdev, | |||
1708 | bool if_running = netif_running(netdev); | 1708 | bool if_running = netif_running(netdev); |
1709 | 1709 | ||
1710 | set_bit(__E1000_TESTING, &adapter->state); | 1710 | set_bit(__E1000_TESTING, &adapter->state); |
1711 | |||
1712 | if (!if_running) { | ||
1713 | /* Get control of and reset hardware */ | ||
1714 | if (adapter->flags & FLAG_HAS_AMT) | ||
1715 | e1000e_get_hw_control(adapter); | ||
1716 | |||
1717 | e1000e_power_up_phy(adapter); | ||
1718 | |||
1719 | adapter->hw.phy.autoneg_wait_to_complete = 1; | ||
1720 | e1000e_reset(adapter); | ||
1721 | adapter->hw.phy.autoneg_wait_to_complete = 0; | ||
1722 | } | ||
1723 | |||
1711 | if (eth_test->flags == ETH_TEST_FL_OFFLINE) { | 1724 | if (eth_test->flags == ETH_TEST_FL_OFFLINE) { |
1712 | /* Offline tests */ | 1725 | /* Offline tests */ |
1713 | 1726 | ||
@@ -1721,8 +1734,6 @@ static void e1000_diag_test(struct net_device *netdev, | |||
1721 | if (if_running) | 1734 | if (if_running) |
1722 | /* indicate we're in test mode */ | 1735 | /* indicate we're in test mode */ |
1723 | dev_close(netdev); | 1736 | dev_close(netdev); |
1724 | else | ||
1725 | e1000e_reset(adapter); | ||
1726 | 1737 | ||
1727 | if (e1000_reg_test(adapter, &data[0])) | 1738 | if (e1000_reg_test(adapter, &data[0])) |
1728 | eth_test->flags |= ETH_TEST_FL_FAILED; | 1739 | eth_test->flags |= ETH_TEST_FL_FAILED; |
@@ -1736,8 +1747,6 @@ static void e1000_diag_test(struct net_device *netdev, | |||
1736 | eth_test->flags |= ETH_TEST_FL_FAILED; | 1747 | eth_test->flags |= ETH_TEST_FL_FAILED; |
1737 | 1748 | ||
1738 | e1000e_reset(adapter); | 1749 | e1000e_reset(adapter); |
1739 | /* make sure the phy is powered up */ | ||
1740 | e1000e_power_up_phy(adapter); | ||
1741 | if (e1000_loopback_test(adapter, &data[3])) | 1750 | if (e1000_loopback_test(adapter, &data[3])) |
1742 | eth_test->flags |= ETH_TEST_FL_FAILED; | 1751 | eth_test->flags |= ETH_TEST_FL_FAILED; |
1743 | 1752 | ||
@@ -1759,28 +1768,29 @@ static void e1000_diag_test(struct net_device *netdev, | |||
1759 | if (if_running) | 1768 | if (if_running) |
1760 | dev_open(netdev); | 1769 | dev_open(netdev); |
1761 | } else { | 1770 | } else { |
1762 | if (!if_running && (adapter->flags & FLAG_HAS_AMT)) { | 1771 | /* Online tests */ |
1763 | clear_bit(__E1000_TESTING, &adapter->state); | ||
1764 | dev_open(netdev); | ||
1765 | set_bit(__E1000_TESTING, &adapter->state); | ||
1766 | } | ||
1767 | 1772 | ||
1768 | e_info("online testing starting\n"); | 1773 | e_info("online testing starting\n"); |
1769 | /* Online tests */ | ||
1770 | if (e1000_link_test(adapter, &data[4])) | ||
1771 | eth_test->flags |= ETH_TEST_FL_FAILED; | ||
1772 | 1774 | ||
1773 | /* Online tests aren't run; pass by default */ | 1775 | /* register, eeprom, intr and loopback tests not run online */ |
1774 | data[0] = 0; | 1776 | data[0] = 0; |
1775 | data[1] = 0; | 1777 | data[1] = 0; |
1776 | data[2] = 0; | 1778 | data[2] = 0; |
1777 | data[3] = 0; | 1779 | data[3] = 0; |
1778 | 1780 | ||
1779 | if (!if_running && (adapter->flags & FLAG_HAS_AMT)) | 1781 | if (e1000_link_test(adapter, &data[4])) |
1780 | dev_close(netdev); | 1782 | eth_test->flags |= ETH_TEST_FL_FAILED; |
1781 | 1783 | ||
1782 | clear_bit(__E1000_TESTING, &adapter->state); | 1784 | clear_bit(__E1000_TESTING, &adapter->state); |
1783 | } | 1785 | } |
1786 | |||
1787 | if (!if_running) { | ||
1788 | e1000e_reset(adapter); | ||
1789 | |||
1790 | if (adapter->flags & FLAG_HAS_AMT) | ||
1791 | e1000e_release_hw_control(adapter); | ||
1792 | } | ||
1793 | |||
1784 | msleep_interruptible(4 * 1000); | 1794 | msleep_interruptible(4 * 1000); |
1785 | } | 1795 | } |
1786 | 1796 | ||
diff --git a/drivers/net/e1000e/netdev.c b/drivers/net/e1000e/netdev.c index 98729a6fb096..fa5b60452547 100644 --- a/drivers/net/e1000e/netdev.c +++ b/drivers/net/e1000e/netdev.c | |||
@@ -1980,15 +1980,15 @@ static void e1000_irq_enable(struct e1000_adapter *adapter) | |||
1980 | } | 1980 | } |
1981 | 1981 | ||
1982 | /** | 1982 | /** |
1983 | * e1000_get_hw_control - get control of the h/w from f/w | 1983 | * e1000e_get_hw_control - get control of the h/w from f/w |
1984 | * @adapter: address of board private structure | 1984 | * @adapter: address of board private structure |
1985 | * | 1985 | * |
1986 | * e1000_get_hw_control sets {CTRL_EXT|SWSM}:DRV_LOAD bit. | 1986 | * e1000e_get_hw_control sets {CTRL_EXT|SWSM}:DRV_LOAD bit. |
1987 | * For ASF and Pass Through versions of f/w this means that | 1987 | * For ASF and Pass Through versions of f/w this means that |
1988 | * the driver is loaded. For AMT version (only with 82573) | 1988 | * the driver is loaded. For AMT version (only with 82573) |
1989 | * of the f/w this means that the network i/f is open. | 1989 | * of the f/w this means that the network i/f is open. |
1990 | **/ | 1990 | **/ |
1991 | static void e1000_get_hw_control(struct e1000_adapter *adapter) | 1991 | void e1000e_get_hw_control(struct e1000_adapter *adapter) |
1992 | { | 1992 | { |
1993 | struct e1000_hw *hw = &adapter->hw; | 1993 | struct e1000_hw *hw = &adapter->hw; |
1994 | u32 ctrl_ext; | 1994 | u32 ctrl_ext; |
@@ -2005,16 +2005,16 @@ static void e1000_get_hw_control(struct e1000_adapter *adapter) | |||
2005 | } | 2005 | } |
2006 | 2006 | ||
2007 | /** | 2007 | /** |
2008 | * e1000_release_hw_control - release control of the h/w to f/w | 2008 | * e1000e_release_hw_control - release control of the h/w to f/w |
2009 | * @adapter: address of board private structure | 2009 | * @adapter: address of board private structure |
2010 | * | 2010 | * |
2011 | * e1000_release_hw_control resets {CTRL_EXT|SWSM}:DRV_LOAD bit. | 2011 | * e1000e_release_hw_control resets {CTRL_EXT|SWSM}:DRV_LOAD bit. |
2012 | * For ASF and Pass Through versions of f/w this means that the | 2012 | * For ASF and Pass Through versions of f/w this means that the |
2013 | * driver is no longer loaded. For AMT version (only with 82573) i | 2013 | * driver is no longer loaded. For AMT version (only with 82573) i |
2014 | * of the f/w this means that the network i/f is closed. | 2014 | * of the f/w this means that the network i/f is closed. |
2015 | * | 2015 | * |
2016 | **/ | 2016 | **/ |
2017 | static void e1000_release_hw_control(struct e1000_adapter *adapter) | 2017 | void e1000e_release_hw_control(struct e1000_adapter *adapter) |
2018 | { | 2018 | { |
2019 | struct e1000_hw *hw = &adapter->hw; | 2019 | struct e1000_hw *hw = &adapter->hw; |
2020 | u32 ctrl_ext; | 2020 | u32 ctrl_ext; |
@@ -2445,7 +2445,7 @@ static void e1000_vlan_rx_kill_vid(struct net_device *netdev, u16 vid) | |||
2445 | E1000_MNG_DHCP_COOKIE_STATUS_VLAN) && | 2445 | E1000_MNG_DHCP_COOKIE_STATUS_VLAN) && |
2446 | (vid == adapter->mng_vlan_id)) { | 2446 | (vid == adapter->mng_vlan_id)) { |
2447 | /* release control to f/w */ | 2447 | /* release control to f/w */ |
2448 | e1000_release_hw_control(adapter); | 2448 | e1000e_release_hw_control(adapter); |
2449 | return; | 2449 | return; |
2450 | } | 2450 | } |
2451 | 2451 | ||
@@ -3187,7 +3187,6 @@ void e1000e_reset(struct e1000_adapter *adapter) | |||
3187 | ew32(PBA, pba); | 3187 | ew32(PBA, pba); |
3188 | } | 3188 | } |
3189 | 3189 | ||
3190 | |||
3191 | /* | 3190 | /* |
3192 | * flow control settings | 3191 | * flow control settings |
3193 | * | 3192 | * |
@@ -3275,7 +3274,7 @@ void e1000e_reset(struct e1000_adapter *adapter) | |||
3275 | * that the network interface is in control | 3274 | * that the network interface is in control |
3276 | */ | 3275 | */ |
3277 | if (adapter->flags & FLAG_HAS_AMT) | 3276 | if (adapter->flags & FLAG_HAS_AMT) |
3278 | e1000_get_hw_control(adapter); | 3277 | e1000e_get_hw_control(adapter); |
3279 | 3278 | ||
3280 | ew32(WUC, 0); | 3279 | ew32(WUC, 0); |
3281 | 3280 | ||
@@ -3288,6 +3287,13 @@ void e1000e_reset(struct e1000_adapter *adapter) | |||
3288 | ew32(VET, ETH_P_8021Q); | 3287 | ew32(VET, ETH_P_8021Q); |
3289 | 3288 | ||
3290 | e1000e_reset_adaptive(hw); | 3289 | e1000e_reset_adaptive(hw); |
3290 | |||
3291 | if (!netif_running(adapter->netdev) && | ||
3292 | !test_bit(__E1000_TESTING, &adapter->state)) { | ||
3293 | e1000_power_down_phy(adapter); | ||
3294 | return; | ||
3295 | } | ||
3296 | |||
3291 | e1000_get_phy_info(hw); | 3297 | e1000_get_phy_info(hw); |
3292 | 3298 | ||
3293 | if ((adapter->flags & FLAG_HAS_SMART_POWER_DOWN) && | 3299 | if ((adapter->flags & FLAG_HAS_SMART_POWER_DOWN) && |
@@ -3573,7 +3579,7 @@ static int e1000_open(struct net_device *netdev) | |||
3573 | * interface is now open and reset the part to a known state. | 3579 | * interface is now open and reset the part to a known state. |
3574 | */ | 3580 | */ |
3575 | if (adapter->flags & FLAG_HAS_AMT) { | 3581 | if (adapter->flags & FLAG_HAS_AMT) { |
3576 | e1000_get_hw_control(adapter); | 3582 | e1000e_get_hw_control(adapter); |
3577 | e1000e_reset(adapter); | 3583 | e1000e_reset(adapter); |
3578 | } | 3584 | } |
3579 | 3585 | ||
@@ -3637,7 +3643,7 @@ static int e1000_open(struct net_device *netdev) | |||
3637 | return 0; | 3643 | return 0; |
3638 | 3644 | ||
3639 | err_req_irq: | 3645 | err_req_irq: |
3640 | e1000_release_hw_control(adapter); | 3646 | e1000e_release_hw_control(adapter); |
3641 | e1000_power_down_phy(adapter); | 3647 | e1000_power_down_phy(adapter); |
3642 | e1000e_free_rx_resources(adapter); | 3648 | e1000e_free_rx_resources(adapter); |
3643 | err_setup_rx: | 3649 | err_setup_rx: |
@@ -3692,8 +3698,9 @@ static int e1000_close(struct net_device *netdev) | |||
3692 | * If AMT is enabled, let the firmware know that the network | 3698 | * If AMT is enabled, let the firmware know that the network |
3693 | * interface is now closed | 3699 | * interface is now closed |
3694 | */ | 3700 | */ |
3695 | if (adapter->flags & FLAG_HAS_AMT) | 3701 | if ((adapter->flags & FLAG_HAS_AMT) && |
3696 | e1000_release_hw_control(adapter); | 3702 | !test_bit(__E1000_TESTING, &adapter->state)) |
3703 | e1000e_release_hw_control(adapter); | ||
3697 | 3704 | ||
3698 | if ((adapter->flags & FLAG_HAS_ERT) || | 3705 | if ((adapter->flags & FLAG_HAS_ERT) || |
3699 | (adapter->hw.mac.type == e1000_pch2lan)) | 3706 | (adapter->hw.mac.type == e1000_pch2lan)) |
@@ -5212,7 +5219,7 @@ static int __e1000_shutdown(struct pci_dev *pdev, bool *enable_wake, | |||
5212 | * Release control of h/w to f/w. If f/w is AMT enabled, this | 5219 | * Release control of h/w to f/w. If f/w is AMT enabled, this |
5213 | * would have already happened in close and is redundant. | 5220 | * would have already happened in close and is redundant. |
5214 | */ | 5221 | */ |
5215 | e1000_release_hw_control(adapter); | 5222 | e1000e_release_hw_control(adapter); |
5216 | 5223 | ||
5217 | pci_disable_device(pdev); | 5224 | pci_disable_device(pdev); |
5218 | 5225 | ||
@@ -5369,7 +5376,7 @@ static int __e1000_resume(struct pci_dev *pdev) | |||
5369 | * under the control of the driver. | 5376 | * under the control of the driver. |
5370 | */ | 5377 | */ |
5371 | if (!(adapter->flags & FLAG_HAS_AMT)) | 5378 | if (!(adapter->flags & FLAG_HAS_AMT)) |
5372 | e1000_get_hw_control(adapter); | 5379 | e1000e_get_hw_control(adapter); |
5373 | 5380 | ||
5374 | return 0; | 5381 | return 0; |
5375 | } | 5382 | } |
@@ -5616,7 +5623,7 @@ static void e1000_io_resume(struct pci_dev *pdev) | |||
5616 | * under the control of the driver. | 5623 | * under the control of the driver. |
5617 | */ | 5624 | */ |
5618 | if (!(adapter->flags & FLAG_HAS_AMT)) | 5625 | if (!(adapter->flags & FLAG_HAS_AMT)) |
5619 | e1000_get_hw_control(adapter); | 5626 | e1000e_get_hw_control(adapter); |
5620 | 5627 | ||
5621 | } | 5628 | } |
5622 | 5629 | ||
@@ -5966,7 +5973,7 @@ static int __devinit e1000_probe(struct pci_dev *pdev, | |||
5966 | * under the control of the driver. | 5973 | * under the control of the driver. |
5967 | */ | 5974 | */ |
5968 | if (!(adapter->flags & FLAG_HAS_AMT)) | 5975 | if (!(adapter->flags & FLAG_HAS_AMT)) |
5969 | e1000_get_hw_control(adapter); | 5976 | e1000e_get_hw_control(adapter); |
5970 | 5977 | ||
5971 | strncpy(netdev->name, "eth%d", sizeof(netdev->name) - 1); | 5978 | strncpy(netdev->name, "eth%d", sizeof(netdev->name) - 1); |
5972 | err = register_netdev(netdev); | 5979 | err = register_netdev(netdev); |
@@ -5985,12 +5992,11 @@ static int __devinit e1000_probe(struct pci_dev *pdev, | |||
5985 | 5992 | ||
5986 | err_register: | 5993 | err_register: |
5987 | if (!(adapter->flags & FLAG_HAS_AMT)) | 5994 | if (!(adapter->flags & FLAG_HAS_AMT)) |
5988 | e1000_release_hw_control(adapter); | 5995 | e1000e_release_hw_control(adapter); |
5989 | err_eeprom: | 5996 | err_eeprom: |
5990 | if (!e1000_check_reset_block(&adapter->hw)) | 5997 | if (!e1000_check_reset_block(&adapter->hw)) |
5991 | e1000_phy_hw_reset(&adapter->hw); | 5998 | e1000_phy_hw_reset(&adapter->hw); |
5992 | err_hw_init: | 5999 | err_hw_init: |
5993 | |||
5994 | kfree(adapter->tx_ring); | 6000 | kfree(adapter->tx_ring); |
5995 | kfree(adapter->rx_ring); | 6001 | kfree(adapter->rx_ring); |
5996 | err_sw_init: | 6002 | err_sw_init: |
@@ -6056,7 +6062,7 @@ static void __devexit e1000_remove(struct pci_dev *pdev) | |||
6056 | * Release control of h/w to f/w. If f/w is AMT enabled, this | 6062 | * Release control of h/w to f/w. If f/w is AMT enabled, this |
6057 | * would have already happened in close and is redundant. | 6063 | * would have already happened in close and is redundant. |
6058 | */ | 6064 | */ |
6059 | e1000_release_hw_control(adapter); | 6065 | e1000e_release_hw_control(adapter); |
6060 | 6066 | ||
6061 | e1000e_reset_interrupt_capability(adapter); | 6067 | e1000e_reset_interrupt_capability(adapter); |
6062 | kfree(adapter->tx_ring); | 6068 | kfree(adapter->tx_ring); |