Skip to content

Commit 4203d84

Browse files
ffainellidavem330
authored andcommitted
net: phy: Ensure state transitions are processed from phy_stop()
In the phy_disconnect() -> phy_stop() path, we will be forcibly setting the PHY state machine to PHY_HALTED. This invalidates the old_state != phydev->state condition in phy_state_machine() such that we will neither display the state change for debugging, nor will we invoke the link_change_notify() callback. Factor the code by introducing phy_process_state_change(), and ensure that we process the state change from phy_stop() as well. Fixes: 5c5f626 ("net: phy: improve handling link_change_notify callback") Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent 739cb49 commit 4203d84

File tree

1 file changed

+16
-7
lines changed

1 file changed

+16
-7
lines changed

drivers/net/phy/phy.c

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,18 @@ static const char *phy_state_to_str(enum phy_state st)
5757
return NULL;
5858
}
5959

60+
static void phy_process_state_change(struct phy_device *phydev,
61+
enum phy_state old_state)
62+
{
63+
if (old_state != phydev->state) {
64+
phydev_dbg(phydev, "PHY state change %s -> %s\n",
65+
phy_state_to_str(old_state),
66+
phy_state_to_str(phydev->state));
67+
if (phydev->drv && phydev->drv->link_change_notify)
68+
phydev->drv->link_change_notify(phydev);
69+
}
70+
}
71+
6072
static void phy_link_up(struct phy_device *phydev)
6173
{
6274
phydev->phy_link_change(phydev, true);
@@ -1301,6 +1313,7 @@ EXPORT_SYMBOL(phy_free_interrupt);
13011313
void phy_stop(struct phy_device *phydev)
13021314
{
13031315
struct net_device *dev = phydev->attached_dev;
1316+
enum phy_state old_state;
13041317

13051318
if (!phy_is_started(phydev) && phydev->state != PHY_DOWN) {
13061319
WARN(1, "called from state %s\n",
@@ -1309,6 +1322,7 @@ void phy_stop(struct phy_device *phydev)
13091322
}
13101323

13111324
mutex_lock(&phydev->lock);
1325+
old_state = phydev->state;
13121326

13131327
if (phydev->state == PHY_CABLETEST) {
13141328
phy_abort_cable_test(phydev);
@@ -1319,6 +1333,7 @@ void phy_stop(struct phy_device *phydev)
13191333
sfp_upstream_stop(phydev->sfp_bus);
13201334

13211335
phydev->state = PHY_HALTED;
1336+
phy_process_state_change(phydev, old_state);
13221337

13231338
mutex_unlock(&phydev->lock);
13241339

@@ -1436,13 +1451,7 @@ void phy_state_machine(struct work_struct *work)
14361451
if (err < 0)
14371452
phy_error(phydev);
14381453

1439-
if (old_state != phydev->state) {
1440-
phydev_dbg(phydev, "PHY state change %s -> %s\n",
1441-
phy_state_to_str(old_state),
1442-
phy_state_to_str(phydev->state));
1443-
if (phydev->drv && phydev->drv->link_change_notify)
1444-
phydev->drv->link_change_notify(phydev);
1445-
}
1454+
phy_process_state_change(phydev, old_state);
14461455

14471456
/* Only re-schedule a PHY state machine change if we are polling the
14481457
* PHY, if PHY_MAC_INTERRUPT is set, then we will be moving

0 commit comments

Comments
 (0)