Subject: [PATCH RFC net 2/2] net: dsa: propagate brentry flag changes

From: Jonas Gorski <[email-masked]>
Date: Sat, 12 Apr 2025 14:24:28 +0200

Currently any flag changes for brentry vlans are ignored, so the
configured cpu port vlan will get stuck at whatever the original flags
were.

E.g.

$ bridge vlan add dev swbridge vid 10 self pvid untagged
$ bridge vlan add dev swbridge vid 10 self

Would cause the vlan to get "stuck" at pvid untagged in the hardware,
despite now being configured as tagged on the bridge.

Fix this by passing on changed vlans to drivers, but do not increase the
refcount for updates.

Since we should never get an update for a non-existing VLAN, add a
WARN_ON() in case it happens.

Fixes: 134ef2388e7f ("net: dsa: add explicit support for host bridge VLANs")
Signed-off-by: Jonas Gorski <[email-masked]>
---
 net/dsa/switch.c | 22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

diff --git a/net/dsa/switch.c b/net/dsa/switch.c
index 3d2feeea897b..dc3cf13ef29a 100644
--- a/net/dsa/switch.c
+++ b/net/dsa/switch.c
@@ -702,23 +702,25 @@ static int dsa_port_do_vlan_add(struct dsa_port *dp,
 		return err;
 	}
 
-	/* No need to propagate on shared ports the existing VLANs that were
-	 * re-notified after just the flags have changed. This would cause a
-	 * refcount bump which we need to avoid, since it unbalances the
-	 * additions with the deletions.
-	 */
-	if (vlan->changed)
-		return 0;
-
 	mutex_lock(&dp->vlans_lock);
 
 	v = dsa_vlan_find(&dp->vlans, vlan);
 	if (v) {
-		refcount_inc(&v->refcount);
-		trace_dsa_vlan_add_bump(dp, vlan, &v->refcount);
+		/* Do not update the refcount for updated VLANs. This would
+		 * cause an imbalance with deletions.
+		 */
+		if (vlan->changed) {
+			err = ds->ops->port_vlan_add(ds, port, vlan, extack);
+			trace_dsa_vlan_add_hw(dp, vlan, err);
+		} else {
+			refcount_inc(&v->refcount);
+			trace_dsa_vlan_add_bump(dp, vlan, &v->refcount);
+		}
 		goto out;
 	}
 
+	WARN_ON(vlan->changed);
+
 	v = kzalloc(sizeof(*v), GFP_KERNEL);
 	if (!v) {
 		err = -ENOMEM;
-- 
2.43.0