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: David S. Miller <davem@davemloft.net>
This commit is contained in:
Коммит
6ff5f8135a
|
@ -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 @@ out_port_failed:
|
|||
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
|
||||
|
|
Загрузка…
Ссылка в новой задаче