aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet
diff options
context:
space:
mode:
authorYan, Zheng <zheng.z.yan@intel.com>2012-01-04 15:23:37 -0500
committerDavid S. Miller <davem@davemloft.net>2012-01-05 13:12:03 -0500
commit749ab2cd127046df79084b6b9165b23491b1db5f (patch)
treefd91fc5d9907d6cffd74876c80acc386d2dd7dac /drivers/net/ethernet
parentbdbc063129e811264cd6c311d8c2d9b95de01231 (diff)
igb: add basic runtime PM support
Use the runtime power management framework to add basic runtime PM support to the igb driver. Namely, make the driver suspend the device when the link is off and set it up for generating a wakeup event after the link has been detected again. This feature is disabled by default. Based on e1000e's runtime PM code. Changes since v1: Don't suspend the device when shutting down the interface. Avoid race between runtime suspending and ethtool operations. Signed-off-by: Zheng Yan <zheng.z.yan@intel.com> Tested-by: Aaron Brown <aaron.f.brown@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/ethernet')
-rw-r--r--drivers/net/ethernet/intel/igb/igb_ethtool.c16
-rw-r--r--drivers/net/ethernet/intel/igb/igb_main.c136
2 files changed, 133 insertions, 19 deletions
diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
index f1206be4e71d..7998bf4d5946 100644
--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
+++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
@@ -36,6 +36,7 @@
36#include <linux/ethtool.h> 36#include <linux/ethtool.h>
37#include <linux/sched.h> 37#include <linux/sched.h>
38#include <linux/slab.h> 38#include <linux/slab.h>
39#include <linux/pm_runtime.h>
39 40
40#include "igb.h" 41#include "igb.h"
41 42
@@ -2161,6 +2162,19 @@ static void igb_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
2161 } 2162 }
2162} 2163}
2163 2164
2165static int igb_ethtool_begin(struct net_device *netdev)
2166{
2167 struct igb_adapter *adapter = netdev_priv(netdev);
2168 pm_runtime_get_sync(&adapter->pdev->dev);
2169 return 0;
2170}
2171
2172static void igb_ethtool_complete(struct net_device *netdev)
2173{
2174 struct igb_adapter *adapter = netdev_priv(netdev);
2175 pm_runtime_put(&adapter->pdev->dev);
2176}
2177
2164static const struct ethtool_ops igb_ethtool_ops = { 2178static const struct ethtool_ops igb_ethtool_ops = {
2165 .get_settings = igb_get_settings, 2179 .get_settings = igb_get_settings,
2166 .set_settings = igb_set_settings, 2180 .set_settings = igb_set_settings,
@@ -2187,6 +2201,8 @@ static const struct ethtool_ops igb_ethtool_ops = {
2187 .get_ethtool_stats = igb_get_ethtool_stats, 2201 .get_ethtool_stats = igb_get_ethtool_stats,
2188 .get_coalesce = igb_get_coalesce, 2202 .get_coalesce = igb_get_coalesce,
2189 .set_coalesce = igb_set_coalesce, 2203 .set_coalesce = igb_set_coalesce,
2204 .begin = igb_ethtool_begin,
2205 .complete = igb_ethtool_complete,
2190}; 2206};
2191 2207
2192void igb_set_ethtool_ops(struct net_device *netdev) 2208void igb_set_ethtool_ops(struct net_device *netdev)
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index dcc68cc19da6..fac71e21e0a4 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -53,6 +53,7 @@
53#include <linux/if_ether.h> 53#include <linux/if_ether.h>
54#include <linux/aer.h> 54#include <linux/aer.h>
55#include <linux/prefetch.h> 55#include <linux/prefetch.h>
56#include <linux/pm_runtime.h>
56#ifdef CONFIG_IGB_DCA 57#ifdef CONFIG_IGB_DCA
57#include <linux/dca.h> 58#include <linux/dca.h>
58#endif 59#endif
@@ -172,8 +173,18 @@ static int igb_check_vf_assignment(struct igb_adapter *adapter);
172#endif 173#endif
173 174
174#ifdef CONFIG_PM 175#ifdef CONFIG_PM
175static int igb_suspend(struct pci_dev *, pm_message_t); 176static int igb_suspend(struct device *);
176static int igb_resume(struct pci_dev *); 177static int igb_resume(struct device *);
178#ifdef CONFIG_PM_RUNTIME
179static int igb_runtime_suspend(struct device *dev);
180static int igb_runtime_resume(struct device *dev);
181static int igb_runtime_idle(struct device *dev);
182#endif
183static const struct dev_pm_ops igb_pm_ops = {
184 SET_SYSTEM_SLEEP_PM_OPS(igb_suspend, igb_resume)
185 SET_RUNTIME_PM_OPS(igb_runtime_suspend, igb_runtime_resume,
186 igb_runtime_idle)
187};
177#endif 188#endif
178static void igb_shutdown(struct pci_dev *); 189static void igb_shutdown(struct pci_dev *);
179#ifdef CONFIG_IGB_DCA 190#ifdef CONFIG_IGB_DCA
@@ -214,9 +225,7 @@ static struct pci_driver igb_driver = {
214 .probe = igb_probe, 225 .probe = igb_probe,
215 .remove = __devexit_p(igb_remove), 226 .remove = __devexit_p(igb_remove),
216#ifdef CONFIG_PM 227#ifdef CONFIG_PM
217 /* Power Management Hooks */ 228 .driver.pm = &igb_pm_ops,
218 .suspend = igb_suspend,
219 .resume = igb_resume,
220#endif 229#endif
221 .shutdown = igb_shutdown, 230 .shutdown = igb_shutdown,
222 .err_handler = &igb_err_handler 231 .err_handler = &igb_err_handler
@@ -2111,6 +2120,8 @@ static int __devinit igb_probe(struct pci_dev *pdev,
2111 default: 2120 default:
2112 break; 2121 break;
2113 } 2122 }
2123
2124 pm_runtime_put_noidle(&pdev->dev);
2114 return 0; 2125 return 0;
2115 2126
2116err_register: 2127err_register:
@@ -2150,6 +2161,8 @@ static void __devexit igb_remove(struct pci_dev *pdev)
2150 struct igb_adapter *adapter = netdev_priv(netdev); 2161 struct igb_adapter *adapter = netdev_priv(netdev);
2151 struct e1000_hw *hw = &adapter->hw; 2162 struct e1000_hw *hw = &adapter->hw;
2152 2163
2164 pm_runtime_get_noresume(&pdev->dev);
2165
2153 /* 2166 /*
2154 * The watchdog timer may be rescheduled, so explicitly 2167 * The watchdog timer may be rescheduled, so explicitly
2155 * disable watchdog from being rescheduled. 2168 * disable watchdog from being rescheduled.
@@ -2472,16 +2485,22 @@ static int __devinit igb_sw_init(struct igb_adapter *adapter)
2472 * handler is registered with the OS, the watchdog timer is started, 2485 * handler is registered with the OS, the watchdog timer is started,
2473 * and the stack is notified that the interface is ready. 2486 * and the stack is notified that the interface is ready.
2474 **/ 2487 **/
2475static int igb_open(struct net_device *netdev) 2488static int __igb_open(struct net_device *netdev, bool resuming)
2476{ 2489{
2477 struct igb_adapter *adapter = netdev_priv(netdev); 2490 struct igb_adapter *adapter = netdev_priv(netdev);
2478 struct e1000_hw *hw = &adapter->hw; 2491 struct e1000_hw *hw = &adapter->hw;
2492 struct pci_dev *pdev = adapter->pdev;
2479 int err; 2493 int err;
2480 int i; 2494 int i;
2481 2495
2482 /* disallow open during test */ 2496 /* disallow open during test */
2483 if (test_bit(__IGB_TESTING, &adapter->state)) 2497 if (test_bit(__IGB_TESTING, &adapter->state)) {
2498 WARN_ON(resuming);
2484 return -EBUSY; 2499 return -EBUSY;
2500 }
2501
2502 if (!resuming)
2503 pm_runtime_get_sync(&pdev->dev);
2485 2504
2486 netif_carrier_off(netdev); 2505 netif_carrier_off(netdev);
2487 2506
@@ -2527,6 +2546,9 @@ static int igb_open(struct net_device *netdev)
2527 2546
2528 netif_tx_start_all_queues(netdev); 2547 netif_tx_start_all_queues(netdev);
2529 2548
2549 if (!resuming)
2550 pm_runtime_put(&pdev->dev);
2551
2530 /* start the watchdog. */ 2552 /* start the watchdog. */
2531 hw->mac.get_link_status = 1; 2553 hw->mac.get_link_status = 1;
2532 schedule_work(&adapter->watchdog_task); 2554 schedule_work(&adapter->watchdog_task);
@@ -2541,10 +2563,17 @@ err_setup_rx:
2541 igb_free_all_tx_resources(adapter); 2563 igb_free_all_tx_resources(adapter);
2542err_setup_tx: 2564err_setup_tx:
2543 igb_reset(adapter); 2565 igb_reset(adapter);
2566 if (!resuming)
2567 pm_runtime_put(&pdev->dev);
2544 2568
2545 return err; 2569 return err;
2546} 2570}
2547 2571
2572static int igb_open(struct net_device *netdev)
2573{
2574 return __igb_open(netdev, false);
2575}
2576
2548/** 2577/**
2549 * igb_close - Disables a network interface 2578 * igb_close - Disables a network interface
2550 * @netdev: network interface device structure 2579 * @netdev: network interface device structure
@@ -2556,21 +2585,32 @@ err_setup_tx:
2556 * needs to be disabled. A global MAC reset is issued to stop the 2585 * needs to be disabled. A global MAC reset is issued to stop the
2557 * hardware, and all transmit and receive resources are freed. 2586 * hardware, and all transmit and receive resources are freed.
2558 **/ 2587 **/
2559static int igb_close(struct net_device *netdev) 2588static int __igb_close(struct net_device *netdev, bool suspending)
2560{ 2589{
2561 struct igb_adapter *adapter = netdev_priv(netdev); 2590 struct igb_adapter *adapter = netdev_priv(netdev);
2591 struct pci_dev *pdev = adapter->pdev;
2562 2592
2563 WARN_ON(test_bit(__IGB_RESETTING, &adapter->state)); 2593 WARN_ON(test_bit(__IGB_RESETTING, &adapter->state));
2564 igb_down(adapter);
2565 2594
2595 if (!suspending)
2596 pm_runtime_get_sync(&pdev->dev);
2597
2598 igb_down(adapter);
2566 igb_free_irq(adapter); 2599 igb_free_irq(adapter);
2567 2600
2568 igb_free_all_tx_resources(adapter); 2601 igb_free_all_tx_resources(adapter);
2569 igb_free_all_rx_resources(adapter); 2602 igb_free_all_rx_resources(adapter);
2570 2603
2604 if (!suspending)
2605 pm_runtime_put_sync(&pdev->dev);
2571 return 0; 2606 return 0;
2572} 2607}
2573 2608
2609static int igb_close(struct net_device *netdev)
2610{
2611 return __igb_close(netdev, false);
2612}
2613
2574/** 2614/**
2575 * igb_setup_tx_resources - allocate Tx resources (Descriptors) 2615 * igb_setup_tx_resources - allocate Tx resources (Descriptors)
2576 * @tx_ring: tx descriptor ring (for a specific queue) to setup 2616 * @tx_ring: tx descriptor ring (for a specific queue) to setup
@@ -3631,6 +3671,9 @@ static void igb_watchdog_task(struct work_struct *work)
3631 3671
3632 link = igb_has_link(adapter); 3672 link = igb_has_link(adapter);
3633 if (link) { 3673 if (link) {
3674 /* Cancel scheduled suspend requests. */
3675 pm_runtime_resume(netdev->dev.parent);
3676
3634 if (!netif_carrier_ok(netdev)) { 3677 if (!netif_carrier_ok(netdev)) {
3635 u32 ctrl; 3678 u32 ctrl;
3636 hw->mac.ops.get_speed_and_duplex(hw, 3679 hw->mac.ops.get_speed_and_duplex(hw,
@@ -3702,6 +3745,9 @@ static void igb_watchdog_task(struct work_struct *work)
3702 if (!test_bit(__IGB_DOWN, &adapter->state)) 3745 if (!test_bit(__IGB_DOWN, &adapter->state))
3703 mod_timer(&adapter->phy_info_timer, 3746 mod_timer(&adapter->phy_info_timer,
3704 round_jiffies(jiffies + 2 * HZ)); 3747 round_jiffies(jiffies + 2 * HZ));
3748
3749 pm_schedule_suspend(netdev->dev.parent,
3750 MSEC_PER_SEC * 5);
3705 } 3751 }
3706 } 3752 }
3707 3753
@@ -6588,13 +6634,14 @@ err_inval:
6588 return -EINVAL; 6634 return -EINVAL;
6589} 6635}
6590 6636
6591static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake) 6637static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake,
6638 bool runtime)
6592{ 6639{
6593 struct net_device *netdev = pci_get_drvdata(pdev); 6640 struct net_device *netdev = pci_get_drvdata(pdev);
6594 struct igb_adapter *adapter = netdev_priv(netdev); 6641 struct igb_adapter *adapter = netdev_priv(netdev);
6595 struct e1000_hw *hw = &adapter->hw; 6642 struct e1000_hw *hw = &adapter->hw;
6596 u32 ctrl, rctl, status; 6643 u32 ctrl, rctl, status;
6597 u32 wufc = adapter->wol; 6644 u32 wufc = runtime ? E1000_WUFC_LNKC : adapter->wol;
6598#ifdef CONFIG_PM 6645#ifdef CONFIG_PM
6599 int retval = 0; 6646 int retval = 0;
6600#endif 6647#endif
@@ -6602,7 +6649,7 @@ static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake)
6602 netif_device_detach(netdev); 6649 netif_device_detach(netdev);
6603 6650
6604 if (netif_running(netdev)) 6651 if (netif_running(netdev))
6605 igb_close(netdev); 6652 __igb_close(netdev, true);
6606 6653
6607 igb_clear_interrupt_scheme(adapter); 6654 igb_clear_interrupt_scheme(adapter);
6608 6655
@@ -6661,12 +6708,13 @@ static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake)
6661} 6708}
6662 6709
6663#ifdef CONFIG_PM 6710#ifdef CONFIG_PM
6664static int igb_suspend(struct pci_dev *pdev, pm_message_t state) 6711static int igb_suspend(struct device *dev)
6665{ 6712{
6666 int retval; 6713 int retval;
6667 bool wake; 6714 bool wake;
6715 struct pci_dev *pdev = to_pci_dev(dev);
6668 6716
6669 retval = __igb_shutdown(pdev, &wake); 6717 retval = __igb_shutdown(pdev, &wake, 0);
6670 if (retval) 6718 if (retval)
6671 return retval; 6719 return retval;
6672 6720
@@ -6680,8 +6728,9 @@ static int igb_suspend(struct pci_dev *pdev, pm_message_t state)
6680 return 0; 6728 return 0;
6681} 6729}
6682 6730
6683static int igb_resume(struct pci_dev *pdev) 6731static int igb_resume(struct device *dev)
6684{ 6732{
6733 struct pci_dev *pdev = to_pci_dev(dev);
6685 struct net_device *netdev = pci_get_drvdata(pdev); 6734 struct net_device *netdev = pci_get_drvdata(pdev);
6686 struct igb_adapter *adapter = netdev_priv(netdev); 6735 struct igb_adapter *adapter = netdev_priv(netdev);
6687 struct e1000_hw *hw = &adapter->hw; 6736 struct e1000_hw *hw = &adapter->hw;
@@ -6702,7 +6751,18 @@ static int igb_resume(struct pci_dev *pdev)
6702 pci_enable_wake(pdev, PCI_D3hot, 0); 6751 pci_enable_wake(pdev, PCI_D3hot, 0);
6703 pci_enable_wake(pdev, PCI_D3cold, 0); 6752 pci_enable_wake(pdev, PCI_D3cold, 0);
6704 6753
6705 if (igb_init_interrupt_scheme(adapter)) { 6754 if (!rtnl_is_locked()) {
6755 /*
6756 * shut up ASSERT_RTNL() warning in
6757 * netif_set_real_num_tx/rx_queues.
6758 */
6759 rtnl_lock();
6760 err = igb_init_interrupt_scheme(adapter);
6761 rtnl_unlock();
6762 } else {
6763 err = igb_init_interrupt_scheme(adapter);
6764 }
6765 if (err) {
6706 dev_err(&pdev->dev, "Unable to allocate memory for queues\n"); 6766 dev_err(&pdev->dev, "Unable to allocate memory for queues\n");
6707 return -ENOMEM; 6767 return -ENOMEM;
6708 } 6768 }
@@ -6715,23 +6775,61 @@ static int igb_resume(struct pci_dev *pdev)
6715 6775
6716 wr32(E1000_WUS, ~0); 6776 wr32(E1000_WUS, ~0);
6717 6777
6718 if (netif_running(netdev)) { 6778 if (netdev->flags & IFF_UP) {
6719 err = igb_open(netdev); 6779 err = __igb_open(netdev, true);
6720 if (err) 6780 if (err)
6721 return err; 6781 return err;
6722 } 6782 }
6723 6783
6724 netif_device_attach(netdev); 6784 netif_device_attach(netdev);
6785 return 0;
6786}
6787
6788#ifdef CONFIG_PM_RUNTIME
6789static int igb_runtime_idle(struct device *dev)
6790{
6791 struct pci_dev *pdev = to_pci_dev(dev);
6792 struct net_device *netdev = pci_get_drvdata(pdev);
6793 struct igb_adapter *adapter = netdev_priv(netdev);
6794
6795 if (!igb_has_link(adapter))
6796 pm_schedule_suspend(dev, MSEC_PER_SEC * 5);
6797
6798 return -EBUSY;
6799}
6800
6801static int igb_runtime_suspend(struct device *dev)
6802{
6803 struct pci_dev *pdev = to_pci_dev(dev);
6804 int retval;
6805 bool wake;
6806
6807 retval = __igb_shutdown(pdev, &wake, 1);
6808 if (retval)
6809 return retval;
6810
6811 if (wake) {
6812 pci_prepare_to_sleep(pdev);
6813 } else {
6814 pci_wake_from_d3(pdev, false);
6815 pci_set_power_state(pdev, PCI_D3hot);
6816 }
6725 6817
6726 return 0; 6818 return 0;
6727} 6819}
6820
6821static int igb_runtime_resume(struct device *dev)
6822{
6823 return igb_resume(dev);
6824}
6825#endif /* CONFIG_PM_RUNTIME */
6728#endif 6826#endif
6729 6827
6730static void igb_shutdown(struct pci_dev *pdev) 6828static void igb_shutdown(struct pci_dev *pdev)
6731{ 6829{
6732 bool wake; 6830 bool wake;
6733 6831
6734 __igb_shutdown(pdev, &wake); 6832 __igb_shutdown(pdev, &wake, 0);
6735 6833
6736 if (system_state == SYSTEM_POWER_OFF) { 6834 if (system_state == SYSTEM_POWER_OFF) {
6737 pci_wake_from_d3(pdev, wake); 6835 pci_wake_from_d3(pdev, wake);