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-introduce-phy-ports-representation'

Maxime Chevallier says:

====================
net: phy: Introduce PHY ports representation

A few important notes:

- This is only a first phase. It instantiates the port, and leverage
that to make the MAC <-> PHY <-> SFP usecase simpler.

- Next phase will deal with controlling the port state, as well as the
netlink uAPI for that.

- The end-goal is to enable support for complex port MUX. This
preliminary work focuses on PHY-driven ports, but this will be
extended to support muxing at the MII level (Multi-phy, or compo PHY
+ SFP as found on Turris Omnia for example).

- The naming is definitely not set in stone. I named that "phy_port",
but this may convey the false sense that this is phylib-specific.
Even the word "port" is not that great, as it already has several
different meanings in the net world (switch port, devlink port,
etc.). I used the term "connector" in the binding.

A bit of history on that work :

The end goal that I personnaly want to achieve is :

+ PHY - RJ45
|
MAC - MUX -+ PHY - RJ45

After many discussions here on netdev@, but also at netdevconf[1] and
LPC[2], there appears to be several analoguous designs that exist out
there.

[1] : https://netdevconf.info/0x17/sessions/talk/improving-multi-phy-and-multi-port-interfaces.html
[2] : https://lpc.events/event/18/contributions/1964/ (video isn't the
right one)

Take the MAchiatobin, it has 2 interfaces that looks like this :

MAC - PHY -+ RJ45
|
+ SFP - Whatever the module does

Now, looking at the Turris Omnia, we have :

MAC - MUX -+ PHY - RJ45
|
+ SFP - Whatever the module does

We can find more example of this kind of designs, the common part is
that we expose multiple front-facing media ports. This is what this
current work aims at supporting. As of right now, it does'nt add any
support for muxing, but this will come later on.

This first phase focuses on phy-driven ports only, but there are already
quite some challenges already. For one, we can't really autodetect how
many ports are sitting behind a PHY. That's why this series introduces a
new binding. Describing ports in DT should however be a last-resort
thing when we need to clear some ambiguity about the PHY media-side.

The only use-cases that we have today for multi-port PHYs are combo PHYs
that drive both a Copper port and an SFP (the Macchiatobin case). This
in itself is challenging and this series only addresses part of this
support, by registering a phy_port for the PHY <-> SFP connection. The
SFP module should in the end be considered as a port as well, but that's
not yet the case.

However, because now PHYs can register phy_ports for every media-side
interface they have, they can register the capabilities of their ports,
which allows making the PHY-driver SFP case much more generic.
====================

Link: https://patch.msgid.link/20260108080041.553250-1-maxime.chevallier@bootlin.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

