summaryrefslogtreecommitdiff
path: root/drivers/net/phy/phylink.c
diff options
context:
space:
mode:
authorRussell King (Oracle) <rmk+kernel@armlinux.org.uk>2022-01-11 10:48:17 +0000
committerRussell King (Oracle) <rmk+kernel@armlinux.org.uk>2022-01-18 10:12:45 +0000
commit0d4ad731785a852965a011786192062d782ca01e (patch)
tree5a6acc62c20e843499085664e2ea1af453d29be5 /drivers/net/phy/phylink.c
parent4fac3d830230b919c5c74a1d459a6fc2373094be (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.c40
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);