diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c index f9cacdfb516e..3fc3a30fe7ed 100644 --- a/drivers/net/phy/phy_device.c +++ b/drivers/net/phy/phy_device.c @@ -1643,6 +1643,32 @@ static void phy_del_port(struct phy_device *phydev, struct phy_port *port) phydev->n_ports--; } +static int phy_setup_sfp_port(struct phy_device *phydev) +{ + struct phy_port *port = phy_port_alloc(); + int ret; + + if (!port) + return -ENOMEM; + + port->parent_type = PHY_PORT_PHY; + port->phy = phydev; + + /* The PHY is a media converter, the port connected to the SFP cage + * is a MII port. + */ + port->is_mii = true; + + /* The port->supported and port->interfaces list will be populated + * when attaching the port to the phydev. + */ + ret = phy_add_port(phydev, port); + if (ret) + phy_port_destroy(port); + + return ret; +} + /** * phy_sfp_probe - probe for a SFP cage attached to this PHY device * @phydev: Pointer to phy_device @@ -1664,6 +1690,10 @@ int phy_sfp_probe(struct phy_device *phydev, ret = sfp_bus_add_upstream(bus, phydev, ops); sfp_bus_put(bus); } + + if (!ret && phydev->sfp_bus) + ret = phy_setup_sfp_port(phydev); + return ret; } EXPORT_SYMBOL(phy_sfp_probe); diff --git a/drivers/net/phy/phy_port.c b/drivers/net/phy/phy_port.c index 70b3ecb8fb09..81e557aae0d6 100644 --- a/drivers/net/phy/phy_port.c +++ b/drivers/net/phy/phy_port.c @@ -131,6 +131,21 @@ void phy_port_update_supported(struct phy_port *port) __ETHTOOL_LINK_MODE_MASK_NBITS) port->pairs = max_t(int, port->pairs, ethtool_linkmode_n_pairs(mode)); + + /* Serdes ports supported through SFP may not have any medium set, + * as they will output PHY_INTERFACE_MODE_XXX modes. In that case, derive + * the supported list based on these interfaces + */ + if (port->is_mii && !port->mediums) { + unsigned long interface, link_caps = 0; + + /* Get each interface's caps */ + for_each_set_bit(interface, port->interfaces, + PHY_INTERFACE_MODE_MAX) + link_caps |= phy_caps_from_interface(interface); + + phy_caps_linkmodes(link_caps, port->supported); + } } EXPORT_SYMBOL_GPL(phy_port_update_supported);