From fe95784fb14e4d56072b7be7325ef859efa38135 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Tue, 8 Mar 2022 11:15:11 +0200 Subject: net: dsa: move port lists initialization to dsa_port_touch &cpu_db->fdbs and &cpu_db->mdbs may be uninitialized lists during some call paths of felix_set_tag_protocol(). There was an attempt to avoid calling dsa_port_walk_fdbs() during setup by using a "bool change" in the felix driver, but this doesn't work when the tagging protocol is defined in the device tree, and a change is triggered by DSA at pseudo-runtime: dsa_tree_setup_switches -> dsa_switch_setup -> dsa_switch_setup_tag_protocol -> ds->ops->change_tag_protocol dsa_tree_setup_ports -> dsa_port_setup -> &dp->fdbs and &db->mdbs only get initialized here So it seems like the only way to fix this is to move the initialization of these lists earlier. dsa_port_touch() is called from dsa_switch_touch_ports() which is called from dsa_switch_parse_of(), and this runs completely before dsa_tree_setup(). Similarly, dsa_switch_release_ports() runs after dsa_tree_teardown(). Fixes: f9cef64fa23f ("net: dsa: felix: migrate host FDB and MDB entries when changing tag proto") Signed-off-by: Vladimir Oltean Signed-off-by: David S. Miller --- net/dsa/dsa2.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c index 04065d3fb09f..39e696185720 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c @@ -457,12 +457,6 @@ static int dsa_port_setup(struct dsa_port *dp) if (dp->setup) return 0; - mutex_init(&dp->addr_lists_lock); - mutex_init(&dp->vlans_lock); - INIT_LIST_HEAD(&dp->fdbs); - INIT_LIST_HEAD(&dp->mdbs); - INIT_LIST_HEAD(&dp->vlans); - if (ds->ops->port_setup) { err = ds->ops->port_setup(ds, dp->index); if (err) @@ -599,10 +593,6 @@ static void dsa_port_teardown(struct dsa_port *dp) break; } - WARN_ON(!list_empty(&dp->fdbs)); - WARN_ON(!list_empty(&dp->mdbs)); - WARN_ON(!list_empty(&dp->vlans)); - dp->setup = false; } @@ -1361,6 +1351,11 @@ static struct dsa_port *dsa_port_touch(struct dsa_switch *ds, int index) dp->ds = ds; dp->index = index; + mutex_init(&dp->addr_lists_lock); + mutex_init(&dp->vlans_lock); + INIT_LIST_HEAD(&dp->fdbs); + INIT_LIST_HEAD(&dp->mdbs); + INIT_LIST_HEAD(&dp->vlans); INIT_LIST_HEAD(&dp->list); list_add_tail(&dp->list, &dst->ports); @@ -1699,6 +1694,9 @@ static void dsa_switch_release_ports(struct dsa_switch *ds) struct dsa_port *dp, *next; dsa_switch_for_each_port_safe(dp, next, ds) { + WARN_ON(!list_empty(&dp->fdbs)); + WARN_ON(!list_empty(&dp->mdbs)); + WARN_ON(!list_empty(&dp->vlans)); list_del(&dp->list); kfree(dp); } -- cgit v1.2.3