diff options
author | Russell King (Oracle) <rmk+kernel@armlinux.org.uk> | 2022-01-11 10:48:17 +0000 |
---|---|---|
committer | Russell King (Oracle) <rmk+kernel@armlinux.org.uk> | 2022-01-18 10:12:45 +0000 |
commit | 0d4ad731785a852965a011786192062d782ca01e (patch) | |
tree | 5a6acc62c20e843499085664e2ea1af453d29be5 /drivers/net/phy/phylink.c | |
parent | 4fac3d830230b919c5c74a1d459a6fc2373094be (diff) |
net: phylink: rejig pcs change
Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
Diffstat (limited to 'drivers/net/phy/phylink.c')
-rw-r--r-- | drivers/net/phy/phylink.c | 40 |
1 files changed, 31 insertions, 9 deletions
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 21f7e01053e5..b975684049b5 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -756,6 +756,18 @@ static void phylink_resolve_flow(struct phylink_link_state *state) } } +static void phylink_pcs_poll_stop(struct phylink *pl) +{ + if (pl->cfg_link_an_mode == MLO_AN_INBAND) + del_timer(&pl->link_poll); +} + +static void phylink_pcs_poll_start(struct phylink *pl) +{ + if (pl->pcs->poll && pl->cfg_link_an_mode == MLO_AN_INBAND) + mod_timer(&pl->link_poll, jiffies + HZ); +} + static void phylink_mac_config(struct phylink *pl, const struct phylink_link_state *state) { @@ -787,6 +799,7 @@ static void phylink_major_config(struct phylink *pl, bool restart, const struct phylink_link_state *state) { struct phylink_pcs *pcs = NULL; + bool pcs_changed; int err; phylink_dbg(pl, "major config %s\n", phy_modes(state->interface)); @@ -814,11 +827,22 @@ static void phylink_major_config(struct phylink *pl, bool restart, /* If we have a new PCS, switch to the new PCS after preparing the MAC * for the change. */ - if (pcs) - phylink_set_pcs(pl, pcs); + pcs_changed = pcs && pl->pcs != pcs; + if (pcs_changed) { + phylink_pcs_poll_stop(pl); + phylink_pcs_disable(pl->pcs); + + pl->pcs = pcs; + pl->pcs_ops = pcs->ops; + } phylink_mac_config(pl, state); + if (pcs_changed) { + phylink_pcs_enable(pl->pcs); + phylink_pcs_poll_start(pl); + } + if (pl->pcs_ops) { err = pl->pcs_ops->pcs_config(pl->pcs, pl->cur_link_an_mode, state->interface, @@ -1295,16 +1319,14 @@ EXPORT_SYMBOL_GPL(phylink_create); */ void phylink_set_pcs(struct phylink *pl, struct phylink_pcs *pcs) { + if (!pl->phylink_disable_state) + phylink_pcs_poll_stop(pl); + pl->pcs = pcs; pl->pcs_ops = pcs->ops; - if (!pl->phylink_disable_state && - pl->cfg_link_an_mode == MLO_AN_INBAND) { - if (pcs->poll) - mod_timer(&pl->link_poll, jiffies + HZ); - else - del_timer(&pl->link_poll); - } + if (!pl->phylink_disable_state) + phylink_pcs_poll_start(pl); } EXPORT_SYMBOL_GPL(phylink_set_pcs); |