From 07c6f9805f12f1bb538ef165a092b300350384aa Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 26 Feb 2020 17:14:21 +0000 Subject: [PATCH 1/2] net: switchdev: do not propagate bridge updates across bridges When configuring a tree of independent bridges, propagating changes from the upper bridge across a bridge master to the lower bridge ports brings surprises. For example, a lower bridge may have vlan filtering enabled. It may have a vlan interface attached to the bridge master, which may then be incorporated into another bridge. As soon as the lower bridge vlan interface is attached to the upper bridge, the lower bridge has vlan filtering disabled. This occurs because switchdev recursively applies its changes to all lower devices no matter what. Reviewed-by: Ido Schimmel Tested-by: Ido Schimmel Signed-off-by: Russell King Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- net/switchdev/switchdev.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/net/switchdev/switchdev.c b/net/switchdev/switchdev.c index 60630762a748b..f25604d68337c 100644 --- a/net/switchdev/switchdev.c +++ b/net/switchdev/switchdev.c @@ -475,6 +475,9 @@ static int __switchdev_handle_port_obj_add(struct net_device *dev, * necessary to go through this helper. */ netdev_for_each_lower_dev(dev, lower_dev, iter) { + if (netif_is_bridge_master(lower_dev)) + continue; + err = __switchdev_handle_port_obj_add(lower_dev, port_obj_info, check_cb, add_cb); if (err && err != -EOPNOTSUPP) @@ -526,6 +529,9 @@ static int __switchdev_handle_port_obj_del(struct net_device *dev, * necessary to go through this helper. */ netdev_for_each_lower_dev(dev, lower_dev, iter) { + if (netif_is_bridge_master(lower_dev)) + continue; + err = __switchdev_handle_port_obj_del(lower_dev, port_obj_info, check_cb, del_cb); if (err && err != -EOPNOTSUPP) @@ -576,6 +582,9 @@ static int __switchdev_handle_port_attr_set(struct net_device *dev, * necessary to go through this helper. */ netdev_for_each_lower_dev(dev, lower_dev, iter) { + if (netif_is_bridge_master(lower_dev)) + continue; + err = __switchdev_handle_port_attr_set(lower_dev, port_attr_info, check_cb, set_cb); if (err && err != -EOPNOTSUPP) From 933b4425086a81a928ce7d05856d2f1ee0bcf15e Mon Sep 17 00:00:00 2001 From: Russell King Date: Wed, 26 Feb 2020 17:14:26 +0000 Subject: [PATCH 2/2] net: dsa: mv88e6xxx: fix duplicate vlan warning When setting VLANs on DSA switches, the VLAN is added to both the port concerned as well as the CPU port by dsa_slave_vlan_add(), as well as any DSA ports. If multiple ports are configured with the same VLAN ID, this triggers a warning on the CPU and DSA ports. Avoid this warning for CPU and DSA ports. Signed-off-by: Russell King Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 4ec09cc8dcdce..705c118f6fdd6 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -1795,7 +1795,7 @@ static int mv88e6xxx_broadcast_setup(struct mv88e6xxx_chip *chip, u16 vid) } static int mv88e6xxx_port_vlan_join(struct mv88e6xxx_chip *chip, int port, - u16 vid, u8 member) + u16 vid, u8 member, bool warn) { const u8 non_member = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_NON_MEMBER; struct mv88e6xxx_vtu_entry vlan; @@ -1840,7 +1840,7 @@ static int mv88e6xxx_port_vlan_join(struct mv88e6xxx_chip *chip, int port, err = mv88e6xxx_vtu_loadpurge(chip, &vlan); if (err) return err; - } else { + } else if (warn) { dev_info(chip->dev, "p%d: already a member of VLAN %d\n", port, vid); } @@ -1854,6 +1854,7 @@ static void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, struct mv88e6xxx_chip *chip = ds->priv; bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED; bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID; + bool warn; u8 member; u16 vid; @@ -1867,10 +1868,15 @@ static void mv88e6xxx_port_vlan_add(struct dsa_switch *ds, int port, else member = MV88E6XXX_G1_VTU_DATA_MEMBER_TAG_TAGGED; + /* net/dsa/slave.c will call dsa_port_vlan_add() for the affected port + * and then the CPU port. Do not warn for duplicates for the CPU port. + */ + warn = !dsa_is_cpu_port(ds, port) && !dsa_is_dsa_port(ds, port); + mv88e6xxx_reg_lock(chip); for (vid = vlan->vid_begin; vid <= vlan->vid_end; ++vid) - if (mv88e6xxx_port_vlan_join(chip, port, vid, member)) + if (mv88e6xxx_port_vlan_join(chip, port, vid, member, warn)) dev_err(ds->dev, "p%d: failed to add VLAN %d%c\n", port, vid, untagged ? 'u' : 't');