Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge branch 'net-phy-rework-linkmodes-handling-in-a-dedicated-file'

Maxime Chevallier says:

====================
net: phy: Rework linkmodes handling in a dedicated file

This is V5 of the phy_caps series. In a nutshell, this series reworks the way
we maintain the list of speed/duplex capablities for each linkmode so that we
no longer have multiple definition of these associations.

That will help making sure that when people add new linkmodes in
include/uapi/linux/ethtool.h, they don't have to update phylib and phylink as
well, making the process more straightforward and less error-prone.

It also generalises the phy_caps interface to be able to lookup linkmodes
from phy_interface_t, which is needed for the multi-port work I've been working
on for a while.

This V5 addresse Russell's and Paolo's reviews, namely :

- Error out when encountering an unknown SPEED_XXX setting

It prints an error and fails to initialize phylib. I've tested by
introducing a dummy 1.6T speed, I guess it's only a matter of time
before that actually happens :)

- Deal more gracefully with the fixed-link settings, keeping some level of
compatibility with what we had before by making sure we report a
single BaseT mode like before.

V1 : https://lore.kernel.org/netdev/20250222142727.894124-1-maxime.chevallier@bootlin.com/
V2 : https://lore.kernel.org/netdev/20250226100929.1646454-1-maxime.chevallier@bootlin.com/
V3 : https://lore.kernel.org/netdev/20250228145540.2209551-1-maxime.chevallier@bootlin.com/
V4 : https://lore.kernel.org/netdev/20250303090321.805785-1-maxime.chevallier@bootlin.com/
====================

Link: https://patch.msgid.link/20250307173611.129125-1-maxime.chevallier@bootlin.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>

