net: phy: add phy_check_link_status
authorHeiner Kallweit <hkallweit1@gmail.com>
Wed, 7 Nov 2018 19:45:58 +0000 (20:45 +0100)
committerDavid S. Miller <davem@davemloft.net>
Thu, 8 Nov 2018 23:02:05 +0000 (15:02 -0800)
In few places in the state machine the state is set to PHY_RUNNING or
PHY_NOLINK after doing a phy_read_status(). So factor this out to
phy_check_link_status().

First use it in phy_start_aneg(): By setting the state to PHY_RUNNING
or PHY_NOLINK directly we can remove the code to handle the case that
we're using interrupts and aneg was finished already.

Definition of phy_link_up and phy_link_down needs to be moved because
they are called in the new function.

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

index 14dffa0da1b8f981478fab1766d1be3c0dcbe983..87ed000307b70a13d841760b7705ed1e2173aa63 100644 (file)
@@ -62,6 +62,17 @@ static const char *phy_state_to_str(enum phy_state st)
        return NULL;
 }
 
+static void phy_link_up(struct phy_device *phydev)
+{
+       phydev->phy_link_change(phydev, true, true);
+       phy_led_trigger_change_speed(phydev);
+}
+
+static void phy_link_down(struct phy_device *phydev, bool do_carrier)
+{
+       phydev->phy_link_change(phydev, false, do_carrier);
+       phy_led_trigger_change_speed(phydev);
+}
 
 /**
  * phy_print_status - Convenience function to print out the current phy status
@@ -493,6 +504,34 @@ static int phy_config_aneg(struct phy_device *phydev)
        return genphy_config_aneg(phydev);
 }
 
+/**
+ * phy_check_link_status - check link status and set state accordingly
+ * @phydev: the phy_device struct
+ *
+ * Description: Check for link and whether autoneg was triggered / is running
+ * and set state accordingly
+ */
+static int phy_check_link_status(struct phy_device *phydev)
+{
+       int err;
+
+       WARN_ON(!mutex_is_locked(&phydev->lock));
+
+       err = phy_read_status(phydev);
+       if (err)
+               return err;
+
+       if (phydev->link && phydev->state != PHY_RUNNING) {
+               phydev->state = PHY_RUNNING;
+               phy_link_up(phydev);
+       } else if (!phydev->link && phydev->state != PHY_NOLINK) {
+               phydev->state = PHY_NOLINK;
+               phy_link_down(phydev, true);
+       }
+
+       return 0;
+}
+
 /**
  * phy_start_aneg - start auto-negotiation for this PHY device
  * @phydev: the phy_device struct
@@ -504,7 +543,6 @@ static int phy_config_aneg(struct phy_device *phydev)
  */
 int phy_start_aneg(struct phy_device *phydev)
 {
-       bool trigger = 0;
        int err;
 
        if (!phydev->drv)
@@ -524,32 +562,16 @@ int phy_start_aneg(struct phy_device *phydev)
 
        if (phydev->state != PHY_HALTED) {
                if (AUTONEG_ENABLE == phydev->autoneg) {
-                       phydev->state = PHY_AN;
-                       phydev->link_timeout = PHY_AN_TIMEOUT;
+                       err = phy_check_link_status(phydev);
                } else {
                        phydev->state = PHY_FORCING;
                        phydev->link_timeout = PHY_FORCE_TIMEOUT;
                }
        }
 
-       /* Re-schedule a PHY state machine to check PHY status because
-        * negotiation may already be done and aneg interrupt may not be
-        * generated.
-        */
-       if (!phy_polling_mode(phydev) && phydev->state == PHY_AN) {
-               err = phy_aneg_done(phydev);
-               if (err > 0) {
-                       trigger = true;
-                       err = 0;
-               }
-       }
-
 out_unlock:
        mutex_unlock(&phydev->lock);
 
-       if (trigger)
-               phy_trigger_machine(phydev);
-
        return err;
 }
 EXPORT_SYMBOL(phy_start_aneg);
@@ -893,18 +915,6 @@ void phy_start(struct phy_device *phydev)
 }
 EXPORT_SYMBOL(phy_start);
 
-static void phy_link_up(struct phy_device *phydev)
-{
-       phydev->phy_link_change(phydev, true, true);
-       phy_led_trigger_change_speed(phydev);
-}
-
-static void phy_link_down(struct phy_device *phydev, bool do_carrier)
-{
-       phydev->phy_link_change(phydev, false, do_carrier);
-       phy_led_trigger_change_speed(phydev);
-}
-
 /**
  * phy_state_machine - Handle the state machine
  * @work: work_struct that describes the work to be done