summaryrefslogtreecommitdiffstats
path: root/net/dsa
diff options
context:
space:
mode:
authorVladimir Oltean <vladimir.oltean@nxp.com>2020-05-12 20:20:29 +0300
committerDavid S. Miller <davem@davemloft.net>2020-05-12 13:08:08 -0700
commitec5ae61076d07be986df19773662506220757c9f (patch)
tree87f3c3e904ed549b8f85104f42264c48c4fa4494 /net/dsa
parent60b33aeb7e0e664865ace822c0a7aeeb5ebe521c (diff)
downloadlinux-ec5ae61076d07be986df19773662506220757c9f.tar.bz2
net: dsa: sja1105: save/restore VLANs using a delta commit method
Managing the VLAN table that is present in hardware will become very difficult once we add a third operating state (best_effort_vlan_filtering). That is because correct cleanup (not too little, not too much) becomes virtually impossible, when VLANs can be added from the bridge layer, from dsa_8021q for basic tagging, for cross-chip bridging, as well as retagging rules for sub-VLANs and cross-chip sub-VLANs. So we need to rethink VLAN interaction with the switch in a more scalable way. In preparation for that, use the priv->expect_dsa_8021q boolean to classify any VLAN request received through .port_vlan_add or .port_vlan_del towards either one of 2 internal lists: bridge VLANs and dsa_8021q VLANs. Then, implement a central sja1105_build_vlan_table method that creates a VLAN configuration from scratch based on the 2 lists of VLANs kept by the driver, and based on the VLAN awareness state. Currently, if we are VLAN-unaware, install the dsa_8021q VLANs, otherwise the bridge VLANs. Then, implement a delta commit procedure that identifies which VLANs from this new configuration are actually different from the config previously committed to hardware. We apply the delta through the dynamic configuration interface (we don't reset the switch). The result is that the hardware should see the exact sequence of operations as before this patch. This also helps remove the "br" argument passed to dsa_8021q_crosschip_bridge_join, which it was only using to figure out whether it should commit the configuration back to us or not, based on the VLAN awareness state of the bridge. We can simplify that, by always allowing those VLANs inside of our dsa_8021q_vlans list, and committing those to hardware when necessary. Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com> Reviewed-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/dsa')
-rw-r--r--net/dsa/tag_8021q.c45
1 files changed, 17 insertions, 28 deletions
diff --git a/net/dsa/tag_8021q.c b/net/dsa/tag_8021q.c
index 4774ecd1f8fc..3236fbbf85b9 100644
--- a/net/dsa/tag_8021q.c
+++ b/net/dsa/tag_8021q.c
@@ -296,9 +296,9 @@ int dsa_port_setup_8021q_tagging(struct dsa_switch *ds, int port, bool enabled)
}
EXPORT_SYMBOL_GPL(dsa_port_setup_8021q_tagging);
-int dsa_8021q_crosschip_link_apply(struct dsa_switch *ds, int port,
- struct dsa_switch *other_ds,
- int other_port, bool enabled)
+static int dsa_8021q_crosschip_link_apply(struct dsa_switch *ds, int port,
+ struct dsa_switch *other_ds,
+ int other_port, bool enabled)
{
u16 rx_vid = dsa_8021q_rx_vid(ds, port);
@@ -308,7 +308,6 @@ int dsa_8021q_crosschip_link_apply(struct dsa_switch *ds, int port,
return dsa_8021q_vid_apply(other_ds, other_port, rx_vid,
BRIDGE_VLAN_INFO_UNTAGGED, enabled);
}
-EXPORT_SYMBOL_GPL(dsa_8021q_crosschip_link_apply);
static int dsa_8021q_crosschip_link_add(struct dsa_switch *ds, int port,
struct dsa_switch *other_ds,
@@ -369,7 +368,7 @@ static void dsa_8021q_crosschip_link_del(struct dsa_switch *ds,
*/
int dsa_8021q_crosschip_bridge_join(struct dsa_switch *ds, int port,
struct dsa_switch *other_ds,
- int other_port, struct net_device *br,
+ int other_port,
struct list_head *crosschip_links)
{
/* @other_upstream is how @other_ds reaches us. If we are part
@@ -385,12 +384,10 @@ int dsa_8021q_crosschip_bridge_join(struct dsa_switch *ds, int port,
if (rc)
return rc;
- if (!br_vlan_enabled(br)) {
- rc = dsa_8021q_crosschip_link_apply(ds, port, other_ds,
- other_port, true);
- if (rc)
- return rc;
- }
+ rc = dsa_8021q_crosschip_link_apply(ds, port, other_ds,
+ other_port, true);
+ if (rc)
+ return rc;
rc = dsa_8021q_crosschip_link_add(ds, port, other_ds,
other_upstream,
@@ -398,20 +395,14 @@ int dsa_8021q_crosschip_bridge_join(struct dsa_switch *ds, int port,
if (rc)
return rc;
- if (!br_vlan_enabled(br)) {
- rc = dsa_8021q_crosschip_link_apply(ds, port, other_ds,
- other_upstream, true);
- if (rc)
- return rc;
- }
-
- return 0;
+ return dsa_8021q_crosschip_link_apply(ds, port, other_ds,
+ other_upstream, true);
}
EXPORT_SYMBOL_GPL(dsa_8021q_crosschip_bridge_join);
int dsa_8021q_crosschip_bridge_leave(struct dsa_switch *ds, int port,
struct dsa_switch *other_ds,
- int other_port, struct net_device *br,
+ int other_port,
struct list_head *crosschip_links)
{
int other_upstream = dsa_upstream_port(other_ds, other_port);
@@ -431,14 +422,12 @@ int dsa_8021q_crosschip_bridge_leave(struct dsa_switch *ds, int port,
if (keep)
continue;
- if (!br_vlan_enabled(br)) {
- rc = dsa_8021q_crosschip_link_apply(ds, port,
- other_ds,
- other_port,
- false);
- if (rc)
- return rc;
- }
+ rc = dsa_8021q_crosschip_link_apply(ds, port,
+ other_ds,
+ other_port,
+ false);
+ if (rc)
+ return rc;
}
}