diff options
Diffstat (limited to 'drivers/net/phy/phy.c')
-rw-r--r-- | drivers/net/phy/phy.c | 81 |
1 files changed, 39 insertions, 42 deletions
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 95f0419ba21e..88237bdb5255 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c @@ -713,60 +713,57 @@ static void phy_timer(unsigned long data) break; 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 * if there's an error */ err = phy_aneg_done(phydev); if (err < 0) break; - /* If auto-negotiation is done, we change to - * either RUNNING, or NOLINK */ + /* If AN is done, we're running */ 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; - 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; case PHY_NOLINK: @@ -782,7 +779,7 @@ static void phy_timer(unsigned long data) } break; case PHY_FORCING: - err = phy_read_status(phydev); + err = genphy_update_link(phydev); if (err) break; |