net: phy: improve handling of PHY_RUNNING in state machine
authorHeiner Kallweit <hkallweit1@gmail.com>
Thu, 11 Oct 2018 20:36:56 +0000 (22:36 +0200)
committerDavid S. Miller <davem@davemloft.net>
Tue, 16 Oct 2018 05:06:38 +0000 (22:06 -0700)
Handling of state PHY_RUNNING seems to be more complex than it needs
to be. If not polling, then we don't have to do anything, we'll
receive an interrupt and go to state PHY_CHANGELINK once the link
goes down. If polling and link is down, we don't have to go the
extra mile over PHY_CHANGELINK and call phy_read_status() again
but can set status PHY_NOLINK directly.

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/phy/phy.c

index 7044282110da0ce2f0b5805194233c8c1235bfca..696955d38dd698850154bbb2f015c36e581834df 100644 (file)
@@ -941,7 +941,6 @@ void phy_state_machine(struct work_struct *work)
        bool needs_aneg = false, do_suspend = false;
        enum phy_state old_state;
        int err = 0;
-       int old_link;
 
        mutex_lock(&phydev->lock);
 
@@ -1025,26 +1024,16 @@ void phy_state_machine(struct work_struct *work)
                }
                break;
        case PHY_RUNNING:
-               /* Only register a CHANGE if we are polling and link changed
-                * since latest checking.
-                */
-               if (phy_polling_mode(phydev)) {
-                       old_link = phydev->link;
-                       err = phy_read_status(phydev);
-                       if (err)
-                               break;
+               if (!phy_polling_mode(phydev))
+                       break;
 
-                       if (old_link != phydev->link)
-                               phydev->state = PHY_CHANGELINK;
-               }
-               /*
-                * Failsafe: check that nobody set phydev->link=0 between two
-                * poll cycles, otherwise we won't leave RUNNING state as long
-                * as link remains down.
-                */
-               if (!phydev->link && phydev->state == PHY_RUNNING) {
-                       phydev->state = PHY_CHANGELINK;
-                       phydev_err(phydev, "no link in PHY_RUNNING\n");
+               err = phy_read_status(phydev);
+               if (err)
+                       break;
+
+               if (!phydev->link) {
+                       phydev->state = PHY_NOLINK;
+                       phy_link_down(phydev, true);
                }
                break;
        case PHY_CHANGELINK: