kernel: backport ipeth CDC NCM support
[openwrt/openwrt.git] / target / linux / generic / backport-6.1 / 703-v6.3-net-mdio-Add-dedicated-C45-API-to-MDIO-bus-drivers.patch
1 From 4e4aafcddbbfcdd6eed5780e190fcbfac8b4685a Mon Sep 17 00:00:00 2001
2 From: Andrew Lunn <andrew@lunn.ch>
3 Date: Mon, 9 Jan 2023 16:30:41 +0100
4 Subject: [PATCH] net: mdio: Add dedicated C45 API to MDIO bus drivers
5
6 Currently C22 and C45 transactions are mixed over a combined API calls
7 which make use of a special bit in the reg address to indicate if a
8 C45 transaction should be performed. This makes it impossible to know
9 if the bus driver actually supports C45. Additionally, many C22 only
10 drivers don't return -EOPNOTSUPP when asked to perform a C45
11 transaction, they mistaking perform a C22 transaction.
12
13 This is the first step to cleanly separate C22 from C45. To maintain
14 backwards compatibility until all drivers which are capable of
15 performing C45 are converted to this new API, the helper functions
16 will fall back to the older API if the new API is not
17 supported. Eventually this fallback will be removed.
18
19 Signed-off-by: Andrew Lunn <andrew@lunn.ch>
20 Signed-off-by: Michael Walle <michael@walle.cc>
21 Signed-off-by: Jakub Kicinski <kuba@kernel.org>
22 ---
23 drivers/net/phy/mdio_bus.c | 189 +++++++++++++++++++++++++++++++++++++
24 include/linux/mdio.h | 39 ++++----
25 include/linux/phy.h | 5 +
26 3 files changed, 214 insertions(+), 19 deletions(-)
27
28 --- a/drivers/net/phy/mdio_bus.c
29 +++ b/drivers/net/phy/mdio_bus.c
30 @@ -832,6 +832,100 @@ int __mdiobus_modify_changed(struct mii_
31 EXPORT_SYMBOL_GPL(__mdiobus_modify_changed);
32
33 /**
34 + * __mdiobus_c45_read - Unlocked version of the mdiobus_c45_read function
35 + * @bus: the mii_bus struct
36 + * @addr: the phy address
37 + * @devad: device address to read
38 + * @regnum: register number to read
39 + *
40 + * Read a MDIO bus register. Caller must hold the mdio bus lock.
41 + *
42 + * NOTE: MUST NOT be called from interrupt context.
43 + */
44 +int __mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum)
45 +{
46 + int retval;
47 +
48 + lockdep_assert_held_once(&bus->mdio_lock);
49 +
50 + if (bus->read_c45)
51 + retval = bus->read_c45(bus, addr, devad, regnum);
52 + else
53 + retval = bus->read(bus, addr, mdiobus_c45_addr(devad, regnum));
54 +
55 + trace_mdio_access(bus, 1, addr, regnum, retval, retval);
56 + mdiobus_stats_acct(&bus->stats[addr], true, retval);
57 +
58 + return retval;
59 +}
60 +EXPORT_SYMBOL(__mdiobus_c45_read);
61 +
62 +/**
63 + * __mdiobus_c45_write - Unlocked version of the mdiobus_write function
64 + * @bus: the mii_bus struct
65 + * @addr: the phy address
66 + * @devad: device address to read
67 + * @regnum: register number to write
68 + * @val: value to write to @regnum
69 + *
70 + * Write a MDIO bus register. Caller must hold the mdio bus lock.
71 + *
72 + * NOTE: MUST NOT be called from interrupt context.
73 + */
74 +int __mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum,
75 + u16 val)
76 +{
77 + int err;
78 +
79 + lockdep_assert_held_once(&bus->mdio_lock);
80 +
81 + if (bus->write_c45)
82 + err = bus->write_c45(bus, addr, devad, regnum, val);
83 + else
84 + err = bus->write(bus, addr, mdiobus_c45_addr(devad, regnum),
85 + val);
86 +
87 + trace_mdio_access(bus, 0, addr, regnum, val, err);
88 + mdiobus_stats_acct(&bus->stats[addr], false, err);
89 +
90 + return err;
91 +}
92 +EXPORT_SYMBOL(__mdiobus_c45_write);
93 +
94 +/**
95 + * __mdiobus_c45_modify_changed - Unlocked version of the mdiobus_modify function
96 + * @bus: the mii_bus struct
97 + * @addr: the phy address
98 + * @devad: device address to read
99 + * @regnum: register number to modify
100 + * @mask: bit mask of bits to clear
101 + * @set: bit mask of bits to set
102 + *
103 + * Read, modify, and if any change, write the register value back to the
104 + * device. Any error returns a negative number.
105 + *
106 + * NOTE: MUST NOT be called from interrupt context.
107 + */
108 +static int __mdiobus_c45_modify_changed(struct mii_bus *bus, int addr,
109 + int devad, u32 regnum, u16 mask,
110 + u16 set)
111 +{
112 + int new, ret;
113 +
114 + ret = __mdiobus_c45_read(bus, addr, devad, regnum);
115 + if (ret < 0)
116 + return ret;
117 +
118 + new = (ret & ~mask) | set;
119 + if (new == ret)
120 + return 0;
121 +
122 + ret = __mdiobus_c45_write(bus, addr, devad, regnum, new);
123 +
124 + return ret < 0 ? ret : 1;
125 +}
126 +
127 +/**
128 * mdiobus_read_nested - Nested version of the mdiobus_read function
129 * @bus: the mii_bus struct
130 * @addr: the phy address
131 @@ -879,6 +973,29 @@ int mdiobus_read(struct mii_bus *bus, in
132 EXPORT_SYMBOL(mdiobus_read);
133
134 /**
135 + * mdiobus_c45_read - Convenience function for reading a given MII mgmt register
136 + * @bus: the mii_bus struct
137 + * @addr: the phy address
138 + * @devad: device address to read
139 + * @regnum: register number to read
140 + *
141 + * NOTE: MUST NOT be called from interrupt context,
142 + * because the bus read/write functions may wait for an interrupt
143 + * to conclude the operation.
144 + */
145 +int mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum)
146 +{
147 + int retval;
148 +
149 + mutex_lock(&bus->mdio_lock);
150 + retval = __mdiobus_c45_read(bus, addr, devad, regnum);
151 + mutex_unlock(&bus->mdio_lock);
152 +
153 + return retval;
154 +}
155 +EXPORT_SYMBOL(mdiobus_c45_read);
156 +
157 +/**
158 * mdiobus_write_nested - Nested version of the mdiobus_write function
159 * @bus: the mii_bus struct
160 * @addr: the phy address
161 @@ -928,6 +1045,31 @@ int mdiobus_write(struct mii_bus *bus, i
162 EXPORT_SYMBOL(mdiobus_write);
163
164 /**
165 + * mdiobus_c45_write - Convenience function for writing a given MII mgmt register
166 + * @bus: the mii_bus struct
167 + * @addr: the phy address
168 + * @devad: device address to read
169 + * @regnum: register number to write
170 + * @val: value to write to @regnum
171 + *
172 + * NOTE: MUST NOT be called from interrupt context,
173 + * because the bus read/write functions may wait for an interrupt
174 + * to conclude the operation.
175 + */
176 +int mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum,
177 + u16 val)
178 +{
179 + int err;
180 +
181 + mutex_lock(&bus->mdio_lock);
182 + err = __mdiobus_c45_write(bus, addr, devad, regnum, val);
183 + mutex_unlock(&bus->mdio_lock);
184 +
185 + return err;
186 +}
187 +EXPORT_SYMBOL(mdiobus_c45_write);
188 +
189 +/**
190 * mdiobus_modify - Convenience function for modifying a given mdio device
191 * register
192 * @bus: the mii_bus struct
193 @@ -949,6 +1091,30 @@ int mdiobus_modify(struct mii_bus *bus,
194 EXPORT_SYMBOL_GPL(mdiobus_modify);
195
196 /**
197 + * mdiobus_c45_modify - Convenience function for modifying a given mdio device
198 + * register
199 + * @bus: the mii_bus struct
200 + * @addr: the phy address
201 + * @devad: device address to read
202 + * @regnum: register number to write
203 + * @mask: bit mask of bits to clear
204 + * @set: bit mask of bits to set
205 + */
206 +int mdiobus_c45_modify(struct mii_bus *bus, int addr, int devad, u32 regnum,
207 + u16 mask, u16 set)
208 +{
209 + int err;
210 +
211 + mutex_lock(&bus->mdio_lock);
212 + err = __mdiobus_c45_modify_changed(bus, addr, devad, regnum,
213 + mask, set);
214 + mutex_unlock(&bus->mdio_lock);
215 +
216 + return err < 0 ? err : 0;
217 +}
218 +EXPORT_SYMBOL_GPL(mdiobus_c45_modify);
219 +
220 +/**
221 * mdiobus_modify_changed - Convenience function for modifying a given mdio
222 * device register and returning if it changed
223 * @bus: the mii_bus struct
224 @@ -971,6 +1137,29 @@ int mdiobus_modify_changed(struct mii_bu
225 EXPORT_SYMBOL_GPL(mdiobus_modify_changed);
226
227 /**
228 + * mdiobus_c45_modify_changed - Convenience function for modifying a given mdio
229 + * device register and returning if it changed
230 + * @bus: the mii_bus struct
231 + * @addr: the phy address
232 + * @devad: device address to read
233 + * @regnum: register number to write
234 + * @mask: bit mask of bits to clear
235 + * @set: bit mask of bits to set
236 + */
237 +int mdiobus_c45_modify_changed(struct mii_bus *bus, int devad, int addr,
238 + u32 regnum, u16 mask, u16 set)
239 +{
240 + int err;
241 +
242 + mutex_lock(&bus->mdio_lock);
243 + err = __mdiobus_c45_modify_changed(bus, addr, devad, regnum, mask, set);
244 + mutex_unlock(&bus->mdio_lock);
245 +
246 + return err;
247 +}
248 +EXPORT_SYMBOL_GPL(mdiobus_c45_modify_changed);
249 +
250 +/**
251 * mdio_bus_match - determine if given MDIO driver supports the given
252 * MDIO device
253 * @dev: target MDIO device
254 --- a/include/linux/mdio.h
255 +++ b/include/linux/mdio.h
256 @@ -423,6 +423,17 @@ int mdiobus_modify(struct mii_bus *bus,
257 u16 set);
258 int mdiobus_modify_changed(struct mii_bus *bus, int addr, u32 regnum,
259 u16 mask, u16 set);
260 +int __mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum);
261 +int mdiobus_c45_read(struct mii_bus *bus, int addr, int devad, u32 regnum);
262 +int __mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum,
263 + u16 val);
264 +int mdiobus_c45_write(struct mii_bus *bus, int addr, int devad, u32 regnum,
265 + u16 val);
266 +int mdiobus_c45_modify(struct mii_bus *bus, int addr, int devad, u32 regnum,
267 + u16 mask, u16 set);
268 +
269 +int mdiobus_c45_modify_changed(struct mii_bus *bus, int addr, int devad,
270 + u32 regnum, u16 mask, u16 set);
271
272 static inline int mdiodev_read(struct mdio_device *mdiodev, u32 regnum)
273 {
274 @@ -463,29 +474,19 @@ static inline u16 mdiobus_c45_devad(u32
275 return FIELD_GET(MII_DEVADDR_C45_MASK, regnum);
276 }
277
278 -static inline int __mdiobus_c45_read(struct mii_bus *bus, int prtad, int devad,
279 - u16 regnum)
280 -{
281 - return __mdiobus_read(bus, prtad, mdiobus_c45_addr(devad, regnum));
282 -}
283 -
284 -static inline int __mdiobus_c45_write(struct mii_bus *bus, int prtad, int devad,
285 - u16 regnum, u16 val)
286 -{
287 - return __mdiobus_write(bus, prtad, mdiobus_c45_addr(devad, regnum),
288 - val);
289 -}
290 -
291 -static inline int mdiobus_c45_read(struct mii_bus *bus, int prtad, int devad,
292 - u16 regnum)
293 +static inline int mdiodev_c45_modify(struct mdio_device *mdiodev, int devad,
294 + u32 regnum, u16 mask, u16 set)
295 {
296 - return mdiobus_read(bus, prtad, mdiobus_c45_addr(devad, regnum));
297 + return mdiobus_c45_modify(mdiodev->bus, mdiodev->addr, devad, regnum,
298 + mask, set);
299 }
300
301 -static inline int mdiobus_c45_write(struct mii_bus *bus, int prtad, int devad,
302 - u16 regnum, u16 val)
303 +static inline int mdiodev_c45_modify_changed(struct mdio_device *mdiodev,
304 + int devad, u32 regnum, u16 mask,
305 + u16 set)
306 {
307 - return mdiobus_write(bus, prtad, mdiobus_c45_addr(devad, regnum), val);
308 + return mdiobus_c45_modify_changed(mdiodev->bus, mdiodev->addr, devad,
309 + regnum, mask, set);
310 }
311
312 int mdiobus_register_device(struct mdio_device *mdiodev);
313 --- a/include/linux/phy.h
314 +++ b/include/linux/phy.h
315 @@ -364,6 +364,11 @@ struct mii_bus {
316 int (*read)(struct mii_bus *bus, int addr, int regnum);
317 /** @write: Perform a write transfer on the bus */
318 int (*write)(struct mii_bus *bus, int addr, int regnum, u16 val);
319 + /** @read_c45: Perform a C45 read transfer on the bus */
320 + int (*read_c45)(struct mii_bus *bus, int addr, int devnum, int regnum);
321 + /** @write_c45: Perform a C45 write transfer on the bus */
322 + int (*write_c45)(struct mii_bus *bus, int addr, int devnum,
323 + int regnum, u16 val);
324 /** @reset: Perform a reset of the bus */
325 int (*reset)(struct mii_bus *bus);
326