[PATCH v2 2/3] net: stmmac: dwmac-rk: keep the PHY up for WoL
From: Vincent Palatin <hidden>
Date: 2016-06-15 18:33:42
Also in:
lkml
Subsystem:
arm/rockchip soc support, networking drivers, stmmac ethernet driver, the rest · Maintainers:
Heiko Stuebner, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Maxime Chevallier, Linus Torvalds
When suspending the machine, do not shutdown the external PHY by cutting its regulator in the mac platform driver suspend code if Wake-on-Lan is enabled, else it cannot wake us up. In order to do this, split the suspend/resume callbacks from the init/exit callbacks, so we can condition the power-down on the lack of need to wake-up from the LAN but do it unconditionally when unloading the module. Signed-off-by: Vincent Palatin <redacted> --- drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c | 48 +++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 5 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
index 0cd3ecf..63c2e4f 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c@@ -46,6 +46,7 @@ struct rk_priv_data { struct platform_device *pdev; int phy_iface; struct regulator *regulator; + bool suspended; const struct rk_gmac_ops *ops; bool clk_enabled;
@@ -529,9 +530,8 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev, return bsp_priv; } -static int rk_gmac_init(struct platform_device *pdev, void *priv) +static int rk_gmac_powerup(struct rk_priv_data *bsp_priv) { - struct rk_priv_data *bsp_priv = priv; int ret; ret = phy_power_on(bsp_priv, true);
@@ -545,14 +545,50 @@ static int rk_gmac_init(struct platform_device *pdev, void *priv) return 0; } -static void rk_gmac_exit(struct platform_device *pdev, void *priv) +static void rk_gmac_powerdown(struct rk_priv_data *gmac) { - struct rk_priv_data *gmac = priv; - phy_power_on(gmac, false); gmac_clk_enable(gmac, false); } +static int rk_gmac_init(struct platform_device *pdev, void *priv) +{ + struct rk_priv_data *bsp_priv = priv; + + return rk_gmac_powerup(bsp_priv); +} + +static void rk_gmac_exit(struct platform_device *pdev, void *priv) +{ + struct rk_priv_data *bsp_priv = priv; + + rk_gmac_powerdown(bsp_priv); +} + +static void rk_gmac_suspend(struct platform_device *pdev, void *priv) +{ + struct rk_priv_data *bsp_priv = priv; + + /* Keep the PHY up if we use Wake-on-Lan. */ + if (device_may_wakeup(&pdev->dev)) + return; + + rk_gmac_powerdown(bsp_priv); + bsp_priv->suspended = true; +} + +static void rk_gmac_resume(struct platform_device *pdev, void *priv) +{ + struct rk_priv_data *bsp_priv = priv; + + /* The PHY was up for Wake-on-Lan. */ + if (!bsp_priv->suspended) + return; + + rk_gmac_powerup(bsp_priv); + bsp_priv->suspended = false; +} + static void rk_fix_speed(void *priv, unsigned int speed) { struct rk_priv_data *bsp_priv = priv;
@@ -591,6 +627,8 @@ static int rk_gmac_probe(struct platform_device *pdev) plat_dat->init = rk_gmac_init; plat_dat->exit = rk_gmac_exit; plat_dat->fix_mac_speed = rk_fix_speed; + plat_dat->suspend = rk_gmac_suspend; + plat_dat->resume = rk_gmac_resume; plat_dat->bsp_priv = rk_gmac_setup(pdev, data); if (IS_ERR(plat_dat->bsp_priv))
--
2.8.0.rc3.226.g39d4020