net: phylink: avoid reducing support mask
authorRussell King <rmk+kernel@armlinux.org.uk>
Sun, 2 Jun 2019 14:12:54 +0000 (15:12 +0100)
committerDavid S. Miller <davem@davemloft.net>
Tue, 4 Jun 2019 18:43:24 +0000 (11:43 -0700)
Avoid reducing the support mask as a result of the interface type
selected for SFP modules, or when setting the link settings through
ethtool - this should only change when the supported link modes of
the hardware combination change.

Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/phy/phylink.c

index 9044b95..4c0616b 100644 (file)
@@ -1073,6 +1073,7 @@ EXPORT_SYMBOL_GPL(phylink_ethtool_ksettings_get);
 int phylink_ethtool_ksettings_set(struct phylink *pl,
                                  const struct ethtool_link_ksettings *kset)
 {
+       __ETHTOOL_DECLARE_LINK_MODE_MASK(support);
        struct ethtool_link_ksettings our_kset;
        struct phylink_link_state config;
        int ret;
@@ -1083,11 +1084,12 @@ int phylink_ethtool_ksettings_set(struct phylink *pl,
            kset->base.autoneg != AUTONEG_ENABLE)
                return -EINVAL;
 
+       linkmode_copy(support, pl->supported);
        config = pl->link_config;
 
        /* Mask out unsupported advertisements */
        linkmode_and(config.advertising, kset->link_modes.advertising,
-                    pl->supported);
+                    support);
 
        /* FIXME: should we reject autoneg if phy/mac does not support it? */
        if (kset->base.autoneg == AUTONEG_DISABLE) {
@@ -1097,7 +1099,7 @@ int phylink_ethtool_ksettings_set(struct phylink *pl,
                 * duplex.
                 */
                s = phy_lookup_setting(kset->base.speed, kset->base.duplex,
-                                      pl->supported, false);
+                                      support, false);
                if (!s)
                        return -EINVAL;
 
@@ -1126,7 +1128,7 @@ int phylink_ethtool_ksettings_set(struct phylink *pl,
                __set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, config.advertising);
        }
 
-       if (phylink_validate(pl, pl->supported, &config))
+       if (phylink_validate(pl, support, &config))
                return -EINVAL;
 
        /* If autonegotiation is enabled, we must have an advertisement */
@@ -1576,6 +1578,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(support1);
        struct phylink_link_state config;
        phy_interface_t iface;
        int ret = 0;
@@ -1603,6 +1606,8 @@ static int phylink_sfp_module_insert(void *upstream,
                return ret;
        }
 
+       linkmode_copy(support1, support);
+
        iface = sfp_select_interface(pl->sfp_bus, id, config.advertising);
        if (iface == PHY_INTERFACE_MODE_NA) {
                netdev_err(pl->netdev,
@@ -1612,7 +1617,7 @@ static int phylink_sfp_module_insert(void *upstream,
        }
 
        config.interface = iface;
-       ret = phylink_validate(pl, support, &config);
+       ret = phylink_validate(pl, support1, &config);
        if (ret) {
                netdev_err(pl->netdev, "validation of %s/%s with support %*pb failed: %d\n",
                           phylink_an_mode_str(MLO_AN_INBAND),