+1399 -391
+56
Documentation/devicetree/bindings/net/ethernet-connector.yaml
··· 1 + # SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 + %YAML 1.2 3 + --- 4 + $id: http://devicetree.org/schemas/net/ethernet-connector.yaml# 5 + $schema: http://devicetree.org/meta-schemas/core.yaml# 6 + 7 + title: Generic Ethernet Connector 8 + 9 + maintainers: 10 + - Maxime Chevallier <maxime.chevallier@bootlin.com> 11 + 12 + description: 13 + An Ethernet Connector represents the output of a network component such as 14 + a PHY, an Ethernet controller with no PHY, or an SFP module. 15 + 16 + properties: 17 + 18 + pairs: 19 + description: 20 + Defines the number of BaseT pairs that are used on the connector. 21 + $ref: /schemas/types.yaml#/definitions/uint32 22 + enum: [1, 2, 4] 23 + 24 + media: 25 + description: 26 + The mediums, as defined in 802.3, that can be used on the port. 27 + enum: 28 + - BaseT 29 + - BaseK 30 + - BaseS 31 + - BaseC 32 + - BaseL 33 + - BaseD 34 + - BaseE 35 + - BaseF 36 + - BaseV 37 + - BaseMLD 38 + 39 + required: 40 + - media 41 + 42 + allOf: 43 + - if: 44 + properties: 45 + media: 46 + const: BaseT 47 + then: 48 + required: 49 + - pairs 50 + else: 51 + properties: 52 + pairs: false 53 + 54 + additionalProperties: true 55 + 56 + ...
+18
Documentation/devicetree/bindings/net/ethernet-phy.yaml
··· 281 281 282 282 additionalProperties: false 283 283 284 + mdi: 285 + type: object 286 + 287 + patternProperties: 288 + '^connector-[0-9]+$': 289 + $ref: /schemas/net/ethernet-connector.yaml# 290 + 291 + unevaluatedProperties: false 292 + 293 + additionalProperties: false 294 + 284 295 required: 285 296 - reg 286 297 ··· 326 315 color = <LED_COLOR_ID_WHITE>; 327 316 function = LED_FUNCTION_LAN; 328 317 default-state = "keep"; 318 + }; 319 + }; 320 + /* Fast Ethernet port, with only 2 pairs wired */ 321 + mdi { 322 + connector-0 { 323 + pairs = <2>; 324 + media = "BaseT"; 329 325 }; 330 326 }; 331 327 };
+8 -1
Documentation/devicetree/bindings/net/ti,dp83822.yaml
··· 47 47 is disabled. 48 48 In fiber mode, auto-negotiation is disabled and the PHY can only work in 49 49 100base-fx (full and half duplex) modes. 50 + This property is deprecated, for details please refer to 51 + Documentation/devicetree/bindings/net/ethernet-connector.yaml 52 + deprecated: true 50 53 51 54 rx-internal-delay-ps: 52 55 description: | ··· 144 141 tx-internal-delay-ps = <1>; 145 142 ti,gpio2-clk-out = "xi"; 146 143 mac-termination-ohms = <43>; 144 + mdi { 145 + connector-0 { 146 + media = "BaseF"; 147 + }; 148 + }; 147 149 }; 148 150 }; 149 - 150 151 ...
+1
Documentation/networking/index.rst
··· 96 96 packet_mmap 97 97 phonet 98 98 phy-link-topology 99 + phy-port 99 100 pktgen 100 101 plip 101 102 ppp_generic
+111
Documentation/networking/phy-port.rst
··· 1 + .. SPDX-License-Identifier: GPL-2.0 2 + .. _phy_port: 3 + 4 + ================= 5 + Ethernet ports 6 + ================= 7 + 8 + This document is a basic description of the phy_port infrastructure, 9 + introduced to represent physical interfaces of Ethernet devices. 10 + 11 + Without phy_port, we already have quite a lot of information about what the 12 + media-facing interface of a NIC can do and looks like, through the 13 + :c:type:`struct ethtool_link_ksettings <ethtool_link_ksettings>` attributes, 14 + which includes : 15 + 16 + - What the NIC can do through the :c:member:`supported` field 17 + - What the Link Partner advertises through :c:member:`lp_advertising` 18 + - Which features we're advertising through :c:member:`advertising` 19 + 20 + We also have info about the number of pairs and the PORT type. These settings 21 + are built by aggregating together information reported by various devices that 22 + are sitting on the link : 23 + 24 + - The NIC itself, through the :c:member:`get_link_ksettings` callback 25 + - Precise information from the MAC and PCS by using phylink in the MAC driver 26 + - Information reported by the PHY device 27 + - Information reported by an SFP module (which can itself include a PHY) 28 + 29 + This model however starts showing its limitations when we consider devices that 30 + have more than one media interface. In such a case, only information about the 31 + actively used interface is reported, and it's not possible to know what the 32 + other interfaces can do. In fact, we have very little information about whether 33 + or not there are any other media interfaces. 34 + 35 + The goal of the phy_port representation is to provide a way of representing a 36 + physical interface of a NIC, regardless of what is driving the port (NIC through 37 + a firmware, SFP module, Ethernet PHY). 38 + 39 + Multi-port interfaces examples 40 + ============================== 41 + 42 + Several cases of multi-interface NICs have been observed so far : 43 + 44 + Internal MII Mux:: 45 + 46 + +------------------+ 47 + | SoC | 48 + | +-----+ | +-----+ 49 + | +-----+ | |-------------| PHY | 50 + | | MAC |--| Mux | | +-----+ +-----+ 51 + | +-----+ | |-----| SFP | 52 + | +-----+ | +-----+ 53 + +------------------+ 54 + 55 + Internal Mux with internal PHY:: 56 + 57 + +------------------------+ 58 + | SoC | 59 + | +-----+ +-----+ 60 + | +-----+ | |-| PHY | 61 + | | MAC |--| Mux | +-----+ +-----+ 62 + | +-----+ | |-----------| SFP | 63 + | +-----+ | +-----+ 64 + +------------------------+ 65 + 66 + External Mux:: 67 + 68 + +---------+ 69 + | SoC | +-----+ +-----+ 70 + | | | |--| PHY | 71 + | +-----+ | | | +-----+ 72 + | | MAC |----| Mux | +-----+ 73 + | +-----+ | | |--| PHY | 74 + | | +-----+ +-----+ 75 + | | | 76 + | GPIO-------+ 77 + +---------+ 78 + 79 + Double-port PHY:: 80 + 81 + +---------+ 82 + | SoC | +-----+ 83 + | | | |--- RJ45 84 + | +-----+ | | | 85 + | | MAC |---| PHY | +-----+ 86 + | +-----+ | | |---| SFP | 87 + +---------+ +-----+ +-----+ 88 + 89 + phy_port aims at providing a path to support all the above topologies, by 90 + representing the media interfaces in a way that's agnostic to what's driving 91 + the interface. the struct phy_port object has its own set of callback ops, and 92 + will eventually be able to report its own ksettings:: 93 + 94 + _____ +------+ 95 + ( )-----| Port | 96 + +-----+ ( ) +------+ 97 + | MAC |--( ??? ) 98 + +-----+ ( ) +------+ 99 + (_____)-----| Port | 100 + +------+ 101 + 102 + Next steps 103 + ========== 104 + 105 + As of writing this documentation, only ports controlled by PHY devices are 106 + supported. The next steps will be to add the Netlink API to expose these 107 + to userspace and add support for raw ports (controlled by some firmware, and directly 108 + managed by the NIC driver). 109 + 110 + Another parallel task is the introduction of a MII muxing framework to allow the 111 + control of non-PHY driver multi-port setups.
+10
MAINTAINERS
··· 9395 9395 L: netdev@vger.kernel.org 9396 9396 S: Maintained 9397 9397 F: Documentation/ABI/testing/sysfs-class-net-phydev 9398 + F: Documentation/devicetree/bindings/net/ethernet-connector.yaml 9398 9399 F: Documentation/devicetree/bindings/net/ethernet-phy.yaml 9399 9400 F: Documentation/devicetree/bindings/net/mdio* 9400 9401 F: Documentation/devicetree/bindings/net/qca,ar803x.yaml 9402 + F: Documentation/networking/phy-port.rst 9401 9403 F: Documentation/networking/phy.rst 9402 9404 F: drivers/net/mdio/ 9403 9405 F: drivers/net/mdio/acpi_mdio.c ··· 18218 18216 F: drivers/net/phy/phy_link_topology.c 18219 18217 F: include/linux/phy_link_topology.h 18220 18218 F: net/ethtool/phy.c 18219 + 18220 + NETWORKING [ETHTOOL PHY PORT] 18221 + M: Maxime Chevallier <maxime.chevallier@bootlin.com> 18222 + F: Documentation/devicetree/bindings/net/ethernet-connector.yaml 18223 + F: Documentation/networking/phy-port.rst 18224 + F: drivers/net/phy/phy_port.c 18225 + F: include/linux/phy_port.h 18226 + K: struct\s+phy_port|phy_port_ 18221 18227 18222 18228 NETWORKING [GENERAL] 18223 18229 M: "David S. Miller" <davem@davemloft.net>
+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_caps.o mdio_bus_provider.o 6 + phy_caps.o mdio_bus_provider.o phy_port.o 7 7 mdio-bus-y += mdio_bus.o mdio_device.o 8 8 9 9 ifdef CONFIG_PHYLIB
+45 -26
drivers/net/phy/dp83822.c
··· 11 11 #include <linux/module.h> 12 12 #include <linux/of.h> 13 13 #include <linux/phy.h> 14 + #include <linux/phy_port.h> 14 15 #include <linux/netdevice.h> 15 16 #include <linux/bitfield.h> 16 17 ··· 812 811 int i, ret; 813 812 u32 val; 814 813 815 - /* Signal detection for the PHY is only enabled if the FX_EN and the 816 - * SD_EN pins are strapped. Signal detection can only enabled if FX_EN 817 - * is strapped otherwise signal detection is disabled for the PHY. 818 - */ 819 - if (dp83822->fx_enabled && dp83822->fx_sd_enable) 820 - dp83822->fx_signal_det_low = device_property_present(dev, 821 - "ti,link-loss-low"); 822 - if (!dp83822->fx_enabled) 823 - dp83822->fx_enabled = device_property_present(dev, 824 - "ti,fiber-mode"); 825 - 826 814 if (!device_property_read_string(dev, "ti,gpio2-clk-out", &of_val)) { 827 815 if (strcmp(of_val, "mac-if") == 0) { 828 816 dp83822->gpio2_clk_out = DP83822_CLK_SRC_MAC_IF; ··· 940 950 return 0; 941 951 } 942 952 953 + static int dp83822_attach_mdi_port(struct phy_device *phydev, 954 + struct phy_port *port) 955 + { 956 + struct dp83822_private *dp83822 = phydev->priv; 957 + int ret; 958 + 959 + if (port->mediums) { 960 + if (phy_port_is_fiber(port)) 961 + dp83822->fx_enabled = true; 962 + } else { 963 + ret = dp83822_read_straps(phydev); 964 + if (ret) 965 + return ret; 966 + 967 + #if IS_ENABLED(CONFIG_OF_MDIO) 968 + if (dp83822->fx_enabled && dp83822->fx_sd_enable) 969 + dp83822->fx_signal_det_low = 970 + device_property_present(&phydev->mdio.dev, 971 + "ti,link-loss-low"); 972 + 973 + /* ti,fiber-mode is still used for backwards compatibility, but 974 + * has been replaced with the mdi node definition, see 975 + * ethernet-port.yaml 976 + */ 977 + if (!dp83822->fx_enabled) 978 + dp83822->fx_enabled = 979 + device_property_present(&phydev->mdio.dev, 980 + "ti,fiber-mode"); 981 + #endif /* CONFIG_OF_MDIO */ 982 + 983 + if (dp83822->fx_enabled) { 984 + port->mediums = BIT(ETHTOOL_LINK_MEDIUM_BASEF); 985 + } else { 986 + /* This PHY can only to 100BaseTX max, so on 2 pairs */ 987 + port->pairs = 2; 988 + port->mediums = BIT(ETHTOOL_LINK_MEDIUM_BASET); 989 + } 990 + } 991 + 992 + return 0; 993 + } 994 + 943 995 static int dp8382x_probe(struct phy_device *phydev) 944 996 { 945 997 struct dp83822_private *dp83822; ··· 1000 968 1001 969 static int dp83822_probe(struct phy_device *phydev) 1002 970 { 1003 - struct dp83822_private *dp83822; 1004 971 int ret; 1005 972 1006 973 ret = dp8382x_probe(phydev); 1007 974 if (ret) 1008 975 return ret; 1009 976 1010 - dp83822 = phydev->priv; 1011 - 1012 - ret = dp83822_read_straps(phydev); 1013 - if (ret) 1014 - return ret; 1015 - 1016 - ret = dp83822_of_init(phydev); 1017 - if (ret) 1018 - return ret; 1019 - 1020 - if (dp83822->fx_enabled) 1021 - phydev->port = PORT_FIBRE; 1022 - 1023 - return 0; 977 + return dp83822_of_init(phydev); 1024 978 } 1025 979 1026 980 static int dp83826_probe(struct phy_device *phydev) ··· 1190 1172 .led_hw_is_supported = dp83822_led_hw_is_supported, \ 1191 1173 .led_hw_control_set = dp83822_led_hw_control_set, \ 1192 1174 .led_hw_control_get = dp83822_led_hw_control_get, \ 1175 + .attach_mdi_port = dp83822_attach_mdi_port \ 1193 1176 } 1194 1177 1195 1178 #define DP83825_PHY_DRIVER(_id, _name) \
+38 -56
drivers/net/phy/marvell-88x2222.c
··· 13 13 #include <linux/mdio.h> 14 14 #include <linux/marvell_phy.h> 15 15 #include <linux/of.h> 16 - #include <linux/sfp.h> 16 + #include <linux/phy_port.h> 17 17 #include <linux/netdevice.h> 18 18 19 19 /* Port PCS Configuration */ ··· 473 473 return 0; 474 474 } 475 475 476 - static int mv2222_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) 476 + static int mv2222_configure_serdes(struct phy_port *port, bool enable, 477 + phy_interface_t interface) 477 478 { 478 - struct phy_device *phydev = upstream; 479 - const struct sfp_module_caps *caps; 480 - phy_interface_t sfp_interface; 479 + struct phy_device *phydev = port_phydev(port); 481 480 struct mv2222_data *priv; 482 - struct device *dev; 483 - int ret; 481 + int ret = 0; 484 482 485 483 priv = phydev->priv; 486 - dev = &phydev->mdio.dev; 484 + priv->line_interface = interface; 487 485 488 - caps = sfp_get_module_caps(phydev->sfp_bus); 486 + if (enable) { 487 + linkmode_and(priv->supported, phydev->supported, port->supported); 489 488 490 - phydev->port = caps->port; 491 - sfp_interface = sfp_select_interface(phydev->sfp_bus, caps->link_modes); 489 + ret = mv2222_config_line(phydev); 490 + if (ret < 0) 491 + return ret; 492 492 493 - dev_info(dev, "%s SFP module inserted\n", phy_modes(sfp_interface)); 493 + if (mutex_trylock(&phydev->lock)) { 494 + ret = mv2222_config_aneg(phydev); 495 + mutex_unlock(&phydev->lock); 496 + } 494 497 495 - if (sfp_interface != PHY_INTERFACE_MODE_10GBASER && 496 - sfp_interface != PHY_INTERFACE_MODE_1000BASEX && 497 - sfp_interface != PHY_INTERFACE_MODE_SGMII) { 498 - dev_err(dev, "Incompatible SFP module inserted\n"); 499 - 500 - return -EINVAL; 501 - } 502 - 503 - priv->line_interface = sfp_interface; 504 - linkmode_and(priv->supported, phydev->supported, caps->link_modes); 505 - 506 - ret = mv2222_config_line(phydev); 507 - if (ret < 0) 508 - return ret; 509 - 510 - if (mutex_trylock(&phydev->lock)) { 511 - ret = mv2222_config_aneg(phydev); 512 - mutex_unlock(&phydev->lock); 498 + } else { 499 + linkmode_zero(priv->supported); 513 500 } 514 501 515 502 return ret; 516 503 } 517 504 518 - static void mv2222_sfp_remove(void *upstream) 505 + static void mv2222_port_link_up(struct phy_port *port) 519 506 { 520 - struct phy_device *phydev = upstream; 521 - struct mv2222_data *priv; 522 - 523 - priv = phydev->priv; 524 - 525 - priv->line_interface = PHY_INTERFACE_MODE_NA; 526 - linkmode_zero(priv->supported); 527 - phydev->port = PORT_NONE; 528 - } 529 - 530 - static void mv2222_sfp_link_up(void *upstream) 531 - { 532 - struct phy_device *phydev = upstream; 507 + struct phy_device *phydev = port_phydev(port); 533 508 struct mv2222_data *priv; 534 509 535 510 priv = phydev->priv; 536 511 priv->sfp_link = true; 537 512 } 538 513 539 - static void mv2222_sfp_link_down(void *upstream) 514 + static void mv2222_port_link_down(struct phy_port *port) 540 515 { 541 - struct phy_device *phydev = upstream; 516 + struct phy_device *phydev = port_phydev(port); 542 517 struct mv2222_data *priv; 543 518 544 519 priv = phydev->priv; 545 520 priv->sfp_link = false; 546 521 } 547 522 548 - static const struct sfp_upstream_ops sfp_phy_ops = { 549 - .module_insert = mv2222_sfp_insert, 550 - .module_remove = mv2222_sfp_remove, 551 - .link_up = mv2222_sfp_link_up, 552 - .link_down = mv2222_sfp_link_down, 553 - .attach = phy_sfp_attach, 554 - .detach = phy_sfp_detach, 555 - .connect_phy = phy_sfp_connect_phy, 556 - .disconnect_phy = phy_sfp_disconnect_phy, 523 + static const struct phy_port_ops mv2222_port_ops = { 524 + .link_up = mv2222_port_link_up, 525 + .link_down = mv2222_port_link_down, 526 + .configure_mii = mv2222_configure_serdes, 557 527 }; 528 + 529 + static int mv2222_attach_mii_port(struct phy_device *phydev, struct phy_port *port) 530 + { 531 + port->ops = &mv2222_port_ops; 532 + 533 + __set_bit(PHY_INTERFACE_MODE_10GBASER, port->interfaces); 534 + __set_bit(PHY_INTERFACE_MODE_1000BASEX, port->interfaces); 535 + __set_bit(PHY_INTERFACE_MODE_SGMII, port->interfaces); 536 + 537 + return 0; 538 + } 558 539 559 540 static int mv2222_probe(struct phy_device *phydev) 560 541 { ··· 572 591 priv->line_interface = PHY_INTERFACE_MODE_NA; 573 592 phydev->priv = priv; 574 593 575 - return phy_sfp_probe(phydev, &sfp_phy_ops); 594 + return 0; 576 595 } 577 596 578 597 static struct phy_driver mv2222_drivers[] = { ··· 589 608 .suspend = mv2222_suspend, 590 609 .resume = mv2222_resume, 591 610 .read_status = mv2222_read_status, 611 + .attach_mii_port = mv2222_attach_mii_port, 592 612 }, 593 613 }; 594 614 module_phy_driver(mv2222_drivers);
+32 -60
drivers/net/phy/marvell.c
··· 29 29 #include <linux/ethtool.h> 30 30 #include <linux/ethtool_netlink.h> 31 31 #include <linux/phy.h> 32 + #include <linux/phy_port.h> 32 33 #include <linux/marvell_phy.h> 33 34 #include <linux/bitfield.h> 34 35 #include <linux/of.h> 35 - #include <linux/sfp.h> 36 36 37 37 #include <linux/io.h> 38 38 #include <asm/irq.h> ··· 3598 3598 return marvell_hwmon_probe(phydev); 3599 3599 } 3600 3600 3601 - static int m88e1510_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) 3601 + static int m88e1510_port_configure_serdes(struct phy_port *port, bool enable, 3602 + phy_interface_t interface) 3602 3603 { 3603 - struct phy_device *phydev = upstream; 3604 - const struct sfp_module_caps *caps; 3605 - phy_interface_t interface; 3604 + struct phy_device *phydev = port_phydev(port); 3606 3605 struct device *dev; 3607 3606 int oldpage; 3608 3607 int ret = 0; ··· 3609 3610 3610 3611 dev = &phydev->mdio.dev; 3611 3612 3612 - caps = sfp_get_module_caps(phydev->sfp_bus); 3613 - interface = sfp_select_interface(phydev->sfp_bus, caps->link_modes); 3613 + if (enable) { 3614 + switch (interface) { 3615 + case PHY_INTERFACE_MODE_1000BASEX: 3616 + mode = MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_1000X; 3614 3617 3615 - dev_info(dev, "%s SFP module inserted\n", phy_modes(interface)); 3618 + break; 3619 + case PHY_INTERFACE_MODE_100BASEX: 3620 + mode = MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_100FX; 3616 3621 3617 - switch (interface) { 3618 - case PHY_INTERFACE_MODE_1000BASEX: 3619 - mode = MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_1000X; 3622 + break; 3623 + case PHY_INTERFACE_MODE_SGMII: 3624 + mode = MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_SGMII; 3620 3625 3621 - break; 3622 - case PHY_INTERFACE_MODE_100BASEX: 3623 - mode = MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_100FX; 3626 + break; 3627 + default: 3628 + dev_err(dev, "Incompatible SFP module inserted\n"); 3624 3629 3625 - break; 3626 - case PHY_INTERFACE_MODE_SGMII: 3627 - mode = MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII_SGMII; 3628 - 3629 - break; 3630 - default: 3631 - dev_err(dev, "Incompatible SFP module inserted\n"); 3632 - 3633 - return -EINVAL; 3630 + return -EINVAL; 3631 + } 3632 + } else { 3633 + mode = MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII; 3634 3634 } 3635 3635 3636 3636 oldpage = phy_select_page(phydev, MII_MARVELL_MODE_PAGE); ··· 3648 3650 return phy_restore_page(phydev, oldpage, ret); 3649 3651 } 3650 3652 3651 - static void m88e1510_sfp_remove(void *upstream) 3652 - { 3653 - struct phy_device *phydev = upstream; 3654 - int oldpage; 3655 - int ret = 0; 3656 - 3657 - oldpage = phy_select_page(phydev, MII_MARVELL_MODE_PAGE); 3658 - if (oldpage < 0) 3659 - goto error; 3660 - 3661 - ret = __phy_modify(phydev, MII_88E1510_GEN_CTRL_REG_1, 3662 - MII_88E1510_GEN_CTRL_REG_1_MODE_MASK, 3663 - MII_88E1510_GEN_CTRL_REG_1_MODE_RGMII); 3664 - if (ret < 0) 3665 - goto error; 3666 - 3667 - ret = __phy_set_bits(phydev, MII_88E1510_GEN_CTRL_REG_1, 3668 - MII_88E1510_GEN_CTRL_REG_1_RESET); 3669 - 3670 - error: 3671 - phy_restore_page(phydev, oldpage, ret); 3672 - } 3673 - 3674 - static const struct sfp_upstream_ops m88e1510_sfp_ops = { 3675 - .module_insert = m88e1510_sfp_insert, 3676 - .module_remove = m88e1510_sfp_remove, 3677 - .attach = phy_sfp_attach, 3678 - .detach = phy_sfp_detach, 3679 - .connect_phy = phy_sfp_connect_phy, 3680 - .disconnect_phy = phy_sfp_disconnect_phy, 3653 + static const struct phy_port_ops m88e1510_serdes_port_ops = { 3654 + .configure_mii = m88e1510_port_configure_serdes, 3681 3655 }; 3682 3656 3683 - static int m88e1510_probe(struct phy_device *phydev) 3657 + static int m88e1510_attach_mii_port(struct phy_device *phy_device, 3658 + struct phy_port *port) 3684 3659 { 3685 - int err; 3660 + port->ops = &m88e1510_serdes_port_ops; 3686 3661 3687 - err = marvell_probe(phydev); 3688 - if (err) 3689 - return err; 3662 + __set_bit(PHY_INTERFACE_MODE_SGMII, port->interfaces); 3663 + __set_bit(PHY_INTERFACE_MODE_1000BASEX, port->interfaces); 3664 + __set_bit(PHY_INTERFACE_MODE_100BASEX, port->interfaces); 3690 3665 3691 - return phy_sfp_probe(phydev, &m88e1510_sfp_ops); 3666 + return 0; 3692 3667 } 3693 3668 3694 3669 static struct phy_driver marvell_drivers[] = { ··· 3921 3950 .driver_data = DEF_MARVELL_HWMON_OPS(m88e1510_hwmon_ops), 3922 3951 .features = PHY_GBIT_FIBRE_FEATURES, 3923 3952 .flags = PHY_POLL_CABLE_TEST, 3924 - .probe = m88e1510_probe, 3953 + .probe = marvell_probe, 3925 3954 .config_init = m88e1510_config_init, 3926 3955 .config_aneg = m88e1510_config_aneg, 3927 3956 .read_status = marvell_read_status, ··· 3947 3976 .led_hw_is_supported = m88e1318_led_hw_is_supported, 3948 3977 .led_hw_control_set = m88e1318_led_hw_control_set, 3949 3978 .led_hw_control_get = m88e1318_led_hw_control_get, 3979 + .attach_mii_port = m88e1510_attach_mii_port, 3950 3980 }, 3951 3981 { 3952 3982 .phy_id = MARVELL_PHY_ID_88E1540,
+30 -21
drivers/net/phy/marvell10g.c
··· 28 28 #include <linux/hwmon.h> 29 29 #include <linux/marvell_phy.h> 30 30 #include <linux/phy.h> 31 - #include <linux/sfp.h> 31 + #include <linux/phy_port.h> 32 32 #include <linux/netdevice.h> 33 33 34 34 #define MV_PHY_ALASKA_NBT_QUIRK_MASK 0xfffffffe ··· 463 463 return err; 464 464 } 465 465 466 - static int mv3310_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) 466 + static int mv3310_attach_mii_port(struct phy_device *phydev, 467 + struct phy_port *port) 467 468 { 468 - struct phy_device *phydev = upstream; 469 - const struct sfp_module_caps *caps; 470 - phy_interface_t iface; 471 - 472 - caps = sfp_get_module_caps(phydev->sfp_bus); 473 - iface = sfp_select_interface(phydev->sfp_bus, caps->link_modes); 474 - 475 - if (iface != PHY_INTERFACE_MODE_10GBASER) { 476 - dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n"); 477 - return -EINVAL; 478 - } 469 + __set_bit(PHY_INTERFACE_MODE_10GBASER, port->interfaces); 479 470 return 0; 480 471 } 481 472 482 - static const struct sfp_upstream_ops mv3310_sfp_ops = { 483 - .attach = phy_sfp_attach, 484 - .detach = phy_sfp_detach, 485 - .connect_phy = phy_sfp_connect_phy, 486 - .disconnect_phy = phy_sfp_disconnect_phy, 487 - .module_insert = mv3310_sfp_insert, 488 - }; 473 + static int mv3310_attach_mdi_port(struct phy_device *phydev, 474 + struct phy_port *port) 475 + { 476 + /* This PHY can do combo-ports, i.e. 2 MDI outputs, usually one 477 + * of them going to an SFP and the other one to a RJ45 478 + * connector. If we don't have any representation for the port 479 + * in DT, and we are dealing with a non-SFP port, then we 480 + * mask the port's capabilities to report BaseT-only modes 481 + */ 482 + if (port->not_described) 483 + return phy_port_restrict_mediums(port, 484 + BIT(ETHTOOL_LINK_MEDIUM_BASET)); 485 + 486 + return 0; 487 + } 489 488 490 489 static int mv3310_probe(struct phy_device *phydev) 491 490 { ··· 543 544 544 545 chip->init_supported_interfaces(priv->supported_interfaces); 545 546 546 - return phy_sfp_probe(phydev, &mv3310_sfp_ops); 547 + phydev->max_n_ports = 2; 548 + 549 + return 0; 547 550 } 548 551 549 552 static void mv3310_remove(struct phy_device *phydev) ··· 1406 1405 .set_loopback = genphy_c45_loopback, 1407 1406 .get_wol = mv3110_get_wol, 1408 1407 .set_wol = mv3110_set_wol, 1408 + .attach_mii_port = mv3310_attach_mii_port, 1409 + .attach_mdi_port = mv3310_attach_mdi_port, 1409 1410 }, 1410 1411 { 1411 1412 .phy_id = MARVELL_PHY_ID_88X3310, ··· 1427 1424 .set_tunable = mv3310_set_tunable, 1428 1425 .remove = mv3310_remove, 1429 1426 .set_loopback = genphy_c45_loopback, 1427 + .attach_mii_port = mv3310_attach_mii_port, 1428 + .attach_mdi_port = mv3310_attach_mdi_port, 1430 1429 }, 1431 1430 { 1432 1431 .phy_id = MARVELL_PHY_ID_88E2110, ··· 1449 1444 .set_loopback = genphy_c45_loopback, 1450 1445 .get_wol = mv3110_get_wol, 1451 1446 .set_wol = mv3110_set_wol, 1447 + .attach_mii_port = mv3310_attach_mii_port, 1448 + .attach_mdi_port = mv3310_attach_mdi_port, 1452 1449 }, 1453 1450 { 1454 1451 .phy_id = MARVELL_PHY_ID_88E2110, ··· 1469 1462 .set_tunable = mv3310_set_tunable, 1470 1463 .remove = mv3310_remove, 1471 1464 .set_loopback = genphy_c45_loopback, 1465 + .attach_mii_port = mv3310_attach_mii_port, 1466 + .attach_mdi_port = mv3310_attach_mdi_port, 1472 1467 }, 1473 1468 }; 1474 1469
+5
drivers/net/phy/phy-caps.h
··· 61 61 phy_caps_lookup(int speed, unsigned int duplex, const unsigned long *supported, 62 62 bool exact); 63 63 64 + void phy_caps_medium_get_supported(unsigned long *supported, 65 + enum ethtool_link_medium medium, 66 + int lanes); 67 + u32 phy_caps_mediums_from_linkmodes(unsigned long *linkmodes); 68 + 64 69 #endif /* __PHY_CAPS_H */
+6
drivers/net/phy/phy-core.c
··· 4 4 */ 5 5 #include <linux/export.h> 6 6 #include <linux/phy.h> 7 + #include <linux/phy_port.h> 7 8 #include <linux/of.h> 8 9 9 10 #include "phylib.h" ··· 209 208 210 209 static void __set_phy_supported(struct phy_device *phydev, u32 max_speed) 211 210 { 211 + struct phy_port *port; 212 + 212 213 phy_caps_linkmode_max_speed(max_speed, phydev->supported); 214 + 215 + phy_for_each_port(phydev, port) 216 + phy_caps_linkmode_max_speed(max_speed, port->supported); 213 217 } 214 218 215 219 /**
+65
drivers/net/phy/phy_caps.c
··· 80 80 /* Fill the caps array from net/ethtool/common.c */ 81 81 for (i = 0; i < __ETHTOOL_LINK_MODE_MASK_NBITS; i++) { 82 82 linkmode = &link_mode_params[i]; 83 + 84 + /* Sanity check the linkmodes array for number of pairs */ 85 + if (linkmode->pairs < linkmode->min_pairs) { 86 + pr_err("Pairs count must not be under min_pairs for linkmode %d\n", 87 + i); 88 + return -EINVAL; 89 + } 90 + 83 91 capa = speed_duplex_to_capa(linkmode->speed, linkmode->duplex); 84 92 85 93 if (capa < 0) { ··· 386 378 return link_caps; 387 379 } 388 380 EXPORT_SYMBOL_GPL(phy_caps_from_interface); 381 + 382 + /** 383 + * phy_caps_medium_get_supported() - Returns linkmodes supported on a given medium 384 + * @supported: After this call, contains all possible linkmodes on a given medium, 385 + * and with the given number of pairs, or less. 386 + * @medium: The medium to get the support from 387 + * @pairs: The number of pairs used on the given medium. Only relevant for modes 388 + * that support this notion, such as BaseT. Pass 0 if not applicable. 389 + * 390 + * If no match exists, the supported field is left untouched. 391 + */ 392 + void phy_caps_medium_get_supported(unsigned long *supported, 393 + enum ethtool_link_medium medium, 394 + int pairs) 395 + { 396 + int i; 397 + 398 + for (i = 0; i < __ETHTOOL_LINK_MODE_MASK_NBITS; i++) { 399 + /* Special bits such as Autoneg, Pause, Asym_pause, etc. are 400 + * set and will be masked away by the port parent. 401 + */ 402 + if (link_mode_params[i].mediums == BIT(ETHTOOL_LINK_MEDIUM_NONE)) { 403 + linkmode_set_bit(i, supported); 404 + continue; 405 + } 406 + 407 + /* If this medium matches, and had a non-zero min-pairs */ 408 + if (link_mode_params[i].mediums & BIT(medium) && 409 + (!link_mode_params[i].min_pairs || 410 + (link_mode_params[i].min_pairs <= pairs && 411 + link_mode_params[i].pairs >= pairs))) 412 + linkmode_set_bit(i, supported); 413 + } 414 + } 415 + EXPORT_SYMBOL_GPL(phy_caps_medium_get_supported); 416 + 417 + /** 418 + * phy_caps_mediums_from_linkmodes() - Get all mediums from a linkmodes list 419 + * @linkmodes: A bitset of linkmodes to get the mediums from 420 + * 421 + * Returns: A bitset of ETHTOOL_MEDIUM_XXX values corresponding to all medium 422 + * types in the linkmodes list 423 + */ 424 + u32 phy_caps_mediums_from_linkmodes(unsigned long *linkmodes) 425 + { 426 + const struct link_mode_info *linkmode; 427 + u32 mediums = 0; 428 + int i; 429 + 430 + for_each_set_bit(i, linkmodes, __ETHTOOL_LINK_MODE_MASK_NBITS) { 431 + linkmode = &link_mode_params[i]; 432 + mediums |= linkmode->mediums; 433 + } 434 + 435 + return mediums; 436 + } 437 + EXPORT_SYMBOL_GPL(phy_caps_mediums_from_linkmodes);
+332 -13
drivers/net/phy/phy_device.c
··· 30 30 #include <linux/phylib_stubs.h> 31 31 #include <linux/phy_led_triggers.h> 32 32 #include <linux/phy_link_topology.h> 33 + #include <linux/phy_port.h> 33 34 #include <linux/pse-pd/pse.h> 34 35 #include <linux/property.h> 35 36 #include <linux/ptp_clock_kernel.h> ··· 846 845 847 846 dev->state = PHY_DOWN; 848 847 INIT_LIST_HEAD(&dev->leds); 848 + INIT_LIST_HEAD(&dev->ports); 849 + 850 + /* The driver's probe function must change that to the real number 851 + * of ports possible on the PHY. We assume by default we are dealing 852 + * with a single-port PHY 853 + */ 854 + dev->max_n_ports = 1; 849 855 850 856 mutex_init(&dev->lock); 851 857 INIT_DELAYED_WORK(&dev->state_queue, phy_state_machine); ··· 1532 1524 * 1533 1525 * Return: 0 on success, otherwise a negative error code. 1534 1526 */ 1535 - int phy_sfp_connect_phy(void *upstream, struct phy_device *phy) 1527 + static int phy_sfp_connect_phy(void *upstream, struct phy_device *phy) 1536 1528 { 1537 1529 struct phy_device *phydev = upstream; 1538 1530 struct net_device *dev = phydev->attached_dev; ··· 1542 1534 1543 1535 return 0; 1544 1536 } 1545 - EXPORT_SYMBOL(phy_sfp_connect_phy); 1546 1537 1547 1538 /** 1548 1539 * phy_sfp_disconnect_phy - Disconnect the SFP module's PHY from the upstream PHY ··· 1553 1546 * will be destroyed, re-inserting the same module will add a new phy with a 1554 1547 * new index. 1555 1548 */ 1556 - void phy_sfp_disconnect_phy(void *upstream, struct phy_device *phy) 1549 + static void phy_sfp_disconnect_phy(void *upstream, struct phy_device *phy) 1557 1550 { 1558 1551 struct phy_device *phydev = upstream; 1559 1552 struct net_device *dev = phydev->attached_dev; ··· 1561 1554 if (dev) 1562 1555 phy_link_topo_del_phy(dev, phy); 1563 1556 } 1564 - EXPORT_SYMBOL(phy_sfp_disconnect_phy); 1565 1557 1566 1558 /** 1567 1559 * phy_sfp_attach - attach the SFP bus to the PHY upstream network device ··· 1569 1563 * 1570 1564 * This is used to fill in the sfp_upstream_ops .attach member. 1571 1565 */ 1572 - void phy_sfp_attach(void *upstream, struct sfp_bus *bus) 1566 + static void phy_sfp_attach(void *upstream, struct sfp_bus *bus) 1573 1567 { 1574 1568 struct phy_device *phydev = upstream; 1575 1569 ··· 1577 1571 phydev->attached_dev->sfp_bus = bus; 1578 1572 phydev->sfp_bus_attached = true; 1579 1573 } 1580 - EXPORT_SYMBOL(phy_sfp_attach); 1581 1574 1582 1575 /** 1583 1576 * phy_sfp_detach - detach the SFP bus from the PHY upstream network device ··· 1585 1580 * 1586 1581 * This is used to fill in the sfp_upstream_ops .detach member. 1587 1582 */ 1588 - void phy_sfp_detach(void *upstream, struct sfp_bus *bus) 1583 + static void phy_sfp_detach(void *upstream, struct sfp_bus *bus) 1589 1584 { 1590 1585 struct phy_device *phydev = upstream; 1591 1586 ··· 1593 1588 phydev->attached_dev->sfp_bus = NULL; 1594 1589 phydev->sfp_bus_attached = false; 1595 1590 } 1596 - EXPORT_SYMBOL(phy_sfp_detach); 1591 + 1592 + static int phy_sfp_module_insert(void *upstream, const struct sfp_eeprom_id *id) 1593 + { 1594 + __ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_support); 1595 + struct phy_device *phydev = upstream; 1596 + const struct sfp_module_caps *caps; 1597 + struct phy_port *port; 1598 + 1599 + phy_interface_t iface; 1600 + 1601 + linkmode_zero(sfp_support); 1602 + 1603 + port = phy_get_sfp_port(phydev); 1604 + if (!port) 1605 + return -EINVAL; 1606 + 1607 + caps = sfp_get_module_caps(phydev->sfp_bus); 1608 + 1609 + linkmode_and(sfp_support, port->supported, caps->link_modes); 1610 + if (linkmode_empty(sfp_support)) { 1611 + dev_err(&phydev->mdio.dev, "incompatible SFP module inserted, no common linkmode\n"); 1612 + return -EINVAL; 1613 + } 1614 + 1615 + iface = sfp_select_interface(phydev->sfp_bus, sfp_support); 1616 + if (iface == PHY_INTERFACE_MODE_NA) { 1617 + dev_err(&phydev->mdio.dev, "PHY %s does not support the SFP module's requested MII interfaces\n", 1618 + phydev_name(phydev)); 1619 + return -EINVAL; 1620 + } 1621 + 1622 + if (phydev->n_ports == 1) 1623 + phydev->port = caps->port; 1624 + 1625 + if (port->ops && port->ops->configure_mii) 1626 + return port->ops->configure_mii(port, true, iface); 1627 + 1628 + return 0; 1629 + } 1630 + 1631 + static void phy_sfp_module_remove(void *upstream) 1632 + { 1633 + struct phy_device *phydev = upstream; 1634 + struct phy_port *port = phy_get_sfp_port(phydev); 1635 + 1636 + if (port && port->ops && port->ops->configure_mii) 1637 + port->ops->configure_mii(port, false, PHY_INTERFACE_MODE_NA); 1638 + 1639 + if (phydev->n_ports == 1) 1640 + phydev->port = PORT_NONE; 1641 + } 1642 + 1643 + static void phy_sfp_link_up(void *upstream) 1644 + { 1645 + struct phy_device *phydev = upstream; 1646 + struct phy_port *port = phy_get_sfp_port(phydev); 1647 + 1648 + if (port && port->ops && port->ops->link_up) 1649 + port->ops->link_up(port); 1650 + } 1651 + 1652 + static void phy_sfp_link_down(void *upstream) 1653 + { 1654 + struct phy_device *phydev = upstream; 1655 + struct phy_port *port = phy_get_sfp_port(phydev); 1656 + 1657 + if (port && port->ops && port->ops->link_down) 1658 + port->ops->link_down(port); 1659 + } 1660 + 1661 + static const struct sfp_upstream_ops sfp_phydev_ops = { 1662 + .attach = phy_sfp_attach, 1663 + .detach = phy_sfp_detach, 1664 + .module_insert = phy_sfp_module_insert, 1665 + .module_remove = phy_sfp_module_remove, 1666 + .link_up = phy_sfp_link_up, 1667 + .link_down = phy_sfp_link_down, 1668 + .connect_phy = phy_sfp_connect_phy, 1669 + .disconnect_phy = phy_sfp_disconnect_phy, 1670 + }; 1671 + 1672 + static int phy_add_port(struct phy_device *phydev, struct phy_port *port) 1673 + { 1674 + int ret = 0; 1675 + 1676 + if (phydev->n_ports == phydev->max_n_ports) 1677 + return -EBUSY; 1678 + 1679 + /* We set all ports as active by default, PHY drivers may deactivate 1680 + * them (when unused) 1681 + */ 1682 + port->active = true; 1683 + 1684 + if (port->is_mii) { 1685 + if (phydev->drv && phydev->drv->attach_mii_port) 1686 + ret = phydev->drv->attach_mii_port(phydev, port); 1687 + } else { 1688 + if (phydev->drv && phydev->drv->attach_mdi_port) 1689 + ret = phydev->drv->attach_mdi_port(phydev, port); 1690 + } 1691 + 1692 + if (ret) 1693 + return ret; 1694 + 1695 + /* The PHY driver might have added, removed or set medium/pairs info, 1696 + * so update the port supported accordingly. 1697 + */ 1698 + phy_port_update_supported(port); 1699 + 1700 + list_add(&port->head, &phydev->ports); 1701 + 1702 + phydev->n_ports++; 1703 + 1704 + return 0; 1705 + } 1706 + 1707 + static void phy_del_port(struct phy_device *phydev, struct phy_port *port) 1708 + { 1709 + if (!phydev->n_ports) 1710 + return; 1711 + 1712 + list_del(&port->head); 1713 + 1714 + phydev->n_ports--; 1715 + } 1716 + 1717 + static int phy_setup_sfp_port(struct phy_device *phydev) 1718 + { 1719 + struct phy_port *port = phy_port_alloc(); 1720 + int ret; 1721 + 1722 + if (!port) 1723 + return -ENOMEM; 1724 + 1725 + port->parent_type = PHY_PORT_PHY; 1726 + port->phy = phydev; 1727 + 1728 + /* The PHY is a media converter, the port connected to the SFP cage 1729 + * is a MII port. 1730 + */ 1731 + port->is_mii = true; 1732 + port->is_sfp = true; 1733 + 1734 + /* The port->supported and port->interfaces list will be populated 1735 + * when attaching the port to the phydev. 1736 + */ 1737 + ret = phy_add_port(phydev, port); 1738 + if (ret) 1739 + phy_port_destroy(port); 1740 + 1741 + return ret; 1742 + } 1597 1743 1598 1744 /** 1599 1745 * phy_sfp_probe - probe for a SFP cage attached to this PHY device 1600 1746 * @phydev: Pointer to phy_device 1601 - * @ops: SFP's upstream operations 1602 1747 */ 1603 - int phy_sfp_probe(struct phy_device *phydev, 1604 - const struct sfp_upstream_ops *ops) 1748 + static int phy_sfp_probe(struct phy_device *phydev) 1605 1749 { 1606 1750 struct sfp_bus *bus; 1607 1751 int ret = 0; ··· 1762 1608 1763 1609 phydev->sfp_bus = bus; 1764 1610 1765 - ret = sfp_bus_add_upstream(bus, phydev, ops); 1611 + ret = sfp_bus_add_upstream(bus, phydev, &sfp_phydev_ops); 1766 1612 sfp_bus_put(bus); 1767 1613 } 1614 + 1615 + if (!ret && phydev->sfp_bus) 1616 + ret = phy_setup_sfp_port(phydev); 1617 + 1768 1618 return ret; 1769 1619 } 1770 - EXPORT_SYMBOL(phy_sfp_probe); 1771 1620 1772 1621 static bool phy_drv_supports_irq(const struct phy_driver *phydrv) 1773 1622 { ··· 3482 3325 return 0; 3483 3326 } 3484 3327 3328 + static void phy_cleanup_ports(struct phy_device *phydev) 3329 + { 3330 + struct phy_port *tmp, *port; 3331 + 3332 + list_for_each_entry_safe(port, tmp, &phydev->ports, head) { 3333 + phy_del_port(phydev, port); 3334 + phy_port_destroy(port); 3335 + } 3336 + } 3337 + 3338 + static int phy_default_setup_single_port(struct phy_device *phydev) 3339 + { 3340 + struct phy_port *port = phy_port_alloc(); 3341 + unsigned long mode; 3342 + 3343 + if (!port) 3344 + return -ENOMEM; 3345 + 3346 + port->parent_type = PHY_PORT_PHY; 3347 + port->phy = phydev; 3348 + 3349 + /* Let the PHY driver know that this port was never described anywhere. 3350 + * This is the usual case, where we assume single-port PHY devices with 3351 + * no SFP. In that case, the port supports exactly the same thing as 3352 + * the PHY itself. 3353 + * 3354 + * However, this can also be because we have a combo-port PHY, with 3355 + * only one port described in DT, through SFP for example. 3356 + * 3357 + * In that case, the PHY driver will be in charge of saying what we can 3358 + * do on that non-represented port. 3359 + */ 3360 + port->not_described = true; 3361 + linkmode_copy(port->supported, phydev->supported); 3362 + port->mediums = phy_caps_mediums_from_linkmodes(port->supported); 3363 + 3364 + for_each_set_bit(mode, port->supported, __ETHTOOL_LINK_MODE_MASK_NBITS) 3365 + port->pairs = max_t(int, port->pairs, 3366 + ethtool_linkmode_n_pairs(mode)); 3367 + 3368 + phy_add_port(phydev, port); 3369 + 3370 + return 0; 3371 + } 3372 + 3373 + static int of_phy_ports(struct phy_device *phydev) 3374 + { 3375 + struct device_node *node = phydev->mdio.dev.of_node; 3376 + struct device_node *mdi; 3377 + struct phy_port *port; 3378 + int err; 3379 + 3380 + if (!IS_ENABLED(CONFIG_OF_MDIO)) 3381 + return 0; 3382 + 3383 + if (!node) 3384 + return 0; 3385 + 3386 + mdi = of_get_child_by_name(node, "mdi"); 3387 + if (!mdi) 3388 + return 0; 3389 + 3390 + for_each_available_child_of_node_scoped(mdi, port_node) { 3391 + port = phy_of_parse_port(port_node); 3392 + if (IS_ERR(port)) { 3393 + err = PTR_ERR(port); 3394 + goto out_err; 3395 + } 3396 + 3397 + port->parent_type = PHY_PORT_PHY; 3398 + port->phy = phydev; 3399 + err = phy_add_port(phydev, port); 3400 + if (err) { 3401 + phy_port_destroy(port); 3402 + goto out_err; 3403 + } 3404 + } 3405 + of_node_put(mdi); 3406 + 3407 + return 0; 3408 + 3409 + out_err: 3410 + phy_cleanup_ports(phydev); 3411 + of_node_put(mdi); 3412 + return err; 3413 + } 3414 + 3415 + static int phy_setup_ports(struct phy_device *phydev) 3416 + { 3417 + __ETHTOOL_DECLARE_LINK_MODE_MASK(ports_supported); 3418 + struct phy_port *port; 3419 + int ret; 3420 + 3421 + ret = of_phy_ports(phydev); 3422 + if (ret) 3423 + return ret; 3424 + 3425 + ret = phy_sfp_probe(phydev); 3426 + if (ret) 3427 + goto out; 3428 + 3429 + if (phydev->n_ports < phydev->max_n_ports) { 3430 + ret = phy_default_setup_single_port(phydev); 3431 + if (ret) 3432 + goto out; 3433 + } 3434 + 3435 + linkmode_zero(ports_supported); 3436 + 3437 + /* Aggregate the supported modes, which are made-up of : 3438 + * - What the PHY itself supports 3439 + * - What the sum of all ports support 3440 + */ 3441 + list_for_each_entry(port, &phydev->ports, head) 3442 + if (port->active) 3443 + linkmode_or(ports_supported, ports_supported, 3444 + port->supported); 3445 + 3446 + if (!linkmode_empty(ports_supported)) 3447 + linkmode_and(phydev->supported, phydev->supported, 3448 + ports_supported); 3449 + 3450 + /* For now, the phy->port field is set as the first active port's type */ 3451 + list_for_each_entry(port, &phydev->ports, head) 3452 + if (port->active) { 3453 + phydev->port = phy_port_get_type(port); 3454 + break; 3455 + } 3456 + 3457 + return 0; 3458 + 3459 + out: 3460 + phy_cleanup_ports(phydev); 3461 + return ret; 3462 + } 3463 + 3464 + /** 3465 + * phy_get_sfp_port() - Returns the first valid SFP port of a PHY 3466 + * @phydev: pointer to the PHY device to get the SFP port from 3467 + * 3468 + * Returns: The first active SFP (serdes) port of a PHY device, NULL if none 3469 + * exist. 3470 + */ 3471 + struct phy_port *phy_get_sfp_port(struct phy_device *phydev) 3472 + { 3473 + struct phy_port *port; 3474 + 3475 + list_for_each_entry(port, &phydev->ports, head) 3476 + if (port->active && port->is_sfp) 3477 + return port; 3478 + 3479 + return NULL; 3480 + } 3481 + EXPORT_SYMBOL_GPL(phy_get_sfp_port); 3482 + 3485 3483 /** 3486 3484 * fwnode_mdio_find_device - Given a fwnode, find the mdio_device 3487 3485 * @fwnode: pointer to the mdio_device's fwnode ··· 3774 3462 phydev->is_gigabit_capable = 1; 3775 3463 3776 3464 of_set_phy_supported(phydev); 3465 + 3466 + err = phy_setup_ports(phydev); 3467 + if (err) 3468 + goto out; 3469 + 3777 3470 phy_advertise_supported(phydev); 3778 3471 3779 3472 /* Get PHY default EEE advertising modes and handle them as potentially ··· 3853 3536 phy_leds_unregister(phydev); 3854 3537 3855 3538 phydev->state = PHY_DOWN; 3539 + 3540 + phy_cleanup_ports(phydev); 3856 3541 3857 3542 sfp_bus_del_upstream(phydev->sfp_bus); 3858 3543 phydev->sfp_bus = NULL;
+212
drivers/net/phy/phy_port.c
··· 1 + // SPDX-License-Identifier: GPL-2.0+ 2 + /* Framework to drive Ethernet ports 3 + * 4 + * Copyright (c) 2024 Maxime Chevallier <maxime.chevallier@bootlin.com> 5 + */ 6 + 7 + #include <linux/linkmode.h> 8 + #include <linux/of.h> 9 + #include <linux/phy_port.h> 10 + 11 + #include "phy-caps.h" 12 + 13 + /** 14 + * phy_port_alloc() - Allocate a new phy_port 15 + * 16 + * Returns: a newly allocated struct phy_port, or NULL. 17 + */ 18 + struct phy_port *phy_port_alloc(void) 19 + { 20 + struct phy_port *port; 21 + 22 + port = kzalloc(sizeof(*port), GFP_KERNEL); 23 + if (!port) 24 + return NULL; 25 + 26 + linkmode_zero(port->supported); 27 + INIT_LIST_HEAD(&port->head); 28 + 29 + return port; 30 + } 31 + EXPORT_SYMBOL_GPL(phy_port_alloc); 32 + 33 + /** 34 + * phy_port_destroy() - Free a struct phy_port 35 + * @port: The port to destroy 36 + */ 37 + void phy_port_destroy(struct phy_port *port) 38 + { 39 + kfree(port); 40 + } 41 + EXPORT_SYMBOL_GPL(phy_port_destroy); 42 + 43 + /** 44 + * phy_of_parse_port() - Create a phy_port from a firmware representation 45 + * @dn: device_node representation of the port, following the 46 + * ethernet-connector.yaml binding 47 + * 48 + * Returns: a newly allocated and initialized phy_port pointer, or an ERR_PTR. 49 + */ 50 + struct phy_port *phy_of_parse_port(struct device_node *dn) 51 + { 52 + struct fwnode_handle *fwnode = of_fwnode_handle(dn); 53 + enum ethtool_link_medium medium; 54 + struct phy_port *port; 55 + const char *med_str; 56 + u32 pairs = 0, mediums = 0; 57 + int ret; 58 + 59 + ret = fwnode_property_read_string(fwnode, "media", &med_str); 60 + if (ret) 61 + return ERR_PTR(ret); 62 + 63 + medium = ethtool_str_to_medium(med_str); 64 + if (medium == ETHTOOL_LINK_MEDIUM_NONE) 65 + return ERR_PTR(-EINVAL); 66 + 67 + if (medium == ETHTOOL_LINK_MEDIUM_BASET) { 68 + ret = fwnode_property_read_u32(fwnode, "pairs", &pairs); 69 + if (ret) 70 + return ERR_PTR(ret); 71 + 72 + switch (pairs) { 73 + case 1: /* BaseT1 */ 74 + case 2: /* 100BaseTX */ 75 + case 4: 76 + break; 77 + default: 78 + pr_err("%u is not a valid number of pairs\n", pairs); 79 + return ERR_PTR(-EINVAL); 80 + } 81 + } 82 + 83 + if (pairs && medium != ETHTOOL_LINK_MEDIUM_BASET) { 84 + pr_err("pairs property is only compatible with BaseT medium\n"); 85 + return ERR_PTR(-EINVAL); 86 + } 87 + 88 + mediums |= BIT(medium); 89 + 90 + if (!mediums) 91 + return ERR_PTR(-EINVAL); 92 + 93 + port = phy_port_alloc(); 94 + if (!port) 95 + return ERR_PTR(-ENOMEM); 96 + 97 + port->pairs = pairs; 98 + port->mediums = mediums; 99 + 100 + return port; 101 + } 102 + EXPORT_SYMBOL_GPL(phy_of_parse_port); 103 + 104 + /** 105 + * phy_port_update_supported() - Setup the port->supported field 106 + * @port: the port to update 107 + * 108 + * Once the port's medium list and number of pairs has been configured based 109 + * on firmware, straps and vendor-specific properties, this function may be 110 + * called to update the port's supported linkmodes list. 111 + * 112 + * Any mode that was manually set in the port's supported list remains set. 113 + */ 114 + void phy_port_update_supported(struct phy_port *port) 115 + { 116 + __ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0 }; 117 + unsigned long mode; 118 + int i; 119 + 120 + for_each_set_bit(i, &port->mediums, __ETHTOOL_LINK_MEDIUM_LAST) { 121 + linkmode_zero(supported); 122 + phy_caps_medium_get_supported(supported, i, port->pairs); 123 + linkmode_or(port->supported, port->supported, supported); 124 + } 125 + 126 + /* If there's no pairs specified, we grab the default number of 127 + * pairs as the max of the default pairs for each linkmode 128 + */ 129 + if (!port->pairs) 130 + for_each_set_bit(mode, port->supported, 131 + __ETHTOOL_LINK_MODE_MASK_NBITS) 132 + port->pairs = max_t(int, port->pairs, 133 + ethtool_linkmode_n_pairs(mode)); 134 + 135 + /* Serdes ports supported through SFP may not have any medium set, 136 + * as they will output PHY_INTERFACE_MODE_XXX modes. In that case, derive 137 + * the supported list based on these interfaces 138 + */ 139 + if (port->is_mii && !port->mediums) { 140 + unsigned long interface, link_caps = 0; 141 + 142 + /* Get each interface's caps */ 143 + for_each_set_bit(interface, port->interfaces, 144 + PHY_INTERFACE_MODE_MAX) 145 + link_caps |= phy_caps_from_interface(interface); 146 + 147 + phy_caps_linkmodes(link_caps, port->supported); 148 + } 149 + } 150 + EXPORT_SYMBOL_GPL(phy_port_update_supported); 151 + 152 + /** 153 + * phy_port_filter_supported() - Make sure that port->supported match port->mediums 154 + * @port: The port to filter 155 + * 156 + * After updating a port's mediums to a more restricted subset, this helper will 157 + * make sure that port->supported only contains linkmodes that are compatible 158 + * with port->mediums. 159 + */ 160 + static void phy_port_filter_supported(struct phy_port *port) 161 + { 162 + __ETHTOOL_DECLARE_LINK_MODE_MASK(supported) = { 0 }; 163 + int i; 164 + 165 + for_each_set_bit(i, &port->mediums, __ETHTOOL_LINK_MEDIUM_LAST) 166 + phy_caps_medium_get_supported(supported, i, port->pairs); 167 + 168 + linkmode_and(port->supported, port->supported, supported); 169 + } 170 + 171 + /** 172 + * phy_port_restrict_mediums - Mask away some of the port's supported mediums 173 + * @port: The port to act upon 174 + * @mediums: A mask of mediums to support on the port 175 + * 176 + * This helper allows removing some mediums from a port's list of supported 177 + * mediums, which occurs once we have enough information about the port to 178 + * know its nature. 179 + * 180 + * Returns: 0 if the change was donne correctly, a negative value otherwise. 181 + */ 182 + int phy_port_restrict_mediums(struct phy_port *port, unsigned long mediums) 183 + { 184 + /* We forbid ending-up with a port with empty mediums */ 185 + if (!(port->mediums & mediums)) 186 + return -EINVAL; 187 + 188 + port->mediums &= mediums; 189 + 190 + phy_port_filter_supported(port); 191 + 192 + return 0; 193 + } 194 + EXPORT_SYMBOL_GPL(phy_port_restrict_mediums); 195 + 196 + /** 197 + * phy_port_get_type() - get the PORT_* attribute for that port. 198 + * @port: The port we want the information from 199 + * 200 + * Returns: A PORT_XXX value. 201 + */ 202 + int phy_port_get_type(struct phy_port *port) 203 + { 204 + if (port->mediums & BIT(ETHTOOL_LINK_MEDIUM_BASET)) 205 + return PORT_TP; 206 + 207 + if (phy_port_is_fiber(port)) 208 + return PORT_FIBRE; 209 + 210 + return PORT_OTHER; 211 + } 212 + EXPORT_SYMBOL_GPL(phy_port_get_type);
+33 -46
drivers/net/phy/qcom/at803x.c
··· 20 20 #include <linux/of.h> 21 21 #include <linux/phylink.h> 22 22 #include <linux/reset.h> 23 - #include <linux/sfp.h> 23 + #include <linux/phy_port.h> 24 24 #include <dt-bindings/net/qca-ar803x.h> 25 25 26 26 #include "qcom.h" ··· 769 769 return 0; 770 770 } 771 771 772 - static int at8031_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) 772 + static int at803x_configure_mii(struct phy_port *port, bool enable, 773 + phy_interface_t interface) 773 774 { 774 - __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_support); 775 - __ETHTOOL_DECLARE_LINK_MODE_MASK(sfp_support); 776 - struct phy_device *phydev = upstream; 777 - const struct sfp_module_caps *caps; 778 - phy_interface_t iface; 775 + struct phy_device *phydev = port_phydev(port); 779 776 780 - linkmode_zero(phy_support); 781 - phylink_set(phy_support, 1000baseX_Full); 782 - phylink_set(phy_support, 1000baseT_Full); 783 - phylink_set(phy_support, Autoneg); 784 - phylink_set(phy_support, Pause); 785 - phylink_set(phy_support, Asym_Pause); 786 - 787 - caps = sfp_get_module_caps(phydev->sfp_bus); 788 - /* Some modules support 10G modes as well as others we support. 789 - * Mask out non-supported modes so the correct interface is picked. 790 - */ 791 - linkmode_and(sfp_support, phy_support, caps->link_modes); 792 - 793 - if (linkmode_empty(sfp_support)) { 794 - dev_err(&phydev->mdio.dev, "incompatible SFP module inserted\n"); 795 - return -EINVAL; 796 - } 797 - 798 - iface = sfp_select_interface(phydev->sfp_bus, sfp_support); 799 - 800 - /* Only 1000Base-X is supported by AR8031/8033 as the downstream SerDes 801 - * interface for use with SFP modules. 802 - * However, some copper modules detected as having a preferred SGMII 803 - * interface do default to and function in 1000Base-X mode, so just 804 - * print a warning and allow such modules, as they may have some chance 805 - * of working. 806 - */ 807 - if (iface == PHY_INTERFACE_MODE_SGMII) 808 - dev_warn(&phydev->mdio.dev, "module may not function if 1000Base-X not supported\n"); 809 - else if (iface != PHY_INTERFACE_MODE_1000BASEX) 810 - return -EINVAL; 777 + if (interface == PHY_INTERFACE_MODE_SGMII) 778 + dev_warn(&phydev->mdio.dev, 779 + "module may not function if 1000Base-X not supported\n"); 811 780 812 781 return 0; 813 782 } 814 783 815 - static const struct sfp_upstream_ops at8031_sfp_ops = { 816 - .attach = phy_sfp_attach, 817 - .detach = phy_sfp_detach, 818 - .module_insert = at8031_sfp_insert, 819 - .connect_phy = phy_sfp_connect_phy, 820 - .disconnect_phy = phy_sfp_disconnect_phy, 784 + static const struct phy_port_ops at803x_port_ops = { 785 + .configure_mii = at803x_configure_mii, 821 786 }; 787 + 788 + static int at8031_attach_mii_port(struct phy_device *phydev, 789 + struct phy_port *port) 790 + { 791 + linkmode_zero(port->supported); 792 + phylink_set(port->supported, 1000baseX_Full); 793 + phylink_set(port->supported, 1000baseT_Full); 794 + phylink_set(port->supported, Autoneg); 795 + phylink_set(port->supported, Pause); 796 + phylink_set(port->supported, Asym_Pause); 797 + 798 + /* This device doesn't really support SGMII. However, do our best 799 + * to be compatible with copper modules (that usually require SGMII), 800 + * in a degraded mode as we only allow 1000BaseT Full 801 + */ 802 + __set_bit(PHY_INTERFACE_MODE_SGMII, port->interfaces); 803 + __set_bit(PHY_INTERFACE_MODE_1000BASEX, port->interfaces); 804 + 805 + port->ops = &at803x_port_ops; 806 + 807 + return 0; 808 + } 822 809 823 810 static int at8031_parse_dt(struct phy_device *phydev) 824 811 { ··· 827 840 return ret; 828 841 } 829 842 830 - /* Only AR8031/8033 support 1000Base-X for SFP modules */ 831 - return phy_sfp_probe(phydev, &at8031_sfp_ops); 843 + return 0; 832 844 } 833 845 834 846 static int at8031_probe(struct phy_device *phydev) ··· 1158 1172 .set_tunable = at803x_set_tunable, 1159 1173 .cable_test_start = at8031_cable_test_start, 1160 1174 .cable_test_get_status = at8031_cable_test_get_status, 1175 + .attach_mii_port = at8031_attach_mii_port, 1161 1176 }, { 1162 1177 /* Qualcomm Atheros AR8032 */ 1163 1178 PHY_ID_MATCH_EXACT(ATH8032_PHY_ID),
+33 -45
drivers/net/phy/qcom/qca807x.c
··· 13 13 #include <linux/phy.h> 14 14 #include <linux/bitfield.h> 15 15 #include <linux/gpio/driver.h> 16 - #include <linux/sfp.h> 16 + #include <linux/phy_port.h> 17 17 18 18 #include "../phylib.h" 19 19 #include "qcom.h" ··· 643 643 return ret; 644 644 } 645 645 646 - static int qca807x_sfp_insert(void *upstream, const struct sfp_eeprom_id *id) 646 + static int qca807x_configure_serdes(struct phy_port *port, bool enable, 647 + phy_interface_t interface) 647 648 { 648 - struct phy_device *phydev = upstream; 649 - const struct sfp_module_caps *caps; 650 - phy_interface_t iface; 649 + struct phy_device *phydev = port_phydev(port); 651 650 int ret; 652 651 653 - caps = sfp_get_module_caps(phydev->sfp_bus); 654 - iface = sfp_select_interface(phydev->sfp_bus, caps->link_modes); 652 + if (!phydev) 653 + return -ENODEV; 655 654 656 - dev_info(&phydev->mdio.dev, "%s SFP module inserted\n", phy_modes(iface)); 657 - 658 - switch (iface) { 659 - case PHY_INTERFACE_MODE_1000BASEX: 660 - case PHY_INTERFACE_MODE_100BASEX: 655 + if (enable) { 661 656 /* Set PHY mode to PSGMII combo (1/4 copper + combo ports) mode */ 662 657 ret = phy_modify(phydev, 663 658 QCA807X_CHIP_CONFIGURATION, 664 659 QCA807X_CHIP_CONFIGURATION_MODE_CFG_MASK, 665 660 QCA807X_CHIP_CONFIGURATION_MODE_PSGMII_FIBER); 661 + if (ret) 662 + return ret; 666 663 /* Enable fiber mode autodection (1000Base-X or 100Base-FX) */ 667 664 ret = phy_set_bits_mmd(phydev, 668 665 MDIO_MMD_AN, 669 666 QCA807X_MMD7_FIBER_MODE_AUTO_DETECTION, 670 667 QCA807X_MMD7_FIBER_MODE_AUTO_DETECTION_EN); 671 - /* Select fiber page */ 672 - ret = phy_clear_bits(phydev, 673 - QCA807X_CHIP_CONFIGURATION, 674 - QCA807X_BT_BX_REG_SEL); 675 - 676 - phydev->port = PORT_FIBRE; 677 - break; 678 - default: 679 - dev_err(&phydev->mdio.dev, "Incompatible SFP module inserted\n"); 680 - return -EINVAL; 668 + if (ret) 669 + return ret; 681 670 } 682 671 683 - return ret; 672 + phydev->port = enable ? PORT_FIBRE : PORT_TP; 673 + 674 + return phy_modify(phydev, QCA807X_CHIP_CONFIGURATION, 675 + QCA807X_BT_BX_REG_SEL, 676 + enable ? 0 : QCA807X_BT_BX_REG_SEL); 684 677 } 685 678 686 - static void qca807x_sfp_remove(void *upstream) 687 - { 688 - struct phy_device *phydev = upstream; 689 - 690 - /* Select copper page */ 691 - phy_set_bits(phydev, 692 - QCA807X_CHIP_CONFIGURATION, 693 - QCA807X_BT_BX_REG_SEL); 694 - 695 - phydev->port = PORT_TP; 696 - } 697 - 698 - static const struct sfp_upstream_ops qca807x_sfp_ops = { 699 - .attach = phy_sfp_attach, 700 - .detach = phy_sfp_detach, 701 - .module_insert = qca807x_sfp_insert, 702 - .module_remove = qca807x_sfp_remove, 703 - .connect_phy = phy_sfp_connect_phy, 704 - .disconnect_phy = phy_sfp_disconnect_phy, 679 + static const struct phy_port_ops qca807x_serdes_port_ops = { 680 + .configure_mii = qca807x_configure_serdes, 705 681 }; 682 + 683 + static int qca807x_attach_mii_port(struct phy_device *phydev, 684 + struct phy_port *port) 685 + { 686 + __set_bit(PHY_INTERFACE_MODE_1000BASEX, port->interfaces); 687 + __set_bit(PHY_INTERFACE_MODE_100BASEX, port->interfaces); 688 + 689 + port->ops = &qca807x_serdes_port_ops; 690 + 691 + return 0; 692 + } 706 693 707 694 static int qca807x_probe(struct phy_device *phydev) 708 695 { ··· 731 744 732 745 /* Attach SFP bus on combo port*/ 733 746 if (phy_read(phydev, QCA807X_CHIP_CONFIGURATION)) { 734 - ret = phy_sfp_probe(phydev, &qca807x_sfp_ops); 735 - if (ret) 736 - return ret; 747 + phydev->max_n_ports = 2; 748 + 737 749 linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->supported); 738 750 linkmode_set_bit(ETHTOOL_LINK_MODE_FIBRE_BIT, phydev->advertising); 739 751 } ··· 810 824 .get_phy_stats = qca807x_get_phy_stats, 811 825 .set_wol = at8031_set_wol, 812 826 .get_wol = at803x_get_wol, 827 + .attach_mii_port = qca807x_attach_mii_port, 813 828 }, 814 829 { 815 830 PHY_ID_MATCH_EXACT(PHY_ID_QCA8075), ··· 838 851 .get_phy_stats = qca807x_get_phy_stats, 839 852 .set_wol = at8031_set_wol, 840 853 .get_wol = at803x_get_wol, 854 + .attach_mii_port = qca807x_attach_mii_port, 841 855 }, 842 856 }; 843 857 module_phy_driver(qca807x_drivers);
+33 -3
include/linux/ethtool.h
··· 216 216 void ethtool_rxfh_context_lost(struct net_device *dev, u32 context_id); 217 217 218 218 struct link_mode_info { 219 - int speed; 220 - u8 lanes; 221 - u8 duplex; 219 + int speed; 220 + u8 lanes; 221 + u8 min_pairs; 222 + u8 pairs; 223 + u8 duplex; 224 + u16 mediums; 222 225 }; 223 226 224 227 extern const struct link_mode_info link_mode_params[]; 228 + 229 + enum ethtool_link_medium { 230 + ETHTOOL_LINK_MEDIUM_BASET = 0, 231 + ETHTOOL_LINK_MEDIUM_BASEK, 232 + ETHTOOL_LINK_MEDIUM_BASES, 233 + ETHTOOL_LINK_MEDIUM_BASEC, 234 + ETHTOOL_LINK_MEDIUM_BASEL, 235 + ETHTOOL_LINK_MEDIUM_BASED, 236 + ETHTOOL_LINK_MEDIUM_BASEE, 237 + ETHTOOL_LINK_MEDIUM_BASEF, 238 + ETHTOOL_LINK_MEDIUM_BASEV, 239 + ETHTOOL_LINK_MEDIUM_BASEMLD, 240 + ETHTOOL_LINK_MEDIUM_NONE, 241 + 242 + __ETHTOOL_LINK_MEDIUM_LAST, 243 + }; 244 + 245 + #define ETHTOOL_MEDIUM_FIBER_BITS (BIT(ETHTOOL_LINK_MEDIUM_BASES) | \ 246 + BIT(ETHTOOL_LINK_MEDIUM_BASEL) | \ 247 + BIT(ETHTOOL_LINK_MEDIUM_BASEF)) 248 + 249 + enum ethtool_link_medium ethtool_str_to_medium(const char *str); 250 + 251 + static inline int ethtool_linkmode_n_pairs(unsigned int mode) 252 + { 253 + return link_mode_params[mode].pairs; 254 + } 225 255 226 256 /* declare a link mode bitmap */ 227 257 #define __ETHTOOL_DECLARE_LINK_MODE_MASK(name) \
+57 -6
include/linux/phy.h
··· 327 327 struct device; 328 328 struct kernel_hwtstamp_config; 329 329 struct phylink; 330 + struct phy_port; 330 331 struct sfp_bus; 331 332 struct sfp_upstream_ops; 332 333 struct sk_buff; ··· 646 645 * @master_slave_state: Current master/slave configuration 647 646 * @mii_ts: Pointer to time stamper callbacks 648 647 * @psec: Pointer to Power Sourcing Equipment control struct 648 + * @ports: List of PHY ports structures 649 + * @n_ports: Number of ports currently attached to the PHY 650 + * @max_n_ports: Max number of ports this PHY can expose 649 651 * @lock: Mutex for serialization access to PHY 650 652 * @state_queue: Work queue for state machine 651 653 * @link_down_events: Number of times link was lost ··· 787 783 struct mii_timestamper *mii_ts; 788 784 struct pse_control *psec; 789 785 786 + struct list_head ports; 787 + int n_ports; 788 + int max_n_ports; 789 + 790 790 u8 mdix; 791 791 u8 mdix_ctrl; 792 792 ··· 814 806 #define PHY_F_RXC_ALWAYS_ON 0x40000000 815 807 816 808 #define to_phy_device(__dev) container_of_const(to_mdio_device(__dev), struct phy_device, mdio) 809 + 810 + #define phy_for_each_port(phydev, port) \ 811 + list_for_each_entry(port, &(phydev)->ports, head) 817 812 818 813 /** 819 814 * struct phy_tdr_config - Configuration of a TDR raw test ··· 1518 1507 * Returns the time in jiffies until the next update event. 1519 1508 */ 1520 1509 unsigned int (*get_next_update_time)(struct phy_device *dev); 1510 + 1511 + /** 1512 + * @attach_mii_port: Attach the given MII port to the PHY device 1513 + * @dev: PHY device to notify 1514 + * @port: The port being added 1515 + * 1516 + * Called when an MII port that needs to be driven by the PHY is found. 1517 + * 1518 + * The port that is being passed may or may not be initialized. If it is 1519 + * already initialized, it is by the generic port representation from 1520 + * devicetree, which superseeds any strapping or vendor-specific 1521 + * properties. 1522 + * 1523 + * If the port isn't initialized, the port->mediums and port->lanes 1524 + * fields must be set, possibly according to strapping information. 1525 + * 1526 + * The PHY driver must set the port->interfaces field to indicate the 1527 + * possible MII modes that this PHY can output on the port. 1528 + * 1529 + * Returns 0, or an error code. 1530 + */ 1531 + int (*attach_mii_port)(struct phy_device *dev, struct phy_port *port); 1532 + 1533 + /** 1534 + * @attach_mdi_port: Attach the given MII port to the PHY device 1535 + * @dev: PHY device to notify 1536 + * @port: The port being added 1537 + * 1538 + * Called when a port that needs to be driven by the PHY is found. The 1539 + * number of time this will be called depends on phydev->max_n_ports, 1540 + * which the driver can change in .probe(). 1541 + * 1542 + * The port that is being passed may or may not be initialized. If it is 1543 + * already initialized, it is by the generic port representation from 1544 + * devicetree, which superseeds any strapping or vendor-specific 1545 + * properties. 1546 + * 1547 + * If the port isn't initialized, the port->mediums and port->lanes 1548 + * fields must be set, possibly according to strapping information. 1549 + * 1550 + * Returns 0, or an error code. 1551 + */ 1552 + int (*attach_mdi_port)(struct phy_device *dev, struct phy_port *port); 1521 1553 }; 1522 1554 #define to_phy_driver(d) container_of_const(to_mdio_common_driver(d), \ 1523 1555 struct phy_driver, mdiodrv) ··· 2151 2097 int phy_resume(struct phy_device *phydev); 2152 2098 int __phy_resume(struct phy_device *phydev); 2153 2099 int phy_loopback(struct phy_device *phydev, bool enable, int speed); 2154 - int phy_sfp_connect_phy(void *upstream, struct phy_device *phy); 2155 - void phy_sfp_disconnect_phy(void *upstream, struct phy_device *phy); 2156 - void phy_sfp_attach(void *upstream, struct sfp_bus *bus); 2157 - void phy_sfp_detach(void *upstream, struct sfp_bus *bus); 2158 - int phy_sfp_probe(struct phy_device *phydev, 2159 - const struct sfp_upstream_ops *ops); 2160 2100 struct phy_device *phy_attach(struct net_device *dev, const char *bus_id, 2161 2101 phy_interface_t interface); 2162 2102 struct phy_device *phy_find_next(struct mii_bus *bus, struct phy_device *pos); ··· 2358 2310 void phy_mac_interrupt(struct phy_device *phydev); 2359 2311 void phy_start_machine(struct phy_device *phydev); 2360 2312 void phy_stop_machine(struct phy_device *phydev); 2313 + 2361 2314 void phy_ethtool_ksettings_get(struct phy_device *phydev, 2362 2315 struct ethtool_link_ksettings *cmd); 2363 2316 int phy_ethtool_ksettings_set(struct phy_device *phydev, ··· 2448 2399 int __phy_hwtstamp_set(struct phy_device *phydev, 2449 2400 struct kernel_hwtstamp_config *config, 2450 2401 struct netlink_ext_ack *extack); 2402 + 2403 + struct phy_port *phy_get_sfp_port(struct phy_device *phydev); 2451 2404 2452 2405 extern const struct bus_type mdio_bus_type; 2453 2406 extern const struct class mdio_bus_class;
+99
include/linux/phy_port.h
··· 1 + /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 + 3 + #ifndef __PHY_PORT_H 4 + #define __PHY_PORT_H 5 + 6 + #include <linux/ethtool.h> 7 + #include <linux/types.h> 8 + #include <linux/phy.h> 9 + 10 + struct phy_port; 11 + 12 + /** 13 + * enum phy_port_parent - The device this port is attached to 14 + * 15 + * @PHY_PORT_PHY: Indicates that the port is driven by a PHY device 16 + */ 17 + enum phy_port_parent { 18 + PHY_PORT_PHY, 19 + }; 20 + 21 + struct phy_port_ops { 22 + /* Sometimes, the link state can be retrieved from physical, 23 + * out-of-band channels such as the LOS signal on SFP. These 24 + * callbacks allows notifying the port about state changes 25 + */ 26 + void (*link_up)(struct phy_port *port); 27 + void (*link_down)(struct phy_port *port); 28 + 29 + /* If the port acts as a Media Independent Interface (Serdes port), 30 + * configures the port with the relevant state and mode. When enable is 31 + * not set, interface should be ignored 32 + */ 33 + int (*configure_mii)(struct phy_port *port, bool enable, phy_interface_t interface); 34 + }; 35 + 36 + /** 37 + * struct phy_port - A representation of a network device physical interface 38 + * 39 + * @head: Used by the port's parent to list ports 40 + * @parent_type: The type of device this port is directly connected to 41 + * @phy: If the parent is PHY_PORT_PHYDEV, the PHY controlling that port 42 + * @ops: Callback ops implemented by the port controller 43 + * @pairs: The number of pairs this port has, 0 if not applicable 44 + * @mediums: Bitmask of the physical mediums this port provides access to 45 + * @supported: The link modes this port can expose, if this port is MDI (not MII) 46 + * @interfaces: The MII interfaces this port supports, if this port is MII 47 + * @not_described: Indicates to the parent driver if this port isn't described, 48 + * so it's up to the parent to filter its capabilities. 49 + * @active: Indicates if the port is currently part of the active link. 50 + * @is_mii: Indicates if this port is MII (Media Independent Interface), 51 + * or MDI (Media Dependent Interface). 52 + * @is_sfp: Indicates if this port drives an SFP cage. 53 + */ 54 + struct phy_port { 55 + struct list_head head; 56 + enum phy_port_parent parent_type; 57 + union { 58 + struct phy_device *phy; 59 + }; 60 + 61 + const struct phy_port_ops *ops; 62 + 63 + int pairs; 64 + unsigned long mediums; 65 + __ETHTOOL_DECLARE_LINK_MODE_MASK(supported); 66 + DECLARE_PHY_INTERFACE_MASK(interfaces); 67 + 68 + unsigned int not_described:1; 69 + unsigned int active:1; 70 + unsigned int is_mii:1; 71 + unsigned int is_sfp:1; 72 + }; 73 + 74 + struct phy_port *phy_port_alloc(void); 75 + void phy_port_destroy(struct phy_port *port); 76 + 77 + static inline struct phy_device *port_phydev(struct phy_port *port) 78 + { 79 + return port->phy; 80 + } 81 + 82 + struct phy_port *phy_of_parse_port(struct device_node *dn); 83 + 84 + static inline bool phy_port_is_copper(struct phy_port *port) 85 + { 86 + return port->mediums == BIT(ETHTOOL_LINK_MEDIUM_BASET); 87 + } 88 + 89 + static inline bool phy_port_is_fiber(struct phy_port *port) 90 + { 91 + return !!(port->mediums & ETHTOOL_MEDIUM_FIBER_BITS); 92 + } 93 + 94 + void phy_port_update_supported(struct phy_port *port); 95 + int phy_port_restrict_mediums(struct phy_port *port, unsigned long mediums); 96 + 97 + int phy_port_get_type(struct phy_port *port); 98 + 99 + #endif
+174 -113
net/ethtool/common.c
··· 285 285 #define __LINK_MODE_LANES_DR8_2 8 286 286 #define __LINK_MODE_LANES_T1BRR 1 287 287 288 - #define __DEFINE_LINK_MODE_PARAMS(_speed, _type, _duplex) \ 288 + #define __DEFINE_LINK_MODE_PARAMS_PAIRS(_speed, _type, _min_pairs, _pairs, _duplex, _medium) \ 289 289 [ETHTOOL_LINK_MODE(_speed, _type, _duplex)] = { \ 290 290 .speed = SPEED_ ## _speed, \ 291 291 .lanes = __LINK_MODE_LANES_ ## _type, \ 292 - .duplex = __DUPLEX_ ## _duplex \ 292 + .min_pairs = _min_pairs, \ 293 + .pairs = _pairs, \ 294 + .duplex = __DUPLEX_ ## _duplex, \ 295 + .mediums = BIT(ETHTOOL_LINK_MEDIUM_BASE ## _medium) \ 293 296 } 297 + 298 + #define __DEFINE_LINK_MODE_PARAMS(_speed, _type, _duplex, _medium) \ 299 + [ETHTOOL_LINK_MODE(_speed, _type, _duplex)] = { \ 300 + .speed = SPEED_ ## _speed, \ 301 + .lanes = __LINK_MODE_LANES_ ## _type, \ 302 + .min_pairs = 0, \ 303 + .pairs = 0, \ 304 + .duplex = __DUPLEX_ ## _duplex, \ 305 + .mediums = BIT(ETHTOOL_LINK_MEDIUM_BASE ## _medium) \ 306 + } 307 + #define __DEFINE_LINK_MODE_PARAMS_MEDIUMS(_speed, _type, _duplex, _mediums) \ 308 + [ETHTOOL_LINK_MODE(_speed, _type, _duplex)] = { \ 309 + .speed = SPEED_ ## _speed, \ 310 + .lanes = __LINK_MODE_LANES_ ## _type, \ 311 + .min_pairs = 0, \ 312 + .pairs = 0, \ 313 + .duplex = __DUPLEX_ ## _duplex, \ 314 + .mediums = (_mediums) \ 315 + } 316 + #define __MED(_medium) (BIT(ETHTOOL_LINK_MEDIUM_BASE ## _medium)) 294 317 #define __DUPLEX_Half DUPLEX_HALF 295 318 #define __DUPLEX_Full DUPLEX_FULL 296 319 #define __DEFINE_SPECIAL_MODE_PARAMS(_mode) \ ··· 321 298 .speed = SPEED_UNKNOWN, \ 322 299 .lanes = 0, \ 323 300 .duplex = DUPLEX_UNKNOWN, \ 301 + .mediums = BIT(ETHTOOL_LINK_MEDIUM_NONE), \ 324 302 } 325 303 326 304 const struct link_mode_info link_mode_params[] = { 327 - __DEFINE_LINK_MODE_PARAMS(10, T, Half), 328 - __DEFINE_LINK_MODE_PARAMS(10, T, Full), 329 - __DEFINE_LINK_MODE_PARAMS(100, T, Half), 330 - __DEFINE_LINK_MODE_PARAMS(100, T, Full), 331 - __DEFINE_LINK_MODE_PARAMS(1000, T, Half), 332 - __DEFINE_LINK_MODE_PARAMS(1000, T, Full), 305 + __DEFINE_LINK_MODE_PARAMS_PAIRS(10, T, 2, 4, Half, T), 306 + __DEFINE_LINK_MODE_PARAMS_PAIRS(10, T, 2, 4, Full, T), 307 + __DEFINE_LINK_MODE_PARAMS_PAIRS(100, T, 2, 4, Half, T), 308 + __DEFINE_LINK_MODE_PARAMS_PAIRS(100, T, 2, 4, Full, T), 309 + __DEFINE_LINK_MODE_PARAMS_PAIRS(1000, T, 4, 4, Half, T), 310 + __DEFINE_LINK_MODE_PARAMS_PAIRS(1000, T, 4, 4, Full, T), 333 311 __DEFINE_SPECIAL_MODE_PARAMS(Autoneg), 334 312 __DEFINE_SPECIAL_MODE_PARAMS(TP), 335 313 __DEFINE_SPECIAL_MODE_PARAMS(AUI), 336 314 __DEFINE_SPECIAL_MODE_PARAMS(MII), 337 315 __DEFINE_SPECIAL_MODE_PARAMS(FIBRE), 338 316 __DEFINE_SPECIAL_MODE_PARAMS(BNC), 339 - __DEFINE_LINK_MODE_PARAMS(10000, T, Full), 317 + __DEFINE_LINK_MODE_PARAMS_PAIRS(10000, T, 4, 4, Full, T), 340 318 __DEFINE_SPECIAL_MODE_PARAMS(Pause), 341 319 __DEFINE_SPECIAL_MODE_PARAMS(Asym_Pause), 342 - __DEFINE_LINK_MODE_PARAMS(2500, X, Full), 320 + __DEFINE_LINK_MODE_PARAMS_MEDIUMS(2500, X, Full, 321 + __MED(C) | __MED(S) | __MED(L)), 343 322 __DEFINE_SPECIAL_MODE_PARAMS(Backplane), 344 - __DEFINE_LINK_MODE_PARAMS(1000, KX, Full), 345 - __DEFINE_LINK_MODE_PARAMS(10000, KX4, Full), 346 - __DEFINE_LINK_MODE_PARAMS(10000, KR, Full), 323 + __DEFINE_LINK_MODE_PARAMS(1000, KX, Full, K), 324 + __DEFINE_LINK_MODE_PARAMS(10000, KX4, Full, K), 325 + __DEFINE_LINK_MODE_PARAMS(10000, KR, Full, K), 347 326 [ETHTOOL_LINK_MODE_10000baseR_FEC_BIT] = { 348 327 .speed = SPEED_10000, 349 328 .lanes = 1, 350 329 .duplex = DUPLEX_FULL, 351 330 }, 352 - __DEFINE_LINK_MODE_PARAMS(20000, MLD2, Full), 353 - __DEFINE_LINK_MODE_PARAMS(20000, KR2, Full), 354 - __DEFINE_LINK_MODE_PARAMS(40000, KR4, Full), 355 - __DEFINE_LINK_MODE_PARAMS(40000, CR4, Full), 356 - __DEFINE_LINK_MODE_PARAMS(40000, SR4, Full), 357 - __DEFINE_LINK_MODE_PARAMS(40000, LR4, Full), 358 - __DEFINE_LINK_MODE_PARAMS(56000, KR4, Full), 359 - __DEFINE_LINK_MODE_PARAMS(56000, CR4, Full), 360 - __DEFINE_LINK_MODE_PARAMS(56000, SR4, Full), 361 - __DEFINE_LINK_MODE_PARAMS(56000, LR4, Full), 362 - __DEFINE_LINK_MODE_PARAMS(25000, CR, Full), 363 - __DEFINE_LINK_MODE_PARAMS(25000, KR, Full), 364 - __DEFINE_LINK_MODE_PARAMS(25000, SR, Full), 365 - __DEFINE_LINK_MODE_PARAMS(50000, CR2, Full), 366 - __DEFINE_LINK_MODE_PARAMS(50000, KR2, Full), 367 - __DEFINE_LINK_MODE_PARAMS(100000, KR4, Full), 368 - __DEFINE_LINK_MODE_PARAMS(100000, SR4, Full), 369 - __DEFINE_LINK_MODE_PARAMS(100000, CR4, Full), 370 - __DEFINE_LINK_MODE_PARAMS(100000, LR4_ER4, Full), 371 - __DEFINE_LINK_MODE_PARAMS(50000, SR2, Full), 372 - __DEFINE_LINK_MODE_PARAMS(1000, X, Full), 373 - __DEFINE_LINK_MODE_PARAMS(10000, CR, Full), 374 - __DEFINE_LINK_MODE_PARAMS(10000, SR, Full), 375 - __DEFINE_LINK_MODE_PARAMS(10000, LR, Full), 376 - __DEFINE_LINK_MODE_PARAMS(10000, LRM, Full), 377 - __DEFINE_LINK_MODE_PARAMS(10000, ER, Full), 378 - __DEFINE_LINK_MODE_PARAMS(2500, T, Full), 379 - __DEFINE_LINK_MODE_PARAMS(5000, T, Full), 331 + __DEFINE_LINK_MODE_PARAMS(20000, MLD2, Full, MLD), 332 + __DEFINE_LINK_MODE_PARAMS(20000, KR2, Full, K), 333 + __DEFINE_LINK_MODE_PARAMS(40000, KR4, Full, K), 334 + __DEFINE_LINK_MODE_PARAMS(40000, CR4, Full, C), 335 + __DEFINE_LINK_MODE_PARAMS(40000, SR4, Full, S), 336 + __DEFINE_LINK_MODE_PARAMS(40000, LR4, Full, L), 337 + __DEFINE_LINK_MODE_PARAMS(56000, KR4, Full, K), 338 + __DEFINE_LINK_MODE_PARAMS(56000, CR4, Full, C), 339 + __DEFINE_LINK_MODE_PARAMS(56000, SR4, Full, S), 340 + __DEFINE_LINK_MODE_PARAMS(56000, LR4, Full, L), 341 + __DEFINE_LINK_MODE_PARAMS(25000, CR, Full, C), 342 + __DEFINE_LINK_MODE_PARAMS(25000, KR, Full, K), 343 + __DEFINE_LINK_MODE_PARAMS(25000, SR, Full, S), 344 + __DEFINE_LINK_MODE_PARAMS(50000, CR2, Full, C), 345 + __DEFINE_LINK_MODE_PARAMS(50000, KR2, Full, K), 346 + __DEFINE_LINK_MODE_PARAMS(100000, KR4, Full, K), 347 + __DEFINE_LINK_MODE_PARAMS(100000, SR4, Full, S), 348 + __DEFINE_LINK_MODE_PARAMS(100000, CR4, Full, C), 349 + __DEFINE_LINK_MODE_PARAMS_MEDIUMS(100000, LR4_ER4, Full, 350 + __MED(L) | __MED(E)), 351 + __DEFINE_LINK_MODE_PARAMS(50000, SR2, Full, S), 352 + __DEFINE_LINK_MODE_PARAMS_MEDIUMS(1000, X, Full, 353 + __MED(C) | __MED(S) | __MED(L)), 354 + __DEFINE_LINK_MODE_PARAMS(10000, CR, Full, C), 355 + __DEFINE_LINK_MODE_PARAMS(10000, SR, Full, S), 356 + __DEFINE_LINK_MODE_PARAMS(10000, LR, Full, L), 357 + __DEFINE_LINK_MODE_PARAMS(10000, LRM, Full, L), 358 + __DEFINE_LINK_MODE_PARAMS(10000, ER, Full, E), 359 + __DEFINE_LINK_MODE_PARAMS_PAIRS(2500, T, 4, 4, Full, T), 360 + __DEFINE_LINK_MODE_PARAMS_PAIRS(5000, T, 4, 4, Full, T), 380 361 __DEFINE_SPECIAL_MODE_PARAMS(FEC_NONE), 381 362 __DEFINE_SPECIAL_MODE_PARAMS(FEC_RS), 382 363 __DEFINE_SPECIAL_MODE_PARAMS(FEC_BASER), 383 - __DEFINE_LINK_MODE_PARAMS(50000, KR, Full), 384 - __DEFINE_LINK_MODE_PARAMS(50000, SR, Full), 385 - __DEFINE_LINK_MODE_PARAMS(50000, CR, Full), 386 - __DEFINE_LINK_MODE_PARAMS(50000, LR_ER_FR, Full), 387 - __DEFINE_LINK_MODE_PARAMS(50000, DR, Full), 388 - __DEFINE_LINK_MODE_PARAMS(100000, KR2, Full), 389 - __DEFINE_LINK_MODE_PARAMS(100000, SR2, Full), 390 - __DEFINE_LINK_MODE_PARAMS(100000, CR2, Full), 391 - __DEFINE_LINK_MODE_PARAMS(100000, LR2_ER2_FR2, Full), 392 - __DEFINE_LINK_MODE_PARAMS(100000, DR2, Full), 393 - __DEFINE_LINK_MODE_PARAMS(200000, KR4, Full), 394 - __DEFINE_LINK_MODE_PARAMS(200000, SR4, Full), 395 - __DEFINE_LINK_MODE_PARAMS(200000, LR4_ER4_FR4, Full), 396 - __DEFINE_LINK_MODE_PARAMS(200000, DR4, Full), 397 - __DEFINE_LINK_MODE_PARAMS(200000, CR4, Full), 398 - __DEFINE_LINK_MODE_PARAMS(100, T1, Full), 399 - __DEFINE_LINK_MODE_PARAMS(1000, T1, Full), 400 - __DEFINE_LINK_MODE_PARAMS(400000, KR8, Full), 401 - __DEFINE_LINK_MODE_PARAMS(400000, SR8, Full), 402 - __DEFINE_LINK_MODE_PARAMS(400000, LR8_ER8_FR8, Full), 403 - __DEFINE_LINK_MODE_PARAMS(400000, DR8, Full), 404 - __DEFINE_LINK_MODE_PARAMS(400000, CR8, Full), 364 + __DEFINE_LINK_MODE_PARAMS(50000, KR, Full, K), 365 + __DEFINE_LINK_MODE_PARAMS(50000, SR, Full, S), 366 + __DEFINE_LINK_MODE_PARAMS(50000, CR, Full, C), 367 + __DEFINE_LINK_MODE_PARAMS_MEDIUMS(50000, LR_ER_FR, Full, 368 + __MED(L) | __MED(E) | __MED(F)), 369 + __DEFINE_LINK_MODE_PARAMS(50000, DR, Full, D), 370 + __DEFINE_LINK_MODE_PARAMS(100000, KR2, Full, K), 371 + __DEFINE_LINK_MODE_PARAMS(100000, SR2, Full, S), 372 + __DEFINE_LINK_MODE_PARAMS(100000, CR2, Full, C), 373 + __DEFINE_LINK_MODE_PARAMS_MEDIUMS(100000, LR2_ER2_FR2, Full, 374 + __MED(L) | __MED(E) | __MED(F)), 375 + __DEFINE_LINK_MODE_PARAMS(100000, DR2, Full, D), 376 + __DEFINE_LINK_MODE_PARAMS(200000, KR4, Full, K), 377 + __DEFINE_LINK_MODE_PARAMS(200000, SR4, Full, S), 378 + __DEFINE_LINK_MODE_PARAMS_MEDIUMS(200000, LR4_ER4_FR4, Full, 379 + __MED(L) | __MED(E) | __MED(F)), 380 + __DEFINE_LINK_MODE_PARAMS(200000, DR4, Full, D), 381 + __DEFINE_LINK_MODE_PARAMS(200000, CR4, Full, C), 382 + __DEFINE_LINK_MODE_PARAMS_PAIRS(100, T1, 1, 1, Full, T), 383 + __DEFINE_LINK_MODE_PARAMS_PAIRS(1000, T1, 1, 1, Full, T), 384 + __DEFINE_LINK_MODE_PARAMS(400000, KR8, Full, K), 385 + __DEFINE_LINK_MODE_PARAMS(400000, SR8, Full, S), 386 + __DEFINE_LINK_MODE_PARAMS_MEDIUMS(400000, LR8_ER8_FR8, Full, 387 + __MED(L) | __MED(E) | __MED(F)), 388 + __DEFINE_LINK_MODE_PARAMS(400000, DR8, Full, D), 389 + __DEFINE_LINK_MODE_PARAMS(400000, CR8, Full, C), 405 390 __DEFINE_SPECIAL_MODE_PARAMS(FEC_LLRS), 406 - __DEFINE_LINK_MODE_PARAMS(100000, KR, Full), 407 - __DEFINE_LINK_MODE_PARAMS(100000, SR, Full), 408 - __DEFINE_LINK_MODE_PARAMS(100000, LR_ER_FR, Full), 409 - __DEFINE_LINK_MODE_PARAMS(100000, DR, Full), 410 - __DEFINE_LINK_MODE_PARAMS(100000, CR, Full), 411 - __DEFINE_LINK_MODE_PARAMS(200000, KR2, Full), 412 - __DEFINE_LINK_MODE_PARAMS(200000, SR2, Full), 413 - __DEFINE_LINK_MODE_PARAMS(200000, LR2_ER2_FR2, Full), 414 - __DEFINE_LINK_MODE_PARAMS(200000, DR2, Full), 415 - __DEFINE_LINK_MODE_PARAMS(200000, CR2, Full), 416 - __DEFINE_LINK_MODE_PARAMS(400000, KR4, Full), 417 - __DEFINE_LINK_MODE_PARAMS(400000, SR4, Full), 418 - __DEFINE_LINK_MODE_PARAMS(400000, LR4_ER4_FR4, Full), 419 - __DEFINE_LINK_MODE_PARAMS(400000, DR4, Full), 420 - __DEFINE_LINK_MODE_PARAMS(400000, CR4, Full), 421 - __DEFINE_LINK_MODE_PARAMS(100, FX, Half), 422 - __DEFINE_LINK_MODE_PARAMS(100, FX, Full), 423 - __DEFINE_LINK_MODE_PARAMS(10, T1L, Full), 424 - __DEFINE_LINK_MODE_PARAMS(800000, CR8, Full), 425 - __DEFINE_LINK_MODE_PARAMS(800000, KR8, Full), 426 - __DEFINE_LINK_MODE_PARAMS(800000, DR8, Full), 427 - __DEFINE_LINK_MODE_PARAMS(800000, DR8_2, Full), 428 - __DEFINE_LINK_MODE_PARAMS(800000, SR8, Full), 429 - __DEFINE_LINK_MODE_PARAMS(800000, VR8, Full), 430 - __DEFINE_LINK_MODE_PARAMS(10, T1S, Full), 431 - __DEFINE_LINK_MODE_PARAMS(10, T1S, Half), 432 - __DEFINE_LINK_MODE_PARAMS(10, T1S_P2MP, Half), 433 - __DEFINE_LINK_MODE_PARAMS(10, T1BRR, Full), 434 - __DEFINE_LINK_MODE_PARAMS(200000, CR, Full), 435 - __DEFINE_LINK_MODE_PARAMS(200000, KR, Full), 436 - __DEFINE_LINK_MODE_PARAMS(200000, DR, Full), 437 - __DEFINE_LINK_MODE_PARAMS(200000, DR_2, Full), 438 - __DEFINE_LINK_MODE_PARAMS(200000, SR, Full), 439 - __DEFINE_LINK_MODE_PARAMS(200000, VR, Full), 440 - __DEFINE_LINK_MODE_PARAMS(400000, CR2, Full), 441 - __DEFINE_LINK_MODE_PARAMS(400000, KR2, Full), 442 - __DEFINE_LINK_MODE_PARAMS(400000, DR2, Full), 443 - __DEFINE_LINK_MODE_PARAMS(400000, DR2_2, Full), 444 - __DEFINE_LINK_MODE_PARAMS(400000, SR2, Full), 445 - __DEFINE_LINK_MODE_PARAMS(400000, VR2, Full), 446 - __DEFINE_LINK_MODE_PARAMS(800000, CR4, Full), 447 - __DEFINE_LINK_MODE_PARAMS(800000, KR4, Full), 448 - __DEFINE_LINK_MODE_PARAMS(800000, DR4, Full), 449 - __DEFINE_LINK_MODE_PARAMS(800000, DR4_2, Full), 450 - __DEFINE_LINK_MODE_PARAMS(800000, SR4, Full), 451 - __DEFINE_LINK_MODE_PARAMS(800000, VR4, Full), 452 - __DEFINE_LINK_MODE_PARAMS(1600000, CR8, Full), 453 - __DEFINE_LINK_MODE_PARAMS(1600000, KR8, Full), 454 - __DEFINE_LINK_MODE_PARAMS(1600000, DR8, Full), 455 - __DEFINE_LINK_MODE_PARAMS(1600000, DR8_2, Full), 391 + __DEFINE_LINK_MODE_PARAMS(100000, KR, Full, K), 392 + __DEFINE_LINK_MODE_PARAMS(100000, SR, Full, S), 393 + __DEFINE_LINK_MODE_PARAMS_MEDIUMS(100000, LR_ER_FR, Full, 394 + __MED(L) | __MED(E) | __MED(F)), 395 + __DEFINE_LINK_MODE_PARAMS(100000, DR, Full, D), 396 + __DEFINE_LINK_MODE_PARAMS(100000, CR, Full, C), 397 + __DEFINE_LINK_MODE_PARAMS(200000, KR2, Full, K), 398 + __DEFINE_LINK_MODE_PARAMS(200000, SR2, Full, S), 399 + __DEFINE_LINK_MODE_PARAMS_MEDIUMS(200000, LR2_ER2_FR2, Full, 400 + __MED(L) | __MED(E) | __MED(F)), 401 + __DEFINE_LINK_MODE_PARAMS(200000, DR2, Full, D), 402 + __DEFINE_LINK_MODE_PARAMS(200000, CR2, Full, C), 403 + __DEFINE_LINK_MODE_PARAMS(400000, KR4, Full, K), 404 + __DEFINE_LINK_MODE_PARAMS(400000, SR4, Full, S), 405 + __DEFINE_LINK_MODE_PARAMS_MEDIUMS(400000, LR4_ER4_FR4, Full, 406 + __MED(L) | __MED(E) | __MED(F)), 407 + __DEFINE_LINK_MODE_PARAMS(400000, DR4, Full, D), 408 + __DEFINE_LINK_MODE_PARAMS(400000, CR4, Full, C), 409 + __DEFINE_LINK_MODE_PARAMS(100, FX, Half, F), 410 + __DEFINE_LINK_MODE_PARAMS(100, FX, Full, F), 411 + __DEFINE_LINK_MODE_PARAMS_PAIRS(10, T1L, 1, 1, Full, T), 412 + __DEFINE_LINK_MODE_PARAMS(800000, CR8, Full, C), 413 + __DEFINE_LINK_MODE_PARAMS(800000, KR8, Full, K), 414 + __DEFINE_LINK_MODE_PARAMS(800000, DR8, Full, D), 415 + __DEFINE_LINK_MODE_PARAMS(800000, DR8_2, Full, D), 416 + __DEFINE_LINK_MODE_PARAMS(800000, SR8, Full, S), 417 + __DEFINE_LINK_MODE_PARAMS(800000, VR8, Full, V), 418 + __DEFINE_LINK_MODE_PARAMS_PAIRS(10, T1S, 1, 1, Full, T), 419 + __DEFINE_LINK_MODE_PARAMS_PAIRS(10, T1S, 1, 1, Half, T), 420 + __DEFINE_LINK_MODE_PARAMS_PAIRS(10, T1S_P2MP, 1, 1, Half, T), 421 + __DEFINE_LINK_MODE_PARAMS_PAIRS(10, T1BRR, 1, 1, Full, T), 422 + __DEFINE_LINK_MODE_PARAMS(200000, CR, Full, C), 423 + __DEFINE_LINK_MODE_PARAMS(200000, KR, Full, K), 424 + __DEFINE_LINK_MODE_PARAMS(200000, DR, Full, D), 425 + __DEFINE_LINK_MODE_PARAMS(200000, DR_2, Full, D), 426 + __DEFINE_LINK_MODE_PARAMS(200000, SR, Full, S), 427 + __DEFINE_LINK_MODE_PARAMS(200000, VR, Full, V), 428 + __DEFINE_LINK_MODE_PARAMS(400000, CR2, Full, C), 429 + __DEFINE_LINK_MODE_PARAMS(400000, KR2, Full, K), 430 + __DEFINE_LINK_MODE_PARAMS(400000, DR2, Full, D), 431 + __DEFINE_LINK_MODE_PARAMS(400000, DR2_2, Full, D), 432 + __DEFINE_LINK_MODE_PARAMS(400000, SR2, Full, S), 433 + __DEFINE_LINK_MODE_PARAMS(400000, VR2, Full, V), 434 + __DEFINE_LINK_MODE_PARAMS(800000, CR4, Full, C), 435 + __DEFINE_LINK_MODE_PARAMS(800000, KR4, Full, K), 436 + __DEFINE_LINK_MODE_PARAMS(800000, DR4, Full, D), 437 + __DEFINE_LINK_MODE_PARAMS(800000, DR4_2, Full, D), 438 + __DEFINE_LINK_MODE_PARAMS(800000, SR4, Full, S), 439 + __DEFINE_LINK_MODE_PARAMS(800000, VR4, Full, V), 440 + __DEFINE_LINK_MODE_PARAMS(1600000, CR8, Full, C), 441 + __DEFINE_LINK_MODE_PARAMS(1600000, KR8, Full, K), 442 + __DEFINE_LINK_MODE_PARAMS(1600000, DR8, Full, D), 443 + __DEFINE_LINK_MODE_PARAMS(1600000, DR8_2, Full, D), 456 444 }; 457 445 static_assert(ARRAY_SIZE(link_mode_params) == __ETHTOOL_LINK_MODE_MASK_NBITS); 458 446 EXPORT_SYMBOL_GPL(link_mode_params); 447 + 448 + static const char ethtool_link_medium_names[][ETH_GSTRING_LEN] = { 449 + [ETHTOOL_LINK_MEDIUM_BASET] = "BaseT", 450 + [ETHTOOL_LINK_MEDIUM_BASEK] = "BaseK", 451 + [ETHTOOL_LINK_MEDIUM_BASES] = "BaseS", 452 + [ETHTOOL_LINK_MEDIUM_BASEC] = "BaseC", 453 + [ETHTOOL_LINK_MEDIUM_BASEL] = "BaseL", 454 + [ETHTOOL_LINK_MEDIUM_BASED] = "BaseD", 455 + [ETHTOOL_LINK_MEDIUM_BASEE] = "BaseE", 456 + [ETHTOOL_LINK_MEDIUM_BASEF] = "BaseF", 457 + [ETHTOOL_LINK_MEDIUM_BASEV] = "BaseV", 458 + [ETHTOOL_LINK_MEDIUM_BASEMLD] = "BaseMLD", 459 + [ETHTOOL_LINK_MEDIUM_NONE] = "None", 460 + }; 461 + static_assert(ARRAY_SIZE(ethtool_link_medium_names) == __ETHTOOL_LINK_MEDIUM_LAST); 459 462 460 463 const char netif_msg_class_names[][ETH_GSTRING_LEN] = { 461 464 [NETIF_MSG_DRV_BIT] = "drv", ··· 1216 1167 ethtool_rss_notify(dev, ETHTOOL_MSG_RSS_DELETE_NTF, context_id); 1217 1168 } 1218 1169 EXPORT_SYMBOL(ethtool_rxfh_context_lost); 1170 + 1171 + enum ethtool_link_medium ethtool_str_to_medium(const char *str) 1172 + { 1173 + int i; 1174 + 1175 + for (i = 0; i < __ETHTOOL_LINK_MEDIUM_LAST; i++) 1176 + if (!strcmp(ethtool_link_medium_names[i], str)) 1177 + return i; 1178 + 1179 + return ETHTOOL_LINK_MEDIUM_NONE; 1180 + } 1181 + EXPORT_SYMBOL_GPL(ethtool_str_to_medium);