Add local network all hosts multicast address (224.0.0.1) and link-local all nodes multicast address (ff02::1) to the ATU so that IGMP/MLD Queries can be forwarded even when multicast flooding is disabled on a port. Signed-off-by: Joseph Huang <Joseph.Huang@xxxxxxxxxx> --- drivers/net/dsa/mv88e6xxx/Kconfig | 12 ++++++++ drivers/net/dsa/mv88e6xxx/chip.c | 47 +++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/drivers/net/dsa/mv88e6xxx/Kconfig b/drivers/net/dsa/mv88e6xxx/Kconfig index e3181d5471df..ef7798bf50d7 100644 --- a/drivers/net/dsa/mv88e6xxx/Kconfig +++ b/drivers/net/dsa/mv88e6xxx/Kconfig @@ -17,3 +17,15 @@ config NET_DSA_MV88E6XXX_PTP help Say Y to enable PTP hardware timestamping on Marvell 88E6xxx switch chips that support it. + +config NET_DSA_MV88E6XXX_ALWAYS_FLOOD_LOCAL_ALL_HOSTS_ADDRESS + bool "Always flood local all hosts multicast packets" + depends on NET_DSA_MV88E6XXX + help + When set to Y, always flood multicast packets destined for + 224.0.0.1 (Local Network All Hosts multicast address) and + ff02::1 (Link-Local All Nodes multicast address), even when + multicast flooding is disabled for a port. This is so that + multicast snooping can continue to function even when + multicast flooding is disabled. + If in doubt, say N. diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 9ed1821184ec..fddcb596c421 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -2488,6 +2488,41 @@ static int mv88e6xxx_broadcast_setup(struct mv88e6xxx_chip *chip, u16 vid) return 0; } +#if IS_ENABLED(CONFIG_NET_DSA_MV88E6XXX_ALWAYS_FLOOD_LOCAL_ALL_HOSTS_ADDRESS) +static int mv88e6xxx_port_add_multicast(struct mv88e6xxx_chip *chip, int port, + u16 vid) +{ + u8 state = MV88E6XXX_G1_ATU_DATA_STATE_MC_STATIC; + const char multicast[][ETH_ALEN] = { + { 0x01, 0x00, 0x5e, 0x00, 0x00, 0x01 }, + { 0x33, 0x33, 0x00, 0x00, 0x00, 0x01 } + }; + int i, err; + + for (i = 0; i < ARRAY_SIZE(multicast); i++) { + err = mv88e6xxx_port_db_load_purge(chip, port, multicast[i], vid, state); + if (err) + return err; + } + + return 0; +} + +static int mv88e6xxx_multicast_setup(struct mv88e6xxx_chip *chip, u16 vid) +{ + int port; + int err; + + for (port = 0; port < mv88e6xxx_num_ports(chip); port++) { + err = mv88e6xxx_port_add_multicast(chip, port, vid); + if (err) + return err; + } + + return 0; +} +#endif + struct mv88e6xxx_port_broadcast_sync_ctx { int port; bool flood; @@ -2572,6 +2607,12 @@ static int mv88e6xxx_port_vlan_join(struct mv88e6xxx_chip *chip, int port, err = mv88e6xxx_broadcast_setup(chip, vlan.vid); if (err) return err; + +#if IS_ENABLED(CONFIG_NET_DSA_MV88E6XXX_ALWAYS_FLOOD_LOCAL_ALL_HOSTS_ADDRESS) + err = mv88e6xxx_multicast_setup(chip, vlan.vid); + if (err) + return err; +#endif } else if (vlan.member[port] != member) { vlan.member[port] = member; @@ -3930,6 +3971,12 @@ static int mv88e6xxx_setup(struct dsa_switch *ds) if (err) goto unlock; +#if IS_ENABLED(CONFIG_NET_DSA_MV88E6XXX_ALWAYS_FLOOD_LOCAL_ALL_HOSTS_ADDRESS) + err = mv88e6xxx_multicast_setup(chip, 0); + if (err) + goto unlock; +#endif + err = mv88e6xxx_pot_setup(chip); if (err) goto unlock; -- 2.17.1