From ab3ce58559d6227a8a54dc78650f5763768a1cfc Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Wed, 15 Oct 2025 23:32:58 +0100 Subject: [PATCH] net: dsa: lantiq_gswip: permit dynamic changes to VLAN filtering state The driver should now tolerate these changes, now that the PVID is automatically recalculated on a VLAN awareness state change. The VLAN-unaware PVID must be installed to hardware even if the joined bridge is currently VLAN-aware. Otherwise, when the bridge VLAN filtering state dynamically changes to VLAN-unaware later, this PVID will be missing. Signed-off-by: Vladimir Oltean Signed-off-by: Daniel Golle Link: https://patch.msgid.link/c58759074fb699581336dc2c2c6bf106257b134e.1760566491.git.daniel@makrotopia.org Signed-off-by: Jakub Kicinski --- drivers/net/dsa/lantiq/lantiq_gswip.c | 38 +++++++++------------------ drivers/net/dsa/lantiq/lantiq_gswip.h | 1 - 2 files changed, 12 insertions(+), 27 deletions(-) diff --git a/drivers/net/dsa/lantiq/lantiq_gswip.c b/drivers/net/dsa/lantiq/lantiq_gswip.c index 30cff623bec0c..58fdd54094d65 100644 --- a/drivers/net/dsa/lantiq/lantiq_gswip.c +++ b/drivers/net/dsa/lantiq/lantiq_gswip.c @@ -590,16 +590,8 @@ static int gswip_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering, struct netlink_ext_ack *extack) { - struct net_device *bridge = dsa_port_bridge_dev_get(dsa_to_port(ds, port)); struct gswip_priv *priv = ds->priv; - /* Do not allow changing the VLAN filtering options while in bridge */ - if (bridge && !!(priv->port_vlan_filter & BIT(port)) != vlan_filtering) { - NL_SET_ERR_MSG_MOD(extack, - "Dynamic toggling of vlan_filtering not supported"); - return -EIO; - } - if (vlan_filtering) { /* Use tag based VLAN */ gswip_switch_mask(priv, @@ -927,18 +919,15 @@ static int gswip_port_bridge_join(struct dsa_switch *ds, int port, struct gswip_priv *priv = ds->priv; int err; - /* When the bridge uses VLAN filtering we have to configure VLAN - * specific bridges. No bridge is configured here. + /* Set up the VLAN for VLAN-unaware bridging for this port, and remove + * it from the "single-port bridge" through which it was operating as + * standalone. */ - if (!br_vlan_enabled(br)) { - err = gswip_vlan_add(priv, br, port, GSWIP_VLAN_UNAWARE_PVID, - true, true, false); - if (err) - return err; - priv->port_vlan_filter &= ~BIT(port); - } else { - priv->port_vlan_filter |= BIT(port); - } + err = gswip_vlan_add(priv, br, port, GSWIP_VLAN_UNAWARE_PVID, + true, true, false); + if (err) + return err; + return gswip_add_single_port_br(priv, port, false); } @@ -948,14 +937,11 @@ static void gswip_port_bridge_leave(struct dsa_switch *ds, int port, struct net_device *br = bridge.dev; struct gswip_priv *priv = ds->priv; - gswip_add_single_port_br(priv, port, true); - - /* When the bridge uses VLAN filtering we have to configure VLAN - * specific bridges. No bridge is configured here. + /* Add the port back to the "single-port bridge", and remove it from + * the VLAN-unaware PVID created for this bridge. */ - if (!br_vlan_enabled(br)) - gswip_vlan_remove(priv, br, port, GSWIP_VLAN_UNAWARE_PVID, true, - false); + gswip_add_single_port_br(priv, port, true); + gswip_vlan_remove(priv, br, port, GSWIP_VLAN_UNAWARE_PVID, true, false); } static int gswip_port_vlan_prepare(struct dsa_switch *ds, int port, diff --git a/drivers/net/dsa/lantiq/lantiq_gswip.h b/drivers/net/dsa/lantiq/lantiq_gswip.h index 6aae1ff2f130f..4590a1a7dbd9b 100644 --- a/drivers/net/dsa/lantiq/lantiq_gswip.h +++ b/drivers/net/dsa/lantiq/lantiq_gswip.h @@ -270,7 +270,6 @@ struct gswip_priv { struct gswip_vlan vlans[64]; int num_gphy_fw; struct gswip_gphy_fw *gphy_fw; - u32 port_vlan_filter; struct mutex pce_table_lock; u16 version; }; -- 2.47.3