Skip to content

Commit

Permalink
net: phy: Ensure state transitions are processed from phy_stop()
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Florian Fainelli authored and David S. Miller committed Mar 19, 2023
1 parent 739cb49 commit 4203d84
Showing 1 changed file with 16 additions and 7 deletions.
23 changes: 16 additions & 7 deletions drivers/net/phy/phy.c
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,18 @@ static const char *phy_state_to_str(enum phy_state st)
return NULL;
}

static void phy_process_state_change(struct phy_device *phydev,
enum phy_state old_state)
{
if (old_state != phydev->state) {
phydev_dbg(phydev, "PHY state change %s -> %s\n",
phy_state_to_str(old_state),
phy_state_to_str(phydev->state));
if (phydev->drv && phydev->drv->link_change_notify)
phydev->drv->link_change_notify(phydev);
}
}

static void phy_link_up(struct phy_device *phydev)
{
phydev->phy_link_change(phydev, true);
Expand Down Expand Up @@ -1301,6 +1313,7 @@ EXPORT_SYMBOL(phy_free_interrupt);
void phy_stop(struct phy_device *phydev)
{
struct net_device *dev = phydev->attached_dev;
enum phy_state old_state;

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

mutex_lock(&phydev->lock);
old_state = phydev->state;

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

phydev->state = PHY_HALTED;
phy_process_state_change(phydev, old_state);

mutex_unlock(&phydev->lock);

Expand Down Expand Up @@ -1436,13 +1451,7 @@ void phy_state_machine(struct work_struct *work)
if (err < 0)
phy_error(phydev);

if (old_state != phydev->state) {
phydev_dbg(phydev, "PHY state change %s -> %s\n",
phy_state_to_str(old_state),
phy_state_to_str(phydev->state));
if (phydev->drv && phydev->drv->link_change_notify)
phydev->drv->link_change_notify(phydev);
}
phy_process_state_change(phydev, old_state);

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

0 comments on commit 4203d84

Please sign in to comment.