net: phylink: allow ethtool -A to change flow control advertisement
authorRussell King <rmk+kernel@armlinux.org.uk>
Sat, 15 Feb 2020 15:49:58 +0000 (15:49 +0000)
committerDavid S. Miller <davem@davemloft.net>
Mon, 17 Feb 2020 03:39:45 +0000 (19:39 -0800)
When ethtool -A is used to change the pause modes, the pause
advertisement is not being changed, but the documentation in
uapi/linux/ethtool.h says we should be. Add that capability to
phylink.

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

index c29648b90ce77e157b3bee572204b0e93015209e..ab72bd1a7dca30b3eb63658bbe7c13c22b002fb0 100644 (file)
@@ -1385,6 +1385,7 @@ int phylink_ethtool_set_pauseparam(struct phylink *pl,
            !pause->autoneg && pause->rx_pause != pause->tx_pause)
                return -EINVAL;
 
+       mutex_lock(&pl->state_mutex);
        config->pause = 0;
        if (pause->autoneg)
                config->pause |= MLO_PAUSE_AN;
@@ -1393,6 +1394,22 @@ int phylink_ethtool_set_pauseparam(struct phylink *pl,
        if (pause->tx_pause)
                config->pause |= MLO_PAUSE_TX;
 
+       /*
+        * See the comments for linkmode_set_pause(), wrt the deficiencies
+        * with the current implementation.  A solution to this issue would
+        * be:
+        * ethtool  Local device
+        *  rx  tx  Pause AsymDir
+        *  0   0   0     0
+        *  1   0   1     1
+        *  0   1   0     1
+        *  1   1   1     1
+        * and then use the ethtool rx/tx enablement status to mask the
+        * rx/tx pause resolution.
+        */
+       linkmode_set_pause(config->advertising, pause->tx_pause,
+                          pause->rx_pause);
+
        /* 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.
@@ -1405,6 +1422,7 @@ int phylink_ethtool_set_pauseparam(struct phylink *pl,
                phylink_mac_config(pl, &pl->link_config);
                phylink_mac_an_restart(pl);
        }
+       mutex_unlock(&pl->state_mutex);
 
        return 0;
 }