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:
parent
8728327e7a
commit
be926fc404
1 changed files with 70 additions and 17 deletions
|
@ -700,23 +700,24 @@ static int gfar_remove(struct of_device *ofdev)
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_PM
|
#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 gfar_private *priv = dev_get_drvdata(dev);
|
||||||
struct net_device *dev = priv->ndev;
|
struct net_device *ndev = priv->ndev;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
u32 tempval;
|
u32 tempval;
|
||||||
|
|
||||||
int magic_packet = priv->wol_en &&
|
int magic_packet = priv->wol_en &&
|
||||||
(priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
|
(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_irqsave(&priv->txlock, flags);
|
||||||
spin_lock(&priv->rxlock);
|
spin_lock(&priv->rxlock);
|
||||||
|
|
||||||
gfar_halt_nodisable(dev);
|
gfar_halt_nodisable(ndev);
|
||||||
|
|
||||||
/* Disable Tx, and Rx if wake-on-LAN is disabled. */
|
/* Disable Tx, and Rx if wake-on-LAN is disabled. */
|
||||||
tempval = gfar_read(&priv->regs->maccfg1);
|
tempval = gfar_read(&priv->regs->maccfg1);
|
||||||
|
@ -749,17 +750,17 @@ static int gfar_suspend(struct of_device *ofdev, pm_message_t state)
|
||||||
return 0;
|
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 gfar_private *priv = dev_get_drvdata(dev);
|
||||||
struct net_device *dev = priv->ndev;
|
struct net_device *ndev = priv->ndev;
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
u32 tempval;
|
u32 tempval;
|
||||||
int magic_packet = priv->wol_en &&
|
int magic_packet = priv->wol_en &&
|
||||||
(priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
|
(priv->device_flags & FSL_GIANFAR_DEV_HAS_MAGIC_PACKET);
|
||||||
|
|
||||||
if (!netif_running(dev)) {
|
if (!netif_running(ndev)) {
|
||||||
netif_device_attach(dev);
|
netif_device_attach(ndev);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -777,20 +778,71 @@ static int gfar_resume(struct of_device *ofdev)
|
||||||
tempval &= ~MACCFG2_MPEN;
|
tempval &= ~MACCFG2_MPEN;
|
||||||
gfar_write(&priv->regs->maccfg2, tempval);
|
gfar_write(&priv->regs->maccfg2, tempval);
|
||||||
|
|
||||||
gfar_start(dev);
|
gfar_start(ndev);
|
||||||
|
|
||||||
spin_unlock(&priv->rxlock);
|
spin_unlock(&priv->rxlock);
|
||||||
spin_unlock_irqrestore(&priv->txlock, flags);
|
spin_unlock_irqrestore(&priv->txlock, flags);
|
||||||
|
|
||||||
netif_device_attach(dev);
|
netif_device_attach(ndev);
|
||||||
|
|
||||||
napi_enable(&priv->napi);
|
napi_enable(&priv->napi);
|
||||||
|
|
||||||
return 0;
|
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
|
#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
|
#endif
|
||||||
|
|
||||||
/* Reads the controller's registers to determine what interface
|
/* Reads the controller's registers to determine what interface
|
||||||
|
@ -2364,8 +2416,9 @@ static struct of_platform_driver gfar_driver = {
|
||||||
|
|
||||||
.probe = gfar_probe,
|
.probe = gfar_probe,
|
||||||
.remove = gfar_remove,
|
.remove = gfar_remove,
|
||||||
.suspend = gfar_suspend,
|
.suspend = gfar_legacy_suspend,
|
||||||
.resume = gfar_resume,
|
.resume = gfar_legacy_resume,
|
||||||
|
.driver.pm = GFAR_PM_OPS,
|
||||||
};
|
};
|
||||||
|
|
||||||
static int __init gfar_init(void)
|
static int __init gfar_init(void)
|
||||||
|
|
Loading…
Add table
Reference in a new issue