Skip to content

Commit

Permalink
net: dsa: sja1105: implement the port MTU callbacks
Browse files Browse the repository at this point in the history
On this switch, the frame length enforcements are performed by the
ingress policers. There are 2 types of those: regular L2 (also called
best-effort) and Virtual Link policers (an ARINC664/AFDX concept for
defining L2 streams with certain QoS abilities). To avoid future
confusion, I prefer to call the reset reason "Best-effort policers",
even though the VL policers are not yet supported.

We also need to change the setup of the initial static config, such that
DSA calls to .change_mtu (which are expensive) become no-ops and don't
reset the switch 5 times.

A driver-level decision is to unconditionally allow single VLAN-tagged
traffic on all ports. The CPU port must accept an additional VLAN header
for the DSA tag, which is again a driver-level decision.

The policers actually count bytes not only from the SDU, but also from
the Ethernet header and FCS, so those need to be accounted for as well.

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: Florian Fainelli <f.fainelli@gmail.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Vladimir Oltean authored and David S. Miller committed Mar 27, 2020
1 parent 6ae5834 commit c279c72
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 4 deletions.
1 change: 1 addition & 0 deletions drivers/net/dsa/sja1105/sja1105.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
50 changes: 46 additions & 4 deletions drivers/net/dsa/sja1105/sja1105_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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,
Expand Down

0 comments on commit c279c72

Please sign in to comment.