net: dsa: b53: fix clearing PVID of a port
authorJonas Gorski <jonas.gorski@gmail.com>
Tue, 29 Apr 2025 20:17:02 +0000 (22:17 +0200)
committerJakub Kicinski <kuba@kernel.org>
Thu, 8 May 2025 02:30:34 +0000 (19:30 -0700)
Currently the PVID of ports are only set when adding/updating VLANs with
PVID set or removing VLANs, but not when clearing the PVID flag of a
VLAN.

E.g. the following flow

$ ip link add br0 type bridge vlan_filtering 1
$ ip link set sw1p1 master bridge
$ bridge vlan add dev sw1p1 vid 10 pvid untagged
$ bridge vlan add dev sw1p1 vid 10 untagged

Would keep the PVID set as 10, despite the flag being cleared. Fix this
by checking if we need to unset the PVID on vlan updates.

Fixes: a2482d2ce349 ("net: dsa: b53: Plug in VLAN support")
Signed-off-by: Jonas Gorski <jonas.gorski@gmail.com>
Tested-by: Florian Fainelli <florian.fainelli@broadcom.com>
Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
Link: https://patch.msgid.link/20250429201710.330937-4-jonas.gorski@gmail.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/dsa/b53/b53_common.c

index 9d4fb54b4ced6b9d4dd0dbba6535c88ed80966a9..65d74c455c573a8be2fbe14201cac9743ff65025 100644 (file)
@@ -1537,12 +1537,21 @@ int b53_vlan_add(struct dsa_switch *ds, int port,
        bool untagged = vlan->flags & BRIDGE_VLAN_INFO_UNTAGGED;
        bool pvid = vlan->flags & BRIDGE_VLAN_INFO_PVID;
        struct b53_vlan *vl;
+       u16 old_pvid, new_pvid;
        int err;
 
        err = b53_vlan_prepare(ds, port, vlan);
        if (err)
                return err;
 
+       b53_read16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port), &old_pvid);
+       if (pvid)
+               new_pvid = vlan->vid;
+       else if (!pvid && vlan->vid == old_pvid)
+               new_pvid = b53_default_pvid(dev);
+       else
+               new_pvid = old_pvid;
+
        vl = &dev->vlans[vlan->vid];
 
        b53_get_vlan_entry(dev, vlan->vid, vl);
@@ -1562,9 +1571,9 @@ int b53_vlan_add(struct dsa_switch *ds, int port,
        b53_set_vlan_entry(dev, vlan->vid, vl);
        b53_fast_age_vlan(dev, vlan->vid);
 
-       if (pvid && !dsa_is_cpu_port(ds, port)) {
+       if (!dsa_is_cpu_port(ds, port) && new_pvid != old_pvid) {
                b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port),
-                           vlan->vid);
+                           new_pvid);
                b53_fast_age_vlan(dev, vlan->vid);
        }