aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafael J. Wysocki <rjw@sisk.pl>2010-12-26 03:44:32 -0500
committerDavid S. Miller <davem@davemloft.net>2010-12-31 14:14:29 -0500
commit0f333d10e3f689640b229c8cf00b16ea51ce4951 (patch)
treed38c7c0107471d68c4276984991afa6cac2e9140
parentc866b7eac073198cef03ea6bac2dc978635a9f5c (diff)
sky2: Do not use legacy PCI power management
The sky2 driver uses the legacy PCI power management, so it has to do some PCI-specific things in its ->suspend() and ->resume() callbacks, which isn't necessary and should better be done by the PCI sybsystem-level power management code. Moreover, it uses device_set_wakeup_enable() incorrectly (that function should be used when the WoL setting is changed rather than during suspend). Convert sky2 to the new PCI power management framework and make it let the PCI subsystem take care of all the PCI-specific aspects of device handling during system power transitions. Tested on a desktop machine with a Marvell 88E8056 PCI-E adapter. Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl> Acked-by: Stephen Hemminger <shemminger@vyatta.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/sky2.c54
1 files changed, 28 insertions, 26 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index d6577084ce70..0d4a236c3bb3 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -3398,12 +3398,24 @@ static int sky2_set_wol(struct net_device *dev, struct ethtool_wolinfo *wol)
3398{ 3398{
3399 struct sky2_port *sky2 = netdev_priv(dev); 3399 struct sky2_port *sky2 = netdev_priv(dev);
3400 struct sky2_hw *hw = sky2->hw; 3400 struct sky2_hw *hw = sky2->hw;
3401 bool enable_wakeup = false;
3402 int i;
3401 3403
3402 if ((wol->wolopts & ~sky2_wol_supported(sky2->hw)) || 3404 if ((wol->wolopts & ~sky2_wol_supported(sky2->hw)) ||
3403 !device_can_wakeup(&hw->pdev->dev)) 3405 !device_can_wakeup(&hw->pdev->dev))
3404 return -EOPNOTSUPP; 3406 return -EOPNOTSUPP;
3405 3407
3406 sky2->wol = wol->wolopts; 3408 sky2->wol = wol->wolopts;
3409
3410 for (i = 0; i < hw->ports; i++) {
3411 struct net_device *dev = hw->dev[i];
3412 struct sky2_port *sky2 = netdev_priv(dev);
3413
3414 if (sky2->wol)
3415 enable_wakeup = true;
3416 }
3417 device_set_wakeup_enable(&hw->pdev->dev, enable_wakeup);
3418
3407 return 0; 3419 return 0;
3408} 3420}
3409 3421
@@ -4920,10 +4932,11 @@ static void __devexit sky2_remove(struct pci_dev *pdev)
4920 pci_set_drvdata(pdev, NULL); 4932 pci_set_drvdata(pdev, NULL);
4921} 4933}
4922 4934
4923static int sky2_suspend(struct pci_dev *pdev, pm_message_t state) 4935static int sky2_suspend(struct device *dev)
4924{ 4936{
4937 struct pci_dev *pdev = to_pci_dev(dev);
4925 struct sky2_hw *hw = pci_get_drvdata(pdev); 4938 struct sky2_hw *hw = pci_get_drvdata(pdev);
4926 int i, wol = 0; 4939 int i;
4927 4940
4928 if (!hw) 4941 if (!hw)
4929 return 0; 4942 return 0;
@@ -4940,41 +4953,24 @@ static int sky2_suspend(struct pci_dev *pdev, pm_message_t state)
4940 4953
4941 if (sky2->wol) 4954 if (sky2->wol)
4942 sky2_wol_init(sky2); 4955 sky2_wol_init(sky2);
4943
4944 wol |= sky2->wol;
4945 } 4956 }
4946 4957
4947 device_set_wakeup_enable(&pdev->dev, wol != 0);
4948
4949 sky2_power_aux(hw); 4958 sky2_power_aux(hw);
4950 rtnl_unlock(); 4959 rtnl_unlock();
4951 4960
4952 pci_save_state(pdev);
4953 pci_enable_wake(pdev, pci_choose_state(pdev, state), wol);
4954 pci_set_power_state(pdev, pci_choose_state(pdev, state));
4955
4956 return 0; 4961 return 0;
4957} 4962}
4958 4963
4959#ifdef CONFIG_PM 4964#ifdef CONFIG_PM
4960static int sky2_resume(struct pci_dev *pdev) 4965static int sky2_resume(struct device *dev)
4961{ 4966{
4967 struct pci_dev *pdev = to_pci_dev(dev);
4962 struct sky2_hw *hw = pci_get_drvdata(pdev); 4968 struct sky2_hw *hw = pci_get_drvdata(pdev);
4963 int err; 4969 int err;
4964 4970
4965 if (!hw) 4971 if (!hw)
4966 return 0; 4972 return 0;
4967 4973
4968 err = pci_set_power_state(pdev, PCI_D0);
4969 if (err)
4970 goto out;
4971
4972 err = pci_restore_state(pdev);
4973 if (err)
4974 goto out;
4975
4976 pci_enable_wake(pdev, PCI_D0, 0);
4977
4978 /* Re-enable all clocks */ 4974 /* Re-enable all clocks */
4979 err = pci_write_config_dword(pdev, PCI_DEV_REG3, 0); 4975 err = pci_write_config_dword(pdev, PCI_DEV_REG3, 0);
4980 if (err) { 4976 if (err) {
@@ -4994,11 +4990,20 @@ out:
4994 pci_disable_device(pdev); 4990 pci_disable_device(pdev);
4995 return err; 4991 return err;
4996} 4992}
4993
4994static SIMPLE_DEV_PM_OPS(sky2_pm_ops, sky2_suspend, sky2_resume);
4995#define SKY2_PM_OPS (&sky2_pm_ops)
4996
4997#else
4998
4999#define SKY2_PM_OPS NULL
4997#endif 5000#endif
4998 5001
4999static void sky2_shutdown(struct pci_dev *pdev) 5002static void sky2_shutdown(struct pci_dev *pdev)
5000{ 5003{
5001 sky2_suspend(pdev, PMSG_SUSPEND); 5004 sky2_suspend(&pdev->dev);
5005 pci_wake_from_d3(pdev, device_may_wakeup(&pdev->dev));
5006 pci_set_power_state(pdev, PCI_D3hot);
5002} 5007}
5003 5008
5004static struct pci_driver sky2_driver = { 5009static struct pci_driver sky2_driver = {
@@ -5006,11 +5011,8 @@ static struct pci_driver sky2_driver = {
5006 .id_table = sky2_id_table, 5011 .id_table = sky2_id_table,
5007 .probe = sky2_probe, 5012 .probe = sky2_probe,
5008 .remove = __devexit_p(sky2_remove), 5013 .remove = __devexit_p(sky2_remove),
5009#ifdef CONFIG_PM
5010 .suspend = sky2_suspend,
5011 .resume = sky2_resume,
5012#endif
5013 .shutdown = sky2_shutdown, 5014 .shutdown = sky2_shutdown,
5015 .driver.pm = SKY2_PM_OPS,
5014}; 5016};
5015 5017
5016static int __init sky2_init_module(void) 5018static int __init sky2_init_module(void)