aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/phy/phy.c')
-rw-r--r--drivers/net/phy/phy.c14
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);