Some copper SFP modules support both SGMII and 1000BaseX, but some drivers/devices only support the 1000BaseX mode. Currently SGMII mode is always being selected as the desired mode for such modules, and this fails if the controller doesn't support SGMII. Add a fallback for this case by trying 1000BaseX instead if the controller rejects SGMII mode.
Signed-off-by: Robert Hancock <hanc...@sedsystems.ca> --- drivers/net/phy/phylink.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c index 68d0a89..4fd72c2 100644 --- a/drivers/net/phy/phylink.c +++ b/drivers/net/phy/phylink.c @@ -1626,6 +1626,7 @@ static int phylink_sfp_module_insert(void *upstream, { struct phylink *pl = upstream; __ETHTOOL_DECLARE_LINK_MODE_MASK(support) = { 0, }; + __ETHTOOL_DECLARE_LINK_MODE_MASK(orig_support) = { 0, }; struct phylink_link_state config; phy_interface_t iface; int ret = 0; @@ -1635,6 +1636,7 @@ static int phylink_sfp_module_insert(void *upstream, ASSERT_RTNL(); sfp_parse_support(pl->sfp_bus, id, support); + linkmode_copy(orig_support, support); port = sfp_parse_port(pl->sfp_bus, id, support); memset(&config, 0, sizeof(config)); @@ -1663,6 +1665,25 @@ static int phylink_sfp_module_insert(void *upstream, config.interface = iface; ret = phylink_validate(pl, support, &config); + + if (ret && iface == PHY_INTERFACE_MODE_SGMII && + phylink_test(orig_support, 1000baseX_Full)) { + /* Copper modules may select SGMII but the interface may not + * support that mode, try 1000BaseX if supported. + */ + + netdev_warn(pl->netdev, "validation of %s/%s with support %*pb " + "failed: %d, trying 1000BaseX\n", + phylink_an_mode_str(MLO_AN_INBAND), + phy_modes(config.interface), + __ETHTOOL_LINK_MODE_MASK_NBITS, orig_support, ret); + iface = PHY_INTERFACE_MODE_1000BASEX; + config.interface = iface; + linkmode_copy(config.advertising, orig_support); + linkmode_copy(support, orig_support); + ret = phylink_validate(pl, support, &config); + } + if (ret) { phylink_err(pl, "validation of %s/%s with support %*pb failed: %d\n", phylink_an_mode_str(MLO_AN_INBAND), -- 1.8.3.1