Commit 6ff5f813 authored by David S. Miller's avatar David S. Miller

Merge branch 'dsa-cross-chip'

Vladimir Oltean says:

====================
Improvement for DSA cross-chip setups

This series improves some aspects in multi-switch DSA tree topologies:
- better device tree validation
- better handling of MTU changes
- better handling of multicast addresses
- removal of some unused code
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 41505d3f f9bcdc36
......@@ -409,6 +409,21 @@ static inline struct dsa_port *dsa_to_port(struct dsa_switch *ds, int p)
return NULL;
}
static inline bool dsa_port_is_dsa(struct dsa_port *port)
{
return port->type == DSA_PORT_TYPE_DSA;
}
static inline bool dsa_port_is_cpu(struct dsa_port *port)
{
return port->type == DSA_PORT_TYPE_CPU;
}
static inline bool dsa_port_is_user(struct dsa_port *dp)
{
return dp->type == DSA_PORT_TYPE_USER;
}
static inline bool dsa_is_unused_port(struct dsa_switch *ds, int p)
{
return dsa_to_port(ds, p)->type == DSA_PORT_TYPE_UNUSED;
......
......@@ -219,21 +219,6 @@ static void dsa_tree_put(struct dsa_switch_tree *dst)
kref_put(&dst->refcount, dsa_tree_release);
}
static bool dsa_port_is_dsa(struct dsa_port *port)
{
return port->type == DSA_PORT_TYPE_DSA;
}
static bool dsa_port_is_cpu(struct dsa_port *port)
{
return port->type == DSA_PORT_TYPE_CPU;
}
static bool dsa_port_is_user(struct dsa_port *dp)
{
return dp->type == DSA_PORT_TYPE_USER;
}
static struct dsa_port *dsa_tree_find_port_by_node(struct dsa_switch_tree *dst,
struct device_node *dn)
{
......@@ -1259,6 +1244,13 @@ static int dsa_switch_parse_member_of(struct dsa_switch *ds,
if (!ds->dst)
return -ENOMEM;
if (dsa_switch_find(ds->dst->index, ds->index)) {
dev_err(ds->dev,
"A DSA switch with index %d already exists in tree %d\n",
ds->index, ds->dst->index);
return -EEXIST;
}
return 0;
}
......
......@@ -84,7 +84,7 @@ struct dsa_notifier_vlan_info {
/* DSA_NOTIFIER_MTU */
struct dsa_notifier_mtu_info {
bool propagate_upstream;
bool targeted_match;
int sw_index;
int port;
int mtu;
......@@ -200,7 +200,7 @@ int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering,
bool dsa_port_skip_vlan_configuration(struct dsa_port *dp);
int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock);
int dsa_port_mtu_change(struct dsa_port *dp, int new_mtu,
bool propagate_upstream);
bool targeted_match);
int dsa_port_fdb_add(struct dsa_port *dp, const unsigned char *addr,
u16 vid);
int dsa_port_fdb_del(struct dsa_port *dp, const unsigned char *addr,
......
......@@ -567,11 +567,11 @@ int dsa_port_mrouter(struct dsa_port *dp, bool mrouter,
}
int dsa_port_mtu_change(struct dsa_port *dp, int new_mtu,
bool propagate_upstream)
bool targeted_match)
{
struct dsa_notifier_mtu_info info = {
.sw_index = dp->ds->index,
.propagate_upstream = propagate_upstream,
.targeted_match = targeted_match,
.port = dp->index,
.mtu = new_mtu,
};
......
......@@ -1528,6 +1528,7 @@ int dsa_slave_change_mtu(struct net_device *dev, int new_mtu)
struct dsa_port *dp = dsa_slave_to_port(dev);
struct dsa_slave_priv *p = netdev_priv(dev);
struct dsa_switch *ds = p->dp->ds;
struct dsa_port *dp_iter;
struct dsa_port *cpu_dp;
int port = p->dp->index;
int largest_mtu = 0;
......@@ -1535,31 +1536,31 @@ int dsa_slave_change_mtu(struct net_device *dev, int new_mtu)
int old_master_mtu;
int mtu_limit;
int cpu_mtu;
int err, i;
int err;
if (!ds->ops->port_change_mtu)
return -EOPNOTSUPP;
for (i = 0; i < ds->num_ports; i++) {
list_for_each_entry(dp_iter, &ds->dst->ports, list) {
int slave_mtu;
if (!dsa_is_user_port(ds, i))
if (!dsa_port_is_user(dp_iter))
continue;
/* During probe, this function will be called for each slave
* device, while not all of them have been allocated. That's
* ok, it doesn't change what the maximum is, so ignore it.
*/
if (!dsa_to_port(ds, i)->slave)
if (!dp_iter->slave)
continue;
/* Pretend that we already applied the setting, which we
* actually haven't (still haven't done all integrity checks)
*/
if (i == port)
if (dp_iter == dp)
slave_mtu = new_mtu;
else
slave_mtu = dsa_to_port(ds, i)->slave->mtu;
slave_mtu = dp_iter->slave->mtu;
if (largest_mtu < slave_mtu)
largest_mtu = slave_mtu;
......@@ -1585,14 +1586,15 @@ int dsa_slave_change_mtu(struct net_device *dev, int new_mtu)
goto out_master_failed;
/* We only need to propagate the MTU of the CPU port to
* upstream switches.
* upstream switches, so create a non-targeted notifier which
* updates all switches.
*/
err = dsa_port_mtu_change(cpu_dp, cpu_mtu, true);
err = dsa_port_mtu_change(cpu_dp, cpu_mtu, false);
if (err)
goto out_cpu_failed;
}
err = dsa_port_mtu_change(dp, new_mtu, false);
err = dsa_port_mtu_change(dp, new_mtu, true);
if (err)
goto out_port_failed;
......@@ -1606,7 +1608,7 @@ int dsa_slave_change_mtu(struct net_device *dev, int new_mtu)
if (new_master_mtu != old_master_mtu)
dsa_port_mtu_change(cpu_dp, old_master_mtu -
dsa_tag_protocol_overhead(cpu_dp->tag_ops),
true);
false);
out_cpu_failed:
if (new_master_mtu != old_master_mtu)
dev_set_mtu(master, old_master_mtu);
......
......@@ -52,10 +52,13 @@ static int dsa_switch_ageing_time(struct dsa_switch *ds,
static bool dsa_switch_mtu_match(struct dsa_switch *ds, int port,
struct dsa_notifier_mtu_info *info)
{
if (ds->index == info->sw_index)
return (port == info->port) || dsa_is_dsa_port(ds, port);
if (ds->index == info->sw_index && port == info->port)
return true;
if (!info->propagate_upstream)
/* Do not propagate to other switches in the tree if the notifier was
* targeted for a single switch.
*/
if (info->targeted_match)
return false;
if (dsa_is_dsa_port(ds, port) || dsa_is_cpu_port(ds, port))
......@@ -232,36 +235,15 @@ static int dsa_switch_lag_leave(struct dsa_switch *ds,
return 0;
}
static bool dsa_switch_mdb_match(struct dsa_switch *ds, int port,
struct dsa_notifier_mdb_info *info)
{
if (ds->index == info->sw_index && port == info->port)
return true;
if (dsa_is_dsa_port(ds, port))
return true;
return false;
}
static int dsa_switch_mdb_add(struct dsa_switch *ds,
struct dsa_notifier_mdb_info *info)
{
int err = 0;
int port;
int port = dsa_towards_port(ds, info->sw_index, info->port);
if (!ds->ops->port_mdb_add)
return -EOPNOTSUPP;
for (port = 0; port < ds->num_ports; port++) {
if (dsa_switch_mdb_match(ds, port, info)) {
err = ds->ops->port_mdb_add(ds, port, info->mdb);
if (err)
break;
}
}
return err;
return ds->ops->port_mdb_add(ds, port, info->mdb);
}
static int dsa_switch_mdb_del(struct dsa_switch *ds,
......@@ -364,36 +346,16 @@ static int dsa_switch_change_tag_proto(struct dsa_switch *ds,
return 0;
}
static bool dsa_switch_mrp_match(struct dsa_switch *ds, int port,
struct dsa_notifier_mrp_info *info)
{
if (ds->index == info->sw_index && port == info->port)
return true;
if (dsa_is_dsa_port(ds, port))
return true;
return false;
}
static int dsa_switch_mrp_add(struct dsa_switch *ds,
struct dsa_notifier_mrp_info *info)
{
int err = 0;
int port;
if (!ds->ops->port_mrp_add)
return -EOPNOTSUPP;
for (port = 0; port < ds->num_ports; port++) {
if (dsa_switch_mrp_match(ds, port, info)) {
err = ds->ops->port_mrp_add(ds, port, info->mrp);
if (err)
break;
}
}
if (ds->index == info->sw_index)
return ds->ops->port_mrp_add(ds, info->port, info->mrp);
return err;
return 0;
}
static int dsa_switch_mrp_del(struct dsa_switch *ds,
......@@ -408,39 +370,18 @@ static int dsa_switch_mrp_del(struct dsa_switch *ds,
return 0;
}
static bool
dsa_switch_mrp_ring_role_match(struct dsa_switch *ds, int port,
struct dsa_notifier_mrp_ring_role_info *info)
{
if (ds->index == info->sw_index && port == info->port)
return true;
if (dsa_is_dsa_port(ds, port))
return true;
return false;
}
static int
dsa_switch_mrp_add_ring_role(struct dsa_switch *ds,
struct dsa_notifier_mrp_ring_role_info *info)
{
int err = 0;
int port;
if (!ds->ops->port_mrp_add)
return -EOPNOTSUPP;
for (port = 0; port < ds->num_ports; port++) {
if (dsa_switch_mrp_ring_role_match(ds, port, info)) {
err = ds->ops->port_mrp_add_ring_role(ds, port,
info->mrp);
if (err)
break;
}
}
if (ds->index == info->sw_index)
return ds->ops->port_mrp_add_ring_role(ds, info->port,
info->mrp);
return err;
return 0;
}
static int
......
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