1 // SPDX-License-Identifier: GPL-2.0-or-later
2
3 #include <linux/ethtool.h>
4 #include <linux/linkmode.h>
5 #include <linux/phy.h>
6
7 #include "phy-caps.h"
8
9 static struct link_capabilities link_caps[__LINK_CAPA_MAX] __ro_after_init = {
10 { SPEED_10, DUPLEX_HALF, {0} }, /* LINK_CAPA_10HD */
11 { SPEED_10, DUPLEX_FULL, {0} }, /* LINK_CAPA_10FD */
12 { SPEED_100, DUPLEX_HALF, {0} }, /* LINK_CAPA_100HD */
13 { SPEED_100, DUPLEX_FULL, {0} }, /* LINK_CAPA_100FD */
14 { SPEED_1000, DUPLEX_HALF, {0} }, /* LINK_CAPA_1000HD */
15 { SPEED_1000, DUPLEX_FULL, {0} }, /* LINK_CAPA_1000FD */
16 { SPEED_2500, DUPLEX_FULL, {0} }, /* LINK_CAPA_2500FD */
17 { SPEED_5000, DUPLEX_FULL, {0} }, /* LINK_CAPA_5000FD */
18 { SPEED_10000, DUPLEX_FULL, {0} }, /* LINK_CAPA_10000FD */
19 { SPEED_20000, DUPLEX_FULL, {0} }, /* LINK_CAPA_20000FD */
20 { SPEED_25000, DUPLEX_FULL, {0} }, /* LINK_CAPA_25000FD */
21 { SPEED_40000, DUPLEX_FULL, {0} }, /* LINK_CAPA_40000FD */
22 { SPEED_50000, DUPLEX_FULL, {0} }, /* LINK_CAPA_50000FD */
23 { SPEED_56000, DUPLEX_FULL, {0} }, /* LINK_CAPA_56000FD */
24 { SPEED_100000, DUPLEX_FULL, {0} }, /* LINK_CAPA_100000FD */
25 { SPEED_200000, DUPLEX_FULL, {0} }, /* LINK_CAPA_200000FD */
26 { SPEED_400000, DUPLEX_FULL, {0} }, /* LINK_CAPA_400000FD */
27 { SPEED_800000, DUPLEX_FULL, {0} }, /* LINK_CAPA_800000FD */
28 };
29
speed_duplex_to_capa(int speed,unsigned int duplex)30 static int speed_duplex_to_capa(int speed, unsigned int duplex)
31 {
32 if (duplex == DUPLEX_UNKNOWN ||
33 (speed > SPEED_1000 && duplex != DUPLEX_FULL))
34 return -EINVAL;
35
36 switch (speed) {
37 case SPEED_10: return duplex == DUPLEX_FULL ?
38 LINK_CAPA_10FD : LINK_CAPA_10HD;
39 case SPEED_100: return duplex == DUPLEX_FULL ?
40 LINK_CAPA_100FD : LINK_CAPA_100HD;
41 case SPEED_1000: return duplex == DUPLEX_FULL ?
42 LINK_CAPA_1000FD : LINK_CAPA_1000HD;
43 case SPEED_2500: return LINK_CAPA_2500FD;
44 case SPEED_5000: return LINK_CAPA_5000FD;
45 case SPEED_10000: return LINK_CAPA_10000FD;
46 case SPEED_20000: return LINK_CAPA_20000FD;
47 case SPEED_25000: return LINK_CAPA_25000FD;
48 case SPEED_40000: return LINK_CAPA_40000FD;
49 case SPEED_50000: return LINK_CAPA_50000FD;
50 case SPEED_56000: return LINK_CAPA_56000FD;
51 case SPEED_100000: return LINK_CAPA_100000FD;
52 case SPEED_200000: return LINK_CAPA_200000FD;
53 case SPEED_400000: return LINK_CAPA_400000FD;
54 case SPEED_800000: return LINK_CAPA_800000FD;
55 }
56
57 return -EINVAL;
58 }
59
60 #define for_each_link_caps_asc_speed(cap) \
61 for (cap = link_caps; cap < &link_caps[__LINK_CAPA_MAX]; cap++)
62
63 #define for_each_link_caps_desc_speed(cap) \
64 for (cap = &link_caps[__LINK_CAPA_MAX - 1]; cap >= link_caps; cap--)
65
66 /**
67 * phy_caps_init() - Initializes the link_caps array from the link_mode_params.
68 *
69 * Returns: 0 if phy caps init was successful, -EINVAL if we found an
70 * unexpected linkmode setting that requires LINK_CAPS update.
71 *
72 */
phy_caps_init(void)73 int phy_caps_init(void)
74 {
75 const struct link_mode_info *linkmode;
76 int i, capa;
77
78 /* Fill the caps array from net/ethtool/common.c */
79 for (i = 0; i < __ETHTOOL_LINK_MODE_MASK_NBITS; i++) {
80 linkmode = &link_mode_params[i];
81 capa = speed_duplex_to_capa(linkmode->speed, linkmode->duplex);
82
83 if (capa < 0) {
84 if (linkmode->speed != SPEED_UNKNOWN) {
85 pr_err("Unknown speed %d, please update LINK_CAPS\n",
86 linkmode->speed);
87 return -EINVAL;
88 }
89 continue;
90 }
91
92 __set_bit(i, link_caps[capa].linkmodes);
93 }
94
95 return 0;
96 }
97
98 /**
99 * phy_caps_speeds() - Fill an array of supported SPEED_* values for given modes
100 * @speeds: Output array to store the speeds list into
101 * @size: Size of the output array
102 * @linkmodes: Linkmodes to get the speeds from
103 *
104 * Fills the speeds array with all possible speeds that can be achieved with
105 * the specified linkmodes.
106 *
107 * Returns: The number of speeds filled into the array. If the input array isn't
108 * big enough to store all speeds, fill it as much as possible.
109 */
phy_caps_speeds(unsigned int * speeds,size_t size,unsigned long * linkmodes)110 size_t phy_caps_speeds(unsigned int *speeds, size_t size,
111 unsigned long *linkmodes)
112 {
113 struct link_capabilities *lcap;
114 size_t count = 0;
115
116 for_each_link_caps_asc_speed(lcap) {
117 if (linkmode_intersects(lcap->linkmodes, linkmodes) &&
118 (count == 0 || speeds[count - 1] != lcap->speed)) {
119 speeds[count++] = lcap->speed;
120 if (count >= size)
121 break;
122 }
123 }
124
125 return count;
126 }
127
128 /**
129 * phy_caps_lookup_by_linkmode() - Lookup the fastest matching link_capabilities
130 * @linkmodes: Linkmodes to match against
131 *
132 * Returns: The highest-speed link_capabilities that intersects the given
133 * linkmodes. In case several DUPLEX_ options exist at that speed,
134 * DUPLEX_FULL is matched first. NULL is returned if no match.
135 */
136 const struct link_capabilities *
phy_caps_lookup_by_linkmode(const unsigned long * linkmodes)137 phy_caps_lookup_by_linkmode(const unsigned long *linkmodes)
138 {
139 struct link_capabilities *lcap;
140
141 for_each_link_caps_desc_speed(lcap)
142 if (linkmode_intersects(lcap->linkmodes, linkmodes))
143 return lcap;
144
145 return NULL;
146 }
147
148 /**
149 * phy_caps_lookup_by_linkmode_rev() - Lookup the slowest matching link_capabilities
150 * @linkmodes: Linkmodes to match against
151 * @fdx_only: Full duplex match only when set
152 *
153 * Returns: The lowest-speed link_capabilities that intersects the given
154 * linkmodes. When set, fdx_only will ignore half-duplex matches.
155 * NULL is returned if no match.
156 */
157 const struct link_capabilities *
phy_caps_lookup_by_linkmode_rev(const unsigned long * linkmodes,bool fdx_only)158 phy_caps_lookup_by_linkmode_rev(const unsigned long *linkmodes, bool fdx_only)
159 {
160 struct link_capabilities *lcap;
161
162 for_each_link_caps_asc_speed(lcap) {
163 if (fdx_only && lcap->duplex != DUPLEX_FULL)
164 continue;
165
166 if (linkmode_intersects(lcap->linkmodes, linkmodes))
167 return lcap;
168 }
169
170 return NULL;
171 }
172
173 /**
174 * phy_caps_lookup() - Lookup capabilities by speed/duplex that matches a mask
175 * @speed: Speed to match
176 * @duplex: Duplex to match
177 * @supported: Mask of linkmodes to match
178 * @exact: Perform an exact match or not.
179 *
180 * Lookup a link_capabilities entry that intersect the supported linkmodes mask,
181 * and that matches the passed speed and duplex.
182 *
183 * When @exact is set, an exact match is performed on speed and duplex, meaning
184 * that if the linkmodes for the given speed and duplex intersect the supported
185 * mask, this capability is returned, otherwise we don't have a match and return
186 * NULL.
187 *
188 * When @exact is not set, we return either an exact match, or matching capabilities
189 * at lower speed, or the lowest matching speed, or NULL.
190 *
191 * Returns: a matched link_capabilities according to the above process, NULL
192 * otherwise.
193 */
194 const struct link_capabilities *
phy_caps_lookup(int speed,unsigned int duplex,const unsigned long * supported,bool exact)195 phy_caps_lookup(int speed, unsigned int duplex, const unsigned long *supported,
196 bool exact)
197 {
198 const struct link_capabilities *lcap, *last = NULL;
199
200 for_each_link_caps_desc_speed(lcap) {
201 if (linkmode_intersects(lcap->linkmodes, supported)) {
202 last = lcap;
203 /* exact match on speed and duplex*/
204 if (lcap->speed == speed && lcap->duplex == duplex) {
205 return lcap;
206 } else if (!exact) {
207 if (lcap->speed <= speed)
208 return lcap;
209 }
210 }
211 }
212
213 if (!exact)
214 return last;
215
216 return NULL;
217 }
218 EXPORT_SYMBOL_GPL(phy_caps_lookup);
219
220 /**
221 * phy_caps_linkmode_max_speed() - Clamp a linkmodes set to a max speed
222 * @max_speed: Speed limit for the linkmode set
223 * @linkmodes: Linkmodes to limit
224 */
phy_caps_linkmode_max_speed(u32 max_speed,unsigned long * linkmodes)225 void phy_caps_linkmode_max_speed(u32 max_speed, unsigned long *linkmodes)
226 {
227 struct link_capabilities *lcap;
228
229 for_each_link_caps_desc_speed(lcap)
230 if (lcap->speed > max_speed)
231 linkmode_andnot(linkmodes, linkmodes, lcap->linkmodes);
232 else
233 break;
234 }
235
236 /**
237 * phy_caps_valid() - Validate a linkmodes set agains given speed and duplex
238 * @speed: input speed to validate
239 * @duplex: input duplex to validate. Passing DUPLEX_UNKNOWN is always not valid
240 * @linkmodes: The linkmodes to validate
241 *
242 * Returns: True if at least one of the linkmodes in @linkmodes can function at
243 * the given speed and duplex, false otherwise.
244 */
phy_caps_valid(int speed,int duplex,const unsigned long * linkmodes)245 bool phy_caps_valid(int speed, int duplex, const unsigned long *linkmodes)
246 {
247 int capa = speed_duplex_to_capa(speed, duplex);
248
249 if (capa < 0)
250 return false;
251
252 return linkmode_intersects(link_caps[capa].linkmodes, linkmodes);
253 }
254
255 /**
256 * phy_caps_linkmodes() - Convert a bitfield of capabilities into linkmodes
257 * @caps: The list of caps, each bit corresponding to a LINK_CAPA value
258 * @linkmodes: The set of linkmodes to fill. Must be previously initialized.
259 */
phy_caps_linkmodes(unsigned long caps,unsigned long * linkmodes)260 void phy_caps_linkmodes(unsigned long caps, unsigned long *linkmodes)
261 {
262 unsigned long capa;
263
264 for_each_set_bit(capa, &caps, __LINK_CAPA_MAX)
265 linkmode_or(linkmodes, linkmodes, link_caps[capa].linkmodes);
266 }
267 EXPORT_SYMBOL_GPL(phy_caps_linkmodes);
268
269 /**
270 * phy_caps_from_interface() - Get the link capa from a given PHY interface
271 * @interface: The PHY interface we want to get the possible Speed/Duplex from
272 *
273 * Returns: A bitmask of LINK_CAPA_xxx values that can be achieved with the
274 * provided interface.
275 */
phy_caps_from_interface(phy_interface_t interface)276 unsigned long phy_caps_from_interface(phy_interface_t interface)
277 {
278 unsigned long link_caps = 0;
279
280 switch (interface) {
281 case PHY_INTERFACE_MODE_USXGMII:
282 link_caps |= BIT(LINK_CAPA_10000FD) | BIT(LINK_CAPA_5000FD);
283 fallthrough;
284
285 case PHY_INTERFACE_MODE_10G_QXGMII:
286 link_caps |= BIT(LINK_CAPA_2500FD);
287 fallthrough;
288
289 case PHY_INTERFACE_MODE_RGMII_TXID:
290 case PHY_INTERFACE_MODE_RGMII_RXID:
291 case PHY_INTERFACE_MODE_RGMII_ID:
292 case PHY_INTERFACE_MODE_RGMII:
293 case PHY_INTERFACE_MODE_PSGMII:
294 case PHY_INTERFACE_MODE_QSGMII:
295 case PHY_INTERFACE_MODE_QUSGMII:
296 case PHY_INTERFACE_MODE_SGMII:
297 case PHY_INTERFACE_MODE_GMII:
298 link_caps |= BIT(LINK_CAPA_1000HD) | BIT(LINK_CAPA_1000FD);
299 fallthrough;
300
301 case PHY_INTERFACE_MODE_REVRMII:
302 case PHY_INTERFACE_MODE_RMII:
303 case PHY_INTERFACE_MODE_SMII:
304 case PHY_INTERFACE_MODE_REVMII:
305 case PHY_INTERFACE_MODE_MII:
306 link_caps |= BIT(LINK_CAPA_10HD) | BIT(LINK_CAPA_10FD);
307 fallthrough;
308
309 case PHY_INTERFACE_MODE_100BASEX:
310 link_caps |= BIT(LINK_CAPA_100HD) | BIT(LINK_CAPA_100FD);
311 break;
312
313 case PHY_INTERFACE_MODE_TBI:
314 case PHY_INTERFACE_MODE_MOCA:
315 case PHY_INTERFACE_MODE_RTBI:
316 case PHY_INTERFACE_MODE_1000BASEX:
317 link_caps |= BIT(LINK_CAPA_1000HD);
318 fallthrough;
319 case PHY_INTERFACE_MODE_1000BASEKX:
320 case PHY_INTERFACE_MODE_TRGMII:
321 link_caps |= BIT(LINK_CAPA_1000FD);
322 break;
323
324 case PHY_INTERFACE_MODE_2500BASEX:
325 link_caps |= BIT(LINK_CAPA_2500FD);
326 break;
327
328 case PHY_INTERFACE_MODE_5GBASER:
329 link_caps |= BIT(LINK_CAPA_5000FD);
330 break;
331
332 case PHY_INTERFACE_MODE_XGMII:
333 case PHY_INTERFACE_MODE_RXAUI:
334 case PHY_INTERFACE_MODE_XAUI:
335 case PHY_INTERFACE_MODE_10GBASER:
336 case PHY_INTERFACE_MODE_10GKR:
337 link_caps |= BIT(LINK_CAPA_10000FD);
338 break;
339
340 case PHY_INTERFACE_MODE_25GBASER:
341 link_caps |= BIT(LINK_CAPA_25000FD);
342 break;
343
344 case PHY_INTERFACE_MODE_XLGMII:
345 link_caps |= BIT(LINK_CAPA_40000FD);
346 break;
347
348 case PHY_INTERFACE_MODE_INTERNAL:
349 link_caps |= LINK_CAPA_ALL;
350 break;
351
352 case PHY_INTERFACE_MODE_NA:
353 case PHY_INTERFACE_MODE_MAX:
354 break;
355 }
356
357 return link_caps;
358 }
359 EXPORT_SYMBOL_GPL(phy_caps_from_interface);
360