kernel: backport phylink changes from mainline Linux
[openwrt/staging/jow.git] / target / linux / generic / backport-6.1 / 792-v6.6-net-phylink-add-pcs_enable-pcs_disable-methods.patch
1 From 90ef0a7b0622c62758b2638604927867775479ea Mon Sep 17 00:00:00 2001
2 From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
3 Date: Thu, 13 Jul 2023 09:42:07 +0100
4 Subject: [PATCH] net: phylink: add pcs_enable()/pcs_disable() methods
5
6 Add phylink PCS enable/disable callbacks that will allow us to place
7 IEEE 802.3 register compliant PCS in power-down mode while not being
8 used.
9
10 Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
11 Signed-off-by: David S. Miller <davem@davemloft.net>
12 ---
13 drivers/net/phy/phylink.c | 48 +++++++++++++++++++++++++++++++--------
14 include/linux/phylink.h | 16 +++++++++++++
15 2 files changed, 55 insertions(+), 9 deletions(-)
16
17 --- a/drivers/net/phy/phylink.c
18 +++ b/drivers/net/phy/phylink.c
19 @@ -34,6 +34,10 @@ enum {
20 PHYLINK_DISABLE_STOPPED,
21 PHYLINK_DISABLE_LINK,
22 PHYLINK_DISABLE_MAC_WOL,
23 +
24 + PCS_STATE_DOWN = 0,
25 + PCS_STATE_STARTING,
26 + PCS_STATE_STARTED,
27 };
28
29 /**
30 @@ -72,6 +76,7 @@ struct phylink {
31 struct phylink_link_state phy_state;
32 struct work_struct resolve;
33 unsigned int pcs_neg_mode;
34 + unsigned int pcs_state;
35
36 bool mac_link_dropped;
37 bool using_mac_select_pcs;
38 @@ -992,6 +997,22 @@ static void phylink_resolve_an_pause(str
39 }
40 }
41
42 +static void phylink_pcs_disable(struct phylink_pcs *pcs)
43 +{
44 + if (pcs && pcs->ops->pcs_disable)
45 + pcs->ops->pcs_disable(pcs);
46 +}
47 +
48 +static int phylink_pcs_enable(struct phylink_pcs *pcs)
49 +{
50 + int err = 0;
51 +
52 + if (pcs && pcs->ops->pcs_enable)
53 + err = pcs->ops->pcs_enable(pcs);
54 +
55 + return err;
56 +}
57 +
58 static int phylink_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode,
59 const struct phylink_link_state *state,
60 bool permit_pause_to_mac)
61 @@ -1094,11 +1115,17 @@ static void phylink_major_config(struct
62 /* If we have a new PCS, switch to the new PCS after preparing the MAC
63 * for the change.
64 */
65 - if (pcs_changed)
66 + if (pcs_changed) {
67 + phylink_pcs_disable(pl->pcs);
68 +
69 pl->pcs = pcs;
70 + }
71
72 phylink_mac_config(pl, state);
73
74 + if (pl->pcs_state == PCS_STATE_STARTING || pcs_changed)
75 + phylink_pcs_enable(pl->pcs);
76 +
77 neg_mode = pl->cur_link_an_mode;
78 if (pl->pcs && pl->pcs->neg_mode)
79 neg_mode = pl->pcs_neg_mode;
80 @@ -1586,6 +1613,7 @@ struct phylink *phylink_create(struct ph
81 pl->link_config.pause = MLO_PAUSE_AN;
82 pl->link_config.speed = SPEED_UNKNOWN;
83 pl->link_config.duplex = DUPLEX_UNKNOWN;
84 + pl->pcs_state = PCS_STATE_DOWN;
85 pl->mac_ops = mac_ops;
86 __set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state);
87 timer_setup(&pl->link_poll, phylink_fixed_poll, 0);
88 @@ -1987,6 +2015,8 @@ void phylink_start(struct phylink *pl)
89 if (pl->netdev)
90 netif_carrier_off(pl->netdev);
91
92 + pl->pcs_state = PCS_STATE_STARTING;
93 +
94 /* Apply the link configuration to the MAC when starting. This allows
95 * a fixed-link to start with the correct parameters, and also
96 * ensures that we set the appropriate advertisement for Serdes links.
97 @@ -1997,6 +2027,8 @@ void phylink_start(struct phylink *pl)
98 */
99 phylink_mac_initial_config(pl, true);
100
101 + pl->pcs_state = PCS_STATE_STARTED;
102 +
103 phylink_enable_and_run_resolve(pl, PHYLINK_DISABLE_STOPPED);
104
105 if (pl->cfg_link_an_mode == MLO_AN_FIXED && pl->link_gpio) {
106 @@ -2015,15 +2047,9 @@ void phylink_start(struct phylink *pl)
107 poll = true;
108 }
109
110 - switch (pl->cfg_link_an_mode) {
111 - case MLO_AN_FIXED:
112 + if (pl->cfg_link_an_mode == MLO_AN_FIXED)
113 poll |= pl->config->poll_fixed_state;
114 - break;
115 - case MLO_AN_INBAND:
116 - if (pl->pcs)
117 - poll |= pl->pcs->poll;
118 - break;
119 - }
120 +
121 if (poll)
122 mod_timer(&pl->link_poll, jiffies + HZ);
123 if (pl->phydev)
124 @@ -2060,6 +2086,10 @@ void phylink_stop(struct phylink *pl)
125 }
126
127 phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_STOPPED);
128 +
129 + pl->pcs_state = PCS_STATE_DOWN;
130 +
131 + phylink_pcs_disable(pl->pcs);
132 }
133 EXPORT_SYMBOL_GPL(phylink_stop);
134
135 --- a/include/linux/phylink.h
136 +++ b/include/linux/phylink.h
137 @@ -533,6 +533,8 @@ struct phylink_pcs {
138 /**
139 * struct phylink_pcs_ops - MAC PCS operations structure.
140 * @pcs_validate: validate the link configuration.
141 + * @pcs_enable: enable the PCS.
142 + * @pcs_disable: disable the PCS.
143 * @pcs_get_state: read the current MAC PCS link state from the hardware.
144 * @pcs_config: configure the MAC PCS for the selected mode and state.
145 * @pcs_an_restart: restart 802.3z BaseX autonegotiation.
146 @@ -542,6 +544,8 @@ struct phylink_pcs {
147 struct phylink_pcs_ops {
148 int (*pcs_validate)(struct phylink_pcs *pcs, unsigned long *supported,
149 const struct phylink_link_state *state);
150 + int (*pcs_enable)(struct phylink_pcs *pcs);
151 + void (*pcs_disable)(struct phylink_pcs *pcs);
152 void (*pcs_get_state)(struct phylink_pcs *pcs,
153 struct phylink_link_state *state);
154 int (*pcs_config)(struct phylink_pcs *pcs, unsigned int neg_mode,
155 @@ -572,6 +576,18 @@ int pcs_validate(struct phylink_pcs *pcs
156 const struct phylink_link_state *state);
157
158 /**
159 + * pcs_enable() - enable the PCS.
160 + * @pcs: a pointer to a &struct phylink_pcs.
161 + */
162 +int pcs_enable(struct phylink_pcs *pcs);
163 +
164 +/**
165 + * pcs_disable() - disable the PCS.
166 + * @pcs: a pointer to a &struct phylink_pcs.
167 + */
168 +void pcs_disable(struct phylink_pcs *pcs);
169 +
170 +/**
171 * pcs_get_state() - Read the current inband link state from the hardware
172 * @pcs: a pointer to a &struct phylink_pcs.
173 * @state: a pointer to a &struct phylink_link_state.