diff options
Diffstat (limited to 'net/dsa/dsa2.c')
| -rw-r--r-- | net/dsa/dsa2.c | 90 | 
1 files changed, 37 insertions, 53 deletions
| diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c index b29262eee00b..826957b6442b 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c @@ -170,7 +170,7 @@ void dsa_bridge_num_put(const struct net_device *bridge_dev, int bridge_num)  	/* Check if the bridge is still in use, otherwise it is time  	 * to clean it up so we can reuse this bridge_num later.  	 */ -	if (!dsa_bridge_num_find(bridge_dev)) +	if (dsa_bridge_num_find(bridge_dev) < 0)  		clear_bit(bridge_num, &dsa_fwd_offloading_bridges);  } @@ -399,11 +399,8 @@ static int dsa_tree_setup_cpu_ports(struct dsa_switch_tree *dst)  		if (!dsa_port_is_cpu(cpu_dp))  			continue; -		list_for_each_entry(dp, &dst->ports, list) { -			/* Prefer a local CPU port */ -			if (dp->ds != cpu_dp->ds) -				continue; - +		/* Prefer a local CPU port */ +		dsa_switch_for_each_port(dp, cpu_dp->ds) {  			/* Prefer the first local CPU port found */  			if (dp->cpu_dp)  				continue; @@ -436,6 +433,7 @@ static int dsa_port_setup(struct dsa_port *dp)  	if (dp->setup)  		return 0; +	mutex_init(&dp->addr_lists_lock);  	INIT_LIST_HEAD(&dp->fdbs);  	INIT_LIST_HEAD(&dp->mdbs); @@ -802,16 +800,17 @@ static int dsa_switch_setup_tag_protocol(struct dsa_switch *ds)  {  	const struct dsa_device_ops *tag_ops = ds->dst->tag_ops;  	struct dsa_switch_tree *dst = ds->dst; -	int port, err; +	struct dsa_port *cpu_dp; +	int err;  	if (tag_ops->proto == dst->default_proto)  		return 0; -	for (port = 0; port < ds->num_ports; port++) { -		if (!dsa_is_cpu_port(ds, port)) -			continue; - -		err = ds->ops->change_tag_protocol(ds, port, tag_ops->proto); +	dsa_switch_for_each_cpu_port(cpu_dp, ds) { +		rtnl_lock(); +		err = ds->ops->change_tag_protocol(ds, cpu_dp->index, +						   tag_ops->proto); +		rtnl_unlock();  		if (err) {  			dev_err(ds->dev, "Unable to use tag protocol \"%s\": %pe\n",  				tag_ops->name, ERR_PTR(err)); @@ -848,19 +847,13 @@ static int dsa_switch_setup(struct dsa_switch *ds)  	dl_priv = devlink_priv(ds->devlink);  	dl_priv->ds = ds; -	err = devlink_register(ds->devlink); -	if (err) -		goto free_devlink; -  	/* Setup devlink port instances now, so that the switch  	 * setup() can register regions etc, against the ports  	 */ -	list_for_each_entry(dp, &ds->dst->ports, list) { -		if (dp->ds == ds) { -			err = dsa_port_devlink_setup(dp); -			if (err) -				goto unregister_devlink_ports; -		} +	dsa_switch_for_each_port(dp, ds) { +		err = dsa_port_devlink_setup(dp); +		if (err) +			goto unregister_devlink_ports;  	}  	err = dsa_switch_register_notifier(ds); @@ -877,8 +870,6 @@ static int dsa_switch_setup(struct dsa_switch *ds)  	if (err)  		goto teardown; -	devlink_params_publish(ds->devlink); -  	if (!ds->slave_mii_bus && ds->ops->phy_read) {  		ds->slave_mii_bus = mdiobus_alloc();  		if (!ds->slave_mii_bus) { @@ -894,7 +885,7 @@ static int dsa_switch_setup(struct dsa_switch *ds)  	}  	ds->setup = true; - +	devlink_register(ds->devlink);  	return 0;  free_slave_mii_bus: @@ -906,14 +897,10 @@ teardown:  unregister_notifier:  	dsa_switch_unregister_notifier(ds);  unregister_devlink_ports: -	list_for_each_entry(dp, &ds->dst->ports, list) -		if (dp->ds == ds) -			dsa_port_devlink_teardown(dp); -	devlink_unregister(ds->devlink); -free_devlink: +	dsa_switch_for_each_port(dp, ds) +		dsa_port_devlink_teardown(dp);  	devlink_free(ds->devlink);  	ds->devlink = NULL; -  	return err;  } @@ -924,22 +911,23 @@ static void dsa_switch_teardown(struct dsa_switch *ds)  	if (!ds->setup)  		return; +	if (ds->devlink) +		devlink_unregister(ds->devlink); +  	if (ds->slave_mii_bus && ds->ops->phy_read) {  		mdiobus_unregister(ds->slave_mii_bus);  		mdiobus_free(ds->slave_mii_bus);  		ds->slave_mii_bus = NULL;  	} -	dsa_switch_unregister_notifier(ds); -  	if (ds->ops->teardown)  		ds->ops->teardown(ds); +	dsa_switch_unregister_notifier(ds); +  	if (ds->devlink) { -		list_for_each_entry(dp, &ds->dst->ports, list) -			if (dp->ds == ds) -				dsa_port_devlink_teardown(dp); -		devlink_unregister(ds->devlink); +		dsa_switch_for_each_port(dp, ds) +			dsa_port_devlink_teardown(dp);  		devlink_free(ds->devlink);  		ds->devlink = NULL;  	} @@ -1155,7 +1143,7 @@ int dsa_tree_change_tag_proto(struct dsa_switch_tree *dst,  		goto out_unlock;  	list_for_each_entry(dp, &dst->ports, list) { -		if (!dsa_is_user_port(dp->ds, dp->index)) +		if (!dsa_port_is_user(dp))  			continue;  		if (dp->slave->flags & IFF_UP) @@ -1186,8 +1174,8 @@ static struct dsa_port *dsa_port_touch(struct dsa_switch *ds, int index)  	struct dsa_switch_tree *dst = ds->dst;  	struct dsa_port *dp; -	list_for_each_entry(dp, &dst->ports, list) -		if (dp->ds == ds && dp->index == index) +	dsa_switch_for_each_port(dp, ds) +		if (dp->index == index)  			return dp;  	dp = kzalloc(sizeof(*dp), GFP_KERNEL); @@ -1372,12 +1360,15 @@ static int dsa_switch_parse_ports_of(struct dsa_switch *ds,  	for_each_available_child_of_node(ports, port) {  		err = of_property_read_u32(port, "reg", ®); -		if (err) +		if (err) { +			of_node_put(port);  			goto out_put_node; +		}  		if (reg >= ds->num_ports) {  			dev_err(ds->dev, "port %pOF index %u exceeds num_ports (%zu)\n",  				port, reg, ds->num_ports); +			of_node_put(port);  			err = -EINVAL;  			goto out_put_node;  		} @@ -1385,8 +1376,10 @@ static int dsa_switch_parse_ports_of(struct dsa_switch *ds,  		dp = dsa_to_port(ds, reg);  		err = dsa_port_parse_of(dp, port); -		if (err) +		if (err) { +			of_node_put(port);  			goto out_put_node; +		}  	}  out_put_node: @@ -1528,12 +1521,9 @@ static int dsa_switch_parse(struct dsa_switch *ds, struct dsa_chip_data *cd)  static void dsa_switch_release_ports(struct dsa_switch *ds)  { -	struct dsa_switch_tree *dst = ds->dst;  	struct dsa_port *dp, *next; -	list_for_each_entry_safe(dp, next, &dst->ports, list) { -		if (dp->ds != ds) -			continue; +	dsa_switch_for_each_port_safe(dp, next, ds) {  		list_del(&dp->list);  		kfree(dp);  	} @@ -1625,13 +1615,7 @@ void dsa_switch_shutdown(struct dsa_switch *ds)  	mutex_lock(&dsa2_mutex);  	rtnl_lock(); -	list_for_each_entry(dp, &ds->dst->ports, list) { -		if (dp->ds != ds) -			continue; - -		if (!dsa_port_is_user(dp)) -			continue; - +	dsa_switch_for_each_user_port(dp, ds) {  		master = dp->cpu_dp->master;  		slave_dev = dp->slave; |