net: phy: add genphy_check_and_restart_aneg()
authorRussell King <rmk+kernel@armlinux.org.uk>
Tue, 17 Dec 2019 13:39:11 +0000 (13:39 +0000)
committerDavid S. Miller <davem@davemloft.net>
Thu, 19 Dec 2019 20:52:34 +0000 (12:52 -0800)
Add a helper for restarting autonegotiation(), similar to the clause 45
variant.  Use it in __genphy_config_aneg()

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/phy/phy_device.c
include/linux/phy.h

index acbdced20c11c2aa4d4f7a3989e50fa2c27f34b1..c61f2295e21e572aa6ea73a34b2689e21609d0b9 100644 (file)
@@ -1770,6 +1770,36 @@ int genphy_restart_aneg(struct phy_device *phydev)
 }
 EXPORT_SYMBOL(genphy_restart_aneg);
 
+/**
+ * genphy_check_and_restart_aneg - Enable and restart auto-negotiation
+ * @phydev: target phy_device struct
+ * @restart: whether aneg restart is requested
+ *
+ * Check, and restart auto-negotiation if needed.
+ */
+int genphy_check_and_restart_aneg(struct phy_device *phydev, bool restart)
+{
+       int ret = 0;
+
+       if (!restart) {
+               /* Advertisement hasn't changed, but maybe aneg was never on to
+                * begin with?  Or maybe phy was isolated?
+                */
+               ret = phy_read(phydev, MII_BMCR);
+               if (ret < 0)
+                       return ret;
+
+               if (!(ret & BMCR_ANENABLE) || (ret & BMCR_ISOLATE))
+                       restart = true;
+       }
+
+       if (restart)
+               ret = genphy_restart_aneg(phydev);
+
+       return ret;
+}
+EXPORT_SYMBOL(genphy_check_and_restart_aneg);
+
 /**
  * __genphy_config_aneg - restart auto-negotiation or write BMCR
  * @phydev: target phy_device struct
@@ -1795,23 +1825,7 @@ int __genphy_config_aneg(struct phy_device *phydev, bool changed)
        else if (err)
                changed = true;
 
-       if (!changed) {
-               /* Advertisement hasn't changed, but maybe aneg was never on to
-                * begin with?  Or maybe phy was isolated?
-                */
-               int ctl = phy_read(phydev, MII_BMCR);
-
-               if (ctl < 0)
-                       return ctl;
-
-               if (!(ctl & BMCR_ANENABLE) || (ctl & BMCR_ISOLATE))
-                       changed = true; /* do restart aneg */
-       }
-
-       /* Only restart aneg if we are advertising something different
-        * than we were before.
-        */
-       return changed ? genphy_restart_aneg(phydev) : 0;
+       return genphy_check_and_restart_aneg(phydev, changed);
 }
 EXPORT_SYMBOL(__genphy_config_aneg);
 
index 5032d453ac66a2a6d3643d6dc59b7dfaeb042346..1c4f97d2631d390e682ae71fdbe30d842c304be2 100644 (file)
@@ -1094,6 +1094,7 @@ void phy_attached_info(struct phy_device *phydev);
 int genphy_read_abilities(struct phy_device *phydev);
 int genphy_setup_forced(struct phy_device *phydev);
 int genphy_restart_aneg(struct phy_device *phydev);
+int genphy_check_and_restart_aneg(struct phy_device *phydev, bool restart);
 int genphy_config_eee_advert(struct phy_device *phydev);
 int __genphy_config_aneg(struct phy_device *phydev, bool changed);
 int genphy_aneg_done(struct phy_device *phydev);