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.

net: phy: Create a phy_port for PHY-driven SFPs

Some PHY devices may be used as media-converters to drive SFP ports (for
example, to allow using SFP when the SoC can only output RGMII). This is
already supported to some extend by allowing PHY drivers to registers
themselves as being SFP upstream.

However, the logic to drive the SFP can actually be split to a per-port
control logic, allowing support for multi-port PHYs, or PHYs that can
either drive SFPs or Copper.

To that extent, create a phy_port when registering an SFP bus onto a
PHY. This port is considered a "serdes" port, in that it can feed data
to another entity on the link. The PHY driver needs to specify the
various PHY_INTERFACE_MODE_XXX that this port supports.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Tested-by: Christophe Leroy <christophe.leroy@csgroup.eu>
Signed-off-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Link: https://patch.msgid.link/20260108080041.553250-7-maxime.chevallier@bootlin.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Maxime Chevallier and committed by
Jakub Kicinski
07f3ca9e ffb85873

+45
+30
drivers/net/phy/phy_device.c
··· 1643 1643 phydev->n_ports--; 1644 1644 } 1645 1645 1646 + static int phy_setup_sfp_port(struct phy_device *phydev) 1647 + { 1648 + struct phy_port *port = phy_port_alloc(); 1649 + int ret; 1650 + 1651 + if (!port) 1652 + return -ENOMEM; 1653 + 1654 + port->parent_type = PHY_PORT_PHY; 1655 + port->phy = phydev; 1656 + 1657 + /* The PHY is a media converter, the port connected to the SFP cage 1658 + * is a MII port. 1659 + */ 1660 + port->is_mii = true; 1661 + 1662 + /* The port->supported and port->interfaces list will be populated 1663 + * when attaching the port to the phydev. 1664 + */ 1665 + ret = phy_add_port(phydev, port); 1666 + if (ret) 1667 + phy_port_destroy(port); 1668 + 1669 + return ret; 1670 + } 1671 + 1646 1672 /** 1647 1673 * phy_sfp_probe - probe for a SFP cage attached to this PHY device 1648 1674 * @phydev: Pointer to phy_device ··· 1690 1664 ret = sfp_bus_add_upstream(bus, phydev, ops); 1691 1665 sfp_bus_put(bus); 1692 1666 } 1667 + 1668 + if (!ret && phydev->sfp_bus) 1669 + ret = phy_setup_sfp_port(phydev); 1670 + 1693 1671 return ret; 1694 1672 } 1695 1673 EXPORT_SYMBOL(phy_sfp_probe);
+15
drivers/net/phy/phy_port.c
··· 131 131 __ETHTOOL_LINK_MODE_MASK_NBITS) 132 132 port->pairs = max_t(int, port->pairs, 133 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 + } 134 149 } 135 150 EXPORT_SYMBOL_GPL(phy_port_update_supported); 136 151