diff options
Diffstat (limited to 'drivers/net/phy/phy.c')
-rw-r--r-- | drivers/net/phy/phy.c | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index bba0ca786aaa..49d9f0a789fe 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c | |||
@@ -538,9 +538,12 @@ void phy_stop_machine(struct phy_device *phydev) | |||
538 | cancel_delayed_work_sync(&phydev->state_queue); | 538 | cancel_delayed_work_sync(&phydev->state_queue); |
539 | 539 | ||
540 | mutex_lock(&phydev->lock); | 540 | mutex_lock(&phydev->lock); |
541 | if (phydev->state > PHY_UP) | 541 | if (phydev->state > PHY_UP && phydev->state != PHY_HALTED) |
542 | phydev->state = PHY_UP; | 542 | phydev->state = PHY_UP; |
543 | mutex_unlock(&phydev->lock); | 543 | mutex_unlock(&phydev->lock); |
544 | |||
545 | /* Now we can run the state machine synchronously */ | ||
546 | phy_state_machine(&phydev->state_queue.work); | ||
544 | } | 547 | } |
545 | 548 | ||
546 | /** | 549 | /** |
@@ -918,6 +921,15 @@ void phy_state_machine(struct work_struct *work) | |||
918 | if (old_link != phydev->link) | 921 | if (old_link != phydev->link) |
919 | phydev->state = PHY_CHANGELINK; | 922 | phydev->state = PHY_CHANGELINK; |
920 | } | 923 | } |
924 | /* | ||
925 | * Failsafe: check that nobody set phydev->link=0 between two | ||
926 | * poll cycles, otherwise we won't leave RUNNING state as long | ||
927 | * as link remains down. | ||
928 | */ | ||
929 | if (!phydev->link && phydev->state == PHY_RUNNING) { | ||
930 | phydev->state = PHY_CHANGELINK; | ||
931 | dev_err(&phydev->dev, "no link in PHY_RUNNING\n"); | ||
932 | } | ||
921 | break; | 933 | break; |
922 | case PHY_CHANGELINK: | 934 | case PHY_CHANGELINK: |
923 | err = phy_read_status(phydev); | 935 | err = phy_read_status(phydev); |