|
@@ -713,60 +713,57 @@ static void phy_timer(unsigned long data)
|
|
|
|
|
|
break;
|
|
break;
|
|
case PHY_AN:
|
|
case PHY_AN:
|
|
|
|
+ err = phy_read_status(phydev);
|
|
|
|
+
|
|
|
|
+ if (err < 0)
|
|
|
|
+ break;
|
|
|
|
+
|
|
|
|
+ /* If the link is down, give up on
|
|
|
|
+ * negotiation for now */
|
|
|
|
+ if (!phydev->link) {
|
|
|
|
+ phydev->state = PHY_NOLINK;
|
|
|
|
+ netif_carrier_off(phydev->attached_dev);
|
|
|
|
+ phydev->adjust_link(phydev->attached_dev);
|
|
|
|
+ break;
|
|
|
|
+ }
|
|
|
|
+
|
|
/* Check if negotiation is done. Break
|
|
/* Check if negotiation is done. Break
|
|
* if there's an error */
|
|
* if there's an error */
|
|
err = phy_aneg_done(phydev);
|
|
err = phy_aneg_done(phydev);
|
|
if (err < 0)
|
|
if (err < 0)
|
|
break;
|
|
break;
|
|
|
|
|
|
- /* If auto-negotiation is done, we change to
|
|
|
|
- * either RUNNING, or NOLINK */
|
|
|
|
|
|
+ /* If AN is done, we're running */
|
|
if (err > 0) {
|
|
if (err > 0) {
|
|
- err = phy_read_status(phydev);
|
|
|
|
|
|
+ phydev->state = PHY_RUNNING;
|
|
|
|
+ netif_carrier_on(phydev->attached_dev);
|
|
|
|
+ phydev->adjust_link(phydev->attached_dev);
|
|
|
|
+
|
|
|
|
+ } else if (0 == phydev->link_timeout--) {
|
|
|
|
+ int idx;
|
|
|
|
|
|
- if (err)
|
|
|
|
|
|
+ needs_aneg = 1;
|
|
|
|
+ /* If we have the magic_aneg bit,
|
|
|
|
+ * we try again */
|
|
|
|
+ if (phydev->drv->flags & PHY_HAS_MAGICANEG)
|
|
break;
|
|
break;
|
|
|
|
|
|
- if (phydev->link) {
|
|
|
|
- phydev->state = PHY_RUNNING;
|
|
|
|
- netif_carrier_on(phydev->attached_dev);
|
|
|
|
- } else {
|
|
|
|
- phydev->state = PHY_NOLINK;
|
|
|
|
- netif_carrier_off(phydev->attached_dev);
|
|
|
|
- }
|
|
|
|
|
|
+ /* The timer expired, and we still
|
|
|
|
+ * don't have a setting, so we try
|
|
|
|
+ * forcing it until we find one that
|
|
|
|
+ * works, starting from the fastest speed,
|
|
|
|
+ * and working our way down */
|
|
|
|
+ idx = phy_find_valid(0, phydev->supported);
|
|
|
|
|
|
- phydev->adjust_link(phydev->attached_dev);
|
|
|
|
|
|
+ phydev->speed = settings[idx].speed;
|
|
|
|
+ phydev->duplex = settings[idx].duplex;
|
|
|
|
|
|
- } else if (0 == phydev->link_timeout--) {
|
|
|
|
- /* The counter expired, so either we
|
|
|
|
- * switch to forced mode, or the
|
|
|
|
- * magic_aneg bit exists, and we try aneg
|
|
|
|
- * again */
|
|
|
|
- if (!(phydev->drv->flags & PHY_HAS_MAGICANEG)) {
|
|
|
|
- int idx;
|
|
|
|
-
|
|
|
|
- /* We'll start from the
|
|
|
|
- * fastest speed, and work
|
|
|
|
- * our way down */
|
|
|
|
- idx = phy_find_valid(0,
|
|
|
|
- phydev->supported);
|
|
|
|
-
|
|
|
|
- phydev->speed = settings[idx].speed;
|
|
|
|
- phydev->duplex = settings[idx].duplex;
|
|
|
|
-
|
|
|
|
- phydev->autoneg = AUTONEG_DISABLE;
|
|
|
|
- phydev->state = PHY_FORCING;
|
|
|
|
- phydev->link_timeout =
|
|
|
|
- PHY_FORCE_TIMEOUT;
|
|
|
|
-
|
|
|
|
- pr_info("Trying %d/%s\n",
|
|
|
|
- phydev->speed,
|
|
|
|
- DUPLEX_FULL ==
|
|
|
|
- phydev->duplex ?
|
|
|
|
- "FULL" : "HALF");
|
|
|
|
- }
|
|
|
|
|
|
+ phydev->autoneg = AUTONEG_DISABLE;
|
|
|
|
|
|
- needs_aneg = 1;
|
|
|
|
|
|
+ pr_info("Trying %d/%s\n", phydev->speed,
|
|
|
|
+ DUPLEX_FULL ==
|
|
|
|
+ phydev->duplex ?
|
|
|
|
+ "FULL" : "HALF");
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
case PHY_NOLINK:
|
|
case PHY_NOLINK:
|
|
@@ -782,7 +779,7 @@ static void phy_timer(unsigned long data)
|
|
}
|
|
}
|
|
break;
|
|
break;
|
|
case PHY_FORCING:
|
|
case PHY_FORCING:
|
|
- err = phy_read_status(phydev);
|
|
|
|
|
|
+ err = genphy_update_link(phydev);
|
|
|
|
|
|
if (err)
|
|
if (err)
|
|
break;
|
|
break;
|