Commit 1a147b74 authored by David S. Miller's avatar David S. Miller
Browse files

Merge branch 'DSA-mtu'

Vladimir Oltean says:

====================
Configure the MTU on DSA switches

This series adds support for configuring the MTU on front-panel switch
ports, while seamlessly adapting the CPU port and the DSA master to the
largest value plus the tagger overhead.

It also implements bridge MTU auto-normalization within the DSA core, as
resulted after the feedback of the implementation of this feature inside
the bridge driver in v2.

Support was added for quite a number of switches, in the hope that this
series would gain some traction:
 - sja1105
 - felix
 - vsc73xx
 - b53 and rest of the platform

V3 of this series was submitted here:
https://patchwork.ozlabs.org/cover/1262394/

V2 of this series was submitted here:
https://patchwork.ozlabs.org/cover/1261471/

V1 of this series was submitted here:
https://patchwork.ozlabs.org/cover/1199868/


====================

Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 22f33971 0b912fc9
Loading
Loading
Loading
Loading
+22 −5
Original line number Diff line number Diff line
@@ -699,9 +699,6 @@ int b53_configure_vlan(struct dsa_switch *ds)
		b53_write16(dev, B53_VLAN_PAGE,
			    B53_VLAN_PORT_DEF_TAG(i), def_vid);

	if (!is5325(dev) && !is5365(dev))
		b53_set_jumbo(dev, dev->enable_jumbo, false);

	return 0;
}
EXPORT_SYMBOL(b53_configure_vlan);
@@ -807,8 +804,6 @@ static int b53_phy_write16(struct dsa_switch *ds, int addr, int reg, u16 val)
static int b53_reset_switch(struct b53_device *priv)
{
	/* reset vlans */
	priv->enable_jumbo = false;

	memset(priv->vlans, 0, sizeof(*priv->vlans) * priv->num_vlans);
	memset(priv->ports, 0, sizeof(*priv->ports) * priv->num_ports);

@@ -2065,6 +2060,26 @@ int b53_set_mac_eee(struct dsa_switch *ds, int port, struct ethtool_eee *e)
}
EXPORT_SYMBOL(b53_set_mac_eee);

static int b53_change_mtu(struct dsa_switch *ds, int port, int mtu)
{
	struct b53_device *dev = ds->priv;
	bool enable_jumbo;
	bool allow_10_100;

	if (is5325(dev) || is5365(dev))
		return -EOPNOTSUPP;

	enable_jumbo = (mtu >= JMS_MIN_SIZE);
	allow_10_100 = (dev->chip_id == BCM583XX_DEVICE_ID);

	return b53_set_jumbo(dev, enable_jumbo, allow_10_100);
}

static int b53_get_max_mtu(struct dsa_switch *ds, int port)
{
	return JMS_MAX_SIZE;
}

