Commit eca68a3c authored by Marek Behún's avatar Marek Behún Committed by David S. Miller

net: phylink: pass supported host PHY interface modes to phylib for SFP's PHYs

Pass the supported PHY interface types to phylib if the PHY we are
connecting is inside a SFP, so that the PHY driver can select an
appropriate host configuration mode for their interface according to
the host capabilities.

For example the Marvell 88X3310 PHY inside RollBall SFP modules
defaults to 10gbase-r mode on host's side, and the marvell10g
driver currently does not change this setting. But a host may not
support 10gbase-r. For example Turris Omnia only supports sgmii,
1000base-x and 2500base-x modes. The PHY can be configured to use
those modes, but in order for the PHY driver to do that, it needs
to know which modes are supported.
Signed-off-by: default avatarMarek Behún <kabel@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent e6084637
...@@ -2814,6 +2814,8 @@ static const phy_interface_t phylink_sfp_interface_preference[] = { ...@@ -2814,6 +2814,8 @@ static const phy_interface_t phylink_sfp_interface_preference[] = {
PHY_INTERFACE_MODE_100BASEX, PHY_INTERFACE_MODE_100BASEX,
}; };
static DECLARE_PHY_INTERFACE_MASK(phylink_sfp_interfaces);
static phy_interface_t phylink_choose_sfp_interface(struct phylink *pl, static phy_interface_t phylink_choose_sfp_interface(struct phylink *pl,
const unsigned long *intf) const unsigned long *intf)
{ {
...@@ -3091,6 +3093,10 @@ static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy) ...@@ -3091,6 +3093,10 @@ static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy)
else else
mode = MLO_AN_INBAND; mode = MLO_AN_INBAND;
/* Set the PHY's host supported interfaces */
phy_interface_and(phy->host_interfaces, phylink_sfp_interfaces,
pl->config->supported_interfaces);
/* Do the initial configuration */ /* Do the initial configuration */
ret = phylink_sfp_config_phy(pl, mode, phy); ret = phylink_sfp_config_phy(pl, mode, phy);
if (ret < 0) if (ret < 0)
...@@ -3444,4 +3450,15 @@ void phylink_mii_c45_pcs_get_state(struct mdio_device *pcs, ...@@ -3444,4 +3450,15 @@ void phylink_mii_c45_pcs_get_state(struct mdio_device *pcs,
} }
EXPORT_SYMBOL_GPL(phylink_mii_c45_pcs_get_state); EXPORT_SYMBOL_GPL(phylink_mii_c45_pcs_get_state);
static int __init phylink_init(void)
{
for (int i = 0; i < ARRAY_SIZE(phylink_sfp_interface_preference); ++i)
__set_bit(phylink_sfp_interface_preference[i],
phylink_sfp_interfaces);
return 0;
}
module_init(phylink_init);
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
...@@ -571,6 +571,7 @@ struct macsec_ops; ...@@ -571,6 +571,7 @@ struct macsec_ops;
* @advertising: Currently advertised linkmodes * @advertising: Currently advertised linkmodes
* @adv_old: Saved advertised while power saving for WoL * @adv_old: Saved advertised while power saving for WoL
* @lp_advertising: Current link partner advertised linkmodes * @lp_advertising: Current link partner advertised linkmodes
* @host_interfaces: PHY interface modes supported by host
* @eee_broken_modes: Energy efficient ethernet modes which should be prohibited * @eee_broken_modes: Energy efficient ethernet modes which should be prohibited
* @autoneg: Flag autoneg being used * @autoneg: Flag autoneg being used
* @rate_matching: Current rate matching mode * @rate_matching: Current rate matching mode
...@@ -670,6 +671,9 @@ struct phy_device { ...@@ -670,6 +671,9 @@ struct phy_device {
/* used with phy_speed_down */ /* used with phy_speed_down */
__ETHTOOL_DECLARE_LINK_MODE_MASK(adv_old); __ETHTOOL_DECLARE_LINK_MODE_MASK(adv_old);
/* Host supported PHY interface types. Should be ignored if empty. */
DECLARE_PHY_INTERFACE_MASK(host_interfaces);
/* Energy efficient ethernet modes which should be prohibited */ /* Energy efficient ethernet modes which should be prohibited */
u32 eee_broken_modes; u32 eee_broken_modes;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment