Skip to content

Commit 00fa91b

Browse files
vladimirolteanPaolo Abeni
authored andcommitted
net: dsa: felix: fix tagging protocol changes with multiple CPU ports
When the device tree has 2 CPU ports defined, a single one is active (has any dp->cpu_dp pointers point to it). Yet the second one is still a CPU port, and DSA still calls ->change_tag_protocol on it. On the NXP LS1028A, the CPU ports are ports 4 and 5. Port 4 is the active CPU port and port 5 is inactive. After the following commands: # Initial setting cat /sys/class/net/eno2/dsa/tagging ocelot echo ocelot-8021q > /sys/class/net/eno2/dsa/tagging echo ocelot > /sys/class/net/eno2/dsa/tagging traffic is now broken, because the driver has moved the NPI port from port 4 to port 5, unbeknown to DSA. The problem can be avoided by detecting that the second CPU port is unused, and not doing anything for it. Further rework will be needed when proper support for multiple CPU ports is added. Treat this as a bug and prepare current kernels to work in single-CPU mode with multiple-CPU DT blobs. Fixes: adb3dcc ("net: dsa: felix: convert to the new .change_tag_protocol DSA API") Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Link: https://lore.kernel.org/r/20220412172209.2531865-1-vladimir.oltean@nxp.com Signed-off-by: Paolo Abeni <pabeni@redhat.com>
1 parent 968a1a5 commit 00fa91b

1 file changed

Lines changed: 23 additions & 0 deletions

File tree

drivers/net/dsa/ocelot/felix.c

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,13 +670,36 @@ static int felix_change_tag_protocol(struct dsa_switch *ds, int cpu,
670670
struct ocelot *ocelot = ds->priv;
671671
struct felix *felix = ocelot_to_felix(ocelot);
672672
enum dsa_tag_protocol old_proto = felix->tag_proto;
673+
bool cpu_port_active = false;
674+
struct dsa_port *dp;
673675
int err;
674676

675677
if (proto != DSA_TAG_PROTO_SEVILLE &&
676678
proto != DSA_TAG_PROTO_OCELOT &&
677679
proto != DSA_TAG_PROTO_OCELOT_8021Q)
678680
return -EPROTONOSUPPORT;
679681

682+
/* We don't support multiple CPU ports, yet the DT blob may have
683+
* multiple CPU ports defined. The first CPU port is the active one,
684+
* the others are inactive. In this case, DSA will call
685+
* ->change_tag_protocol() multiple times, once per CPU port.
686+
* Since we implement the tagging protocol change towards "ocelot" or
687+
* "seville" as effectively initializing the NPI port, what we are
688+
* doing is effectively changing who the NPI port is to the last @cpu
689+
* argument passed, which is an unused DSA CPU port and not the one
690+
* that should actively pass traffic.
691+
* Suppress DSA's calls on CPU ports that are inactive.
692+
*/
693+
dsa_switch_for_each_user_port(dp, ds) {
694+
if (dp->cpu_dp->index == cpu) {
695+
cpu_port_active = true;
696+
break;
697+
}
698+
}
699+
700+
if (!cpu_port_active)
701+
return 0;
702+
680703
felix_del_tag_protocol(ds, cpu, old_proto);
681704

682705
err = felix_set_tag_protocol(ds, cpu, proto);

0 commit comments

Comments
 (0)