diff options
-rw-r--r-- | drivers/net/dsa/ocelot/felix.c | 7 | ||||
-rw-r--r-- | drivers/net/ethernet/mscc/ocelot.c | 31 |
2 files changed, 31 insertions, 7 deletions
diff --git a/drivers/net/dsa/ocelot/felix.c b/drivers/net/dsa/ocelot/felix.c index 78c32b7de185..1299f6a8ac5b 100644 --- a/drivers/net/dsa/ocelot/felix.c +++ b/drivers/net/dsa/ocelot/felix.c @@ -253,9 +253,6 @@ static void felix_8021q_cpu_port_init(struct ocelot *ocelot, int port) ocelot_port_set_dsa_8021q_cpu(ocelot, port); - /* Overwrite PGID_CPU with the non-tagging port */ - ocelot_write_rix(ocelot, BIT(port), ANA_PGID_PGID, PGID_CPU); - ocelot_apply_bridge_fwd_mask(ocelot, true); mutex_unlock(&ocelot->fwd_domain_lock); @@ -267,10 +264,6 @@ static void felix_8021q_cpu_port_deinit(struct ocelot *ocelot, int port) ocelot_port_unset_dsa_8021q_cpu(ocelot, port); - /* Restore PGID_CPU */ - ocelot_write_rix(ocelot, BIT(ocelot->num_phys_ports), ANA_PGID_PGID, - PGID_CPU); - ocelot_apply_bridge_fwd_mask(ocelot, true); mutex_unlock(&ocelot->fwd_domain_lock); 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); |