Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

net: phylink: fix link mode modification in PHY mode

Modifying the link settings via phylink_ethtool_ksettings_set() and
phylink_ethtool_set_pauseparam() didn't always work as intended for
PHY based setups, as calling phylink_mac_config() would result in the
unresolved configuration being committed to the MAC, rather than the
configuration with the speed and duplex setting.

This would work fine if the update caused the link to renegotiate,
but if no settings have changed, phylib won't trigger a renegotiation
cycle, and the MAC will be left incorrectly configured.

Avoid calling phylink_mac_config() unless we are using an inband mode
in phylink_ethtool_ksettings_set(), and use phy_set_asym_pause() as
introduced in 4.20 to set the PHY settings in
phylink_ethtool_set_pauseparam().

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

authored by

Russell King and committed by
David S. Miller
d9922c0e 269a6b5f

+16 -9
+16 -9
drivers/net/phy/phylink.c
··· 1258 1258 pl->link_config.duplex = our_kset.base.duplex; 1259 1259 pl->link_config.an_enabled = our_kset.base.autoneg != AUTONEG_DISABLE; 1260 1260 1261 - if (!test_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state)) { 1261 + /* If we have a PHY, phylib will call our link state function if the 1262 + * mode has changed, which will trigger a resolve and update the MAC 1263 + * configuration. For a fixed link, this isn't able to change any 1264 + * parameters, which just leaves inband mode. 1265 + */ 1266 + if (pl->link_an_mode == MLO_AN_INBAND && 1267 + !test_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state)) { 1262 1268 phylink_mac_config(pl, &pl->link_config); 1263 1269 phylink_mac_an_restart(pl); 1264 1270 } ··· 1344 1338 if (pause->tx_pause) 1345 1339 config->pause |= MLO_PAUSE_TX; 1346 1340 1347 - if (!test_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state)) { 1341 + /* If we have a PHY, phylib will call our link state function if the 1342 + * mode has changed, which will trigger a resolve and update the MAC 1343 + * configuration. 1344 + */ 1345 + if (pl->phydev) { 1346 + phy_set_asym_pause(pl->phydev, pause->rx_pause, 1347 + pause->tx_pause); 1348 + } else if (!test_bit(PHYLINK_DISABLE_STOPPED, 1349 + &pl->phylink_disable_state)) { 1348 1350 switch (pl->link_an_mode) { 1349 - case MLO_AN_PHY: 1350 - /* Silently mark the carrier down, and then trigger a resolve */ 1351 - if (pl->netdev) 1352 - netif_carrier_off(pl->netdev); 1353 - phylink_run_resolve(pl); 1354 - break; 1355 - 1356 1351 case MLO_AN_FIXED: 1357 1352 /* Should we allow fixed links to change against the config? */ 1358 1353 phylink_resolve_flow(pl, config);