Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+18 −13
Original line number Original line Diff line number Diff line
@@ -1301,30 +1301,35 @@ 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)
{
{
	struct dsa_slave_priv *p = netdev_priv(slave_dev);
	struct dsa_slave_priv *p = netdev_priv(slave_dev);