net: phy: warn if phy_start is called from invalid state

phy_start() should be called from states PHY_READY or PHY_HALTED only.
Check for this to detect misbehaving drivers. Also the state machine
should be started only when being called from one of the valid states.

Some more background:
For all invalid states phy_start() basically was a no-op. All it did
was triggering a state machine run, but for all "running" states the
poll loop was active anyway. And if called from PHY_DOWN, the state
machine does nothing.

v3:
- extended commit message

Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Heiner Kallweit 2019-01-23 07:30:38 +01:00 committed by David S. Miller
parent a016becd3a
commit 2179626156
1 changed files with 9 additions and 2 deletions

View File

@ -856,9 +856,16 @@ void phy_start(struct phy_device *phydev)
mutex_lock(&phydev->lock); mutex_lock(&phydev->lock);
if (phydev->state != PHY_READY && phydev->state != PHY_HALTED) {
WARN(1, "called from state %s\n",
phy_state_to_str(phydev->state));
goto out;
}
switch (phydev->state) { switch (phydev->state) {
case PHY_READY: case PHY_READY:
phydev->state = PHY_UP; phydev->state = PHY_UP;
phy_start_machine(phydev);
break; break;
case PHY_HALTED: case PHY_HALTED:
/* if phy was suspended, bring the physical link up again */ /* if phy was suspended, bring the physical link up again */
@ -872,13 +879,13 @@ void phy_start(struct phy_device *phydev)
} }
phydev->state = PHY_RESUMING; phydev->state = PHY_RESUMING;
phy_start_machine(phydev);
break; break;
default: default:
break; break;
} }
out:
mutex_unlock(&phydev->lock); mutex_unlock(&phydev->lock);
phy_start_machine(phydev);
} }
EXPORT_SYMBOL(phy_start); EXPORT_SYMBOL(phy_start);