@@ -1156,6 +1156,8 @@ static int dsa_port_parse_cpu(struct dsa_port *dp, struct net_device *conduit,
struct dsa_switch *ds = dp->ds;
struct dsa_switch_tree *dst = ds->dst;
enum dsa_tag_protocol default_proto;
+ struct nd_lock *nd_lock, *nd_lock2;
+ struct dsa_port *first_dp;
/* Find out which protocol the switch would prefer. */
default_proto = dsa_get_tag_protocol(dp, conduit);
@@ -1213,6 +1215,18 @@ static int dsa_port_parse_cpu(struct dsa_port *dp, struct net_device *conduit,
dst->tag_ops = tag_ops;
}
+ first_dp = dsa_tree_find_first_cpu(dst);
+ if (first_dp && first_dp->conduit) {
+ /* All conduits must relate the same nd_lock
+ * since dsa_tree_migrate_ports_from_lag_conduit()
+ * may take any of them from list.
+ */
+ double_lock_netdev(first_dp->conduit, &nd_lock,
+ conduit, &nd_lock2);
+ nd_lock_transfer_devices(&nd_lock, &nd_lock2);
+ double_unlock_netdev(nd_lock, nd_lock2);
+ }
+
dp->conduit = conduit;
dp->type = DSA_PORT_TYPE_CPU;
dsa_port_set_tag_protocol(dp, dst->tag_ops);
dsa_tree_migrate_ports_from_lag_conduit() may take any of ports as new conduit, and it will be connected to the rest of ports (and using netdev_upper_dev_link()), so all of them must share the same nd_lock. xxx: Keep in mind NETDEV_CHANGEUPPER is called by netdev_upper_dev_unlink(). Signed-off-by: Kirill Tkhai <tkhai@ya.ru> --- net/dsa/dsa.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+)