Commit 1571e700 authored by Russell King's avatar Russell King Committed by David S. Miller
Browse files

net: phylink: in-band pause mode advertisement update for PCS



Re-code the pause in-band advertisement update in light of the addition
of PCS support, so that we perform the minimum required; only the PCS
configuration function needs to be called in this case, followed by the
request to trigger a restart of negotiation if the programmed
advertisement changed.

We need to change the pcs_config() signature to pass whether resolved
pause should be passed to the MAC for setups such as mvneta and mvpp2
where doing so overrides the MAC manual flow controls.

Signed-off-by: default avatarRussell King <rmk+kernel@armlinux.org.uk>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 1e1bf14a
Loading
Loading
Loading
Loading
+51 −4
Original line number Diff line number Diff line
@@ -441,7 +441,9 @@ static void phylink_pcs_config(struct phylink *pl, bool force_restart,
	if (pl->pcs_ops && pl->pcs_ops->pcs_config(pl->config,
						   pl->cur_link_an_mode,
						   state->interface,
						   state->advertising))
						   state->advertising,
						   !!(pl->link_config.pause &
						      MLO_PAUSE_AN)))
		restart = true;

	phylink_mac_config(pl, state);
@@ -450,6 +452,49 @@ static void phylink_pcs_config(struct phylink *pl, bool force_restart,
		phylink_mac_pcs_an_restart(pl);
}

/*
 * Reconfigure for a change of inband advertisement.
 * If we have a separate PCS, we only need to call its pcs_config() method,
 * and then restart AN if it indicates something changed. Otherwise, we do
 * the full MAC reconfiguration.
 */
static int phylink_change_inband_advert(struct phylink *pl)
{
	int ret;

	if (test_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state))
		return 0;

	if (!pl->pcs_ops) {
		/* Legacy method */
		phylink_mac_config(pl, &pl->link_config);
		phylink_mac_pcs_an_restart(pl);
		return 0;
	}

	phylink_dbg(pl, "%s: mode=%s/%s adv=%*pb pause=%02x\n", __func__,
		    phylink_an_mode_str(pl->cur_link_an_mode),
		    phy_modes(pl->link_config.interface),
		    __ETHTOOL_LINK_MODE_MASK_NBITS, pl->link_config.advertising,
		    pl->link_config.pause);

	/* Modern PCS-based method; update the advert at the PCS, and
	 * restart negotiation if the pcs_config() helper indicates that
	 * the programmed advertisement has changed.
	 */
	ret = pl->pcs_ops->pcs_config(pl->config, pl->cur_link_an_mode,
				      pl->link_config.interface,
				      pl->link_config.advertising,
				      !!(pl->link_config.pause & MLO_PAUSE_AN));
	if (ret < 0)
		return ret;

	if (ret > 0)
		phylink_mac_pcs_an_restart(pl);

	return 0;
}

static void phylink_mac_pcs_get_state(struct phylink *pl,
				      struct phylink_link_state *state)
{
@@ -1524,9 +1569,11 @@ int phylink_ethtool_set_pauseparam(struct phylink *pl,

	config->pause = pause_state;

	if (!pl->phydev && !test_bit(PHYLINK_DISABLE_STOPPED,
				     &pl->phylink_disable_state))
		phylink_pcs_config(pl, true, &pl->link_config);
	/* Update our in-band advertisement, triggering a renegotiation if
	 * the advertisement changed.
	 */
	if (!pl->phydev)
		phylink_change_inband_advert(pl);

	mutex_unlock(&pl->state_mutex);

+5 −2
Original line number Diff line number Diff line
@@ -286,7 +286,8 @@ struct phylink_pcs_ops {
			      struct phylink_link_state *state);
	int (*pcs_config)(struct phylink_config *config, unsigned int mode,
			  phy_interface_t interface,
			  const unsigned long *advertising);
			  const unsigned long *advertising,
			  bool permit_pause_to_mac);
	void (*pcs_an_restart)(struct phylink_config *config);
	void (*pcs_link_up)(struct phylink_config *config, unsigned int mode,
			    phy_interface_t interface, int speed, int duplex);
@@ -317,9 +318,11 @@ void pcs_get_state(struct phylink_config *config,
 * @mode: one of %MLO_AN_FIXED, %MLO_AN_PHY, %MLO_AN_INBAND.
 * @interface: interface mode to be used
 * @advertising: adertisement ethtool link mode mask
 * @permit_pause_to_mac: permit forwarding pause resolution to MAC
 *
 * Configure the PCS for the operating mode, the interface mode, and set
 * the advertisement mask.
 * the advertisement mask. @permit_pause_to_mac indicates whether the
 * hardware may forward the pause mode resolution to the MAC.
 *
 * When operating in %MLO_AN_INBAND, inband should always be enabled,
 * otherwise inband should be disabled.