diff options
author | Anton Vorontsov <avorontsov@ru.mvista.com> | 2009-10-12 02:00:42 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2009-10-13 02:54:05 -0400 |
commit | be926fc4046913d9ad921aeacdf9329978241c38 (patch) | |
tree | b8299b4cc899913a3072e002a304c6bcdc6a92b5 /drivers/net/gianfar.c | |
parent | 8728327e7a7a7f21f3a7109e65503f4cc3305e78 (diff) |
gianfar: Add support for hibernation
Thanks to various cleanups and refactorings this is now straightforward:
convert the gianfar driver to dev_pm_ops, plus add ->restore() callback
that will fully reinitialize MAC internal registers and BDs.
Note that I kept legacy suspend/resume callbacks so that this patch
doesn't depend on PowerPC changes (i.e. dev_pm_ops support for OF
platform drivers).
Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/gianfar.c')
-rw-r--r-- | drivers/net/gianfar.c | 87 |
1 files changed, 70 insertions, 17 deletions
diff --git a/drivers/net/gianfar.c b/drivers/net/gianfar.c index c2a508fe1cce..c6f6d3b7f4df 100644 --- a/drivers/net/gianfar.c +++ b/drivers/net/gianfar.c | |||
@@ -700,23 +700,24 @@ static int gfar_remove(struct of_device *ofdev) | |||
700 | } | 700 | } |
701 | 701 | ||
702 | #ifdef CONFIG_PM | 702 | #ifdef CONFIG_PM |
703 | static int gfar_suspend(struct of_device *ofdev, pm_message_t state) | 703 | |
704 | static int gfar_suspend(struct device *dev) | ||
704 | { | 705 | { |
705 | struct gfar_private *priv = dev_get_drvdata(&ofdev->dev); | 706 | struct gfar_private *priv = dev_get_drvdata(dev); |
706 | struct net_device *dev = priv->ndev; | 707 | struct net_device *ndev = priv->ndev; |
707 | unsigned long flags; | 708 | unsigned long flags; |
708 | u32 tempval; | 709 | u32 tempval; |
709 | 710 | ||
710 | int magic_packet = priv->wol_en && | 711 | int magic_packet = priv->wol_en && |
711 | (priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET); | 712 | (priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET); |
712 | 713 | ||
713 | netif_device_detach(dev); | 714 | netif_device_detach(ndev); |
714 | 715 | ||
715 | if (netif_running(dev)) { | 716 | if (netif_running(ndev)) { |
716 | spin_lock_irqsave(&priv->txlock, flags); | 717 | spin_lock_irqsave(&priv->txlock, flags); |
717 | spin_lock(&priv->rxlock); | 718 | spin_lock(&priv->rxlock); |
718 | 719 | ||
719 | gfar_halt_nodisable(dev); | 720 | gfar_halt_nodisable(ndev); |
720 | 721 | ||
721 | /* Disable Tx, and Rx if wake-on-LAN is disabled. */ | 722 | /* Disable Tx, and Rx if wake-on-LAN is disabled. */ |
722 | tempval = gfar_read(&priv->regs->maccfg1); | 723 | tempval = gfar_read(&priv->regs->maccfg1); |
@@ -749,17 +750,17 @@ static int gfar_suspend(struct of_device *ofdev, pm_message_t state) | |||
749 | return 0; | 750 | return 0; |
750 | } | 751 | } |
751 | 752 | ||
752 | static int gfar_resume(struct of_device *ofdev) | 753 | static int gfar_resume(struct device *dev) |
753 | { | 754 | { |
754 | struct gfar_private *priv = dev_get_drvdata(&ofdev->dev); | 755 | struct gfar_private *priv = dev_get_drvdata(dev); |
755 | struct net_device *dev = priv->ndev; | 756 | struct net_device *ndev = priv->ndev; |
756 | unsigned long flags; | 757 | unsigned long flags; |
757 | u32 tempval; | 758 | u32 tempval; |
758 | int magic_packet = priv->wol_en && | 759 | int magic_packet = priv->wol_en && |
759 | (priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET); | 760 | (priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET); |
760 | 761 | ||
761 | if (!netif_running(dev)) { | 762 | if (!netif_running(ndev)) { |
762 | netif_device_attach(dev); | 763 | netif_device_attach(ndev); |
763 | return 0; | 764 | return 0; |
764 | } | 765 | } |
765 | 766 | ||
@@ -777,20 +778,71 @@ static int gfar_resume(struct of_device *ofdev) | |||
777 | tempval &= ~MACCFG2_MPEN; | 778 | tempval &= ~MACCFG2_MPEN; |
778 | gfar_write(&priv->regs->maccfg2, tempval); | 779 | gfar_write(&priv->regs->maccfg2, tempval); |
779 | 780 | ||
780 | gfar_start(dev); | 781 | gfar_start(ndev); |
781 | 782 | ||
782 | spin_unlock(&priv->rxlock); | 783 | spin_unlock(&priv->rxlock); |
783 | spin_unlock_irqrestore(&priv->txlock, flags); | 784 | spin_unlock_irqrestore(&priv->txlock, flags); |
784 | 785 | ||
785 | netif_device_attach(dev); | 786 | netif_device_attach(ndev); |
787 | |||
788 | napi_enable(&priv->napi); | ||
789 | |||
790 | return 0; | ||
791 | } | ||
792 | |||
793 | static int gfar_restore(struct device *dev) | ||
794 | { | ||
795 | struct gfar_private *priv = dev_get_drvdata(dev); | ||
796 | struct net_device *ndev = priv->ndev; | ||
797 | |||
798 | if (!netif_running(ndev)) | ||
799 | return 0; | ||
800 | |||
801 | gfar_init_bds(ndev); | ||
802 | init_registers(ndev); | ||
803 | gfar_set_mac_address(ndev); | ||
804 | gfar_init_mac(ndev); | ||
805 | gfar_start(ndev); | ||
806 | |||
807 | priv->oldlink = 0; | ||
808 | priv->oldspeed = 0; | ||
809 | priv->oldduplex = -1; | ||
810 | |||
811 | if (priv->phydev) | ||
812 | phy_start(priv->phydev); | ||
786 | 813 | ||
814 | netif_device_attach(ndev); | ||
787 | napi_enable(&priv->napi); | 815 | napi_enable(&priv->napi); |
788 | 816 | ||
789 | return 0; | 817 | return 0; |
790 | } | 818 | } |
819 | |||
820 | static struct dev_pm_ops gfar_pm_ops = { | ||
821 | .suspend = gfar_suspend, | ||
822 | .resume = gfar_resume, | ||
823 | .freeze = gfar_suspend, | ||
824 | .thaw = gfar_resume, | ||
825 | .restore = gfar_restore, | ||
826 | }; | ||
827 | |||
828 | #define GFAR_PM_OPS (&gfar_pm_ops) | ||
829 | |||
830 | static int gfar_legacy_suspend(struct of_device *ofdev, pm_message_t state) | ||
831 | { | ||
832 | return gfar_suspend(&ofdev->dev); | ||
833 | } | ||
834 | |||
835 | static int gfar_legacy_resume(struct of_device *ofdev) | ||
836 | { | ||
837 | return gfar_resume(&ofdev->dev); | ||
838 | } | ||
839 | |||
791 | #else | 840 | #else |
792 | #define gfar_suspend NULL | 841 | |
793 | #define gfar_resume NULL | 842 | #define GFAR_PM_OPS NULL |
843 | #define gfar_legacy_suspend NULL | ||
844 | #define gfar_legacy_resume NULL | ||
845 | |||
794 | #endif | 846 | #endif |
795 | 847 | ||
796 | /* Reads the controller's registers to determine what interface | 848 | /* Reads the controller's registers to determine what interface |
@@ -2364,8 +2416,9 @@ static struct of_platform_driver gfar_driver = { | |||
2364 | 2416 | ||
2365 | .probe = gfar_probe, | 2417 | .probe = gfar_probe, |
2366 | .remove = gfar_remove, | 2418 | .remove = gfar_remove, |
2367 | .suspend = gfar_suspend, | 2419 | .suspend = gfar_legacy_suspend, |
2368 | .resume = gfar_resume, | 2420 | .resume = gfar_legacy_resume, |
2421 | .driver.pm = GFAR_PM_OPS, | ||
2369 | }; | 2422 | }; |
2370 | 2423 | ||
2371 | static int __init gfar_init(void) | 2424 | static int __init gfar_init(void) |