1 From 11fd667dac315ea3f2469961f6d2869271a46cae Mon Sep 17 00:00:00 2001
2 From: Vladimir Oltean <vladimir.oltean@nxp.com>
3 Date: Thu, 6 Jan 2022 01:11:17 +0200
4 Subject: [PATCH 6/6] net: dsa: setup master before ports
6 It is said that as soon as a network interface is registered, all its
7 resources should have already been prepared, so that it is available for
8 sending and receiving traffic. One of the resources needed by a DSA
9 slave interface is the master.
12 -> dsa_tree_setup_ports
16 -> dsa_tree_setup_master
18 -> sets up master->dsa_ptr, which enables reception
20 Therefore, there is a short period of time after register_netdevice()
21 during which the master isn't prepared to pass traffic to the DSA layer
22 (master->dsa_ptr is checked by eth_type_trans). Same thing during
23 unregistration, there is a time frame in which packets might be missed.
25 Note that this change opens us to another race: dsa_master_find_slave()
26 will get invoked potentially earlier than the slave creation, and later
27 than the slave deletion. Since dp->slave starts off as a NULL pointer,
28 the earlier calls aren't a problem, but the later calls are. To avoid
29 use-after-free, we should zeroize dp->slave before calling
32 In practice I cannot really test real life improvements brought by this
33 change, since in my systems, netdevice creation races with PHY autoneg
34 which takes a few seconds to complete, and that masks quite a few races.
35 Effects might be noticeable in a setup with fixed links all the way to
38 Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
39 Signed-off-by: David S. Miller <davem@davemloft.net>
41 net/dsa/dsa2.c | 23 +++++++++++++----------
42 1 file changed, 13 insertions(+), 10 deletions(-)
46 @@ -545,6 +545,7 @@ static void dsa_port_teardown(struct dsa
47 struct devlink_port *dlp = &dp->devlink_port;
48 struct dsa_switch *ds = dp->ds;
49 struct dsa_mac_addr *a, *tmp;
50 + struct net_device *slave;
54 @@ -566,9 +567,11 @@ static void dsa_port_teardown(struct dsa
55 dsa_port_link_unregister_of(dp);
57 case DSA_PORT_TYPE_USER:
59 - dsa_slave_destroy(dp->slave);
64 + dsa_slave_destroy(slave);
68 @@ -1130,17 +1133,17 @@ static int dsa_tree_setup(struct dsa_swi
70 goto teardown_cpu_ports;
72 - err = dsa_tree_setup_ports(dst);
73 + err = dsa_tree_setup_master(dst);
75 goto teardown_switches;
77 - err = dsa_tree_setup_master(dst);
78 + err = dsa_tree_setup_ports(dst);
80 - goto teardown_ports;
81 + goto teardown_master;
83 err = dsa_tree_setup_lags(dst);
85 - goto teardown_master;
86 + goto teardown_ports;
90 @@ -1148,10 +1151,10 @@ static int dsa_tree_setup(struct dsa_swi
95 - dsa_tree_teardown_master(dst);
97 dsa_tree_teardown_ports(dst);
99 + dsa_tree_teardown_master(dst);
101 dsa_tree_teardown_switches(dst);
103 @@ -1169,10 +1172,10 @@ static void dsa_tree_teardown(struct dsa
105 dsa_tree_teardown_lags(dst);
107 - dsa_tree_teardown_master(dst);
109 dsa_tree_teardown_ports(dst);
111 + dsa_tree_teardown_master(dst);
113 dsa_tree_teardown_switches(dst);
115 dsa_tree_teardown_cpu_ports(dst);