ucc_geth: Implement suspend/resume and Wake-On-LAN support

This patch implements suspend/resume and WOL support for UCC Ethernet
driver.

We support two wake up events: wake on PHY/link changes and wake
on magic packet.

In some CPUs (like MPC8569) QE shuts down during sleep, so magic packet
detection is unusable, and also on resume we should fully reinitialize
UCC structures.

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-08-27 07:35:57 +00:00
committed by David S. Miller
parent bf5aec2e79
commit 2394905f67
3 changed files with 126 additions and 0 deletions

View File

@@ -359,6 +359,44 @@ uec_get_drvinfo(struct net_device *netdev,
drvinfo->regdump_len = uec_get_regs_len(netdev);
}
#ifdef CONFIG_PM
static void uec_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
{
struct ucc_geth_private *ugeth = netdev_priv(netdev);
struct phy_device *phydev = ugeth->phydev;
if (phydev && phydev->irq)
wol->supported |= WAKE_PHY;
if (qe_alive_during_sleep())
wol->supported |= WAKE_MAGIC;
wol->wolopts = ugeth->wol_en;
}
static int uec_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
{
struct ucc_geth_private *ugeth = netdev_priv(netdev);
struct phy_device *phydev = ugeth->phydev;
if (wol->wolopts & ~(WAKE_PHY | WAKE_MAGIC))
return -EINVAL;
else if (wol->wolopts & WAKE_PHY && (!phydev || !phydev->irq))
return -EINVAL;
else if (wol->wolopts & WAKE_MAGIC && !qe_alive_during_sleep())
return -EINVAL;
ugeth->wol_en = wol->wolopts;
device_set_wakeup_enable(&netdev->dev, ugeth->wol_en);
return 0;
}
#else
#define uec_get_wol NULL
#define uec_set_wol NULL
#endif /* CONFIG_PM */
static const struct ethtool_ops uec_ethtool_ops = {
.get_settings = uec_get_settings,
.set_settings = uec_set_settings,
@@ -377,6 +415,8 @@ static const struct ethtool_ops uec_ethtool_ops = {
.get_sset_count = uec_get_sset_count,
.get_strings = uec_get_strings,
.get_ethtool_stats = uec_get_ethtool_stats,
.get_wol = uec_get_wol,
.set_wol = uec_set_wol,
};
void uec_set_ethtool_ops(struct net_device *netdev)