diff options
author | Vladimir Oltean <vladimir.oltean@nxp.com> | 2022-05-22 00:37:39 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2022-05-23 12:39:54 +0300 |
commit | 61be79ba2d90162b0b213384f35eb8db7eb183b8 (patch) | |
tree | e99092abb9bf3632f0d9162f63b2ee0c2385cff2 /drivers/net/ethernet | |
parent | 129b7532a0edc3f381a6c5f3bb1a155e743d141b (diff) | |
download | linux-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.c | 31 |
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); |