summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet
diff options
context:
space:
mode:
authorVladimir Oltean <vladimir.oltean@nxp.com>2022-05-22 00:37:39 +0300
committerDavid S. Miller <davem@davemloft.net>2022-05-23 12:39:54 +0300
commit61be79ba2d90162b0b213384f35eb8db7eb183b8 (patch)
treee99092abb9bf3632f0d9162f63b2ee0c2385cff2 /drivers/net/ethernet
parent129b7532a0edc3f381a6c5f3bb1a155e743d141b (diff)
downloadlinux-61be79ba2d90162b0b213384f35eb8db7eb183b8.tar.xz
net: dsa: felix: move the updating of PGID_CPU to the ocelot lib
PGID_CPU must be updated every time a port is configured or unconfigured as a tag_8021q CPU port. The ocelot switch lib already has a hook for that operation, so move the updating of PGID_CPU to those hooks. These bits are pretty specific to DSA, so normally I would keep them out of the common switch lib, but when tag_8021q is in use, this has implications upon the forwarding mask determined by ocelot_apply_bridge_fwd_mask() and called extensively by the switch lib. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r--drivers/net/ethernet/mscc/ocelot.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/drivers/net/ethernet/mscc/ocelot.c b/drivers/net/ethernet/mscc/ocelot.c
index e0d1d5b59981..ac9faf1923c5 100644
--- a/drivers/net/ethernet/mscc/ocelot.c
+++ b/drivers/net/ethernet/mscc/ocelot.c
@@ -2165,6 +2165,33 @@ void ocelot_apply_bridge_fwd_mask(struct ocelot *ocelot, bool joining)
}
EXPORT_SYMBOL(ocelot_apply_bridge_fwd_mask);
+/* Update PGID_CPU which is the destination port mask used for whitelisting
+ * unicast addresses filtered towards the host. In the normal and NPI modes,
+ * this points to the analyzer entry for the CPU port module, while in DSA
+ * tag_8021q mode, it is a bit mask of all active CPU ports.
+ * PGID_SRC will take care of forwarding a packet from one user port to
+ * no more than a single CPU port.
+ */
+static void ocelot_update_pgid_cpu(struct ocelot *ocelot)
+{
+ int pgid_cpu = 0;
+ int port;
+
+ for (port = 0; port < ocelot->num_phys_ports; port++) {
+ struct ocelot_port *ocelot_port = ocelot->ports[port];
+
+ if (!ocelot_port || !ocelot_port->is_dsa_8021q_cpu)
+ continue;
+
+ pgid_cpu |= BIT(port);
+ }
+
+ if (!pgid_cpu)
+ pgid_cpu = BIT(ocelot->num_phys_ports);
+
+ ocelot_write_rix(ocelot, pgid_cpu, ANA_PGID_PGID, PGID_CPU);
+}
+
void ocelot_port_set_dsa_8021q_cpu(struct ocelot *ocelot, int port)
{
u16 vid;
@@ -2173,6 +2200,8 @@ void ocelot_port_set_dsa_8021q_cpu(struct ocelot *ocelot, int port)
for (vid = OCELOT_RSV_VLAN_RANGE_START; vid < VLAN_N_VID; vid++)
ocelot_vlan_member_add(ocelot, port, vid, true);
+
+ ocelot_update_pgid_cpu(ocelot);
}
EXPORT_SYMBOL_GPL(ocelot_port_set_dsa_8021q_cpu);
@@ -2184,6 +2213,8 @@ void ocelot_port_unset_dsa_8021q_cpu(struct ocelot *ocelot, int port)
for (vid = OCELOT_RSV_VLAN_RANGE_START; vid < VLAN_N_VID; vid++)
ocelot_vlan_member_del(ocelot, port, vid);
+
+ ocelot_update_pgid_cpu(ocelot);
}
EXPORT_SYMBOL_GPL(ocelot_port_unset_dsa_8021q_cpu);