Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit be926fc4 authored by Anton Vorontsov's avatar Anton Vorontsov Committed by David S. Miller
Browse files

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: default avatarAnton Vorontsov <avorontsov@ru.mvista.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 8728327e
Loading
Loading
Loading
Loading
+70 −17
Original line number Diff line number Diff line
@@ -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)