xref: /linux/drivers/net/phy/phy_caps.c (revision 37a93dd5c49b5fda807fd204edf2547c3493319c)
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_80000, DUPLEX_FULL, {0} }, /* LINK_CAPA_80000FD */
25 	{ SPEED_100000, DUPLEX_FULL, {0} }, /* LINK_CAPA_100000FD */
26 	{ SPEED_200000, DUPLEX_FULL, {0} }, /* LINK_CAPA_200000FD */
27 	{ SPEED_400000, DUPLEX_FULL, {0} }, /* LINK_CAPA_400000FD */
28 	{ SPEED_800000, DUPLEX_FULL, {0} }, /* LINK_CAPA_800000FD */
29 	{ SPEED_1600000, DUPLEX_FULL, {0} }, /* LINK_CAPA_1600000FD */
30 };
31 
32 static int speed_duplex_to_capa(int speed, unsigned int duplex)
33 {
34 	if (duplex == DUPLEX_UNKNOWN ||
35 	    (speed > SPEED_1000 && duplex != DUPLEX_FULL))
36 		return -EINVAL;
37 
38 	switch (speed) {
39 	case SPEED_10: return duplex == DUPLEX_FULL ?
40 			      LINK_CAPA_10FD : LINK_CAPA_10HD;
41 	case SPEED_100: return duplex == DUPLEX_FULL ?
42 			       LINK_CAPA_100FD : LINK_CAPA_100HD;
43 	case SPEED_1000: return duplex == DUPLEX_FULL ?
44 				LINK_CAPA_1000FD : LINK_CAPA_1000HD;
45 	case SPEED_2500: return LINK_CAPA_2500FD;
46 	case SPEED_5000: return LINK_CAPA_5000FD;
47 	case SPEED_10000: return LINK_CAPA_10000FD;
48 	case SPEED_20000: return LINK_CAPA_20000FD;
49 	case SPEED_25000: return LINK_CAPA_25000FD;
50 	case SPEED_40000: return LINK_CAPA_40000FD;
51 	case SPEED_50000: return LINK_CAPA_50000FD;
52 	case SPEED_56000: return LINK_CAPA_56000FD;
53 	case SPEED_80000: return LINK_CAPA_80000FD;
54 	case SPEED_100000: return LINK_CAPA_100000FD;
55 	case SPEED_200000: return LINK_CAPA_200000FD;
56 	case SPEED_400000: return LINK_CAPA_400000FD;
57 	case SPEED_800000: return LINK_CAPA_800000FD;
58 	case SPEED_1600000: return LINK_CAPA_1600000FD;
59 	}
60 
61 	return -EINVAL;
62 }
63 
64 #define for_each_link_caps_asc_speed(cap) \
65 	for (cap = link_caps; cap < &link_caps[__LINK_CAPA_MAX]; cap++)
66 
67 #define for_each_link_caps_desc_speed(cap) \
68 	for (cap = &link_caps[__LINK_CAPA_MAX - 1]; cap >= link_caps; cap--)
69 
70 /**
71  * phy_caps_init() - Initializes the link_caps array from the link_mode_params.
72  *
73  * Returns: 0 if phy caps init was successful, -EINVAL if we found an
74  *	    unexpected linkmode setting that requires LINK_CAPS update.
75  *
76  */
77 int __init phy_caps_init(void)
78 {
79 	const struct link_mode_info *linkmode;
80 	int i, capa;
81 
82 	/* Fill the caps array from net/ethtool/common.c */
83 	for (i = 0; i < __ETHTOOL_LINK_MODE_MASK_NBITS; i++) {
84 		linkmode = &link_mode_params[i];
85 
86 		/* Sanity check the linkmodes array for number of pairs */
87 		if (linkmode->pairs < linkmode->min_pairs) {
88 			pr_err("Pairs count must not be under min_pairs for linkmode %d\n",
89 			       i);
90 			return -EINVAL;
91 		}
92 
93 		capa = speed_duplex_to_capa(linkmode->speed, linkmode->duplex);
94 
95 		if (capa < 0) {
96 			if (linkmode->speed != SPEED_UNKNOWN) {
97 				pr_err("Unknown speed %d, please update LINK_CAPS\n",
98 				       linkmode->speed);
99 				return -EINVAL;
100 			}
101 			continue;
102 		}
103 
104 		__set_bit(i, link_caps[capa].linkmodes);
105 	}
106 
107 	return 0;
108 }
109 
110 /**
111  * phy_caps_speeds() - Fill an array of supported SPEED_* values for given modes
112  * @speeds: Output array to store the speeds list into
113  * @size: Size of the output array
114  * @linkmodes: Linkmodes to get the speeds from
115  *
116  * Fills the speeds array with all possible speeds that can be achieved with
117  * the specified linkmodes.
118  *
119  * Returns: The number of speeds filled into the array. If the input array isn't
120  *	    big enough to store all speeds, fill it as much as possible.
121  */
122 size_t phy_caps_speeds(unsigned int *speeds, size_t size,
123 		       unsigned long *linkmodes)
124 {
125 	struct link_capabilities *lcap;
126 	size_t count = 0;
127 
128 	for_each_link_caps_asc_speed(lcap) {
129 		if (linkmode_intersects(lcap->linkmodes, linkmodes) &&
130 		    (count == 0 || speeds[count - 1] != lcap->speed)) {
131 			speeds[count++] = lcap->speed;
132 			if (count >= size)
133 				break;
134 		}
135 	}
136 
137 	return count;
138 }
139 
140 /**
141  * phy_caps_lookup_by_linkmode() - Lookup the fastest matching link_capabilities
142  * @linkmodes: Linkmodes to match against
143  *
144  * Returns: The highest-speed link_capabilities that intersects the given
145  *	    linkmodes. In case several DUPLEX_ options exist at that speed,
146  *	    DUPLEX_FULL is matched first. NULL is returned if no match.
147  */
148 const struct link_capabilities *
149 phy_caps_lookup_by_linkmode(const unsigned long *linkmodes)
150 {
151 	struct link_capabilities *lcap;
152 
153 	for_each_link_caps_desc_speed(lcap)
154 		if (linkmode_intersects(lcap->linkmodes, linkmodes))
155 			return lcap;
156 
157 	return NULL;
158 }
159 
160 /**
161  * phy_caps_lookup_by_linkmode_rev() - Lookup the slowest matching link_capabilities
162  * @linkmodes: Linkmodes to match against
163  * @fdx_only: Full duplex match only when set
164  *
165  * Returns: The lowest-speed link_capabilities that intersects the given
166  *	    linkmodes. When set, fdx_only will ignore half-duplex matches.
167  *	    NULL is returned if no match.
168  */
169 const struct link_capabilities *
170 phy_caps_lookup_by_linkmode_rev(const unsigned long *linkmodes, bool fdx_only)
171 {
172 	struct link_capabilities *lcap;
173 
174 	for_each_link_caps_asc_speed(lcap) {
175 		if (fdx_only && lcap->duplex != DUPLEX_FULL)
176 			continue;
177 
178 		if (linkmode_intersects(lcap->linkmodes, linkmodes))
179 			return lcap;
180 	}
181 
182 	return NULL;
183 }
184 
185 /**
186  * phy_caps_lookup() - Lookup capabilities by speed/duplex that matches a mask
187  * @speed: Speed to match
188  * @duplex: Duplex to match
189  * @supported: Mask of linkmodes to match
190  * @exact: Perform an exact match or not.
191  *
192  * Lookup a link_capabilities entry that intersect the supported linkmodes mask,
193  * and that matches the passed speed and duplex.
194  *
195  * When @exact is set, an exact match is performed on speed and duplex, meaning
196  * that if the linkmodes for the given speed and duplex intersect the supported
197  * mask, this capability is returned, otherwise we don't have a match and return
198  * NULL.
199  *
200  * When @exact is not set, we return either an exact match, or matching capabilities
201  * at lower speed, or the lowest matching speed, or NULL.
202  *
203  * Non-exact matches will try to return an exact speed and duplex match, but may
204  * return matching capabilities with same speed but a different duplex.
205  *
206  * Returns: a matched link_capabilities according to the above process, NULL
207  *	    otherwise.
208  */
209 const struct link_capabilities *
210 phy_caps_lookup(int speed, unsigned int duplex, const unsigned long *supported,
211 		bool exact)
212 {
213 	const struct link_capabilities *lcap, *match = NULL, *last = NULL;
214 
215 	for_each_link_caps_desc_speed(lcap) {
216 		if (linkmode_intersects(lcap->linkmodes, supported)) {
217 			last = lcap;
218 			/* exact match on speed and duplex*/
219 			if (lcap->speed == speed && lcap->duplex == duplex) {
220 				return lcap;
221 			} else if (!exact) {
222 				if (!match && lcap->speed <= speed)
223 					match = lcap;
224 
225 				if (lcap->speed < speed)
226 					break;
227 			}
228 		}
229 	}
230 
231 	if (!match && !exact)
232 		match = last;
233 
234 	return match;
235 }
236 EXPORT_SYMBOL_GPL(phy_caps_lookup);
237 
238 /**
239  * phy_caps_linkmode_max_speed() - Clamp a linkmodes set to a max speed
240  * @max_speed: Speed limit for the linkmode set
241  * @linkmodes: Linkmodes to limit
242  */
243 void phy_caps_linkmode_max_speed(u32 max_speed, unsigned long *linkmodes)
244 {
245 	struct link_capabilities *lcap;
246 
247 	for_each_link_caps_desc_speed(lcap)
248 		if (lcap->speed > max_speed)
249 			linkmode_andnot(linkmodes, linkmodes, lcap->linkmodes);
250 		else
251 			break;
252 }
253 
254 /**
255  * phy_caps_valid() - Validate a linkmodes set agains given speed and duplex
256  * @speed: input speed to validate
257  * @duplex: input duplex to validate. Passing DUPLEX_UNKNOWN is always not valid
258  * @linkmodes: The linkmodes to validate
259  *
260  * Returns: True if at least one of the linkmodes in @linkmodes can function at
261  *          the given speed and duplex, false otherwise.
262  */
263 bool phy_caps_valid(int speed, int duplex, const unsigned long *linkmodes)
264 {
265 	int capa = speed_duplex_to_capa(speed, duplex);
266 
267 	if (capa < 0)
268 		return false;
269 
270 	return linkmode_intersects(link_caps[capa].linkmodes, linkmodes);
271 }
272 
273 /**
274  * phy_caps_linkmodes() - Convert a bitfield of capabilities into linkmodes
275  * @caps: The list of caps, each bit corresponding to a LINK_CAPA value
276  * @linkmodes: The set of linkmodes to fill. Must be previously initialized.
277  */
278 void phy_caps_linkmodes(unsigned long caps, unsigned long *linkmodes)
279 {
280 	unsigned long capa;
281 
282 	for_each_set_bit(capa, &caps, __LINK_CAPA_MAX)
283 		linkmode_or(linkmodes, linkmodes, link_caps[capa].linkmodes);
284 }
285 EXPORT_SYMBOL_GPL(phy_caps_linkmodes);
286 
287 /**
288  * phy_caps_from_interface() - Get the link capa from a given PHY interface
289  * @interface: The PHY interface we want to get the possible Speed/Duplex from
290  *
291  * Returns: A bitmask of LINK_CAPA_xxx values that can be achieved with the
292  *          provided interface.
293  */
294 unsigned long phy_caps_from_interface(phy_interface_t interface)
295 {
296 	unsigned long link_caps = 0;
297 
298 	switch (interface) {
299 	case PHY_INTERFACE_MODE_USXGMII:
300 		link_caps |= BIT(LINK_CAPA_10000FD) | BIT(LINK_CAPA_5000FD);
301 		fallthrough;
302 
303 	case PHY_INTERFACE_MODE_10G_QXGMII:
304 		link_caps |= BIT(LINK_CAPA_2500FD);
305 		fallthrough;
306 
307 	case PHY_INTERFACE_MODE_RGMII_TXID:
308 	case PHY_INTERFACE_MODE_RGMII_RXID:
309 	case PHY_INTERFACE_MODE_RGMII_ID:
310 	case PHY_INTERFACE_MODE_RGMII:
311 	case PHY_INTERFACE_MODE_PSGMII:
312 	case PHY_INTERFACE_MODE_QSGMII:
313 	case PHY_INTERFACE_MODE_QUSGMII:
314 	case PHY_INTERFACE_MODE_SGMII:
315 	case PHY_INTERFACE_MODE_GMII:
316 		link_caps |= BIT(LINK_CAPA_1000HD) | BIT(LINK_CAPA_1000FD);
317 		fallthrough;
318 
319 	case PHY_INTERFACE_MODE_REVRMII:
320 	case PHY_INTERFACE_MODE_RMII:
321 	case PHY_INTERFACE_MODE_SMII:
322 	case PHY_INTERFACE_MODE_REVMII:
323 	case PHY_INTERFACE_MODE_MII:
324 		link_caps |= BIT(LINK_CAPA_10HD) | BIT(LINK_CAPA_10FD);
325 		fallthrough;
326 
327 	case PHY_INTERFACE_MODE_100BASEX:
328 		link_caps |= BIT(LINK_CAPA_100HD) | BIT(LINK_CAPA_100FD);
329 		break;
330 
331 	case PHY_INTERFACE_MODE_MIILITE:
332 		link_caps |= BIT(LINK_CAPA_10FD) | BIT(LINK_CAPA_100FD);
333 		break;
334 
335 	case PHY_INTERFACE_MODE_TBI:
336 	case PHY_INTERFACE_MODE_MOCA:
337 	case PHY_INTERFACE_MODE_RTBI:
338 	case PHY_INTERFACE_MODE_1000BASEX:
339 		link_caps |= BIT(LINK_CAPA_1000HD);
340 		fallthrough;
341 	case PHY_INTERFACE_MODE_1000BASEKX:
342 	case PHY_INTERFACE_MODE_TRGMII:
343 		link_caps |= BIT(LINK_CAPA_1000FD);
344 		break;
345 
346 	case PHY_INTERFACE_MODE_2500BASEX:
347 		link_caps |= BIT(LINK_CAPA_2500FD);
348 		break;
349 
350 	case PHY_INTERFACE_MODE_5GBASER:
351 		link_caps |= BIT(LINK_CAPA_5000FD);
352 		break;
353 
354 	case PHY_INTERFACE_MODE_XGMII:
355 	case PHY_INTERFACE_MODE_RXAUI:
356 	case PHY_INTERFACE_MODE_XAUI:
357 	case PHY_INTERFACE_MODE_10GBASER:
358 	case PHY_INTERFACE_MODE_10GKR:
359 		link_caps |= BIT(LINK_CAPA_10000FD);
360 		break;
361 
362 	case PHY_INTERFACE_MODE_25GBASER:
363 		link_caps |= BIT(LINK_CAPA_25000FD);
364 		break;
365 
366 	case PHY_INTERFACE_MODE_XLGMII:
367 		link_caps |= BIT(LINK_CAPA_40000FD);
368 		break;
369 
370 	case PHY_INTERFACE_MODE_50GBASER:
371 	case PHY_INTERFACE_MODE_LAUI:
372 		link_caps |= BIT(LINK_CAPA_50000FD);
373 		break;
374 
375 	case PHY_INTERFACE_MODE_100GBASEP:
376 		link_caps |= BIT(LINK_CAPA_100000FD);
377 		break;
378 
379 	case PHY_INTERFACE_MODE_INTERNAL:
380 		link_caps |= LINK_CAPA_ALL;
381 		break;
382 
383 	case PHY_INTERFACE_MODE_NA:
384 	case PHY_INTERFACE_MODE_MAX:
385 		break;
386 	}
387 
388 	return link_caps;
389 }
390 EXPORT_SYMBOL_GPL(phy_caps_from_interface);
391 
392 /**
393  * phy_caps_medium_get_supported() - Returns linkmodes supported on a given medium
394  * @supported: After this call, contains all possible linkmodes on a given medium,
395  *	       and with the given number of pairs, or less.
396  * @medium: The medium to get the support from
397  * @pairs: The number of pairs used on the given medium. Only relevant for modes
398  *	   that support this notion, such as BaseT. Pass 0 if not applicable.
399  *
400  * If no match exists, the supported field is left untouched.
401  */
402 void phy_caps_medium_get_supported(unsigned long *supported,
403 				   enum ethtool_link_medium medium,
404 				   int pairs)
405 {
406 	int i;
407 
408 	for (i = 0; i < __ETHTOOL_LINK_MODE_MASK_NBITS; i++) {
409 		/* Special bits such as Autoneg, Pause, Asym_pause, etc. are
410 		 * set and will be masked away by the port parent.
411 		 */
412 		if (link_mode_params[i].mediums == BIT(ETHTOOL_LINK_MEDIUM_NONE)) {
413 			linkmode_set_bit(i, supported);
414 			continue;
415 		}
416 
417 		/* If this medium matches, and had a non-zero min-pairs */
418 		if (link_mode_params[i].mediums & BIT(medium) &&
419 		    (!link_mode_params[i].min_pairs ||
420 		      (link_mode_params[i].min_pairs <= pairs &&
421 		      link_mode_params[i].pairs >= pairs)))
422 			linkmode_set_bit(i, supported);
423 	}
424 }
425 EXPORT_SYMBOL_GPL(phy_caps_medium_get_supported);
426 
427 /**
428  * phy_caps_mediums_from_linkmodes() - Get all mediums from a linkmodes list
429  * @linkmodes: A bitset of linkmodes to get the mediums from
430  *
431  * Returns: A bitset of ETHTOOL_MEDIUM_XXX values corresponding to all medium
432  *	    types in the linkmodes list
433  */
434 u32 phy_caps_mediums_from_linkmodes(unsigned long *linkmodes)
435 {
436 	const struct link_mode_info *linkmode;
437 	u32 mediums = 0;
438 	int i;
439 
440 	for_each_set_bit(i, linkmodes, __ETHTOOL_LINK_MODE_MASK_NBITS) {
441 		linkmode = &link_mode_params[i];
442 		mediums |= linkmode->mediums;
443 	}
444 
445 	return mediums;
446 }
447 EXPORT_SYMBOL_GPL(phy_caps_mediums_from_linkmodes);
448