kernel: bump 5.15 to 5.15.132
[openwrt/openwrt.git] / target / linux / generic / backport-5.15 / 765-v5.17-06-net-next-net-dsa-setup-master-before-ports.patch
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
5
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.
10
11 dsa_tree_setup
12 -> dsa_tree_setup_ports
13 -> dsa_port_setup
14 -> dsa_slave_create
15 -> register_netdevice
16 -> dsa_tree_setup_master
17 -> dsa_master_setup
18 -> sets up master->dsa_ptr, which enables reception
19
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.
24
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
30 dsa_slave_destroy().
31
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
36 an external system.
37
38 Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
39 Signed-off-by: David S. Miller <davem@davemloft.net>
40 ---
41 net/dsa/dsa2.c | 23 +++++++++++++----------
42 1 file changed, 13 insertions(+), 10 deletions(-)
43
44 --- a/net/dsa/dsa2.c
45 +++ b/net/dsa/dsa2.c
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;
51
52 if (!dp->setup)
53 return;
54 @@ -566,9 +567,11 @@ static void dsa_port_teardown(struct dsa
55 dsa_port_link_unregister_of(dp);
56 break;
57 case DSA_PORT_TYPE_USER:
58 - if (dp->slave) {
59 - dsa_slave_destroy(dp->slave);
60 + slave = dp->slave;
61 +
62 + if (slave) {
63 dp->slave = NULL;
64 + dsa_slave_destroy(slave);
65 }
66 break;
67 }
68 @@ -1130,17 +1133,17 @@ static int dsa_tree_setup(struct dsa_swi
69 if (err)
70 goto teardown_cpu_ports;
71
72 - err = dsa_tree_setup_ports(dst);
73 + err = dsa_tree_setup_master(dst);
74 if (err)
75 goto teardown_switches;
76
77 - err = dsa_tree_setup_master(dst);
78 + err = dsa_tree_setup_ports(dst);
79 if (err)
80 - goto teardown_ports;
81 + goto teardown_master;
82
83 err = dsa_tree_setup_lags(dst);
84 if (err)
85 - goto teardown_master;
86 + goto teardown_ports;
87
88 dst->setup = true;
89
90 @@ -1148,10 +1151,10 @@ static int dsa_tree_setup(struct dsa_swi
91
92 return 0;
93
94 -teardown_master:
95 - dsa_tree_teardown_master(dst);
96 teardown_ports:
97 dsa_tree_teardown_ports(dst);
98 +teardown_master:
99 + dsa_tree_teardown_master(dst);
100 teardown_switches:
101 dsa_tree_teardown_switches(dst);
102 teardown_cpu_ports:
103 @@ -1169,10 +1172,10 @@ static void dsa_tree_teardown(struct dsa
104
105 dsa_tree_teardown_lags(dst);
106
107 - dsa_tree_teardown_master(dst);
108 -
109 dsa_tree_teardown_ports(dst);
110
111 + dsa_tree_teardown_master(dst);
112 +
113 dsa_tree_teardown_switches(dst);
114
115 dsa_tree_teardown_cpu_ports(dst);