]> git.baikalelectronics.ru Git - kernel.git/commitdiff
net: mscc: ocelot: set up tag_8021q CPU ports independent of user port affinity
authorVladimir Oltean <vladimir.oltean@nxp.com>
Fri, 19 Aug 2022 17:48:19 +0000 (20:48 +0300)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 23 Aug 2022 09:39:22 +0000 (11:39 +0200)
This is a partial revert of commit ddb1c1946b0c ("net: mscc: ocelot:
switch from {,un}set to {,un}assign for tag_8021q CPU ports"), because
as it turns out, this isn't how tag_8021q CPU ports under a LAG are
supposed to work.

Under that scenario, all user ports are "assigned" to the single
tag_8021q CPU port represented by the logical port corresponding to the
bonding interface. So one CPU port in a LAG would have is_dsa_8021q_cpu
set to true (the one whose physical port ID is equal to the logical port
ID), and the other one to false.

In turn, this makes 2 undesirable things happen:

(1) PGID_CPU contains only the first physical CPU port, rather than both
(2) only the first CPU port will be added to the private VLANs used by
    ocelot for VLAN-unaware bridging

To make the driver behave in the same way for both bonded CPU ports, we
need to bring back the old concept of setting up a port as a tag_8021q
CPU port, and this is what deals with VLAN membership and PGID_CPU
updating. But we also need the CPU port "assignment" (the user to CPU
port affinity), and this is what updates the PGID_SRC forwarding rules.

All DSA CPU ports are statically configured for tag_8021q mode when the
tagging protocol is changed to ocelot-8021q. User ports are "assigned"
to one CPU port or the other dynamically (this will be handled by a
future change).

Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/dsa/ocelot/felix.c
drivers/net/ethernet/mscc/ocelot.c
include/soc/mscc/ocelot.h

index aadb0bd7c24f1296e6e0ce676418dd34aa705314..ee19ed96f284c312ab8f16a10bdcc9d4b6b747c1 100644 (file)
@@ -445,6 +445,9 @@ static int felix_tag_8021q_setup(struct dsa_switch *ds)
        if (err)
                return err;
 
+       dsa_switch_for_each_cpu_port(dp, ds)
+               ocelot_port_setup_dsa_8021q_cpu(ocelot, dp->index);
+
        dsa_switch_for_each_user_port(dp, ds)
                ocelot_port_assign_dsa_8021q_cpu(ocelot, dp->index,
                                                 dp->cpu_dp->index);
@@ -493,6 +496,9 @@ static void felix_tag_8021q_teardown(struct dsa_switch *ds)
        dsa_switch_for_each_user_port(dp, ds)
                ocelot_port_unassign_dsa_8021q_cpu(ocelot, dp->index);
 
+       dsa_switch_for_each_cpu_port(dp, ds)
+               ocelot_port_teardown_dsa_8021q_cpu(ocelot, dp->index);
+
        dsa_tag_8021q_unregister(ds);
 }
 
index 306026e6aa111b392e7be765b262d83a88078bbe..d883681e2285e22eded50e04a8bf778b708dbdc9 100644 (file)
@@ -2214,61 +2214,61 @@ static void ocelot_update_pgid_cpu(struct ocelot *ocelot)
        ocelot_write_rix(ocelot, pgid_cpu, ANA_PGID_PGID, PGID_CPU);
 }
 
-void ocelot_port_assign_dsa_8021q_cpu(struct ocelot *ocelot, int port,
-                                     int cpu)
+void ocelot_port_setup_dsa_8021q_cpu(struct ocelot *ocelot, int cpu)
 {
        struct ocelot_port *cpu_port = ocelot->ports[cpu];
        u16 vid;
 
        mutex_lock(&ocelot->fwd_domain_lock);
 
-       ocelot->ports[port]->dsa_8021q_cpu = cpu_port;
+       cpu_port->is_dsa_8021q_cpu = true;
 
-       if (!cpu_port->is_dsa_8021q_cpu) {
-               cpu_port->is_dsa_8021q_cpu = true;
+       for (vid = OCELOT_RSV_VLAN_RANGE_START; vid < VLAN_N_VID; vid++)
+               ocelot_vlan_member_add(ocelot, cpu, vid, true);
 
-               for (vid = OCELOT_RSV_VLAN_RANGE_START; vid < VLAN_N_VID; vid++)
-                       ocelot_vlan_member_add(ocelot, cpu, vid, true);
-
-               ocelot_update_pgid_cpu(ocelot);
-       }
-
-       ocelot_apply_bridge_fwd_mask(ocelot, true);
+       ocelot_update_pgid_cpu(ocelot);
 
        mutex_unlock(&ocelot->fwd_domain_lock);
 }