static const struct dsa_switch_ops b53_switch_ops = {
	.get_tag_protocol	= b53_get_tag_protocol,
	.setup			= b53_setup,
@@ -2102,6 +2117,8 @@ static const struct dsa_switch_ops b53_switch_ops = {
	.port_mdb_prepare	= b53_mdb_prepare,
	.port_mdb_add		= b53_mdb_add,
	.port_mdb_del		= b53_mdb_del,
	.port_max_mtu		= b53_get_max_mtu,
	.port_change_mtu	= b53_change_mtu,
};

struct b53_chip_data {
+19 −0
Original line number Diff line number Diff line
@@ -532,6 +532,7 @@ static int felix_setup(struct dsa_switch *ds)
			 ANA_PGID_PGID_PGID(GENMASK(ocelot->num_phys_ports, 0)),
			 ANA_PGID_PGID, PGID_UC);

	ds->mtu_enforcement_ingress = true;
	/* It looks like the MAC/PCS interrupt register - PM0_IEVENT (0x8040)
	 * isn't instantiated for the Felix PF.
	 * In-band AN may take a few ms to complete, so we need to poll.
@@ -609,6 +610,22 @@ static bool felix_txtstamp(struct dsa_switch *ds, int port,
	return false;
}

static int felix_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
{
	struct ocelot *ocelot = ds->priv;

	ocelot_port_set_maxlen(ocelot, port, new_mtu);

	return 0;
}

static int felix_get_max_mtu(struct dsa_switch *ds, int port)
{
	struct ocelot *ocelot = ds->priv;

	return ocelot_get_max_mtu(ocelot, port);
}

static int felix_cls_flower_add(struct dsa_switch *ds, int port,
				struct flow_cls_offload *cls, bool ingress)
{
@@ -664,6 +681,8 @@ static const struct dsa_switch_ops felix_switch_ops = {
	.port_hwtstamp_set	= felix_hwtstamp_set,
	.port_rxtstamp		= felix_rxtstamp,
	.port_txtstamp		= felix_txtstamp,
	.port_change_mtu	= felix_change_mtu,
	.port_max_mtu		= felix_get_max_mtu,
	.cls_flower_add		= felix_cls_flower_add,
	.cls_flower_del		= felix_cls_flower_del,
	.cls_flower_stats	= felix_cls_flower_stats,
+1 −0
Original line number Diff line number Diff line
@@ -126,6 +126,7 @@ enum sja1105_reset_reason {
	SJA1105_RX_HWTSTAMPING,
	SJA1105_AGEING_TIME,
	SJA1105_SCHEDULING,
	SJA1105_BEST_EFFORT_POLICING,
};

int sja1105_static_config_reload(struct sja1105_private *priv,
+46 −4
Original line number Diff line number Diff line
@@ -519,12 +519,12 @@ static int sja1105_init_avb_params(struct sja1105_private *priv)
#define SJA1105_RATE_MBPS(speed) (((speed) * 64000) / 1000)

static void sja1105_setup_policer(struct sja1105_l2_policing_entry *policing,
				  int index)
				  int index, int mtu)
{
	policing[index].sharindx = index;
	policing[index].smax = 65535; /* Burst size in bytes */
	policing[index].rate = SJA1105_RATE_MBPS(1000);
	policing[index].maxlen = ETH_FRAME_LEN + VLAN_HLEN + ETH_FCS_LEN;
	policing[index].maxlen = mtu;
	policing[index].partition = 0;
}

@@ -556,12 +556,16 @@ static int sja1105_init_l2_policing(struct sja1105_private *priv)
	 */
	for (i = 0, k = 0; i < SJA1105_NUM_PORTS; i++) {
		int bcast = (SJA1105_NUM_PORTS * SJA1105_NUM_TC) + i;
		int mtu = VLAN_ETH_FRAME_LEN + ETH_FCS_LEN;

		if (dsa_is_cpu_port(priv->ds, i))
			mtu += VLAN_HLEN;

		for (j = 0; j < SJA1105_NUM_TC; j++, k++)
			sja1105_setup_policer(policing, k);
			sja1105_setup_policer(policing, k, mtu);

		/* Set up this port's policer for broadcast traffic */
		sja1105_setup_policer(policing, bcast);
		sja1105_setup_policer(policing, bcast, mtu);
	}
	return 0;
}
@@ -1544,6 +1548,7 @@ static const char * const sja1105_reset_reasons[] = {
	[SJA1105_RX_HWTSTAMPING] = "RX timestamping",
	[SJA1105_AGEING_TIME] = "Ageing time",
	[SJA1105_SCHEDULING] = "Time-aware scheduling",
	[SJA1105_BEST_EFFORT_POLICING] = "Best-effort policing",
};

