This is based on juhosg's patch to fully suspend an ag71xx device on phy_stop and resume it on phy_start [1], along with my addition to set the initial state to suspended, corresponding to the initial down state of the interface [2]. This makes the hardware link state on an ag71xx device track the up/down state of its interface.
[1] https://lists.openwrt.org/pipermail/openwrt-devel/2012-August/016540.html [2] https://lists.openwrt.org/pipermail/openwrt-devel/2012-October/016996.html Signed-off-by: Mark Mentovai <m...@moxienet.com> --- Index: target/linux/ar71xx/patches-3.8/910-phy-add-phy_suspend-resume-helpers.patch =================================================================== --- target/linux/ar71xx/patches-3.8/910-phy-add-phy_suspend-resume-helpers.patch (revision 0) +++ target/linux/ar71xx/patches-3.8/910-phy-add-phy_suspend-resume-helpers.patch (working copy) @@ -0,0 +1,21 @@ +--- a/include/linux/phy.h ++++ b/include/linux/phy.h +@@ -510,6 +510,18 @@ static inline int phy_read_status(struct + return phydev->drv->read_status(phydev); + } + ++static inline void phy_suspend(struct phy_device *phydev) ++{ ++ if (phydev->drv->suspend) ++ phydev->drv->suspend(phydev); ++} ++ ++static inline void phy_resume(struct phy_device *phydev) ++{ ++ if (phydev->drv->resume) ++ phydev->drv->resume(phydev); ++} ++ + int genphy_restart_aneg(struct phy_device *phydev); + int genphy_config_aneg(struct phy_device *phydev); + int genphy_update_link(struct phy_device *phydev); Index: target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_phy.c =================================================================== --- target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_phy.c (revision 35844) +++ target/linux/ar71xx/files/drivers/net/ethernet/atheros/ag71xx/ag71xx_phy.c (working copy) @@ -47,6 +47,7 @@ struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); if (ag->phy_dev) { + phy_resume(ag->phy_dev); phy_start(ag->phy_dev); } else if (pdata->mii_bus_dev && pdata->switch_data) { ag71xx_ar7240_start(ag); @@ -61,10 +62,12 @@ struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag); unsigned long flags; - if (ag->phy_dev) + if (ag->phy_dev) { phy_stop(ag->phy_dev); - else if (pdata->mii_bus_dev && pdata->switch_data) + } else if (pdata->mii_bus_dev && pdata->switch_data) { + phy_suspend(ag->phy_dev); ag71xx_ar7240_stop(ag); + } spin_lock_irqsave(&ag->lock, flags); if (ag->link) { @@ -218,10 +221,16 @@ if (pdata->switch_data) return ag71xx_ar7240_init(ag); + int ret; if (pdata->phy_mask) - return ag71xx_phy_connect_multi(ag); + ret = ag71xx_phy_connect_multi(ag); + else + ret = ag71xx_phy_connect_fixed(ag); - return ag71xx_phy_connect_fixed(ag); + if (ag->phy_dev) + phy_suspend(ag->phy_dev); + + return ret; } void ag71xx_phy_disconnect(struct ag71xx *ag) @@ -230,6 +239,8 @@ if (pdata->switch_data) ag71xx_ar7240_cleanup(ag); - else if (ag->phy_dev) + else if (ag->phy_dev) { phy_disconnect(ag->phy_dev); + phy_suspend(ag->phy_dev); + } } _______________________________________________ openwrt-devel mailing list openwrt-devel@lists.openwrt.org https://lists.openwrt.org/mailman/listinfo/openwrt-devel