summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorFlorian Fainelli <f.fainelli@gmail.com>2017-09-25 22:55:53 (GMT)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2017-10-12 09:51:22 (GMT)
commit6eab1f829417973122f235af002499d786a22023 (patch)
tree426147ad6e83ed56f7e76c8c33ca969a7c1a2089 /net
parentb8990d2e77c6652c9318adc55f698ee4de5e3ee1 (diff)
downloadlinux-6eab1f829417973122f235af002499d786a22023.tar.xz
net: dsa: Fix network device registration order
[ Upstream commit e804441cfe0b60f6c430901946a69c01eac09df1 ] We cannot be registering the network device first, then setting its carrier off and finally connecting it to a PHY, doing that leaves a window during which the carrier is at best inconsistent, and at worse the device is not usable without a down/up sequence since the network device is visible to user space with possibly no PHY device attached. Re-order steps so that they make logical sense. This fixes some devices where the port was not usable after e.g: an unbind then bind of the driver. Fixes: 0071f56e46da ("dsa: Register netdev before phy") Fixes: 91da11f870f0 ("net: Distributed Switch Architecture protocol support") Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'net')
-rw-r--r--net/dsa/slave.c28
1 files changed, 17 insertions, 11 deletions
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 079d76b..5000e6f 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -1269,26 +1269,32 @@ int dsa_slave_create(struct dsa_switch *ds, struct device *parent,
p->old_duplex = -1;
ds->ports[port].netdev = slave_dev;
- ret = register_netdev(slave_dev);
- if (ret) {
- netdev_err(master, "error %d registering interface %s\n",
- ret, slave_dev->name);
- ds->ports[port].netdev = NULL;
- free_netdev(slave_dev);
- return ret;
- }
netif_carrier_off(slave_dev);
ret = dsa_slave_phy_setup(p, slave_dev);
if (ret) {
netdev_err(master, "error %d setting up slave phy\n", ret);
- unregister_netdev(slave_dev);
- free_netdev(slave_dev);
- return ret;
+ goto out_free;
+ }
+
+ ret = register_netdev(slave_dev);
+ if (ret) {
+ netdev_err(master, "error %d registering interface %s\n",
+ ret, slave_dev->name);
+ goto out_phy;
}
return 0;
+
+out_phy:
+ phy_disconnect(p->phy);
+ if (of_phy_is_fixed_link(ds->ports[port].dn))
+ of_phy_deregister_fixed_link(ds->ports[port].dn);
+out_free:
+ free_netdev(slave_dev);
+ ds->ports[port].netdev = NULL;
+ return ret;
}
void dsa_slave_destroy(struct net_device *slave_dev)