/* For situations where we need to change a setting at runtime that is only
@@ -1952,6 +1957,8 @@ static int sja1105_setup(struct dsa_switch *ds)
	/* Advertise the 8 egress queues */
	ds->num_tx_queues = SJA1105_NUM_TC;

	ds->mtu_enforcement_ingress = true;

	/* The DSA/switchdev model brings up switch ports in standalone mode by
	 * default, and that means vlan_filtering is 0 since they're not under
	 * a bridge, so it's safe to set up switch tagging at this time.
@@ -2120,6 +2127,39 @@ static int sja1105_set_ageing_time(struct dsa_switch *ds,
	return sja1105_static_config_reload(priv, SJA1105_AGEING_TIME);
}

static int sja1105_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
{
	int bcast = (SJA1105_NUM_PORTS * SJA1105_NUM_TC) + port;
	struct sja1105_l2_policing_entry *policing;
	struct sja1105_private *priv = ds->priv;
	int tc;

	new_mtu += VLAN_ETH_HLEN + ETH_FCS_LEN;

	if (dsa_is_cpu_port(ds, port))
		new_mtu += VLAN_HLEN;

	policing = priv->static_config.tables[BLK_IDX_L2_POLICING].entries;

	/* We set all 9 port policers to the same value, so just checking the
	 * broadcast one is fine.
	 */
	if (policing[bcast].maxlen == new_mtu)
		return 0;

	for (tc = 0; tc < SJA1105_NUM_TC; tc++)
		policing[port * SJA1105_NUM_TC + tc].maxlen = new_mtu;

	policing[bcast].maxlen = new_mtu;

	return sja1105_static_config_reload(priv, SJA1105_BEST_EFFORT_POLICING);
}

static int sja1105_get_max_mtu(struct dsa_switch *ds, int port)
{
	return 2043 - VLAN_ETH_HLEN - ETH_FCS_LEN;
}

static int sja1105_port_setup_tc(struct dsa_switch *ds, int port,
				 enum tc_setup_type type,
				 void *type_data)
@@ -2215,6 +2255,8 @@ static const struct dsa_switch_ops sja1105_switch_ops = {
	.setup			= sja1105_setup,
	.teardown		= sja1105_teardown,
	.set_ageing_time	= sja1105_set_ageing_time,
	.port_change_mtu	= sja1105_change_mtu,
	.port_max_mtu		= sja1105_get_max_mtu,
	.phylink_validate	= sja1105_phylink_validate,
	.phylink_mac_link_state	= sja1105_mac_pcs_get_state,
	.phylink_mac_config	= sja1105_mac_config,
+20 −10
Original line number Diff line number Diff line
@@ -664,16 +664,6 @@ static void vsc73xx_init_port(struct vsc73xx *vsc, int port)
		      VSC73XX_MAC_CFG_TX_EN |
		      VSC73XX_MAC_CFG_RX_EN);

	/* Max length, we can do up to 9.6 KiB, so allow that.
	 * According to application not "VSC7398 Jumbo Frames" setting
	 * up the MTU to 9.6 KB does not affect the performance on standard
	 * frames, so just enable it. It is clear from the application note
	 * that "9.6 kilobytes" == 9600 bytes.
	 */
	vsc73xx_write(vsc, VSC73XX_BLOCK_MAC,
		      port,
		      VSC73XX_MAXLEN, 9600);

	/* Flow control for the CPU port:
	 * Use a zero delay pause frame when pause condition is left
	 * Obey pause control frames
@@ -1030,6 +1020,24 @@ static void vsc73xx_get_ethtool_stats(struct dsa_switch *ds, int port,
	}
}

static int vsc73xx_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
{
	struct vsc73xx *vsc = ds->priv;

	return vsc73xx_write(vsc, VSC73XX_BLOCK_MAC, port,
			     VSC73XX_MAXLEN, new_mtu);
}

/* According to application not "VSC7398 Jumbo Frames" setting
 * up the MTU to 9.6 KB does not affect the performance on standard
 * frames. It is clear from the application note that
 * "9.6 kilobytes" == 9600 bytes.
 */
static int vsc73xx_get_max_mtu(struct dsa_switch *ds, int port)
{
	return 9600;
}

static const struct dsa_switch_ops vsc73xx_ds_ops = {
	.get_tag_protocol = vsc73xx_get_tag_protocol,
	.setup = vsc73xx_setup,
@@ -1041,6 +1049,8 @@ static const struct dsa_switch_ops vsc73xx_ds_ops = {
	.get_sset_count = vsc73xx_get_sset_count,
	.port_enable = vsc73xx_port_enable,
	.port_disable = vsc73xx_port_disable,
	.port_change_mtu = vsc73xx_change_mtu,
	.port_max_mtu = vsc73xx_get_max_mtu,
};

static int vsc73xx_gpio_get(struct gpio_chip *chip, unsigned int offset)
Loading