kernel: 5.15: backport v6.1 PHY changes required for Aquantia
[openwrt/staging/dangole.git] / target / linux / generic / backport-5.15 / 731-v6.1-0004-net-phy-Add-support-for-rate-matching.patch
1 From 0c3e10cb44232833a50cb8e3e784c432906a60c1 Mon Sep 17 00:00:00 2001
2 From: Sean Anderson <sean.anderson@seco.com>
3 Date: Tue, 20 Sep 2022 18:12:31 -0400
4 Subject: [PATCH] net: phy: Add support for rate matching
5
6 This adds support for rate matching (also known as rate adaptation) to
7 the phy subsystem. The general idea is that the phy interface runs at
8 one speed, and the MAC throttles the rate at which it sends packets to
9 the link speed. There's a good overview of several techniques for
10 achieving this at [1]. This patch adds support for three: pause-frame
11 based (such as in Aquantia phys), CRS-based (such as in 10PASS-TS and
12 2BASE-TL), and open-loop-based (such as in 10GBASE-W).
13
14 This patch makes a few assumptions and a few non assumptions about the
15 types of rate matching available. First, it assumes that different phys
16 may use different forms of rate matching. Second, it assumes that phys
17 can use rate matching for any of their supported link speeds (e.g. if a
18 phy supports 10BASE-T and XGMII, then it can adapt XGMII to 10BASE-T).
19 Third, it does not assume that all interface modes will use the same
20 form of rate matching. Fourth, it does not assume that all phy devices
21 will support rate matching (even if some do). Relaxing or strengthening
22 these (non-)assumptions could result in a different API. For example, if
23 all interface modes were assumed to use the same form of rate matching,
24 then a bitmask of interface modes supportting rate matching would
25 suffice.
26
27 For some better visibility into the process, the current rate matching
28 mode is exposed as part of the ethtool ksettings. For the moment, only
29 read access is supported. I'm not sure what userspace might want to
30 configure yet (disable it altogether, disable just one mode, specify the
31 mode to use, etc.). For the moment, since only pause-based rate
32 adaptation support is added in the next few commits, rate matching can
33 be disabled altogether by adjusting the advertisement.
34
35 802.3 calls this feature "rate adaptation" in clause 49 (10GBASE-R) and
36 "rate matching" in clause 61 (10PASS-TL and 2BASE-TS). Aquantia also calls
37 this feature "rate adaptation". I chose "rate matching" because it is
38 shorter, and because Russell doesn't think "adaptation" is correct in this
39 context.
40
41 Signed-off-by: Sean Anderson <sean.anderson@seco.com>
42 Signed-off-by: David S. Miller <davem@davemloft.net>
43 ---
44 Documentation/networking/ethtool-netlink.rst | 2 ++
45 drivers/net/phy/phy-core.c | 21 +++++++++++++++
46 drivers/net/phy/phy.c | 28 ++++++++++++++++++++
47 include/linux/phy.h | 22 ++++++++++++++-
48 include/uapi/linux/ethtool.h | 18 +++++++++++--
49 include/uapi/linux/ethtool_netlink.h | 1 +
50 net/ethtool/ioctl.c | 1 +
51 net/ethtool/linkmodes.c | 5 ++++
52 8 files changed, 95 insertions(+), 3 deletions(-)
53
54 --- a/Documentation/networking/ethtool-netlink.rst
55 +++ b/Documentation/networking/ethtool-netlink.rst
56 @@ -418,6 +418,7 @@ Kernel response contents:
57 ``ETHTOOL_A_LINKMODES_DUPLEX`` u8 duplex mode
58 ``ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG`` u8 Master/slave port mode
59 ``ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE`` u8 Master/slave port state
60 + ``ETHTOOL_A_LINKMODES_RATE_MATCHING`` u8 PHY rate matching
61 ========================================== ====== ==========================
62
63 For ``ETHTOOL_A_LINKMODES_OURS``, value represents advertised modes and mask
64 @@ -441,6 +442,7 @@ Request contents:
65 ``ETHTOOL_A_LINKMODES_SPEED`` u32 link speed (Mb/s)
66 ``ETHTOOL_A_LINKMODES_DUPLEX`` u8 duplex mode
67 ``ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG`` u8 Master/slave port mode
68 + ``ETHTOOL_A_LINKMODES_RATE_MATCHING`` u8 PHY rate matching
69 ``ETHTOOL_A_LINKMODES_LANES`` u32 lanes
70 ========================================== ====== ==========================
71
72 --- a/drivers/net/phy/phy-core.c
73 +++ b/drivers/net/phy/phy-core.c
74 @@ -75,6 +75,27 @@ const char *phy_duplex_to_str(unsigned i
75 EXPORT_SYMBOL_GPL(phy_duplex_to_str);
76
77 /**
78 + * phy_rate_matching_to_str - Return a string describing the rate matching
79 + *
80 + * @rate_matching: Type of rate matching to describe
81 + */
82 +const char *phy_rate_matching_to_str(int rate_matching)
83 +{
84 + switch (rate_matching) {
85 + case RATE_MATCH_NONE:
86 + return "none";
87 + case RATE_MATCH_PAUSE:
88 + return "pause";
89 + case RATE_MATCH_CRS:
90 + return "crs";
91 + case RATE_MATCH_OPEN_LOOP:
92 + return "open-loop";
93 + }
94 + return "Unsupported (update phy-core.c)";
95 +}
96 +EXPORT_SYMBOL_GPL(phy_rate_matching_to_str);
97 +
98 +/**
99 * phy_interface_num_ports - Return the number of links that can be carried by
100 * a given MAC-PHY physical link. Returns 0 if this is
101 * unknown, the number of links else.
102 --- a/drivers/net/phy/phy.c
103 +++ b/drivers/net/phy/phy.c
104 @@ -127,6 +127,33 @@ void phy_print_status(struct phy_device
105 EXPORT_SYMBOL(phy_print_status);
106
107 /**
108 + * phy_get_rate_matching - determine if rate matching is supported
109 + * @phydev: The phy device to return rate matching for
110 + * @iface: The interface mode to use
111 + *
112 + * This determines the type of rate matching (if any) that @phy supports
113 + * using @iface. @iface may be %PHY_INTERFACE_MODE_NA to determine if any
114 + * interface supports rate matching.
115 + *
116 + * Return: The type of rate matching @phy supports for @iface, or
117 + * %RATE_MATCH_NONE.
118 + */
119 +int phy_get_rate_matching(struct phy_device *phydev,
120 + phy_interface_t iface)
121 +{
122 + int ret = RATE_MATCH_NONE;
123 +
124 + if (phydev->drv->get_rate_matching) {
125 + mutex_lock(&phydev->lock);
126 + ret = phydev->drv->get_rate_matching(phydev, iface);
127 + mutex_unlock(&phydev->lock);
128 + }
129 +
130 + return ret;
131 +}
132 +EXPORT_SYMBOL_GPL(phy_get_rate_matching);
133 +
134 +/**
135 * phy_config_interrupt - configure the PHY device for the requested interrupts
136 * @phydev: the phy_device struct
137 * @interrupts: interrupt flags to configure for this @phydev
138 @@ -268,6 +295,7 @@ void phy_ethtool_ksettings_get(struct ph
139 cmd->base.duplex = phydev->duplex;
140 cmd->base.master_slave_cfg = phydev->master_slave_get;
141 cmd->base.master_slave_state = phydev->master_slave_state;
142 + cmd->base.rate_matching = phydev->rate_matching;
143 if (phydev->interface == PHY_INTERFACE_MODE_MOCA)
144 cmd->base.port = PORT_BNC;
145 else
146 --- a/include/linux/phy.h
147 +++ b/include/linux/phy.h
148 @@ -280,7 +280,6 @@ static inline const char *phy_modes(phy_
149 }
150 }
151
152 -
153 #define PHY_INIT_TIMEOUT 100000
154 #define PHY_FORCE_TIMEOUT 10
155
156 @@ -573,6 +572,7 @@ struct macsec_ops;
157 * @lp_advertising: Current link partner advertised linkmodes
158 * @eee_broken_modes: Energy efficient ethernet modes which should be prohibited
159 * @autoneg: Flag autoneg being used
160 + * @rate_matching: Current rate matching mode
161 * @link: Current link state
162 * @autoneg_complete: Flag auto negotiation of the link has completed
163 * @mdix: Current crossover
164 @@ -639,6 +639,8 @@ struct phy_device {
165 unsigned irq_suspended:1;
166 unsigned irq_rerun:1;
167
168 + int rate_matching;
169 +
170 enum phy_state state;
171
172 u32 dev_flags;
173 @@ -801,6 +803,21 @@ struct phy_driver {
174 */
175 int (*get_features)(struct phy_device *phydev);
176
177 + /**
178 + * @get_rate_matching: Get the supported type of rate matching for a
179 + * particular phy interface. This is used by phy consumers to determine
180 + * whether to advertise lower-speed modes for that interface. It is
181 + * assumed that if a rate matching mode is supported on an interface,
182 + * then that interface's rate can be adapted to all slower link speeds
183 + * supported by the phy. If iface is %PHY_INTERFACE_MODE_NA, and the phy
184 + * supports any kind of rate matching for any interface, then it must
185 + * return that rate matching mode (preferring %RATE_MATCH_PAUSE to
186 + * %RATE_MATCH_CRS). If the interface is not supported, this should
187 + * return %RATE_MATCH_NONE.
188 + */
189 + int (*get_rate_matching)(struct phy_device *phydev,
190 + phy_interface_t iface);
191 +
192 /* PHY Power Management */
193 /** @suspend: Suspend the hardware, saving state if needed */
194 int (*suspend)(struct phy_device *phydev);
195 @@ -967,6 +984,7 @@ struct phy_fixup {
196
197 const char *phy_speed_to_str(int speed);
198 const char *phy_duplex_to_str(unsigned int duplex);
199 +const char *phy_rate_matching_to_str(int rate_matching);
200
201 int phy_interface_num_ports(phy_interface_t interface);
202
203 @@ -1675,6 +1693,8 @@ int phy_disable_interrupts(struct phy_de
204 void phy_request_interrupt(struct phy_device *phydev);
205 void phy_free_interrupt(struct phy_device *phydev);
206 void phy_print_status(struct phy_device *phydev);
207 +int phy_get_rate_matching(struct phy_device *phydev,
208 + phy_interface_t iface);
209 int phy_set_max_speed(struct phy_device *phydev, u32 max_speed);
210 void phy_remove_link_mode(struct phy_device *phydev, u32 link_mode);
211 void phy_advertise_supported(struct phy_device *phydev);
212 --- a/include/uapi/linux/ethtool.h
213 +++ b/include/uapi/linux/ethtool.h
214 @@ -1809,6 +1809,20 @@ static inline int ethtool_validate_duple
215 #define MASTER_SLAVE_STATE_SLAVE 3
216 #define MASTER_SLAVE_STATE_ERR 4
217
218 +/* These are used to throttle the rate of data on the phy interface when the
219 + * native speed of the interface is higher than the link speed. These should
220 + * not be used for phy interfaces which natively support multiple speeds (e.g.
221 + * MII or SGMII).
222 + */
223 +/* No rate matching performed. */
224 +#define RATE_MATCH_NONE 0
225 +/* The phy sends pause frames to throttle the MAC. */
226 +#define RATE_MATCH_PAUSE 1
227 +/* The phy asserts CRS to prevent the MAC from transmitting. */
228 +#define RATE_MATCH_CRS 2
229 +/* The MAC is programmed with a sufficiently-large IPG. */
230 +#define RATE_MATCH_OPEN_LOOP 3
231 +
232 /* Which connector port. */
233 #define PORT_TP 0x00
234 #define PORT_AUI 0x01
235 @@ -2002,8 +2016,8 @@ enum ethtool_reset_flags {
236 * reported consistently by PHYLIB. Read-only.
237 * @master_slave_cfg: Master/slave port mode.
238 * @master_slave_state: Master/slave port state.
239 + * @rate_matching: Rate adaptation performed by the PHY
240 * @reserved: Reserved for future use; see the note on reserved space.
241 - * @reserved1: Reserved for future use; see the note on reserved space.
242 * @link_mode_masks: Variable length bitmaps.
243 *
244 * If autonegotiation is disabled, the speed and @duplex represent the
245 @@ -2054,7 +2068,7 @@ struct ethtool_link_settings {
246 __u8 transceiver;
247 __u8 master_slave_cfg;
248 __u8 master_slave_state;
249 - __u8 reserved1[1];
250 + __u8 rate_matching;
251 __u32 reserved[7];
252 __u32 link_mode_masks[0];
253 /* layout of link_mode_masks fields:
254 --- a/include/uapi/linux/ethtool_netlink.h
255 +++ b/include/uapi/linux/ethtool_netlink.h
256 @@ -238,6 +238,7 @@ enum {
257 ETHTOOL_A_LINKMODES_MASTER_SLAVE_CFG, /* u8 */
258 ETHTOOL_A_LINKMODES_MASTER_SLAVE_STATE, /* u8 */
259 ETHTOOL_A_LINKMODES_LANES, /* u32 */
260 + ETHTOOL_A_LINKMODES_RATE_MATCHING, /* u8 */
261
262 /* add new constants above here */
263 __ETHTOOL_A_LINKMODES_CNT,
264 --- a/net/ethtool/ioctl.c
265 +++ b/net/ethtool/ioctl.c
266 @@ -559,6 +559,7 @@ static int ethtool_get_link_ksettings(st
267 = __ETHTOOL_LINK_MODE_MASK_NU32;
268 link_ksettings.base.master_slave_cfg = MASTER_SLAVE_CFG_UNSUPPORTED;
269 link_ksettings.base.master_slave_state = MASTER_SLAVE_STATE_UNSUPPORTED;
270 + link_ksettings.base.rate_matching = RATE_MATCH_NONE;
271
272 return store_link_ksettings_for_user(useraddr, &link_ksettings);
273 }
274 --- a/net/ethtool/linkmodes.c
275 +++ b/net/ethtool/linkmodes.c
276 @@ -70,6 +70,7 @@ static int linkmodes_reply_size(const st
277 + nla_total_size(sizeof(u32)) /* LINKMODES_SPEED */
278 + nla_total_size(sizeof(u32)) /* LINKMODES_LANES */
279 + nla_total_size(sizeof(u8)) /* LINKMODES_DUPLEX */
280 + + nla_total_size(sizeof(u8)) /* LINKMODES_RATE_MATCHING */
281 + 0;
282 ret = ethnl_bitset_size(ksettings->link_modes.advertising,
283 ksettings->link_modes.supported,
284 @@ -143,6 +144,10 @@ static int linkmodes_fill_reply(struct s
285 lsettings->master_slave_state))
286 return -EMSGSIZE;
287
288 + if (nla_put_u8(skb, ETHTOOL_A_LINKMODES_RATE_MATCHING,
289 + lsettings->rate_matching))
290 + return -EMSGSIZE;
291 +
292 return 0;
293 }
294