stmmac: convert to dev_pm_ops.

This patch updates the PM support using the dev_pm_ops
and reviews the hibernation support.

Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Giuseppe CAVALLARO 2010-11-24 02:38:11 +00:00 committed by David S. Miller
parent 293bb1c41b
commit 874bd42d24
2 changed files with 69 additions and 52 deletions

View File

@ -77,7 +77,6 @@ struct stmmac_priv {
spinlock_t lock; spinlock_t lock;
int wolopts; int wolopts;
int wolenabled; int wolenabled;
int shutdown;
#ifdef CONFIG_STMMAC_TIMER #ifdef CONFIG_STMMAC_TIMER
struct stmmac_timer *tm; struct stmmac_timer *tm;
#endif #endif

View File

@ -844,8 +844,6 @@ static int stmmac_open(struct net_device *dev)
if (priv->plat->tx_coe) if (priv->plat->tx_coe)
pr_info("\tTX Checksum insertion supported\n"); pr_info("\tTX Checksum insertion supported\n");
priv->shutdown = 0;
/* Initialise the MMC (if present) to disable all interrupts. */ /* Initialise the MMC (if present) to disable all interrupts. */
writel(0xffffffff, priv->ioaddr + MMC_HIGH_INTR_MASK); writel(0xffffffff, priv->ioaddr + MMC_HIGH_INTR_MASK);
writel(0xffffffff, priv->ioaddr + MMC_LOW_INTR_MASK); writel(0xffffffff, priv->ioaddr + MMC_LOW_INTR_MASK);
@ -1799,61 +1797,53 @@ static int stmmac_dvr_remove(struct platform_device *pdev)
} }
#ifdef CONFIG_PM #ifdef CONFIG_PM
static int stmmac_suspend(struct platform_device *pdev, pm_message_t state) static int stmmac_suspend(struct device *dev)
{ {
struct net_device *dev = platform_get_drvdata(pdev); struct net_device *ndev = dev_get_drvdata(dev);
struct stmmac_priv *priv = netdev_priv(dev); struct stmmac_priv *priv = netdev_priv(ndev);
int dis_ic = 0; int dis_ic = 0;
if (!dev || !netif_running(dev)) if (!ndev || !netif_running(ndev))
return 0; return 0;
spin_lock(&priv->lock); spin_lock(&priv->lock);
if (state.event == PM_EVENT_SUSPEND) { netif_device_detach(ndev);
netif_device_detach(dev); netif_stop_queue(ndev);
netif_stop_queue(dev); if (priv->phydev)
if (priv->phydev) phy_stop(priv->phydev);
phy_stop(priv->phydev);
#ifdef CONFIG_STMMAC_TIMER #ifdef CONFIG_STMMAC_TIMER
priv->tm->timer_stop(); priv->tm->timer_stop();
if (likely(priv->tm->enable)) if (likely(priv->tm->enable))
dis_ic = 1; dis_ic = 1;
#endif #endif
napi_disable(&priv->napi); napi_disable(&priv->napi);
/* Stop TX/RX DMA */ /* Stop TX/RX DMA */
priv->hw->dma->stop_tx(priv->ioaddr); priv->hw->dma->stop_tx(priv->ioaddr);
priv->hw->dma->stop_rx(priv->ioaddr); priv->hw->dma->stop_rx(priv->ioaddr);
/* Clear the Rx/Tx descriptors */ /* Clear the Rx/Tx descriptors */
priv->hw->desc->init_rx_desc(priv->dma_rx, priv->dma_rx_size, priv->hw->desc->init_rx_desc(priv->dma_rx, priv->dma_rx_size,
dis_ic); dis_ic);
priv->hw->desc->init_tx_desc(priv->dma_tx, priv->dma_tx_size); priv->hw->desc->init_tx_desc(priv->dma_tx, priv->dma_tx_size);
/* Enable Power down mode by programming the PMT regs */ /* Enable Power down mode by programming the PMT regs */
if (device_can_wakeup(priv->device)) if (device_may_wakeup(priv->device))
priv->hw->mac->pmt(priv->ioaddr, priv->wolopts); priv->hw->mac->pmt(priv->ioaddr, priv->wolopts);
else else
stmmac_disable_mac(priv->ioaddr); stmmac_disable_mac(priv->ioaddr);
} else {
priv->shutdown = 1;
/* Although this can appear slightly redundant it actually
* makes fast the standby operation and guarantees the driver
* working if hibernation is on media. */
stmmac_release(dev);
}
spin_unlock(&priv->lock); spin_unlock(&priv->lock);
return 0; return 0;
} }
static int stmmac_resume(struct platform_device *pdev) static int stmmac_resume(struct device *dev)
{ {
struct net_device *dev = platform_get_drvdata(pdev); struct net_device *ndev = dev_get_drvdata(dev);
struct stmmac_priv *priv = netdev_priv(dev); struct stmmac_priv *priv = netdev_priv(ndev);
if (!netif_running(dev)) if (!netif_running(ndev))
return 0; return 0;
if (priv->shutdown) { if (priv->shutdown) {
@ -1870,10 +1860,10 @@ static int stmmac_resume(struct platform_device *pdev)
* is received. Anyway, it's better to manually clear * is received. Anyway, it's better to manually clear
* this bit because it can generate problems while resuming * this bit because it can generate problems while resuming
* from another devices (e.g. serial console). */ * from another devices (e.g. serial console). */
if (device_can_wakeup(priv->device)) if (device_may_wakeup(priv->device))
priv->hw->mac->pmt(priv->ioaddr, 0); priv->hw->mac->pmt(priv->ioaddr, 0);
netif_device_attach(dev); netif_device_attach(ndev);
/* Enable the MAC and DMA */ /* Enable the MAC and DMA */
stmmac_enable_mac(priv->ioaddr); stmmac_enable_mac(priv->ioaddr);
@ -1881,31 +1871,59 @@ static int stmmac_resume(struct platform_device *pdev)
priv->hw->dma->start_rx(priv->ioaddr); priv->hw->dma->start_rx(priv->ioaddr);
#ifdef CONFIG_STMMAC_TIMER #ifdef CONFIG_STMMAC_TIMER
priv->tm->timer_start(tmrate); if (likely(priv->tm->enable))
priv->tm->timer_start(tmrate);
#endif #endif
napi_enable(&priv->napi); napi_enable(&priv->napi);
if (priv->phydev) if (priv->phydev)
phy_start(priv->phydev); phy_start(priv->phydev);
netif_start_queue(dev); netif_start_queue(ndev);
spin_unlock(&priv->lock); spin_unlock(&priv->lock);
return 0; return 0;
} }
#endif
static struct platform_driver stmmac_driver = { static int stmmac_freeze(struct device *dev)
.driver = { {
.name = STMMAC_RESOURCE_NAME, struct net_device *ndev = dev_get_drvdata(dev);
},
.probe = stmmac_dvr_probe, if (!ndev || !netif_running(ndev))
.remove = stmmac_dvr_remove, return 0;
#ifdef CONFIG_PM
return stmmac_release(ndev);
}
static int stmmac_restore(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
if (!ndev || !netif_running(ndev))
return 0;
return stmmac_open(ndev);
}
static const struct dev_pm_ops stmmac_pm_ops = {
.suspend = stmmac_suspend, .suspend = stmmac_suspend,
.resume = stmmac_resume, .resume = stmmac_resume,
#endif .freeze = stmmac_freeze,
.thaw = stmmac_restore,
.restore = stmmac_restore,
};
#else
static const struct dev_pm_ops stmmac_pm_ops;
#endif /* CONFIG_PM */
static struct platform_driver stmmac_driver = {
.probe = stmmac_dvr_probe,
.remove = stmmac_dvr_remove,
.driver = {
.name = STMMAC_RESOURCE_NAME,
.owner = THIS_MODULE,
.pm = &stmmac_pm_ops,
},
}; };
/** /**