-EXPORT_SYMBOL_GPL(ocelot_port_assign_dsa_8021q_cpu);
+EXPORT_SYMBOL_GPL(ocelot_port_setup_dsa_8021q_cpu);
 
-void ocelot_port_unassign_dsa_8021q_cpu(struct ocelot *ocelot, int port)
+void ocelot_port_teardown_dsa_8021q_cpu(struct ocelot *ocelot, int cpu)
 {
-       struct ocelot_port *cpu_port = ocelot->ports[port]->dsa_8021q_cpu;
-       bool keep = false;
+       struct ocelot_port *cpu_port = ocelot->ports[cpu];
        u16 vid;
-       int p;
 
        mutex_lock(&ocelot->fwd_domain_lock);
 
-       ocelot->ports[port]->dsa_8021q_cpu = NULL;
+       cpu_port->is_dsa_8021q_cpu = false;
 
-       for (p = 0; p < ocelot->num_phys_ports; p++) {
-               if (!ocelot->ports[p])
-                       continue;
+       for (vid = OCELOT_RSV_VLAN_RANGE_START; vid < VLAN_N_VID; vid++)
+               ocelot_vlan_member_del(ocelot, cpu_port->index, vid);
 
-               if (ocelot->ports[p]->dsa_8021q_cpu == cpu_port) {
-                       keep = true;
-                       break;
-               }
-       }
+       ocelot_update_pgid_cpu(ocelot);
 
-       if (!keep) {
-               cpu_port->is_dsa_8021q_cpu = false;
+       mutex_unlock(&ocelot->fwd_domain_lock);
+}
+EXPORT_SYMBOL_GPL(ocelot_port_teardown_dsa_8021q_cpu);
 
-               for (vid = OCELOT_RSV_VLAN_RANGE_START; vid < VLAN_N_VID; vid++)
-                       ocelot_vlan_member_del(ocelot, cpu_port->index, vid);
+void ocelot_port_assign_dsa_8021q_cpu(struct ocelot *ocelot, int port,
+                                     int cpu)
+{
+       struct ocelot_port *cpu_port = ocelot->ports[cpu];
 
-               ocelot_update_pgid_cpu(ocelot);
-       }
+       mutex_lock(&ocelot->fwd_domain_lock);
 
+       ocelot->ports[port]->dsa_8021q_cpu = cpu_port;
+       ocelot_apply_bridge_fwd_mask(ocelot, true);
+
+       mutex_unlock(&ocelot->fwd_domain_lock);
+}
+EXPORT_SYMBOL_GPL(ocelot_port_assign_dsa_8021q_cpu);
+
+void ocelot_port_unassign_dsa_8021q_cpu(struct ocelot *ocelot, int port)
+{
+       mutex_lock(&ocelot->fwd_domain_lock);
+
+       ocelot->ports[port]->dsa_8021q_cpu = NULL;
        ocelot_apply_bridge_fwd_mask(ocelot, true);
 
        mutex_unlock(&ocelot->fwd_domain_lock);
index 2edea901bbd5a89368c7146bbc62e7e723c93b04..2a7e18ee5577b20fb8412700cfb9f49e16af3f40 100644 (file)
@@ -1024,6 +1024,8 @@ void ocelot_deinit(struct ocelot *ocelot);
 void ocelot_init_port(struct ocelot *ocelot, int port);
 void ocelot_deinit_port(struct ocelot *ocelot, int port);
 
+void ocelot_port_setup_dsa_8021q_cpu(struct ocelot *ocelot, int cpu);
+void ocelot_port_teardown_dsa_8021q_cpu(struct ocelot *ocelot, int cpu);
 void ocelot_port_assign_dsa_8021q_cpu(struct ocelot *ocelot, int port, int cpu);
 void ocelot_port_unassign_dsa_8021q_cpu(struct ocelot *ocelot, int port);
 u32 ocelot_port_assigned_dsa_8021q_cpu_mask(struct ocelot *ocelot, int port);