Skip to content

Commit 2e919bc

Browse files
Russell Kingdavem330
authored andcommitted
net: phylink: ensure manual pause mode configuration takes effect
We have been relying on link events and mac_config() when the manual pause modes are changed. With recent developments, such as moving the programming of link state to mac_link_up(), this no longer works. To ensure that we update the MAC, we must generate a link-down followed by a link-up event; we can do that by setting mac_link_dropped and triggering a resolve. Fixes: 91a208f ("net: phylink: propagate resolved link config via mac_link_up()") Signed-off-by: Russell King <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent c718af2 commit 2e919bc

File tree

1 file changed

+22
-5
lines changed

1 file changed

+22
-5
lines changed

drivers/net/phy/phylink.c

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1463,6 +1463,8 @@ int phylink_ethtool_set_pauseparam(struct phylink *pl,
14631463
struct ethtool_pauseparam *pause)
14641464
{
14651465
struct phylink_link_state *config = &pl->link_config;
1466+
bool manual_changed;
1467+
int pause_state;
14661468

14671469
ASSERT_RTNL();
14681470

@@ -1477,15 +1479,15 @@ int phylink_ethtool_set_pauseparam(struct phylink *pl,
14771479
!pause->autoneg && pause->rx_pause != pause->tx_pause)
14781480
return -EINVAL;
14791481

1480-
mutex_lock(&pl->state_mutex);
1481-
config->pause = 0;
1482+
pause_state = 0;
14821483
if (pause->autoneg)
1483-
config->pause |= MLO_PAUSE_AN;
1484+
pause_state |= MLO_PAUSE_AN;
14841485
if (pause->rx_pause)
1485-
config->pause |= MLO_PAUSE_RX;
1486+
pause_state |= MLO_PAUSE_RX;
14861487
if (pause->tx_pause)
1487-
config->pause |= MLO_PAUSE_TX;
1488+
pause_state |= MLO_PAUSE_TX;
14881489

1490+
mutex_lock(&pl->state_mutex);
14891491
/*
14901492
* See the comments for linkmode_set_pause(), wrt the deficiencies
14911493
* with the current implementation. A solution to this issue would
@@ -1502,6 +1504,12 @@ int phylink_ethtool_set_pauseparam(struct phylink *pl,
15021504
linkmode_set_pause(config->advertising, pause->tx_pause,
15031505
pause->rx_pause);
15041506

1507+
manual_changed = (config->pause ^ pause_state) & MLO_PAUSE_AN ||
1508+
(!(pause_state & MLO_PAUSE_AN) &&
1509+
(config->pause ^ pause_state) & MLO_PAUSE_TXRX_MASK);
1510+
1511+
config->pause = pause_state;
1512+
15051513
if (!pl->phydev && !test_bit(PHYLINK_DISABLE_STOPPED,
15061514
&pl->phylink_disable_state))
15071515
phylink_pcs_config(pl, true, &pl->link_config);
@@ -1517,6 +1525,15 @@ int phylink_ethtool_set_pauseparam(struct phylink *pl,
15171525
phy_set_asym_pause(pl->phydev, pause->rx_pause,
15181526
pause->tx_pause);
15191527

1528+
/* If the manual pause settings changed, make sure we trigger a
1529+
* resolve to update their state; we can not guarantee that the
1530+
* link will cycle.
1531+
*/
1532+
if (manual_changed) {
1533+
pl->mac_link_dropped = true;
1534+
phylink_run_resolve(pl);
1535+
}
1536+
15201537
return 0;
15211538
}
15221539
EXPORT_SYMBOL_GPL(phylink_ethtool_set_pauseparam);

0 commit comments

Comments
 (0)