Commit e804441c authored by Florian Fainelli's avatar Florian Fainelli Committed by David S. Miller

net: dsa: Fix network device registration order

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: 0071f56e ("dsa: Register netdev before phy")
Fixes: 91da11f8 ("net: Distributed Switch Architecture protocol support")
Signed-off-by: default avatarFlorian Fainelli <f.fainelli@gmail.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent db06ae41
...@@ -1301,28 +1301,33 @@ int dsa_slave_create(struct dsa_port *port, const char *name) ...@@ -1301,28 +1301,33 @@ int dsa_slave_create(struct dsa_port *port, const char *name)
p->old_duplex = -1; p->old_duplex = -1;
port->netdev = slave_dev; port->netdev = slave_dev;
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);
goto out_free;
}
ret = register_netdev(slave_dev); ret = register_netdev(slave_dev);
if (ret) { if (ret) {
netdev_err(master, "error %d registering interface %s\n", netdev_err(master, "error %d registering interface %s\n",
ret, slave_dev->name); ret, slave_dev->name);
port->netdev = NULL; goto out_phy;
free_percpu(p->stats64);
free_netdev(slave_dev);
return ret;
} }
netif_carrier_off(slave_dev); return 0;
ret = dsa_slave_phy_setup(p, slave_dev); out_phy:
if (ret) { phy_disconnect(p->phy);
netdev_err(master, "error %d setting up slave phy\n", ret); if (of_phy_is_fixed_link(p->dp->dn))
unregister_netdev(slave_dev); of_phy_deregister_fixed_link(p->dp->dn);
out_free:
free_percpu(p->stats64); free_percpu(p->stats64);
free_netdev(slave_dev); free_netdev(slave_dev);
port->netdev = NULL;
return ret; return ret;
}
return 0;
} }
void dsa_slave_destroy(struct net_device *slave_dev) void dsa_slave_destroy(struct net_device *slave_dev)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment