Commit af8c6db1 authored by David S. Miller's avatar David S. Miller

Merge branch 'dsa-init-cleanups'

Vladimir Oltean says:

====================
DSA initialization cleanups

These patches contain miscellaneous work that makes the DSA init code
path symmetric with the teardown path, and some additional patches
carried by Ansuel Smith for his register access over Ethernet work, but
those patches can be applied as-is too.
https://patchwork.kernel.org/project/netdevbpf/patch/20211214224409.5770-3-ansuelsmth@gmail.com/
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents d093d17c 11fd667d
...@@ -561,6 +561,7 @@ static void dsa_port_teardown(struct dsa_port *dp) ...@@ -561,6 +561,7 @@ static void dsa_port_teardown(struct dsa_port *dp)
struct devlink_port *dlp = &dp->devlink_port; struct devlink_port *dlp = &dp->devlink_port;
struct dsa_switch *ds = dp->ds; struct dsa_switch *ds = dp->ds;
struct dsa_mac_addr *a, *tmp; struct dsa_mac_addr *a, *tmp;
struct net_device *slave;
if (!dp->setup) if (!dp->setup)
return; return;
...@@ -582,9 +583,11 @@ static void dsa_port_teardown(struct dsa_port *dp) ...@@ -582,9 +583,11 @@ static void dsa_port_teardown(struct dsa_port *dp)
dsa_port_link_unregister_of(dp); dsa_port_link_unregister_of(dp);
break; break;
case DSA_PORT_TYPE_USER: case DSA_PORT_TYPE_USER:
if (dp->slave) { slave = dp->slave;
dsa_slave_destroy(dp->slave);
if (slave) {
dp->slave = NULL; dp->slave = NULL;
dsa_slave_destroy(slave);
} }
break; break;
} }
...@@ -1003,23 +1006,28 @@ static void dsa_tree_teardown_switches(struct dsa_switch_tree *dst) ...@@ -1003,23 +1006,28 @@ static void dsa_tree_teardown_switches(struct dsa_switch_tree *dst)
dsa_switch_teardown(dp->ds); dsa_switch_teardown(dp->ds);
} }
static int dsa_tree_setup_switches(struct dsa_switch_tree *dst) /* Bring shared ports up first, then non-shared ports */
static int dsa_tree_setup_ports(struct dsa_switch_tree *dst)
{ {
struct dsa_port *dp; struct dsa_port *dp;
int err; int err = 0;
list_for_each_entry(dp, &dst->ports, list) { list_for_each_entry(dp, &dst->ports, list) {
err = dsa_switch_setup(dp->ds); if (dsa_port_is_dsa(dp) || dsa_port_is_cpu(dp)) {
if (err) err = dsa_port_setup(dp);
goto teardown; if (err)
goto teardown;
}
} }
list_for_each_entry(dp, &dst->ports, list) { list_for_each_entry(dp, &dst->ports, list) {
err = dsa_port_setup(dp); if (dsa_port_is_user(dp) || dsa_port_is_unused(dp)) {
if (err) { err = dsa_port_setup(dp);
err = dsa_port_reinit_as_unused(dp); if (err) {
if (err) err = dsa_port_reinit_as_unused(dp);
goto teardown; if (err)
goto teardown;
}
} }
} }
...@@ -1028,7 +1036,21 @@ static int dsa_tree_setup_switches(struct dsa_switch_tree *dst) ...@@ -1028,7 +1036,21 @@ static int dsa_tree_setup_switches(struct dsa_switch_tree *dst)
teardown: teardown:
dsa_tree_teardown_ports(dst); dsa_tree_teardown_ports(dst);
dsa_tree_teardown_switches(dst); return err;
}
static int dsa_tree_setup_switches(struct dsa_switch_tree *dst)
{
struct dsa_port *dp;
int err = 0;
list_for_each_entry(dp, &dst->ports, list) {
err = dsa_switch_setup(dp->ds);
if (err) {
dsa_tree_teardown_switches(dst);
break;
}
}
return err; return err;
} }
...@@ -1038,6 +1060,8 @@ static int dsa_tree_setup_master(struct dsa_switch_tree *dst) ...@@ -1038,6 +1060,8 @@ static int dsa_tree_setup_master(struct dsa_switch_tree *dst)
struct dsa_port *dp; struct dsa_port *dp;
int err; int err;
rtnl_lock();
list_for_each_entry(dp, &dst->ports, list) { list_for_each_entry(dp, &dst->ports, list) {
if (dsa_port_is_cpu(dp)) { if (dsa_port_is_cpu(dp)) {
err = dsa_master_setup(dp->master, dp); err = dsa_master_setup(dp->master, dp);
...@@ -1046,6 +1070,8 @@ static int dsa_tree_setup_master(struct dsa_switch_tree *dst) ...@@ -1046,6 +1070,8 @@ static int dsa_tree_setup_master(struct dsa_switch_tree *dst)
} }
} }
rtnl_unlock();
return 0; return 0;
} }
...@@ -1053,9 +1079,13 @@ static void dsa_tree_teardown_master(struct dsa_switch_tree *dst) ...@@ -1053,9 +1079,13 @@ static void dsa_tree_teardown_master(struct dsa_switch_tree *dst)
{ {
struct dsa_port *dp; struct dsa_port *dp;
rtnl_lock();
list_for_each_entry(dp, &dst->ports, list) list_for_each_entry(dp, &dst->ports, list)
if (dsa_port_is_cpu(dp)) if (dsa_port_is_cpu(dp))
dsa_master_teardown(dp->master); dsa_master_teardown(dp->master);
rtnl_unlock();
} }
static int dsa_tree_setup_lags(struct dsa_switch_tree *dst) static int dsa_tree_setup_lags(struct dsa_switch_tree *dst)
...@@ -1111,20 +1141,25 @@ static int dsa_tree_setup(struct dsa_switch_tree *dst) ...@@ -1111,20 +1141,25 @@ static int dsa_tree_setup(struct dsa_switch_tree *dst)
if (err) if (err)
goto teardown_switches; goto teardown_switches;
err = dsa_tree_setup_lags(dst); err = dsa_tree_setup_ports(dst);
if (err) if (err)
goto teardown_master; goto teardown_master;
err = dsa_tree_setup_lags(dst);
if (err)
goto teardown_ports;
dst->setup = true; dst->setup = true;
pr_info("DSA: tree %d setup\n", dst->index); pr_info("DSA: tree %d setup\n", dst->index);
return 0; return 0;
teardown_ports:
dsa_tree_teardown_ports(dst);
teardown_master: teardown_master:
dsa_tree_teardown_master(dst); dsa_tree_teardown_master(dst);
teardown_switches: teardown_switches:
dsa_tree_teardown_ports(dst);
dsa_tree_teardown_switches(dst); dsa_tree_teardown_switches(dst);
teardown_cpu_ports: teardown_cpu_ports:
dsa_tree_teardown_cpu_ports(dst); dsa_tree_teardown_cpu_ports(dst);
...@@ -1141,10 +1176,10 @@ static void dsa_tree_teardown(struct dsa_switch_tree *dst) ...@@ -1141,10 +1176,10 @@ static void dsa_tree_teardown(struct dsa_switch_tree *dst)
dsa_tree_teardown_lags(dst); dsa_tree_teardown_lags(dst);
dsa_tree_teardown_master(dst);
dsa_tree_teardown_ports(dst); dsa_tree_teardown_ports(dst);
dsa_tree_teardown_master(dst);
dsa_tree_teardown_switches(dst); dsa_tree_teardown_switches(dst);
dsa_tree_teardown_cpu_ports(dst); dsa_tree_teardown_cpu_ports(dst);
......
...@@ -267,9 +267,9 @@ static void dsa_master_set_promiscuity(struct net_device *dev, int inc) ...@@ -267,9 +267,9 @@ static void dsa_master_set_promiscuity(struct net_device *dev, int inc)
if (!ops->promisc_on_master) if (!ops->promisc_on_master)
return; return;
rtnl_lock(); ASSERT_RTNL();
dev_set_promiscuity(dev, inc); dev_set_promiscuity(dev, inc);
rtnl_unlock();
} }
static ssize_t tagging_show(struct device *d, struct device_attribute *attr, static ssize_t tagging_show(struct device *d, struct device_attribute *attr,
...@@ -330,28 +330,13 @@ static const struct attribute_group dsa_group = { ...@@ -330,28 +330,13 @@ static const struct attribute_group dsa_group = {
.attrs = dsa_slave_attrs, .attrs = dsa_slave_attrs,
}; };
static void dsa_master_reset_mtu(struct net_device *dev)
{
int err;
rtnl_lock();
err = dev_set_mtu(dev, ETH_DATA_LEN);
if (err)
netdev_dbg(dev,
"Unable to reset MTU to exclude DSA overheads\n");
rtnl_unlock();
}
static struct lock_class_key dsa_master_addr_list_lock_key; static struct lock_class_key dsa_master_addr_list_lock_key;
int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp) int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp)
{ {
const struct dsa_device_ops *tag_ops = cpu_dp->tag_ops;
struct dsa_switch *ds = cpu_dp->ds; struct dsa_switch *ds = cpu_dp->ds;
struct device_link *consumer_link; struct device_link *consumer_link;
int mtu, ret; int ret;
mtu = ETH_DATA_LEN + dsa_tag_protocol_overhead(tag_ops);
/* The DSA master must use SET_NETDEV_DEV for this to work. */ /* The DSA master must use SET_NETDEV_DEV for this to work. */
consumer_link = device_link_add(ds->dev, dev->dev.parent, consumer_link = device_link_add(ds->dev, dev->dev.parent,
...@@ -361,13 +346,6 @@ int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp) ...@@ -361,13 +346,6 @@ int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp)
"Failed to create a device link to DSA switch %s\n", "Failed to create a device link to DSA switch %s\n",
dev_name(ds->dev)); dev_name(ds->dev));
rtnl_lock();
ret = dev_set_mtu(dev, mtu);
rtnl_unlock();
if (ret)
netdev_warn(dev, "error %d setting MTU to %d to include DSA overhead\n",
ret, mtu);
/* If we use a tagging format that doesn't have an ethertype /* If we use a tagging format that doesn't have an ethertype
* field, make sure that all packets from this point on get * field, make sure that all packets from this point on get
* sent to the tag format's receive function. * sent to the tag format's receive function.
...@@ -405,7 +383,6 @@ void dsa_master_teardown(struct net_device *dev) ...@@ -405,7 +383,6 @@ void dsa_master_teardown(struct net_device *dev)
sysfs_remove_group(&dev->dev.kobj, &dsa_group); sysfs_remove_group(&dev->dev.kobj, &dsa_group);
dsa_netdev_ops_set(dev, NULL); dsa_netdev_ops_set(dev, NULL);
dsa_master_ethtool_teardown(dev); dsa_master_ethtool_teardown(dev);
dsa_master_reset_mtu(dev);
dsa_master_set_promiscuity(dev, -1); dsa_master_set_promiscuity(dev, -1);
dev->dsa_ptr = NULL; dev->dsa_ptr = NULL;
......
...@@ -2011,13 +2011,6 @@ int dsa_slave_create(struct dsa_port *port) ...@@ -2011,13 +2011,6 @@ int dsa_slave_create(struct dsa_port *port)
port->slave = slave_dev; port->slave = slave_dev;
dsa_slave_setup_tagger(slave_dev); dsa_slave_setup_tagger(slave_dev);
rtnl_lock();
ret = dsa_slave_change_mtu(slave_dev, ETH_DATA_LEN);
rtnl_unlock();
if (ret && ret != -EOPNOTSUPP)
dev_warn(ds->dev, "nonfatal error %d setting MTU to %d on port %d\n",
ret, ETH_DATA_LEN, port->index);
netif_carrier_off(slave_dev); netif_carrier_off(slave_dev);
ret = dsa_slave_phy_setup(slave_dev); ret = dsa_slave_phy_setup(slave_dev);
...@@ -2030,6 +2023,11 @@ int dsa_slave_create(struct dsa_port *port) ...@@ -2030,6 +2023,11 @@ int dsa_slave_create(struct dsa_port *port)
rtnl_lock(); rtnl_lock();
ret = dsa_slave_change_mtu(slave_dev, ETH_DATA_LEN);
if (ret && ret != -EOPNOTSUPP)
dev_warn(ds->dev, "nonfatal error %d setting MTU to %d on port %d\n",
ret, ETH_DATA_LEN, port->index);
ret = register_netdevice(slave_dev); ret = register_netdevice(slave_dev);
if (ret) { if (ret) {
netdev_err(master, "error %d registering interface %s\n", netdev_err(master, "error %d registering interface %s\n",
......
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