summaryrefslogtreecommitdiff
path: root/drivers/net
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@armlinux.org.uk>2020-03-03 12:12:43 +0000
committerRussell King (Oracle) <rmk+kernel@armlinux.org.uk>2021-06-29 14:23:09 +0100
commitc3c185de8c898a76f43fd75fad93f2453742e950 (patch)
tree5976b195c52bb25388346ed18642b2562d8da538 /drivers/net
parentef3991b0a60fbfdc19d1f9cf7f2151989d318fe1 (diff)
net: phylink: use phy interface mode bitmaps for optical modules
Where a MAC provides the PHY interface mode capabilities, use the PHY interface mode bitmaps to select the operating interface mode for optical SFP modules, rather than using the linkmode bitmaps. Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/phy/phylink.c56
1 files changed, 49 insertions, 7 deletions
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index b28e770a6be9..d2f77dc5b6a8 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -2026,6 +2026,41 @@ static void phylink_sfp_detach(void *upstream, struct sfp_bus *bus)
pl->netdev->sfp_bus = NULL;
}
+static const phy_interface_t phylink_sfp_interface_preference[] = {
+ PHY_INTERFACE_MODE_USXGMII,
+ PHY_INTERFACE_MODE_10GBASER,
+ PHY_INTERFACE_MODE_10GKR,
+ PHY_INTERFACE_MODE_2500BASEX,
+ PHY_INTERFACE_MODE_SGMII,
+ PHY_INTERFACE_MODE_1000BASEX,
+};
+
+static phy_interface_t phylink_select_interface(struct phylink *pl,
+ const unsigned long *intf,
+ const char *intf_name)
+{
+ DECLARE_PHY_INTERFACE_MASK(u);
+ phy_interface_t interface;
+ size_t i;
+
+ phy_interface_and(u, intf, pl->config->supported_interfaces);
+
+ interface = PHY_INTERFACE_MODE_NA;
+ for (i = 0; i < ARRAY_SIZE(phylink_sfp_interface_preference); i++)
+ if (test_bit(phylink_sfp_interface_preference[i], u)) {
+ interface = phylink_sfp_interface_preference[i];
+ break;
+ }
+
+ phylink_info(pl, "interfaces=[mac=%*pbl %s=%*pbl] selected %d (%s)\n",
+ (int)PHY_INTERFACE_MODE_MAX,
+ pl->config->supported_interfaces,
+ intf_name, (int)PHY_INTERFACE_MODE_MAX, intf,
+ interface, phy_modes(interface));
+
+ return interface;
+}
+
static int phylink_sfp_config(struct phylink *pl, u8 mode,
const unsigned long *supported,
const unsigned long *advertising)
@@ -2108,25 +2143,33 @@ static int phylink_sfp_config(struct phylink *pl, u8 mode,
return ret;
}
+static int phylink_sfp_config_nophy(struct phylink *pl)
+{
+ if (!phy_interface_empty(pl->config->supported_interfaces))
+ phylink_select_interface(pl, pl->sfp_interfaces, "sfp");
+
+ return phylink_sfp_config(pl, MLO_AN_INBAND,
+ pl->sfp_support, pl->sfp_support);
+}
+
static int phylink_sfp_module_insert(void *upstream,
const struct sfp_eeprom_id *id)
{
struct phylink *pl = upstream;
- unsigned long *support = pl->sfp_support;
ASSERT_RTNL();
- linkmode_zero(support);
+ linkmode_zero(pl->sfp_support);
phy_interface_zero(pl->sfp_interfaces);
- sfp_parse_support(pl->sfp_bus, id, support, pl->sfp_interfaces);
- pl->sfp_port = sfp_parse_port(pl->sfp_bus, id, support);
+ sfp_parse_support(pl->sfp_bus, id, pl->sfp_support, pl->sfp_interfaces);
+ pl->sfp_port = sfp_parse_port(pl->sfp_bus, id, pl->sfp_support);
/* If this module may have a PHY connecting later, defer until later */
pl->sfp_may_have_phy = sfp_may_have_phy(pl->sfp_bus, id);
if (pl->sfp_may_have_phy)
return 0;
- return phylink_sfp_config(pl, MLO_AN_INBAND, support, support);
+ return phylink_sfp_config_nophy(pl);
}
static int phylink_sfp_module_start(void *upstream)
@@ -2145,8 +2188,7 @@ static int phylink_sfp_module_start(void *upstream)
if (!pl->sfp_may_have_phy)
return 0;
- return phylink_sfp_config(pl, MLO_AN_INBAND,
- pl->sfp_support, pl->sfp_support);
+ return phylink_sfp_config_nophy(pl);
}
static void phylink_sfp_module_stop(void *upstream)