Commit 4203d840 authored by Florian Fainelli's avatar Florian Fainelli Committed by David S. Miller

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: 5c5f626b ("net: phy: improve handling link_change_notify callback")
Signed-off-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 739cb499
...@@ -57,6 +57,18 @@ static const char *phy_state_to_str(enum phy_state st) ...@@ -57,6 +57,18 @@ static const char *phy_state_to_str(enum phy_state st)
return NULL; 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) static void phy_link_up(struct phy_device *phydev)
{ {
phydev->phy_link_change(phydev, true); phydev->phy_link_change(phydev, true);
...@@ -1301,6 +1313,7 @@ EXPORT_SYMBOL(phy_free_interrupt); ...@@ -1301,6 +1313,7 @@ EXPORT_SYMBOL(phy_free_interrupt);
void phy_stop(struct phy_device *phydev) void phy_stop(struct phy_device *phydev)
{ {
struct net_device *dev = phydev->attached_dev; struct net_device *dev = phydev->attached_dev;
enum phy_state old_state;
if (!phy_is_started(phydev) && phydev->state != PHY_DOWN) { if (!phy_is_started(phydev) && phydev->state != PHY_DOWN) {
WARN(1, "called from state %s\n", WARN(1, "called from state %s\n",
...@@ -1309,6 +1322,7 @@ void phy_stop(struct phy_device *phydev) ...@@ -1309,6 +1322,7 @@ void phy_stop(struct phy_device *phydev)
} }
mutex_lock(&phydev->lock); mutex_lock(&phydev->lock);
old_state = phydev->state;
if (phydev->state == PHY_CABLETEST) { if (phydev->state == PHY_CABLETEST) {
phy_abort_cable_test(phydev); phy_abort_cable_test(phydev);
...@@ -1319,6 +1333,7 @@ void phy_stop(struct phy_device *phydev) ...@@ -1319,6 +1333,7 @@ void phy_stop(struct phy_device *phydev)
sfp_upstream_stop(phydev->sfp_bus); sfp_upstream_stop(phydev->sfp_bus);
phydev->state = PHY_HALTED; phydev->state = PHY_HALTED;
phy_process_state_change(phydev, old_state);
mutex_unlock(&phydev->lock); mutex_unlock(&phydev->lock);
...@@ -1436,13 +1451,7 @@ void phy_state_machine(struct work_struct *work) ...@@ -1436,13 +1451,7 @@ void phy_state_machine(struct work_struct *work)
if (err < 0) if (err < 0)
phy_error(phydev); phy_error(phydev);
if (old_state != phydev->state) { phy_process_state_change(phydev, old_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);
}
/* Only re-schedule a PHY state machine change if we are polling the /* 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 * PHY, if PHY_MAC_INTERRUPT is set, then we will be moving
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment