From: Vladimir Oltean Date: Wed, 28 Jul 2021 21:54:27 +0000 (+0300) Subject: net: dsa: sja1105: reset the port pvid when leaving a VLAN-aware bridge X-Git-Tag: v5.15-rc1~157^2~359^2~2 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cde8078e83e32022e30a4f670c2c8179f2f08991;p=thirdparty%2Fkernel%2Flinux.git net: dsa: sja1105: reset the port pvid when leaving a VLAN-aware bridge Now that we no longer have the ultra-central sja1105_build_vlan_table(), we need to be more careful about checking all corner cases manually. For example, when a port leaves a VLAN-aware bridge, it becomes standalone so its pvid should become a tag_8021q RX VLAN again. However, sja1105_commit_pvid() only gets called from sja1105_bridge_vlan_add() and from sja1105_vlan_filtering(), and no VLAN awareness change takes place (VLAN filtering is a global setting for sja1105, so the switch remains VLAN-aware overall). This means that we need to put another sja1105_commit_pvid() call in sja1105_bridge_member(). Fixes: 6dfd23d35e75 ("net: dsa: sja1105: delete vlan delta save/restore logic") Signed-off-by: Vladimir Oltean Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c index 3047704c24d39..293c776226574 100644 --- a/drivers/net/dsa/sja1105/sja1105_main.c +++ b/drivers/net/dsa/sja1105/sja1105_main.c @@ -57,6 +57,35 @@ static bool sja1105_can_forward(struct sja1105_l2_forwarding_entry *l2_fwd, return !!(l2_fwd[from].reach_port & BIT(to)); } +static int sja1105_pvid_apply(struct sja1105_private *priv, int port, u16 pvid) +{ + struct sja1105_mac_config_entry *mac; + + mac = priv->static_config.tables[BLK_IDX_MAC_CONFIG].entries; + + if (mac[port].vlanid == pvid) + return 0; + + mac[port].vlanid = pvid; + + return sja1105_dynamic_config_write(priv, BLK_IDX_MAC_CONFIG, port, + &mac[port], true); +} + +static int sja1105_commit_pvid(struct dsa_switch *ds, int port) +{ + struct dsa_port *dp = dsa_to_port(ds, port); + struct sja1105_private *priv = ds->priv; + u16 pvid; + + if (dp->bridge_dev && br_vlan_enabled(dp->bridge_dev)) + pvid = priv->bridge_pvid[port]; + else + pvid = priv->tag_8021q_pvid[port]; + + return sja1105_pvid_apply(priv, port, pvid); +} + static int sja1105_init_mac_settings(struct sja1105_private *priv) { struct sja1105_mac_config_entry default_mac = { @@ -1656,6 +1685,10 @@ static int sja1105_bridge_member(struct dsa_switch *ds, int port, if (rc) return rc; + rc = sja1105_commit_pvid(ds, port); + if (rc) + return rc; + return sja1105_manage_flood_domains(priv); } @@ -1955,35 +1988,6 @@ out: return rc; } -static int sja1105_pvid_apply(struct sja1105_private *priv, int port, u16 pvid) -{ - struct sja1105_mac_config_entry *mac; - - mac = priv->static_config.tables[BLK_IDX_MAC_CONFIG].entries; - - if (mac[port].vlanid == pvid) - return 0; - - mac[port].vlanid = pvid; - - return sja1105_dynamic_config_write(priv, BLK_IDX_MAC_CONFIG, port, - &mac[port], true); -} - -static int sja1105_commit_pvid(struct dsa_switch *ds, int port) -{ - struct dsa_port *dp = dsa_to_port(ds, port); - struct sja1105_private *priv = ds->priv; - u16 pvid; - - if (dp->bridge_dev && br_vlan_enabled(dp->bridge_dev)) - pvid = priv->bridge_pvid[port]; - else - pvid = priv->tag_8021q_pvid[port]; - - return sja1105_pvid_apply(priv, port, pvid); -} - static enum dsa_tag_protocol sja1105_get_tag_protocol(struct dsa_switch *ds, int port, enum dsa_tag_protocol mp)