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>
This commit is contained in:
Anton Vorontsov 2009-10-12 06:00:42 +00:00 committed by David S. Miller
parent 8728327e7a
commit be926fc404

View File

@ -700,23 +700,24 @@ static int gfar_remove(struct of_device *ofdev)
}
#ifdef CONFIG_PM
static int gfar_suspend(struct of_device *ofdev, pm_message_t state)
static int gfar_suspend(struct device *dev)
{
struct gfar_private *priv = dev_get_drvdata(&ofdev->dev);
struct net_device *dev = priv->ndev;
struct gfar_private *priv = dev_get_drvdata(dev);
struct net_device *ndev = priv->ndev;
unsigned long flags;
u32 tempval;
int magic_packet = priv->wol_en &&
(priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
netif_device_detach(dev);
netif_device_detach(ndev);
if (netif_running(dev)) {
if (netif_running(ndev)) {
spin_lock_irqsave(&priv->txlock, flags);
spin_lock(&priv->rxlock);
gfar_halt_nodisable(dev);
gfar_halt_nodisable(ndev);
/* Disable Tx, and Rx if wake-on-LAN is disabled. */
tempval = gfar_read(&priv->regs->maccfg1);
@ -749,17 +750,17 @@ static int gfar_suspend(struct of_device *ofdev, pm_message_t state)
return 0;
}
static int gfar_resume(struct of_device *ofdev)
static int gfar_resume(struct device *dev)
{
struct gfar_private *priv = dev_get_drvdata(&ofdev->dev);
struct net_device *dev = priv->ndev;
struct gfar_private *priv = dev_get_drvdata(dev);
struct net_device *ndev = priv->ndev;
unsigned long flags;
u32 tempval;
int magic_packet = priv->wol_en &&
(priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
if (!netif_running(dev)) {
netif_device_attach(dev);
if (!netif_running(ndev)) {
netif_device_attach(ndev);
return 0;
}
@ -777,20 +778,71 @@ static int gfar_resume(struct of_device *ofdev)
tempval &= ~MACCFG2_MPEN;
gfar_write(&priv->regs->maccfg2, tempval);
gfar_start(dev);
gfar_start(ndev);
spin_unlock(&priv->rxlock);
spin_unlock_irqrestore(&priv->txlock, flags);
netif_device_attach(dev);
netif_device_attach(ndev);
napi_enable(&priv->napi);
return 0;
}
static int gfar_restore(struct device *dev)
{
struct gfar_private *priv = dev_get_drvdata(dev);
struct net_device *ndev = priv->ndev;
if (!netif_running(ndev))
return 0;
gfar_init_bds(ndev);
init_registers(ndev);
gfar_set_mac_address(ndev);
gfar_init_mac(ndev);
gfar_start(ndev);
priv->oldlink = 0;
priv->oldspeed = 0;
priv->oldduplex = -1;
if (priv->phydev)
phy_start(priv->phydev);
netif_device_attach(ndev);
napi_enable(&priv->napi);
return 0;
}
static struct dev_pm_ops gfar_pm_ops = {
.suspend = gfar_suspend,
.resume = gfar_resume,
.freeze = gfar_suspend,
.thaw = gfar_resume,
.restore = gfar_restore,
};
#define GFAR_PM_OPS (&gfar_pm_ops)
static int gfar_legacy_suspend(struct of_device *ofdev, pm_message_t state)
{
return gfar_suspend(&ofdev->dev);
}
static int gfar_legacy_resume(struct of_device *ofdev)
{
return gfar_resume(&ofdev->dev);
}
#else
#define gfar_suspend NULL
#define gfar_resume NULL
#define GFAR_PM_OPS NULL
#define gfar_legacy_suspend NULL
#define gfar_legacy_resume NULL
#endif
/* Reads the controller's registers to determine what interface
@ -2364,8 +2416,9 @@ static struct of_platform_driver gfar_driver = {
.probe = gfar_probe,
.remove = gfar_remove,
.suspend = gfar_suspend,
.resume = gfar_resume,
.suspend = gfar_legacy_suspend,
.resume = gfar_legacy_resume,
.driver.pm = GFAR_PM_OPS,
};
static int __init gfar_init(void)