diff options
-rw-r--r-- | drivers/net/ethernet/intel/igb/igb_ethtool.c | 16 | ||||
-rw-r--r-- | drivers/net/ethernet/intel/igb/igb_main.c | 136 |
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 | ||
2165 | static 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 | |||
2172 | static 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 | |||
2164 | static const struct ethtool_ops igb_ethtool_ops = { | 2178 | static 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 | ||
2192 | void igb_set_ethtool_ops(struct net_device *netdev) | 2208 | void 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 |
175 | static int igb_suspend(struct pci_dev *, pm_message_t); | 176 | static int igb_suspend(struct device *); |
176 | static int igb_resume(struct pci_dev *); | 177 | static int igb_resume(struct device *); |
178 | #ifdef CONFIG_PM_RUNTIME | ||
179 | static int igb_runtime_suspend(struct device *dev); | ||
180 | static int igb_runtime_resume(struct device *dev); | ||
181 | static int igb_runtime_idle(struct device *dev); | ||
182 | #endif | ||
183 | static 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 |
178 | static void igb_shutdown(struct pci_dev *); | 189 | static 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 | ||
2116 | err_register: | 2127 | err_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 | **/ |
2475 | static int igb_open(struct net_device *netdev) | 2488 | static 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); |
2542 | err_setup_tx: | 2564 | err_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 | ||
2572 | static 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 | **/ |
2559 | static int igb_close(struct net_device *netdev) | 2588 | static 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 | ||
2609 | static 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 | ||
6591 | static int __igb_shutdown(struct pci_dev *pdev, bool *enable_wake) | 6637 | static 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 |
6664 | static int igb_suspend(struct pci_dev *pdev, pm_message_t state) | 6711 | static 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 | ||
6683 | static int igb_resume(struct pci_dev *pdev) | 6731 | static 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 | ||
6789 | static 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 | |||
6801 | static 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 | |||
6821 | static 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 | ||
6730 | static void igb_shutdown(struct pci_dev *pdev) | 6828 | static 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); |