diff options
-rw-r--r-- | drivers/net/ethernet/socionext/sni_ave.c | 60 |
1 files changed, 59 insertions, 1 deletions
diff --git a/drivers/net/ethernet/socionext/sni_ave.c b/drivers/net/ethernet/socionext/sni_ave.c index 9e7391faa1dc..1f9ef68d91ee 100644 --- a/drivers/net/ethernet/socionext/sni_ave.c +++ b/drivers/net/ethernet/socionext/sni_ave.c | |||
@@ -261,6 +261,7 @@ struct ave_private { | |||
261 | struct regmap *regmap; | 261 | struct regmap *regmap; |
262 | unsigned int pinmode_mask; | 262 | unsigned int pinmode_mask; |
263 | unsigned int pinmode_val; | 263 | unsigned int pinmode_val; |
264 | u32 wolopts; | ||
264 | 265 | ||
265 | /* stats */ | 266 | /* stats */ |
266 | struct ave_stats stats_rx; | 267 | struct ave_stats stats_rx; |
@@ -1208,9 +1209,13 @@ static int ave_init(struct net_device *ndev) | |||
1208 | 1209 | ||
1209 | priv->phydev = phydev; | 1210 | priv->phydev = phydev; |
1210 | 1211 | ||
1211 | phy_ethtool_get_wol(phydev, &wol); | 1212 | ave_ethtool_get_wol(ndev, &wol); |
1212 | device_set_wakeup_capable(&ndev->dev, !!wol.supported); | 1213 | device_set_wakeup_capable(&ndev->dev, !!wol.supported); |
1213 | 1214 | ||
1215 | /* set wol initial state disabled */ | ||
1216 | wol.wolopts = 0; | ||
1217 | ave_ethtool_set_wol(ndev, &wol); | ||
1218 | |||
1214 | if (!phy_interface_is_rgmii(phydev)) | 1219 | if (!phy_interface_is_rgmii(phydev)) |
1215 | phy_set_max_speed(phydev, SPEED_100); | 1220 | phy_set_max_speed(phydev, SPEED_100); |
1216 | 1221 | ||
@@ -1734,6 +1739,58 @@ static int ave_remove(struct platform_device *pdev) | |||
1734 | return 0; | 1739 | return 0; |
1735 | } | 1740 | } |
1736 | 1741 | ||
1742 | #ifdef CONFIG_PM_SLEEP | ||
1743 | static int ave_suspend(struct device *dev) | ||
1744 | { | ||
1745 | struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL }; | ||
1746 | struct net_device *ndev = dev_get_drvdata(dev); | ||
1747 | struct ave_private *priv = netdev_priv(ndev); | ||
1748 | int ret = 0; | ||
1749 | |||
1750 | if (netif_running(ndev)) { | ||
1751 | ret = ave_stop(ndev); | ||
1752 | netif_device_detach(ndev); | ||
1753 | } | ||
1754 | |||
1755 | ave_ethtool_get_wol(ndev, &wol); | ||
1756 | priv->wolopts = wol.wolopts; | ||
1757 | |||
1758 | return ret; | ||
1759 | } | ||
1760 | |||
1761 | static int ave_resume(struct device *dev) | ||
1762 | { | ||
1763 | struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL }; | ||
1764 | struct net_device *ndev = dev_get_drvdata(dev); | ||
1765 | struct ave_private *priv = netdev_priv(ndev); | ||
1766 | int ret = 0; | ||
1767 | |||
1768 | ave_global_reset(ndev); | ||
1769 | |||
1770 | ave_ethtool_get_wol(ndev, &wol); | ||
1771 | wol.wolopts = priv->wolopts; | ||
1772 | ave_ethtool_set_wol(ndev, &wol); | ||
1773 | |||
1774 | if (ndev->phydev) { | ||
1775 | ret = phy_resume(ndev->phydev); | ||
1776 | if (ret) | ||
1777 | return ret; | ||
1778 | } | ||
1779 | |||
1780 | if (netif_running(ndev)) { | ||
1781 | ret = ave_open(ndev); | ||
1782 | netif_device_attach(ndev); | ||
1783 | } | ||
1784 | |||
1785 | return ret; | ||
1786 | } | ||
1787 | |||
1788 | static SIMPLE_DEV_PM_OPS(ave_pm_ops, ave_suspend, ave_resume); | ||
1789 | #define AVE_PM_OPS (&ave_pm_ops) | ||
1790 | #else | ||
1791 | #define AVE_PM_OPS NULL | ||
1792 | #endif | ||
1793 | |||
1737 | static int ave_pro4_get_pinmode(struct ave_private *priv, | 1794 | static int ave_pro4_get_pinmode(struct ave_private *priv, |
1738 | phy_interface_t phy_mode, u32 arg) | 1795 | phy_interface_t phy_mode, u32 arg) |
1739 | { | 1796 | { |
@@ -1908,6 +1965,7 @@ static struct platform_driver ave_driver = { | |||
1908 | .remove = ave_remove, | 1965 | .remove = ave_remove, |
1909 | .driver = { | 1966 | .driver = { |
1910 | .name = "ave", | 1967 | .name = "ave", |
1968 | .pm = AVE_PM_OPS, | ||
1911 | .of_match_table = of_ave_match, | 1969 | .of_match_table = of_ave_match, |
1912 | }, | 1970 | }, |
1913 | }; | 1971 | }; |