cda77e3e2d83ad733f1876812823d75281df7b26
[openwrt/staging/linusw.git] /
1 From bfac8c490d605bea03b1f1927582b6f396462164 Mon Sep 17 00:00:00 2001
2 From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
3 Date: Mon, 27 Jun 2022 12:44:43 +0100
4 Subject: [PATCH] net: phylink: disable PCS polling over major configuration
5
6 While we are performing a major configuration, there is no point having
7 the PCS polling timer running. Stop it before we begin preparing for
8 the configuration change, and restart it only once we've successfully
9 completed the change.
10
11 Reviewed-by: Andrew Lunn <andrew@lunn.ch>
12 Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
13 Signed-off-by: Jakub Kicinski <kuba@kernel.org>
14 ---
15 drivers/net/phy/phylink.c | 30 ++++++++++++++++++++----------
16 1 file changed, 20 insertions(+), 10 deletions(-)
17
18 --- a/drivers/net/phy/phylink.c
19 +++ b/drivers/net/phy/phylink.c
20 @@ -756,6 +756,18 @@ static void phylink_resolve_flow(struct
21 }
22 }
23
24 +static void phylink_pcs_poll_stop(struct phylink *pl)
25 +{
26 + if (pl->cfg_link_an_mode == MLO_AN_INBAND)
27 + del_timer(&pl->link_poll);
28 +}
29 +
30 +static void phylink_pcs_poll_start(struct phylink *pl)
31 +{
32 + if (pl->pcs->poll && pl->cfg_link_an_mode == MLO_AN_INBAND)
33 + mod_timer(&pl->link_poll, jiffies + HZ);
34 +}
35 +
36 static void phylink_mac_config(struct phylink *pl,
37 const struct phylink_link_state *state)
38 {
39 @@ -787,6 +799,7 @@ static void phylink_major_config(struct
40 const struct phylink_link_state *state)
41 {
42 struct phylink_pcs *pcs = NULL;
43 + bool pcs_changed = false;
44 int err;
45
46 phylink_dbg(pl, "major config %s\n", phy_modes(state->interface));
47 @@ -799,8 +812,12 @@ static void phylink_major_config(struct
48 pcs);
49 return;
50 }
51 +
52 + pcs_changed = pcs && pl->pcs != pcs;
53 }
54
55 + phylink_pcs_poll_stop(pl);
56 +
57 if (pl->mac_ops->mac_prepare) {
58 err = pl->mac_ops->mac_prepare(pl->config, pl->cur_link_an_mode,
59 state->interface);
60 @@ -814,8 +831,10 @@ static void phylink_major_config(struct
61 /* If we have a new PCS, switch to the new PCS after preparing the MAC
62 * for the change.
63 */
64 - if (pcs)
65 - phylink_set_pcs(pl, pcs);
66 + if (pcs_changed) {
67 + pl->pcs = pcs;
68 + pl->pcs_ops = pcs->ops;
69 + }
70
71 phylink_mac_config(pl, state);
72
73 @@ -841,6 +860,8 @@ static void phylink_major_config(struct
74 phylink_err(pl, "mac_finish failed: %pe\n",
75 ERR_PTR(err));
76 }
77 +
78 + phylink_pcs_poll_start(pl);
79 }
80
81 /*