]>
Commit | Line | Data |
---|---|---|
014275a0 GKH |
1 | From foo@baz Mon Oct 9 09:32:35 CEST 2017 |
2 | From: Florian Fainelli <f.fainelli@gmail.com> | |
3 | Date: Mon, 25 Sep 2017 15:55:53 -0700 | |
4 | Subject: net: dsa: Fix network device registration order | |
5 | ||
6 | From: Florian Fainelli <f.fainelli@gmail.com> | |
7 | ||
8 | ||
9 | [ Upstream commit e804441cfe0b60f6c430901946a69c01eac09df1 ] | |
10 | ||
11 | We cannot be registering the network device first, then setting its | |
12 | carrier off and finally connecting it to a PHY, doing that leaves a | |
13 | window during which the carrier is at best inconsistent, and at worse | |
14 | the device is not usable without a down/up sequence since the network | |
15 | device is visible to user space with possibly no PHY device attached. | |
16 | ||
17 | Re-order steps so that they make logical sense. This fixes some devices | |
18 | where the port was not usable after e.g: an unbind then bind of the | |
19 | driver. | |
20 | ||
21 | Fixes: 0071f56e46da ("dsa: Register netdev before phy") | |
22 | Fixes: 91da11f870f0 ("net: Distributed Switch Architecture protocol support") | |
23 | Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> | |
24 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
25 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
26 | --- | |
27 | net/dsa/slave.c | 28 +++++++++++++++++----------- | |
28 | 1 file changed, 17 insertions(+), 11 deletions(-) | |
29 | ||
30 | --- a/net/dsa/slave.c | |
31 | +++ b/net/dsa/slave.c | |
32 | @@ -1180,26 +1180,32 @@ int dsa_slave_create(struct dsa_switch * | |
33 | p->old_duplex = -1; | |
34 | ||
35 | ds->ports[port].netdev = slave_dev; | |
36 | - ret = register_netdev(slave_dev); | |
37 | - if (ret) { | |
38 | - netdev_err(master, "error %d registering interface %s\n", | |
39 | - ret, slave_dev->name); | |
40 | - ds->ports[port].netdev = NULL; | |
41 | - free_netdev(slave_dev); | |
42 | - return ret; | |
43 | - } | |
44 | ||
45 | netif_carrier_off(slave_dev); | |
46 | ||
47 | ret = dsa_slave_phy_setup(p, slave_dev); | |
48 | if (ret) { | |
49 | netdev_err(master, "error %d setting up slave phy\n", ret); | |
50 | - unregister_netdev(slave_dev); | |
51 | - free_netdev(slave_dev); | |
52 | - return ret; | |
53 | + goto out_free; | |
54 | + } | |
55 | + | |
56 | + ret = register_netdev(slave_dev); | |
57 | + if (ret) { | |
58 | + netdev_err(master, "error %d registering interface %s\n", | |
59 | + ret, slave_dev->name); | |
60 | + goto out_phy; | |
61 | } | |
62 | ||
63 | return 0; | |
64 | + | |
65 | +out_phy: | |
66 | + phy_disconnect(p->phy); | |
67 | + if (of_phy_is_fixed_link(p->dp->dn)) | |
68 | + of_phy_deregister_fixed_link(p->dp->dn); | |
69 | +out_free: | |
70 | + free_netdev(slave_dev); | |
71 | + ds->ports[port].netdev = NULL; | |
72 | + return ret; | |
73 | } | |
74 | ||
75 | void dsa_slave_destroy(struct net_device *slave_dev) |