aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/r8169.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2009-04-05 04:40:04 -0400
committerDavid S. Miller <davem@davemloft.net>2009-04-13 19:21:03 -0400
commit861ab44059350e5cab350238606cf8814abab93b (patch)
treef4b3ac294a0ddc7b7ac496bcbcb0c9c78dcb8347 /drivers/net/r8169.c
parent0ee904c35cc3fdd26a9c76077d9692d458309186 (diff)
NET/r8169: Rework suspend and resume
The recent changes of the PCI PM core allow us to simplify the suspend and resume handling in a number of device drivers, since they don't need to carry out the general PCI PM operations, such as changing the power state of the device, during suspend and resume any more. Simplify the suspend and resume callbacks of r8169 using the observation that the PCI PM core can take care of some operations carried out by the driver. Additionally, make the shutdown callback of r8169 only put the device into a low power state if the system is going to be powered off (kexec is known to have problems with network adapters that are put into low power states on shutdown). This patch has been tested on MSI Wind U100. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Tested-by: Bruno Prémont <bonbons@linux-vserver.org> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/r8169.c')
-rw-r--r--drivers/net/r8169.c61
1 files changed, 39 insertions, 22 deletions
diff --git a/drivers/net/r8169.c b/drivers/net/r8169.c
index 0b6e8c896835..c812e16b7ab4 100644
--- a/drivers/net/r8169.c
+++ b/drivers/net/r8169.c
@@ -3791,16 +3791,13 @@ static struct net_device_stats *rtl8169_get_stats(struct net_device *dev)
3791 return &dev->stats; 3791 return &dev->stats;
3792} 3792}
3793 3793
3794#ifdef CONFIG_PM 3794static void rtl8169_net_suspend(struct net_device *dev)
3795
3796static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state)
3797{ 3795{
3798 struct net_device *dev = pci_get_drvdata(pdev);
3799 struct rtl8169_private *tp = netdev_priv(dev); 3796 struct rtl8169_private *tp = netdev_priv(dev);
3800 void __iomem *ioaddr = tp->mmio_addr; 3797 void __iomem *ioaddr = tp->mmio_addr;
3801 3798
3802 if (!netif_running(dev)) 3799 if (!netif_running(dev))
3803 goto out_pci_suspend; 3800 return;
3804 3801
3805 netif_device_detach(dev); 3802 netif_device_detach(dev);
3806 netif_stop_queue(dev); 3803 netif_stop_queue(dev);
@@ -3812,24 +3809,25 @@ static int rtl8169_suspend(struct pci_dev *pdev, pm_message_t state)
3812 rtl8169_rx_missed(dev, ioaddr); 3809 rtl8169_rx_missed(dev, ioaddr);
3813 3810
3814 spin_unlock_irq(&tp->lock); 3811 spin_unlock_irq(&tp->lock);
3812}
3813
3814#ifdef CONFIG_PM
3815
3816static int rtl8169_suspend(struct device *device)
3817{
3818 struct pci_dev *pdev = to_pci_dev(device);
3819 struct net_device *dev = pci_get_drvdata(pdev);
3815 3820
3816out_pci_suspend: 3821 rtl8169_net_suspend(dev);
3817 pci_save_state(pdev);
3818 pci_enable_wake(pdev, pci_choose_state(pdev, state),
3819 (tp->features & RTL_FEATURE_WOL) ? 1 : 0);
3820 pci_set_power_state(pdev, pci_choose_state(pdev, state));
3821 3822
3822 return 0; 3823 return 0;
3823} 3824}
3824 3825
3825static int rtl8169_resume(struct pci_dev *pdev) 3826static int rtl8169_resume(struct device *device)
3826{ 3827{
3828 struct pci_dev *pdev = to_pci_dev(device);
3827 struct net_device *dev = pci_get_drvdata(pdev); 3829 struct net_device *dev = pci_get_drvdata(pdev);
3828 3830
3829 pci_set_power_state(pdev, PCI_D0);
3830 pci_restore_state(pdev);
3831 pci_enable_wake(pdev, PCI_D0, 0);
3832
3833 if (!netif_running(dev)) 3831 if (!netif_running(dev))
3834 goto out; 3832 goto out;
3835 3833
@@ -3840,23 +3838,42 @@ out:
3840 return 0; 3838 return 0;
3841} 3839}
3842 3840
3841static struct dev_pm_ops rtl8169_pm_ops = {
3842 .suspend = rtl8169_suspend,
3843 .resume = rtl8169_resume,
3844 .freeze = rtl8169_suspend,
3845 .thaw = rtl8169_resume,
3846 .poweroff = rtl8169_suspend,
3847 .restore = rtl8169_resume,
3848};
3849
3850#define RTL8169_PM_OPS (&rtl8169_pm_ops)
3851
3852#else /* !CONFIG_PM */
3853
3854#define RTL8169_PM_OPS NULL
3855
3856#endif /* !CONFIG_PM */
3857
3843static void rtl_shutdown(struct pci_dev *pdev) 3858static void rtl_shutdown(struct pci_dev *pdev)
3844{ 3859{
3845 rtl8169_suspend(pdev, PMSG_SUSPEND); 3860 struct net_device *dev = pci_get_drvdata(pdev);
3846} 3861
3862 rtl8169_net_suspend(dev);
3847 3863
3848#endif /* CONFIG_PM */ 3864 if (system_state == SYSTEM_POWER_OFF) {
3865 pci_wake_from_d3(pdev, true);
3866 pci_set_power_state(pdev, PCI_D3hot);
3867 }
3868}
3849 3869
3850static struct pci_driver rtl8169_pci_driver = { 3870static struct pci_driver rtl8169_pci_driver = {
3851 .name = MODULENAME, 3871 .name = MODULENAME,
3852 .id_table = rtl8169_pci_tbl, 3872 .id_table = rtl8169_pci_tbl,
3853 .probe = rtl8169_init_one, 3873 .probe = rtl8169_init_one,
3854 .remove = __devexit_p(rtl8169_remove_one), 3874 .remove = __devexit_p(rtl8169_remove_one),
3855#ifdef CONFIG_PM
3856 .suspend = rtl8169_suspend,
3857 .resume = rtl8169_resume,
3858 .shutdown = rtl_shutdown, 3875 .shutdown = rtl_shutdown,
3859#endif 3876 .driver.pm = RTL8169_PM_OPS,
3860}; 3877};
3861 3878
3862static int __init rtl8169_init_module(void) 3879static int __init rtl8169_init_module(void)