Commit 443b5ca4 authored by Jakub Kicinski's avatar Jakub Kicinski
Browse files

Merge branch 'net: dsa: add support for phylink managed EEE'

Russell King says:

====================
net: dsa: add support for phylink managed EEE

This series adds support for phylink managed EEE to DSA, and converts
mt753x to make use of this feature.

Patch 1 implements a helper to indicate whether the MAC LPI operations
are populated (suggested by Vladimir)

Patch 2 makes the necessary changes to the core code - we retain calling
set_mac_eee(), but this method now becomes a way to merely validate the
arguments when using phylink managed EEE rather than performing any
configuration.

Patch 3 converts the mt7530 driver to use phylink managed EEE.
====================

Link: https://patch.msgid.link/Z6nWujbjxlkzK_3P@shell.armlinux.org.uk


Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 2f472031 9cf21773
Loading
Loading
Loading
Loading
+47 −21
Original line number Diff line number Diff line
@@ -2957,28 +2957,61 @@ static void mt753x_phylink_mac_link_up(struct phylink_config *config,
			mcr |= PMCR_FORCE_RX_FC_EN;
	}

	if (mode == MLO_AN_PHY && phydev && phy_init_eee(phydev, false) >= 0) {
		switch (speed) {
		case SPEED_1000:
		case SPEED_2500:
			mcr |= PMCR_FORCE_EEE1G;
			break;
		case SPEED_100:
			mcr |= PMCR_FORCE_EEE100;
			break;
	mt7530_set(priv, MT753X_PMCR_P(dp->index), mcr);
}

static void mt753x_phylink_mac_disable_tx_lpi(struct phylink_config *config)
{
	struct dsa_port *dp = dsa_phylink_to_port(config);
	struct mt7530_priv *priv = dp->ds->priv;

	mt7530_clear(priv, MT753X_PMCR_P(dp->index),
		     PMCR_FORCE_EEE1G | PMCR_FORCE_EEE100);
}

	mt7530_set(priv, MT753X_PMCR_P(dp->index), mcr);
static int mt753x_phylink_mac_enable_tx_lpi(struct phylink_config *config,
					    u32 timer, bool tx_clock_stop)
{
	struct dsa_port *dp = dsa_phylink_to_port(config);
	struct mt7530_priv *priv = dp->ds->priv;
	u32 val;

	/* If the timer is zero, then set LPI_MODE_EN, which allows the
	 * system to enter LPI mode immediately rather than waiting for
	 * the LPI threshold.
	 */
	if (!timer)
		val = LPI_MODE_EN;
	else if (FIELD_FIT(LPI_THRESH_MASK, timer))
		val = FIELD_PREP(LPI_THRESH_MASK, timer);
	else
		val = LPI_THRESH_MASK;

	mt7530_rmw(priv, MT753X_PMEEECR_P(dp->index),
		   LPI_THRESH_MASK | LPI_MODE_EN, val);

	mt7530_set(priv, MT753X_PMCR_P(dp->index),
		   PMCR_FORCE_EEE1G | PMCR_FORCE_EEE100);

	return 0;
}

static void mt753x_phylink_get_caps(struct dsa_switch *ds, int port,
				    struct phylink_config *config)
{
	struct mt7530_priv *priv = ds->priv;
	u32 eeecr;

	config->mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE;

	config->lpi_capabilities = MAC_100FD | MAC_1000FD | MAC_2500FD;

	eeecr = mt7530_read(priv, MT753X_PMEEECR_P(port));
	/* tx_lpi_timer should be in microseconds. The time units for
	 * LPI threshold are unspecified.
	 */
	config->lpi_timer_default = FIELD_GET(LPI_THRESH_MASK, eeecr);

	priv->info->mac_port_get_caps(ds, port, config);
}

@@ -3088,18 +3121,9 @@ mt753x_setup(struct dsa_switch *ds)
static int mt753x_set_mac_eee(struct dsa_switch *ds, int port,
			      struct ethtool_keee *e)
{
	struct mt7530_priv *priv = ds->priv;
	u32 set, mask = LPI_THRESH_MASK | LPI_MODE_EN;

	if (e->tx_lpi_timer > 0xFFF)
		return -EINVAL;

	set = LPI_THRESH_SET(e->tx_lpi_timer);
	if (!e->tx_lpi_enabled)
		/* Force LPI Mode without a delay */
		set |= LPI_MODE_EN;
	mt7530_rmw(priv, MT753X_PMEEECR_P(port), mask, set);

	return 0;
}

@@ -3238,6 +3262,8 @@ static const struct phylink_mac_ops mt753x_phylink_mac_ops = {
	.mac_config	= mt753x_phylink_mac_config,
	.mac_link_down	= mt753x_phylink_mac_link_down,
	.mac_link_up	= mt753x_phylink_mac_link_up,
	.mac_disable_tx_lpi = mt753x_phylink_mac_disable_tx_lpi,
	.mac_enable_tx_lpi = mt753x_phylink_mac_enable_tx_lpi,
};

const struct mt753x_info mt753x_table[] = {
+1 −2
Original line number Diff line number Diff line
@@ -1957,8 +1957,7 @@ struct phylink *phylink_create(struct phylink_config *config,
		return ERR_PTR(-EINVAL);
	}

	pl->mac_supports_eee_ops = mac_ops->mac_disable_tx_lpi &&
				   mac_ops->mac_enable_tx_lpi;
	pl->mac_supports_eee_ops = phylink_mac_implements_lpi(mac_ops);
	pl->mac_supports_eee = pl->mac_supports_eee_ops &&
			       pl->config->lpi_capabilities &&
			       !phy_interface_empty(pl->config->lpi_interfaces);
+12 −0
Original line number Diff line number Diff line
@@ -737,6 +737,18 @@ static inline int phylink_get_link_timer_ns(phy_interface_t interface)
	}
}

/**
 * phylink_mac_implements_lpi() - determine if MAC implements LPI ops
 * @ops: phylink_mac_ops structure
 *
 * Returns true if the phylink MAC operations structure indicates that the
 * LPI operations have been implemented, false otherwise.
 */
static inline bool phylink_mac_implements_lpi(const struct phylink_mac_ops *ops)
{
	return ops && ops->mac_disable_tx_lpi && ops->mac_enable_tx_lpi;
}

void phylink_mii_c22_pcs_decode_state(struct phylink_link_state *state,
				      unsigned int neg_mode, u16 bmsr, u16 lpa);
void phylink_mii_c22_pcs_get_state(struct mdio_device *pcs,
+17 −8
Original line number Diff line number Diff line
@@ -1243,6 +1243,10 @@ static int dsa_user_set_eee(struct net_device *dev, struct ethtool_keee *e)
	if (!ds->ops->support_eee || !ds->ops->support_eee(ds, dp->index))
		return -EOPNOTSUPP;

	/* If the port is using phylink managed EEE, then an unimplemented
	 * set_mac_eee() is permissible.
	 */
	if (!phylink_mac_implements_lpi(ds->phylink_mac_ops)) {
		/* Port's PHY and MAC both need to be EEE capable */
		if (!dev->phydev)
			return -ENODEV;
@@ -1253,6 +1257,11 @@ static int dsa_user_set_eee(struct net_device *dev, struct ethtool_keee *e)
		ret = ds->ops->set_mac_eee(ds, dp->index, e);
		if (ret)
			return ret;
	} else if (ds->ops->set_mac_eee) {
		ret = ds->ops->set_mac_eee(ds, dp->index, e);
		if (ret)
			return ret;
	}

	return phylink_ethtool_set_eee(dp->pl, e);
}