+571 -545
+1 -1
drivers/net/phy/Makefile
··· 3 3 4 4 libphy-y := phy.o phy-c45.o phy-core.o phy_device.o \ 5 5 linkmode.o phy_link_topology.o \ 6 - phy_package.o 6 + phy_package.o phy_caps.o 7 7 mdio-bus-y += mdio_bus.o mdio_device.o 8 8 9 9 ifdef CONFIG_MDIO_DEVICE
+63
drivers/net/phy/phy-caps.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 + /* 3 + * link caps internal header, for link modes <-> capabilities <-> interfaces 4 + * conversions. 5 + */ 6 + 7 + #ifndef __PHY_CAPS_H 8 + #define __PHY_CAPS_H 9 + 10 + #include <linux/ethtool.h> 11 + #include <linux/phy.h> 12 + 13 + enum { 14 + LINK_CAPA_10HD = 0, 15 + LINK_CAPA_10FD, 16 + LINK_CAPA_100HD, 17 + LINK_CAPA_100FD, 18 + LINK_CAPA_1000HD, 19 + LINK_CAPA_1000FD, 20 + LINK_CAPA_2500FD, 21 + LINK_CAPA_5000FD, 22 + LINK_CAPA_10000FD, 23 + LINK_CAPA_20000FD, 24 + LINK_CAPA_25000FD, 25 + LINK_CAPA_40000FD, 26 + LINK_CAPA_50000FD, 27 + LINK_CAPA_56000FD, 28 + LINK_CAPA_100000FD, 29 + LINK_CAPA_200000FD, 30 + LINK_CAPA_400000FD, 31 + LINK_CAPA_800000FD, 32 + 33 + __LINK_CAPA_MAX, 34 + }; 35 + 36 + #define LINK_CAPA_ALL GENMASK((__LINK_CAPA_MAX - 1), 0) 37 + 38 + struct link_capabilities { 39 + int speed; 40 + unsigned int duplex; 41 + __ETHTOOL_DECLARE_LINK_MODE_MASK(linkmodes); 42 + }; 43 + 44 + int phy_caps_init(void); 45 + 46 + size_t phy_caps_speeds(unsigned int *speeds, size_t size, 47 + unsigned long *linkmodes); 48 + void phy_caps_linkmode_max_speed(u32 max_speed, unsigned long *linkmodes); 49 + bool phy_caps_valid(int speed, int duplex, const unsigned long *linkmodes); 50 + void phy_caps_linkmodes(unsigned long caps, unsigned long *linkmodes); 51 + unsigned long phy_caps_from_interface(phy_interface_t interface); 52 + 53 + const struct link_capabilities * 54 + phy_caps_lookup_by_linkmode(const unsigned long *linkmodes); 55 + 56 + const struct link_capabilities * 57 + phy_caps_lookup_by_linkmode_rev(const unsigned long *linkmodes, bool fdx_only); 58 + 59 + const struct link_capabilities * 60 + phy_caps_lookup(int speed, unsigned int duplex, const unsigned long *supported, 61 + bool exact); 62 + 63 + #endif /* __PHY_CAPS_H */
+18 -235
drivers/net/phy/phy-core.c
··· 8 8 9 9 #include "phylib.h" 10 10 #include "phylib-internal.h" 11 + #include "phy-caps.h" 11 12 12 13 /** 13 14 * phy_speed_to_str - Return a string representing the PHY link speed ··· 157 156 } 158 157 EXPORT_SYMBOL_GPL(phy_interface_num_ports); 159 158 160 - /* A mapping of all SUPPORTED settings to speed/duplex. This table 161 - * must be grouped by speed and sorted in descending match priority 162 - * - iow, descending speed. 163 - */ 164 - 165 - #define PHY_SETTING(s, d, b) { .speed = SPEED_ ## s, .duplex = DUPLEX_ ## d, \ 166 - .bit = ETHTOOL_LINK_MODE_ ## b ## _BIT} 167 - 168 - static const struct phy_setting settings[] = { 169 - /* 800G */ 170 - PHY_SETTING( 800000, FULL, 800000baseCR8_Full ), 171 - PHY_SETTING( 800000, FULL, 800000baseKR8_Full ), 172 - PHY_SETTING( 800000, FULL, 800000baseDR8_Full ), 173 - PHY_SETTING( 800000, FULL, 800000baseDR8_2_Full ), 174 - PHY_SETTING( 800000, FULL, 800000baseSR8_Full ), 175 - PHY_SETTING( 800000, FULL, 800000baseVR8_Full ), 176 - PHY_SETTING( 800000, FULL, 800000baseCR4_Full ), 177 - PHY_SETTING( 800000, FULL, 800000baseKR4_Full ), 178 - PHY_SETTING( 800000, FULL, 800000baseDR4_Full ), 179 - PHY_SETTING( 800000, FULL, 800000baseDR4_2_Full ), 180 - PHY_SETTING( 800000, FULL, 800000baseSR4_Full ), 181 - PHY_SETTING( 800000, FULL, 800000baseVR4_Full ), 182 - /* 400G */ 183 - PHY_SETTING( 400000, FULL, 400000baseCR8_Full ), 184 - PHY_SETTING( 400000, FULL, 400000baseKR8_Full ), 185 - PHY_SETTING( 400000, FULL, 400000baseLR8_ER8_FR8_Full ), 186 - PHY_SETTING( 400000, FULL, 400000baseDR8_Full ), 187 - PHY_SETTING( 400000, FULL, 400000baseSR8_Full ), 188 - PHY_SETTING( 400000, FULL, 400000baseCR4_Full ), 189 - PHY_SETTING( 400000, FULL, 400000baseKR4_Full ), 190 - PHY_SETTING( 400000, FULL, 400000baseLR4_ER4_FR4_Full ), 191 - PHY_SETTING( 400000, FULL, 400000baseDR4_Full ), 192 - PHY_SETTING( 400000, FULL, 400000baseSR4_Full ), 193 - PHY_SETTING( 400000, FULL, 400000baseCR2_Full ), 194 - PHY_SETTING( 400000, FULL, 400000baseKR2_Full ), 195 - PHY_SETTING( 400000, FULL, 400000baseDR2_Full ), 196 - PHY_SETTING( 400000, FULL, 400000baseDR2_2_Full ), 197 - PHY_SETTING( 400000, FULL, 400000baseSR2_Full ), 198 - PHY_SETTING( 400000, FULL, 400000baseVR2_Full ), 199 - /* 200G */ 200 - PHY_SETTING( 200000, FULL, 200000baseCR4_Full ), 201 - PHY_SETTING( 200000, FULL, 200000baseKR4_Full ), 202 - PHY_SETTING( 200000, FULL, 200000baseLR4_ER4_FR4_Full ), 203 - PHY_SETTING( 200000, FULL, 200000baseDR4_Full ), 204 - PHY_SETTING( 200000, FULL, 200000baseSR4_Full ), 205 - PHY_SETTING( 200000, FULL, 200000baseCR2_Full ), 206 - PHY_SETTING( 200000, FULL, 200000baseKR2_Full ), 207 - PHY_SETTING( 200000, FULL, 200000baseLR2_ER2_FR2_Full ), 208 - PHY_SETTING( 200000, FULL, 200000baseDR2_Full ), 209 - PHY_SETTING( 200000, FULL, 200000baseSR2_Full ), 210 - PHY_SETTING( 200000, FULL, 200000baseCR_Full ), 211 - PHY_SETTING( 200000, FULL, 200000baseKR_Full ), 212 - PHY_SETTING( 200000, FULL, 200000baseDR_Full ), 213 - PHY_SETTING( 200000, FULL, 200000baseDR_2_Full ), 214 - PHY_SETTING( 200000, FULL, 200000baseSR_Full ), 215 - PHY_SETTING( 200000, FULL, 200000baseVR_Full ), 216 - /* 100G */ 217 - PHY_SETTING( 100000, FULL, 100000baseCR4_Full ), 218 - PHY_SETTING( 100000, FULL, 100000baseKR4_Full ), 219 - PHY_SETTING( 100000, FULL, 100000baseLR4_ER4_Full ), 220 - PHY_SETTING( 100000, FULL, 100000baseSR4_Full ), 221 - PHY_SETTING( 100000, FULL, 100000baseCR2_Full ), 222 - PHY_SETTING( 100000, FULL, 100000baseKR2_Full ), 223 - PHY_SETTING( 100000, FULL, 100000baseLR2_ER2_FR2_Full ), 224 - PHY_SETTING( 100000, FULL, 100000baseDR2_Full ), 225 - PHY_SETTING( 100000, FULL, 100000baseSR2_Full ), 226 - PHY_SETTING( 100000, FULL, 100000baseCR_Full ), 227 - PHY_SETTING( 100000, FULL, 100000baseKR_Full ), 228 - PHY_SETTING( 100000, FULL, 100000baseLR_ER_FR_Full ), 229 - PHY_SETTING( 100000, FULL, 100000baseDR_Full ), 230 - PHY_SETTING( 100000, FULL, 100000baseSR_Full ), 231 - /* 56G */ 232 - PHY_SETTING( 56000, FULL, 56000baseCR4_Full ), 233 - PHY_SETTING( 56000, FULL, 56000baseKR4_Full ), 234 - PHY_SETTING( 56000, FULL, 56000baseLR4_Full ), 235 - PHY_SETTING( 56000, FULL, 56000baseSR4_Full ), 236 - /* 50G */ 237 - PHY_SETTING( 50000, FULL, 50000baseCR2_Full ), 238 - PHY_SETTING( 50000, FULL, 50000baseKR2_Full ), 239 - PHY_SETTING( 50000, FULL, 50000baseSR2_Full ), 240 - PHY_SETTING( 50000, FULL, 50000baseCR_Full ), 241 - PHY_SETTING( 50000, FULL, 50000baseKR_Full ), 242 - PHY_SETTING( 50000, FULL, 50000baseLR_ER_FR_Full ), 243 - PHY_SETTING( 50000, FULL, 50000baseDR_Full ), 244 - PHY_SETTING( 50000, FULL, 50000baseSR_Full ), 245 - /* 40G */ 246 - PHY_SETTING( 40000, FULL, 40000baseCR4_Full ), 247 - PHY_SETTING( 40000, FULL, 40000baseKR4_Full ), 248 - PHY_SETTING( 40000, FULL, 40000baseLR4_Full ), 249 - PHY_SETTING( 40000, FULL, 40000baseSR4_Full ), 250 - /* 25G */ 251 - PHY_SETTING( 25000, FULL, 25000baseCR_Full ), 252 - PHY_SETTING( 25000, FULL, 25000baseKR_Full ), 253 - PHY_SETTING( 25000, FULL, 25000baseSR_Full ), 254 - /* 20G */ 255 - PHY_SETTING( 20000, FULL, 20000baseKR2_Full ), 256 - PHY_SETTING( 20000, FULL, 20000baseMLD2_Full ), 257 - /* 10G */ 258 - PHY_SETTING( 10000, FULL, 10000baseCR_Full ), 259 - PHY_SETTING( 10000, FULL, 10000baseER_Full ), 260 - PHY_SETTING( 10000, FULL, 10000baseKR_Full ), 261 - PHY_SETTING( 10000, FULL, 10000baseKX4_Full ), 262 - PHY_SETTING( 10000, FULL, 10000baseLR_Full ), 263 - PHY_SETTING( 10000, FULL, 10000baseLRM_Full ), 264 - PHY_SETTING( 10000, FULL, 10000baseR_FEC ), 265 - PHY_SETTING( 10000, FULL, 10000baseSR_Full ), 266 - PHY_SETTING( 10000, FULL, 10000baseT_Full ), 267 - /* 5G */ 268 - PHY_SETTING( 5000, FULL, 5000baseT_Full ), 269 - /* 2.5G */ 270 - PHY_SETTING( 2500, FULL, 2500baseT_Full ), 271 - PHY_SETTING( 2500, FULL, 2500baseX_Full ), 272 - /* 1G */ 273 - PHY_SETTING( 1000, FULL, 1000baseT_Full ), 274 - PHY_SETTING( 1000, HALF, 1000baseT_Half ), 275 - PHY_SETTING( 1000, FULL, 1000baseT1_Full ), 276 - PHY_SETTING( 1000, FULL, 1000baseX_Full ), 277 - PHY_SETTING( 1000, FULL, 1000baseKX_Full ), 278 - /* 100M */ 279 - PHY_SETTING( 100, FULL, 100baseT_Full ), 280 - PHY_SETTING( 100, FULL, 100baseT1_Full ), 281 - PHY_SETTING( 100, HALF, 100baseT_Half ), 282 - PHY_SETTING( 100, HALF, 100baseFX_Half ), 283 - PHY_SETTING( 100, FULL, 100baseFX_Full ), 284 - /* 10M */ 285 - PHY_SETTING( 10, FULL, 10baseT_Full ), 286 - PHY_SETTING( 10, HALF, 10baseT_Half ), 287 - PHY_SETTING( 10, FULL, 10baseT1L_Full ), 288 - PHY_SETTING( 10, FULL, 10baseT1S_Full ), 289 - PHY_SETTING( 10, HALF, 10baseT1S_Half ), 290 - PHY_SETTING( 10, HALF, 10baseT1S_P2MP_Half ), 291 - PHY_SETTING( 10, FULL, 10baseT1BRR_Full ), 292 - }; 293 - #undef PHY_SETTING 294 - 295 - /** 296 - * phy_lookup_setting - lookup a PHY setting 297 - * @speed: speed to match 298 - * @duplex: duplex to match 299 - * @mask: allowed link modes 300 - * @exact: an exact match is required 301 - * 302 - * Search the settings array for a setting that matches the speed and 303 - * duplex, and which is supported. 304 - * 305 - * If @exact is unset, either an exact match or %NULL for no match will 306 - * be returned. 307 - * 308 - * If @exact is set, an exact match, the fastest supported setting at 309 - * or below the specified speed, the slowest supported setting, or if 310 - * they all fail, %NULL will be returned. 311 - */ 312 - const struct phy_setting * 313 - phy_lookup_setting(int speed, int duplex, const unsigned long *mask, bool exact) 314 - { 315 - const struct phy_setting *p, *match = NULL, *last = NULL; 316 - int i; 317 - 318 - for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) { 319 - if (p->bit < __ETHTOOL_LINK_MODE_MASK_NBITS && 320 - test_bit(p->bit, mask)) { 321 - last = p; 322 - if (p->speed == speed && p->duplex == duplex) { 323 - /* Exact match for speed and duplex */ 324 - match = p; 325 - break; 326 - } else if (!exact) { 327 - if (!match && p->speed <= speed) 328 - /* Candidate */ 329 - match = p; 330 - 331 - if (p->speed < speed) 332 - break; 333 - } 334 - } 335 - } 336 - 337 - if (!match && !exact) 338 - match = last; 339 - 340 - return match; 341 - } 342 - EXPORT_SYMBOL_GPL(phy_lookup_setting); 343 - 344 - size_t phy_speeds(unsigned int *speeds, size_t size, 345 - unsigned long *mask) 346 - { 347 - size_t count; 348 - int i; 349 - 350 - for (i = 0, count = 0; i < ARRAY_SIZE(settings) && count < size; i++) 351 - if (settings[i].bit < __ETHTOOL_LINK_MODE_MASK_NBITS && 352 - test_bit(settings[i].bit, mask) && 353 - (count == 0 || speeds[count - 1] != settings[i].speed)) 354 - speeds[count++] = settings[i].speed; 355 - 356 - return count; 357 - } 358 - 359 - static void __set_linkmode_max_speed(u32 max_speed, unsigned long *addr) 360 - { 361 - const struct phy_setting *p; 362 - int i; 363 - 364 - for (i = 0, p = settings; i < ARRAY_SIZE(settings); i++, p++) { 365 - if (p->speed > max_speed) 366 - linkmode_clear_bit(p->bit, addr); 367 - else 368 - break; 369 - } 370 - } 371 - 372 159 static void __set_phy_supported(struct phy_device *phydev, u32 max_speed) 373 160 { 374 - __set_linkmode_max_speed(max_speed, phydev->supported); 161 + phy_caps_linkmode_max_speed(max_speed, phydev->supported); 375 162 } 376 163 377 164 /** ··· 285 496 void phy_resolve_aneg_linkmode(struct phy_device *phydev) 286 497 { 287 498 __ETHTOOL_DECLARE_LINK_MODE_MASK(common); 288 - int i; 499 + const struct link_capabilities *c; 289 500 290 501 linkmode_and(common, phydev->lp_advertising, phydev->advertising); 291 502 292 - for (i = 0; i < ARRAY_SIZE(settings); i++) 293 - if (test_bit(settings[i].bit, common)) { 294 - phydev->speed = settings[i].speed; 295 - phydev->duplex = settings[i].duplex; 296 - break; 297 - } 503 + c = phy_caps_lookup_by_linkmode(common); 504 + if (c) { 505 + phydev->speed = c->speed; 506 + phydev->duplex = c->duplex; 507 + } 298 508 299 509 phy_resolve_aneg_pause(phydev); 300 510 } ··· 311 523 void phy_check_downshift(struct phy_device *phydev) 312 524 { 313 525 __ETHTOOL_DECLARE_LINK_MODE_MASK(common); 314 - int i, speed = SPEED_UNKNOWN; 526 + const struct link_capabilities *c; 527 + int speed = SPEED_UNKNOWN; 315 528 316 529 phydev->downshifted_rate = 0; 317 530 ··· 322 533 323 534 linkmode_and(common, phydev->lp_advertising, phydev->advertising); 324 535 325 - for (i = 0; i < ARRAY_SIZE(settings); i++) 326 - if (test_bit(settings[i].bit, common)) { 327 - speed = settings[i].speed; 328 - break; 329 - } 536 + c = phy_caps_lookup_by_linkmode(common); 537 + if (c) 538 + speed = c->speed; 330 539 331 540 if (speed == SPEED_UNKNOWN || phydev->speed >= speed) 332 541 return; ··· 338 551 static int phy_resolve_min_speed(struct phy_device *phydev, bool fdx_only) 339 552 { 340 553 __ETHTOOL_DECLARE_LINK_MODE_MASK(common); 341 - int i = ARRAY_SIZE(settings); 554 + const struct link_capabilities *c; 342 555 343 556 linkmode_and(common, phydev->lp_advertising, phydev->advertising); 344 557 345 - while (--i >= 0) { 346 - if (test_bit(settings[i].bit, common)) { 347 - if (fdx_only && settings[i].duplex != DUPLEX_FULL) 348 - continue; 349 - return settings[i].speed; 350 - } 351 - } 558 + c = phy_caps_lookup_by_linkmode_rev(common, fdx_only); 559 + if (c) 560 + return c->speed; 352 561 353 562 return SPEED_UNKNOWN; 354 563 } ··· 356 573 if (min_common_speed == SPEED_UNKNOWN) 357 574 return -EINVAL; 358 575 359 - __set_linkmode_max_speed(min_common_speed, phydev->advertising); 576 + phy_caps_linkmode_max_speed(min_common_speed, phydev->advertising); 360 577 361 578 return 0; 362 579 }
+10 -27
drivers/net/phy/phy.c
··· 37 37 #include <net/sock.h> 38 38 39 39 #include "phylib-internal.h" 40 + #include "phy-caps.h" 40 41 41 42 #define PHY_STATE_TIME HZ 42 43 ··· 214 213 EXPORT_SYMBOL(phy_aneg_done); 215 214 216 215 /** 217 - * phy_find_valid - find a PHY setting that matches the requested parameters 218 - * @speed: desired speed 219 - * @duplex: desired duplex 220 - * @supported: mask of supported link modes 221 - * 222 - * Locate a supported phy setting that is, in priority order: 223 - * - an exact match for the specified speed and duplex mode 224 - * - a match for the specified speed, or slower speed 225 - * - the slowest supported speed 226 - * Returns the matched phy_setting entry, or %NULL if no supported phy 227 - * settings were found. 228 - */ 229 - static const struct phy_setting * 230 - phy_find_valid(int speed, int duplex, unsigned long *supported) 231 - { 232 - return phy_lookup_setting(speed, duplex, supported, false); 233 - } 234 - 235 - /** 236 216 * phy_supported_speeds - return all speeds currently supported by a phy device 237 217 * @phy: The phy device to return supported speeds of. 238 218 * @speeds: buffer to store supported speeds in. ··· 227 245 unsigned int *speeds, 228 246 unsigned int size) 229 247 { 230 - return phy_speeds(speeds, size, phy->supported); 248 + return phy_caps_speeds(speeds, size, phy->supported); 231 249 } 232 250 233 251 /** ··· 241 259 */ 242 260 bool phy_check_valid(int speed, int duplex, unsigned long *features) 243 261 { 244 - return !!phy_lookup_setting(speed, duplex, features, true); 262 + return phy_caps_valid(speed, duplex, features); 245 263 } 246 264 EXPORT_SYMBOL(phy_check_valid); 247 265 ··· 255 273 */ 256 274 static void phy_sanitize_settings(struct phy_device *phydev) 257 275 { 258 - const struct phy_setting *setting; 276 + const struct link_capabilities *c; 259 277 260 - setting = phy_find_valid(phydev->speed, phydev->duplex, 261 - phydev->supported); 262 - if (setting) { 263 - phydev->speed = setting->speed; 264 - phydev->duplex = setting->duplex; 278 + c = phy_caps_lookup(phydev->speed, phydev->duplex, phydev->supported, 279 + false); 280 + 281 + if (c) { 282 + phydev->speed = c->speed; 283 + phydev->duplex = c->duplex; 265 284 } else { 266 285 /* We failed to find anything (no supported speeds?) */ 267 286 phydev->speed = SPEED_UNKNOWN;
+359
drivers/net/phy/phy_caps.c
··· 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 + 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 + */ 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 + */ 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 * 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 * 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 * 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 + */ 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 + */ 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 + */ 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 + */ 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);
+11 -5
drivers/net/phy/phy_device.c
··· 42 42 #include <linux/unistd.h> 43 43 44 44 #include "phylib-internal.h" 45 + #include "phy-caps.h" 45 46 46 47 MODULE_DESCRIPTION("PHY library"); 47 48 MODULE_AUTHOR("Andy Fleming"); ··· 2120 2119 int __genphy_config_aneg(struct phy_device *phydev, bool changed) 2121 2120 { 2122 2121 __ETHTOOL_DECLARE_LINK_MODE_MASK(fixed_advert); 2123 - const struct phy_setting *set; 2122 + const struct link_capabilities *c; 2124 2123 unsigned long *advert; 2125 2124 int err; 2126 2125 ··· 2146 2145 } else { 2147 2146 linkmode_zero(fixed_advert); 2148 2147 2149 - set = phy_lookup_setting(phydev->speed, phydev->duplex, 2150 - phydev->supported, true); 2151 - if (set) 2152 - linkmode_set_bit(set->bit, fixed_advert); 2148 + c = phy_caps_lookup(phydev->speed, phydev->duplex, 2149 + phydev->supported, true); 2150 + if (c) 2151 + linkmode_and(fixed_advert, phydev->supported, 2152 + c->linkmodes); 2153 2153 2154 2154 advert = fixed_advert; 2155 2155 } ··· 3559 3557 rc = mdio_bus_init(); 3560 3558 if (rc) 3561 3559 goto err_ethtool_phy_ops; 3560 + 3561 + rc = phy_caps_init(); 3562 + if (rc) 3563 + goto err_mdio_bus; 3562 3564 3563 3565 features_init(); 3564 3566
+100 -255
drivers/net/phy/phylink.c
··· 20 20 #include <linux/timer.h> 21 21 #include <linux/workqueue.h> 22 22 23 + #include "phy-caps.h" 23 24 #include "sfp.h" 24 25 #include "swphy.h" 25 26 ··· 292 291 return SPEED_UNKNOWN; 293 292 } 294 293 294 + static struct { 295 + unsigned long mask; 296 + int speed; 297 + unsigned int duplex; 298 + unsigned int caps_bit; 299 + } phylink_caps_params[] = { 300 + { MAC_400000FD, SPEED_400000, DUPLEX_FULL, BIT(LINK_CAPA_400000FD) }, 301 + { MAC_200000FD, SPEED_200000, DUPLEX_FULL, BIT(LINK_CAPA_200000FD) }, 302 + { MAC_100000FD, SPEED_100000, DUPLEX_FULL, BIT(LINK_CAPA_100000FD) }, 303 + { MAC_56000FD, SPEED_56000, DUPLEX_FULL, BIT(LINK_CAPA_56000FD) }, 304 + { MAC_50000FD, SPEED_50000, DUPLEX_FULL, BIT(LINK_CAPA_50000FD) }, 305 + { MAC_40000FD, SPEED_40000, DUPLEX_FULL, BIT(LINK_CAPA_40000FD) }, 306 + { MAC_25000FD, SPEED_25000, DUPLEX_FULL, BIT(LINK_CAPA_25000FD) }, 307 + { MAC_20000FD, SPEED_20000, DUPLEX_FULL, BIT(LINK_CAPA_20000FD) }, 308 + { MAC_10000FD, SPEED_10000, DUPLEX_FULL, BIT(LINK_CAPA_10000FD) }, 309 + { MAC_5000FD, SPEED_5000, DUPLEX_FULL, BIT(LINK_CAPA_5000FD) }, 310 + { MAC_2500FD, SPEED_2500, DUPLEX_FULL, BIT(LINK_CAPA_2500FD) }, 311 + { MAC_1000FD, SPEED_1000, DUPLEX_FULL, BIT(LINK_CAPA_1000FD) }, 312 + { MAC_1000HD, SPEED_1000, DUPLEX_HALF, BIT(LINK_CAPA_1000HD) }, 313 + { MAC_100FD, SPEED_100, DUPLEX_FULL, BIT(LINK_CAPA_100FD) }, 314 + { MAC_100HD, SPEED_100, DUPLEX_HALF, BIT(LINK_CAPA_100HD) }, 315 + { MAC_10FD, SPEED_10, DUPLEX_FULL, BIT(LINK_CAPA_10FD) }, 316 + { MAC_10HD, SPEED_10, DUPLEX_HALF, BIT(LINK_CAPA_10HD) }, 317 + }; 318 + 319 + /** 320 + * phylink_caps_to_link_caps() - Convert a set of MAC capabilities LINK caps 321 + * @caps: A set of MAC capabilities 322 + * 323 + * Returns: The corresponding set of LINK_CAPA as defined in phy-caps.h 324 + */ 325 + static unsigned long phylink_caps_to_link_caps(unsigned long caps) 326 + { 327 + unsigned long link_caps = 0; 328 + int i; 329 + 330 + for (i = 0; i < ARRAY_SIZE(phylink_caps_params); i++) 331 + if (caps & phylink_caps_params[i].mask) 332 + link_caps |= phylink_caps_params[i].caps_bit; 333 + 334 + return link_caps; 335 + } 336 + 337 + static unsigned long phylink_link_caps_to_mac_caps(unsigned long link_caps) 338 + { 339 + unsigned long caps = 0; 340 + int i; 341 + 342 + for (i = 0; i < ARRAY_SIZE(phylink_caps_params); i++) 343 + if (link_caps & phylink_caps_params[i].caps_bit) 344 + caps |= phylink_caps_params[i].mask; 345 + 346 + return caps; 347 + } 348 + 295 349 /** 296 350 * phylink_caps_to_linkmodes() - Convert capabilities to ethtool link modes 297 351 * @linkmodes: ethtool linkmode mask (must be already initialised) ··· 358 302 static void phylink_caps_to_linkmodes(unsigned long *linkmodes, 359 303 unsigned long caps) 360 304 { 305 + unsigned long link_caps = phylink_caps_to_link_caps(caps); 306 + 361 307 if (caps & MAC_SYM_PAUSE) 362 308 __set_bit(ETHTOOL_LINK_MODE_Pause_BIT, linkmodes); 363 309 364 310 if (caps & MAC_ASYM_PAUSE) 365 311 __set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, linkmodes); 366 312 367 - if (caps & MAC_10HD) { 368 - __set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, linkmodes); 369 - __set_bit(ETHTOOL_LINK_MODE_10baseT1S_Half_BIT, linkmodes); 370 - __set_bit(ETHTOOL_LINK_MODE_10baseT1S_P2MP_Half_BIT, linkmodes); 371 - } 372 - 373 - if (caps & MAC_10FD) { 374 - __set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, linkmodes); 375 - __set_bit(ETHTOOL_LINK_MODE_10baseT1L_Full_BIT, linkmodes); 376 - __set_bit(ETHTOOL_LINK_MODE_10baseT1S_Full_BIT, linkmodes); 377 - } 378 - 379 - if (caps & MAC_100HD) { 380 - __set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, linkmodes); 381 - __set_bit(ETHTOOL_LINK_MODE_100baseFX_Half_BIT, linkmodes); 382 - } 383 - 384 - if (caps & MAC_100FD) { 385 - __set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, linkmodes); 386 - __set_bit(ETHTOOL_LINK_MODE_100baseT1_Full_BIT, linkmodes); 387 - __set_bit(ETHTOOL_LINK_MODE_100baseFX_Full_BIT, linkmodes); 388 - } 389 - 390 - if (caps & MAC_1000HD) 391 - __set_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, linkmodes); 392 - 393 - if (caps & MAC_1000FD) { 394 - __set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, linkmodes); 395 - __set_bit(ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, linkmodes); 396 - __set_bit(ETHTOOL_LINK_MODE_1000baseX_Full_BIT, linkmodes); 397 - __set_bit(ETHTOOL_LINK_MODE_1000baseT1_Full_BIT, linkmodes); 398 - } 399 - 400 - if (caps & MAC_2500FD) { 401 - __set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, linkmodes); 402 - __set_bit(ETHTOOL_LINK_MODE_2500baseX_Full_BIT, linkmodes); 403 - } 404 - 405 - if (caps & MAC_5000FD) 406 - __set_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, linkmodes); 407 - 408 - if (caps & MAC_10000FD) { 409 - __set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, linkmodes); 410 - __set_bit(ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, linkmodes); 411 - __set_bit(ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, linkmodes); 412 - __set_bit(ETHTOOL_LINK_MODE_10000baseR_FEC_BIT, linkmodes); 413 - __set_bit(ETHTOOL_LINK_MODE_10000baseCR_Full_BIT, linkmodes); 414 - __set_bit(ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, linkmodes); 415 - __set_bit(ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, linkmodes); 416 - __set_bit(ETHTOOL_LINK_MODE_10000baseLRM_Full_BIT, linkmodes); 417 - __set_bit(ETHTOOL_LINK_MODE_10000baseER_Full_BIT, linkmodes); 418 - } 419 - 420 - if (caps & MAC_25000FD) { 421 - __set_bit(ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, linkmodes); 422 - __set_bit(ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, linkmodes); 423 - __set_bit(ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, linkmodes); 424 - } 425 - 426 - if (caps & MAC_40000FD) { 427 - __set_bit(ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, linkmodes); 428 - __set_bit(ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, linkmodes); 429 - __set_bit(ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT, linkmodes); 430 - __set_bit(ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT, linkmodes); 431 - } 432 - 433 - if (caps & MAC_50000FD) { 434 - __set_bit(ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT, linkmodes); 435 - __set_bit(ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT, linkmodes); 436 - __set_bit(ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT, linkmodes); 437 - __set_bit(ETHTOOL_LINK_MODE_50000baseKR_Full_BIT, linkmodes); 438 - __set_bit(ETHTOOL_LINK_MODE_50000baseSR_Full_BIT, linkmodes); 439 - __set_bit(ETHTOOL_LINK_MODE_50000baseCR_Full_BIT, linkmodes); 440 - __set_bit(ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT, 441 - linkmodes); 442 - __set_bit(ETHTOOL_LINK_MODE_50000baseDR_Full_BIT, linkmodes); 443 - } 444 - 445 - if (caps & MAC_56000FD) { 446 - __set_bit(ETHTOOL_LINK_MODE_56000baseKR4_Full_BIT, linkmodes); 447 - __set_bit(ETHTOOL_LINK_MODE_56000baseCR4_Full_BIT, linkmodes); 448 - __set_bit(ETHTOOL_LINK_MODE_56000baseSR4_Full_BIT, linkmodes); 449 - __set_bit(ETHTOOL_LINK_MODE_56000baseLR4_Full_BIT, linkmodes); 450 - } 451 - 452 - if (caps & MAC_100000FD) { 453 - __set_bit(ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, linkmodes); 454 - __set_bit(ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT, linkmodes); 455 - __set_bit(ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, linkmodes); 456 - __set_bit(ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT, 457 - linkmodes); 458 - __set_bit(ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT, linkmodes); 459 - __set_bit(ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT, linkmodes); 460 - __set_bit(ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT, linkmodes); 461 - __set_bit(ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT, 462 - linkmodes); 463 - __set_bit(ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT, linkmodes); 464 - __set_bit(ETHTOOL_LINK_MODE_100000baseKR_Full_BIT, linkmodes); 465 - __set_bit(ETHTOOL_LINK_MODE_100000baseSR_Full_BIT, linkmodes); 466 - __set_bit(ETHTOOL_LINK_MODE_100000baseLR_ER_FR_Full_BIT, 467 - linkmodes); 468 - __set_bit(ETHTOOL_LINK_MODE_100000baseCR_Full_BIT, linkmodes); 469 - __set_bit(ETHTOOL_LINK_MODE_100000baseDR_Full_BIT, linkmodes); 470 - } 471 - 472 - if (caps & MAC_200000FD) { 473 - __set_bit(ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT, linkmodes); 474 - __set_bit(ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT, linkmodes); 475 - __set_bit(ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT, 476 - linkmodes); 477 - __set_bit(ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT, linkmodes); 478 - __set_bit(ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT, linkmodes); 479 - __set_bit(ETHTOOL_LINK_MODE_200000baseKR2_Full_BIT, linkmodes); 480 - __set_bit(ETHTOOL_LINK_MODE_200000baseSR2_Full_BIT, linkmodes); 481 - __set_bit(ETHTOOL_LINK_MODE_200000baseLR2_ER2_FR2_Full_BIT, 482 - linkmodes); 483 - __set_bit(ETHTOOL_LINK_MODE_200000baseDR2_Full_BIT, linkmodes); 484 - __set_bit(ETHTOOL_LINK_MODE_200000baseCR2_Full_BIT, linkmodes); 485 - } 486 - 487 - if (caps & MAC_400000FD) { 488 - __set_bit(ETHTOOL_LINK_MODE_400000baseKR8_Full_BIT, linkmodes); 489 - __set_bit(ETHTOOL_LINK_MODE_400000baseSR8_Full_BIT, linkmodes); 490 - __set_bit(ETHTOOL_LINK_MODE_400000baseLR8_ER8_FR8_Full_BIT, 491 - linkmodes); 492 - __set_bit(ETHTOOL_LINK_MODE_400000baseDR8_Full_BIT, linkmodes); 493 - __set_bit(ETHTOOL_LINK_MODE_400000baseCR8_Full_BIT, linkmodes); 494 - __set_bit(ETHTOOL_LINK_MODE_400000baseKR4_Full_BIT, linkmodes); 495 - __set_bit(ETHTOOL_LINK_MODE_400000baseSR4_Full_BIT, linkmodes); 496 - __set_bit(ETHTOOL_LINK_MODE_400000baseLR4_ER4_FR4_Full_BIT, 497 - linkmodes); 498 - __set_bit(ETHTOOL_LINK_MODE_400000baseDR4_Full_BIT, linkmodes); 499 - __set_bit(ETHTOOL_LINK_MODE_400000baseCR4_Full_BIT, linkmodes); 500 - } 313 + phy_caps_linkmodes(link_caps, linkmodes); 501 314 } 502 - 503 - static struct { 504 - unsigned long mask; 505 - int speed; 506 - unsigned int duplex; 507 - } phylink_caps_params[] = { 508 - { MAC_400000FD, SPEED_400000, DUPLEX_FULL }, 509 - { MAC_200000FD, SPEED_200000, DUPLEX_FULL }, 510 - { MAC_100000FD, SPEED_100000, DUPLEX_FULL }, 511 - { MAC_56000FD, SPEED_56000, DUPLEX_FULL }, 512 - { MAC_50000FD, SPEED_50000, DUPLEX_FULL }, 513 - { MAC_40000FD, SPEED_40000, DUPLEX_FULL }, 514 - { MAC_25000FD, SPEED_25000, DUPLEX_FULL }, 515 - { MAC_20000FD, SPEED_20000, DUPLEX_FULL }, 516 - { MAC_10000FD, SPEED_10000, DUPLEX_FULL }, 517 - { MAC_5000FD, SPEED_5000, DUPLEX_FULL }, 518 - { MAC_2500FD, SPEED_2500, DUPLEX_FULL }, 519 - { MAC_1000FD, SPEED_1000, DUPLEX_FULL }, 520 - { MAC_1000HD, SPEED_1000, DUPLEX_HALF }, 521 - { MAC_100FD, SPEED_100, DUPLEX_FULL }, 522 - { MAC_100HD, SPEED_100, DUPLEX_HALF }, 523 - { MAC_10FD, SPEED_10, DUPLEX_FULL }, 524 - { MAC_10HD, SPEED_10, DUPLEX_HALF }, 525 - }; 526 315 527 316 /** 528 317 * phylink_limit_mac_speed - limit the phylink_config to a maximum speed ··· 424 523 unsigned long mac_capabilities, 425 524 int rate_matching) 426 525 { 526 + unsigned long link_caps = phy_caps_from_interface(interface); 427 527 int max_speed = phylink_interface_max_speed(interface); 428 528 unsigned long caps = MAC_SYM_PAUSE | MAC_ASYM_PAUSE; 429 529 unsigned long matched_caps = 0; 430 530 431 - switch (interface) { 432 - case PHY_INTERFACE_MODE_USXGMII: 433 - caps |= MAC_10000FD | MAC_5000FD; 434 - fallthrough; 435 - 436 - case PHY_INTERFACE_MODE_10G_QXGMII: 437 - caps |= MAC_2500FD; 438 - fallthrough; 439 - 440 - case PHY_INTERFACE_MODE_RGMII_TXID: 441 - case PHY_INTERFACE_MODE_RGMII_RXID: 442 - case PHY_INTERFACE_MODE_RGMII_ID: 443 - case PHY_INTERFACE_MODE_RGMII: 444 - case PHY_INTERFACE_MODE_PSGMII: 445 - case PHY_INTERFACE_MODE_QSGMII: 446 - case PHY_INTERFACE_MODE_QUSGMII: 447 - case PHY_INTERFACE_MODE_SGMII: 448 - case PHY_INTERFACE_MODE_GMII: 449 - caps |= MAC_1000HD | MAC_1000FD; 450 - fallthrough; 451 - 452 - case PHY_INTERFACE_MODE_REVRMII: 453 - case PHY_INTERFACE_MODE_RMII: 454 - case PHY_INTERFACE_MODE_SMII: 455 - case PHY_INTERFACE_MODE_REVMII: 456 - case PHY_INTERFACE_MODE_MII: 457 - caps |= MAC_10HD | MAC_10FD; 458 - fallthrough; 459 - 460 - case PHY_INTERFACE_MODE_100BASEX: 461 - caps |= MAC_100HD | MAC_100FD; 462 - break; 463 - 464 - case PHY_INTERFACE_MODE_TBI: 465 - case PHY_INTERFACE_MODE_MOCA: 466 - case PHY_INTERFACE_MODE_RTBI: 467 - case PHY_INTERFACE_MODE_1000BASEX: 468 - caps |= MAC_1000HD; 469 - fallthrough; 470 - case PHY_INTERFACE_MODE_1000BASEKX: 471 - case PHY_INTERFACE_MODE_TRGMII: 472 - caps |= MAC_1000FD; 473 - break; 474 - 475 - case PHY_INTERFACE_MODE_2500BASEX: 476 - caps |= MAC_2500FD; 477 - break; 478 - 479 - case PHY_INTERFACE_MODE_5GBASER: 480 - caps |= MAC_5000FD; 481 - break; 482 - 483 - case PHY_INTERFACE_MODE_XGMII: 484 - case PHY_INTERFACE_MODE_RXAUI: 485 - case PHY_INTERFACE_MODE_XAUI: 486 - case PHY_INTERFACE_MODE_10GBASER: 487 - case PHY_INTERFACE_MODE_10GKR: 488 - caps |= MAC_10000FD; 489 - break; 490 - 491 - case PHY_INTERFACE_MODE_25GBASER: 492 - caps |= MAC_25000FD; 493 - break; 494 - 495 - case PHY_INTERFACE_MODE_XLGMII: 496 - caps |= MAC_40000FD; 497 - break; 498 - 499 - case PHY_INTERFACE_MODE_INTERNAL: 500 - caps |= ~0; 501 - break; 502 - 503 - case PHY_INTERFACE_MODE_NA: 504 - case PHY_INTERFACE_MODE_MAX: 505 - break; 506 - } 531 + caps |= phylink_link_caps_to_mac_caps(link_caps); 507 532 508 533 switch (rate_matching) { 509 534 case RATE_MATCH_OPEN_LOOP: ··· 628 801 return phylink_validate_mac_and_pcs(pl, supported, state); 629 802 } 630 803 804 + static void phylink_fill_fixedlink_supported(unsigned long *supported) 805 + { 806 + linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Half_BIT, supported); 807 + linkmode_set_bit(ETHTOOL_LINK_MODE_10baseT_Full_BIT, supported); 808 + linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Half_BIT, supported); 809 + linkmode_set_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, supported); 810 + linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Half_BIT, supported); 811 + linkmode_set_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, supported); 812 + linkmode_set_bit(ETHTOOL_LINK_MODE_2500baseT_Full_BIT, supported); 813 + linkmode_set_bit(ETHTOOL_LINK_MODE_5000baseT_Full_BIT, supported); 814 + linkmode_set_bit(ETHTOOL_LINK_MODE_10000baseT_Full_BIT, supported); 815 + } 816 + 631 817 static int phylink_parse_fixedlink(struct phylink *pl, 632 818 const struct fwnode_handle *fwnode) 633 819 { 820 + __ETHTOOL_DECLARE_LINK_MODE_MASK(match) = { 0, }; 634 821 __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; 822 + const struct link_capabilities *c; 635 823 struct fwnode_handle *fixed_node; 636 - const struct phy_setting *s; 637 824 struct gpio_desc *desc; 638 825 u32 speed; 639 826 int ret; ··· 715 874 phylink_warn(pl, "fixed link specifies half duplex for %dMbps link?\n", 716 875 pl->link_config.speed); 717 876 718 - linkmode_fill(pl->supported); 877 + linkmode_zero(pl->supported); 878 + phylink_fill_fixedlink_supported(pl->supported); 879 + 719 880 linkmode_copy(pl->link_config.advertising, pl->supported); 720 881 phylink_validate(pl, pl->supported, &pl->link_config); 721 882 722 - s = phy_lookup_setting(pl->link_config.speed, pl->link_config.duplex, 723 - pl->supported, true); 883 + c = phy_caps_lookup(pl->link_config.speed, pl->link_config.duplex, 884 + pl->supported, true); 885 + if (c) 886 + linkmode_and(match, pl->supported, c->linkmodes); 724 887 725 888 linkmode_set_bit(ETHTOOL_LINK_MODE_Pause_BIT, mask); 726 889 linkmode_set_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, mask); ··· 733 888 734 889 phylink_set(pl->supported, MII); 735 890 736 - if (s) { 737 - __set_bit(s->bit, pl->supported); 738 - __set_bit(s->bit, pl->link_config.lp_advertising); 891 + if (c) { 892 + linkmode_or(pl->supported, pl->supported, match); 893 + linkmode_or(pl->link_config.lp_advertising, 894 + pl->link_config.lp_advertising, match); 739 895 } else { 740 896 phylink_warn(pl, "fixed link %s duplex %dMbps not recognised\n", 741 897 pl->link_config.duplex == DUPLEX_FULL ? "full" : "half", ··· 1724 1878 int phylink_set_fixed_link(struct phylink *pl, 1725 1879 const struct phylink_link_state *state) 1726 1880 { 1727 - const struct phy_setting *s; 1881 + const struct link_capabilities *c; 1728 1882 unsigned long *adv; 1729 1883 1730 1884 if (pl->cfg_link_an_mode != MLO_AN_PHY || !state || 1731 1885 !test_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state)) 1732 1886 return -EINVAL; 1733 1887 1734 - s = phy_lookup_setting(state->speed, state->duplex, 1735 - pl->supported, true); 1736 - if (!s) 1888 + c = phy_caps_lookup(state->speed, state->duplex, 1889 + pl->supported, true); 1890 + if (!c) 1737 1891 return -EINVAL; 1738 1892 1739 1893 adv = pl->link_config.advertising; 1740 - linkmode_zero(adv); 1741 - linkmode_set_bit(s->bit, adv); 1894 + linkmode_and(adv, pl->supported, c->linkmodes); 1742 1895 linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, adv); 1743 1896 1744 1897 pl->link_config.speed = state->speed; ··· 2697 2852 const struct ethtool_link_ksettings *kset) 2698 2853 { 2699 2854 __ETHTOOL_DECLARE_LINK_MODE_MASK(support); 2855 + const struct link_capabilities *c; 2700 2856 struct phylink_link_state config; 2701 - const struct phy_setting *s; 2702 2857 2703 2858 ASSERT_RTNL(); 2704 2859 ··· 2741 2896 /* Autonegotiation disabled, select a suitable speed and 2742 2897 * duplex. 2743 2898 */ 2744 - s = phy_lookup_setting(kset->base.speed, kset->base.duplex, 2745 - pl->supported, false); 2746 - if (!s) 2899 + c = phy_caps_lookup(kset->base.speed, kset->base.duplex, 2900 + pl->supported, false); 2901 + if (!c) 2747 2902 return -EINVAL; 2748 2903 2749 2904 /* If we have a fixed link, refuse to change link parameters. 2750 2905 * If the link parameters match, accept them but do nothing. 2751 2906 */ 2752 2907 if (pl->req_link_an_mode == MLO_AN_FIXED) { 2753 - if (s->speed != pl->link_config.speed || 2754 - s->duplex != pl->link_config.duplex) 2908 + if (c->speed != pl->link_config.speed || 2909 + c->duplex != pl->link_config.duplex) 2755 2910 return -EINVAL; 2756 2911 return 0; 2757 2912 } 2758 2913 2759 - config.speed = s->speed; 2760 - config.duplex = s->duplex; 2914 + config.speed = c->speed; 2915 + config.duplex = c->duplex; 2761 2916 break; 2762 2917 2763 2918 case AUTONEG_ENABLE:
+8
include/linux/ethtool.h
··· 210 210 211 211 void ethtool_rxfh_context_lost(struct net_device *dev, u32 context_id); 212 212 213 + struct link_mode_info { 214 + int speed; 215 + u8 lanes; 216 + u8 duplex; 217 + }; 218 + 219 + extern const struct link_mode_info link_mode_params[]; 220 + 213 221 /* declare a link mode bitmap */ 214 222 #define __ETHTOOL_DECLARE_LINK_MODE_MASK(name) \ 215 223 DECLARE_BITMAP(name, __ETHTOOL_LINK_MODE_MASK_NBITS)
-15
include/linux/phy.h
··· 1275 1275 1276 1276 int phy_interface_num_ports(phy_interface_t interface); 1277 1277 1278 - /* A structure for mapping a particular speed and duplex 1279 - * combination to a particular SUPPORTED and ADVERTISED value 1280 - */ 1281 - struct phy_setting { 1282 - u32 speed; 1283 - u8 duplex; 1284 - u8 bit; 1285 - }; 1286 - 1287 - const struct phy_setting * 1288 - phy_lookup_setting(int speed, int duplex, const unsigned long *mask, 1289 - bool exact); 1290 - size_t phy_speeds(unsigned int *speeds, size_t size, 1291 - unsigned long *mask); 1292 - 1293 1278 /** 1294 1279 * phy_is_started - Convenience function to check whether PHY is started 1295 1280 * @phydev: The phy_device struct
+1
net/ethtool/common.c
··· 424 424 __DEFINE_LINK_MODE_PARAMS(800000, VR4, Full), 425 425 }; 426 426 static_assert(ARRAY_SIZE(link_mode_params) == __ETHTOOL_LINK_MODE_MASK_NBITS); 427 + EXPORT_SYMBOL_GPL(link_mode_params); 427 428 428 429 const char netif_msg_class_names[][ETH_GSTRING_LEN] = { 429 430 [NETIF_MSG_DRV_BIT] = "drv",
-7
net/ethtool/common.h
··· 15 15 #define __SOF_TIMESTAMPING_CNT (const_ilog2(SOF_TIMESTAMPING_LAST) + 1) 16 16 #define __HWTSTAMP_FLAG_CNT (const_ilog2(HWTSTAMP_FLAG_LAST) + 1) 17 17 18 - struct link_mode_info { 19 - int speed; 20 - u8 lanes; 21 - u8 duplex; 22 - }; 23 - 24 18 struct genl_info; 25 19 struct hwtstamp_provider_desc; 26 20 ··· 27 33 extern const char 28 34 phy_tunable_strings[__ETHTOOL_PHY_TUNABLE_COUNT][ETH_GSTRING_LEN]; 29 35 extern const char link_mode_names[][ETH_GSTRING_LEN]; 30 - extern const struct link_mode_info link_mode_params[]; 31 36 extern const char netif_msg_class_names[][ETH_GSTRING_LEN]; 32 37 extern const char wol_mode_names[][ETH_GSTRING_LEN]; 33 38 extern const char sof_timestamping_names[][ETH_GSTRING_LEN];