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

Reply via email to