]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - drivers/net/phy/phylink.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next
[linux.git] / drivers / net / phy / phylink.c
index 1e0e32c466ee4c38b348a6e0c1ed9ec0a261564e..ba9468cc8e13444e4bb5ac446046c98568c42221 100644 (file)
@@ -446,8 +446,7 @@ static void phylink_mac_link_up(struct phylink *pl,
 
        pl->cur_interface = link_state.interface;
        pl->ops->mac_link_up(pl->config, pl->cur_link_an_mode,
-                            pl->phy_state.interface,
-                            pl->phydev);
+                            pl->cur_interface, pl->phydev);
 
        if (ndev)
                netif_carrier_on(ndev);
@@ -736,7 +735,19 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy,
        memset(&config, 0, sizeof(config));
        linkmode_copy(supported, phy->supported);
        linkmode_copy(config.advertising, phy->advertising);
-       config.interface = interface;
+
+       /* Clause 45 PHYs switch their Serdes lane between several different
+        * modes, normally 10GBASE-R, SGMII. Some use 2500BASE-X for 2.5G
+        * speeds. We really need to know which interface modes the PHY and
+        * MAC supports to properly work out which linkmodes can be supported.
+        */
+       if (phy->is_c45 &&
+           interface != PHY_INTERFACE_MODE_RXAUI &&
+           interface != PHY_INTERFACE_MODE_XAUI &&
+           interface != PHY_INTERFACE_MODE_USXGMII)
+               config.interface = PHY_INTERFACE_MODE_NA;
+       else
+               config.interface = interface;
 
        ret = phylink_validate(pl, supported, &config);
        if (ret)
@@ -1230,44 +1241,66 @@ int phylink_ethtool_ksettings_set(struct phylink *pl,
                __set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT, config.advertising);
        }
 
-       if (phylink_validate(pl, support, &config))
-               return -EINVAL;
-
-       /* If autonegotiation is enabled, we must have an advertisement */
-       if (config.an_enabled && phylink_is_empty_linkmode(config.advertising))
-               return -EINVAL;
-
-       our_kset = *kset;
-       linkmode_copy(our_kset.link_modes.advertising, config.advertising);
-       our_kset.base.speed = config.speed;
-       our_kset.base.duplex = config.duplex;
-
-       /* If we have a PHY, configure the phy */
        if (pl->phydev) {
+               /* If we have a PHY, we process the kset change via phylib.
+                * phylib will call our link state function if the PHY
+                * parameters have changed, which will trigger a resolve
+                * and update the MAC configuration.
+                */
+               our_kset = *kset;
+               linkmode_copy(our_kset.link_modes.advertising,
+                             config.advertising);
+               our_kset.base.speed = config.speed;
+               our_kset.base.duplex = config.duplex;
+
                ret = phy_ethtool_ksettings_set(pl->phydev, &our_kset);
                if (ret)
                        return ret;
-       }
 
-       mutex_lock(&pl->state_mutex);
-       /* Configure the MAC to match the new settings */
-       linkmode_copy(pl->link_config.advertising, our_kset.link_modes.advertising);
-       pl->link_config.interface = config.interface;
-       pl->link_config.speed = our_kset.base.speed;
-       pl->link_config.duplex = our_kset.base.duplex;
-       pl->link_config.an_enabled = our_kset.base.autoneg != AUTONEG_DISABLE;
+               mutex_lock(&pl->state_mutex);
+               /* Save the new configuration */
+               linkmode_copy(pl->link_config.advertising,
+                             our_kset.link_modes.advertising);
+               pl->link_config.interface = config.interface;
+               pl->link_config.speed = our_kset.base.speed;
+               pl->link_config.duplex = our_kset.base.duplex;
+               pl->link_config.an_enabled = our_kset.base.autoneg !=
+                                            AUTONEG_DISABLE;
+               mutex_unlock(&pl->state_mutex);
+       } else {
+               /* For a fixed link, this isn't able to change any parameters,
+                * which just leaves inband mode.
+                */
+               if (phylink_validate(pl, support, &config))
+                       return -EINVAL;
 
-       /* If we have a PHY, phylib will call our link state function if the
-        * mode has changed, which will trigger a resolve and update the MAC
-        * configuration. For a fixed link, this isn't able to change any
-        * parameters, which just leaves inband mode.
-        */
-       if (pl->cur_link_an_mode == MLO_AN_INBAND &&
-           !test_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state)) {
-               phylink_mac_config(pl, &pl->link_config);
-               phylink_mac_an_restart(pl);
+               /* If autonegotiation is enabled, we must have an advertisement */
+               if (config.an_enabled &&
+                   phylink_is_empty_linkmode(config.advertising))
+                       return -EINVAL;
+
+               mutex_lock(&pl->state_mutex);
+               linkmode_copy(pl->link_config.advertising, config.advertising);
+               pl->link_config.interface = config.interface;
+               pl->link_config.speed = config.speed;
+               pl->link_config.duplex = config.duplex;
+               pl->link_config.an_enabled = kset->base.autoneg !=
+                                            AUTONEG_DISABLE;
+
+               if (pl->cur_link_an_mode == MLO_AN_INBAND &&
+                   !test_bit(PHYLINK_DISABLE_STOPPED,
+                             &pl->phylink_disable_state)) {
+                       /* If in 802.3z mode, this updates the advertisement.
+                        *
+                        * If we are in SGMII mode without a PHY, there is no
+                        * advertisement; the only thing we have is the pause
+                        * modes which can only come from a PHY.
+                        */
+                       phylink_mac_config(pl, &pl->link_config);
+                       phylink_mac_an_restart(pl);
+               }
+               mutex_unlock(&pl->state_mutex);
        }
-       mutex_unlock(&pl->state_mutex);
 
        return 0;
 }
@@ -1880,14 +1913,6 @@ static int phylink_sfp_connect_phy(void *upstream, struct phy_device *phy)
        if (ret < 0)
                return ret;
 
-       /* Clause 45 PHYs switch their Serdes lane between several different
-        * modes, normally 10GBASE-R, SGMII. Some use 2500BASE-X for 2.5G
-        * speeds.  We really need to know which interface modes the PHY and
-        * MAC supports to properly work out which linkmodes can be supported.
-        */
-       if (phy->is_c45)
-               interface = PHY_INTERFACE_MODE_NA;
-
        ret = phylink_bringup_phy(pl, phy, interface);
        if (ret)
                phy_detach(phy);