diff options
Diffstat (limited to 'net/dsa/dsa2.c')
| -rw-r--r-- | net/dsa/dsa2.c | 184 | 
1 files changed, 77 insertions, 107 deletions
diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c index 7024e2120de1..af0e2c0394ac 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c @@ -461,6 +461,72 @@ static void dsa_tree_teardown_cpu_ports(struct dsa_switch_tree *dst)  			dp->cpu_dp = NULL;  } +static int dsa_port_devlink_setup(struct dsa_port *dp) +{ +	struct devlink_port *dlp = &dp->devlink_port; +	struct dsa_switch_tree *dst = dp->ds->dst; +	struct devlink_port_attrs attrs = {}; +	struct devlink *dl = dp->ds->devlink; +	struct dsa_switch *ds = dp->ds; +	const unsigned char *id; +	unsigned char len; +	int err; + +	memset(dlp, 0, sizeof(*dlp)); +	devlink_port_init(dl, dlp); + +	if (ds->ops->port_setup) { +		err = ds->ops->port_setup(ds, dp->index); +		if (err) +			return err; +	} + +	id = (const unsigned char *)&dst->index; +	len = sizeof(dst->index); + +	attrs.phys.port_number = dp->index; +	memcpy(attrs.switch_id.id, id, len); +	attrs.switch_id.id_len = len; + +	switch (dp->type) { +	case DSA_PORT_TYPE_UNUSED: +		attrs.flavour = DEVLINK_PORT_FLAVOUR_UNUSED; +		break; +	case DSA_PORT_TYPE_CPU: +		attrs.flavour = DEVLINK_PORT_FLAVOUR_CPU; +		break; +	case DSA_PORT_TYPE_DSA: +		attrs.flavour = DEVLINK_PORT_FLAVOUR_DSA; +		break; +	case DSA_PORT_TYPE_USER: +		attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; +		break; +	} + +	devlink_port_attrs_set(dlp, &attrs); +	err = devlink_port_register(dl, dlp, dp->index); +	if (err) { +		if (ds->ops->port_teardown) +			ds->ops->port_teardown(ds, dp->index); +		return err; +	} + +	return 0; +} + +static void dsa_port_devlink_teardown(struct dsa_port *dp) +{ +	struct devlink_port *dlp = &dp->devlink_port; +	struct dsa_switch *ds = dp->ds; + +	devlink_port_unregister(dlp); + +	if (ds->ops->port_teardown) +		ds->ops->port_teardown(ds, dp->index); + +	devlink_port_fini(dlp); +} +  static int dsa_port_setup(struct dsa_port *dp)  {  	struct devlink_port *dlp = &dp->devlink_port; @@ -472,11 +538,9 @@ static int dsa_port_setup(struct dsa_port *dp)  	if (dp->setup)  		return 0; -	if (ds->ops->port_setup) { -		err = ds->ops->port_setup(ds, dp->index); -		if (err) -			return err; -	} +	err = dsa_port_devlink_setup(dp); +	if (err) +		return err;  	switch (dp->type) {  	case DSA_PORT_TYPE_UNUSED: @@ -533,8 +597,7 @@ static int dsa_port_setup(struct dsa_port *dp)  	if (err && dsa_port_link_registered)  		dsa_shared_port_link_unregister_of(dp);  	if (err) { -		if (ds->ops->port_teardown) -			ds->ops->port_teardown(ds, dp->index); +		dsa_port_devlink_teardown(dp);  		return err;  	} @@ -543,59 +606,13 @@ static int dsa_port_setup(struct dsa_port *dp)  	return 0;  } -static int dsa_port_devlink_setup(struct dsa_port *dp) -{ -	struct devlink_port *dlp = &dp->devlink_port; -	struct dsa_switch_tree *dst = dp->ds->dst; -	struct devlink_port_attrs attrs = {}; -	struct devlink *dl = dp->ds->devlink; -	const unsigned char *id; -	unsigned char len; -	int err; - -	id = (const unsigned char *)&dst->index; -	len = sizeof(dst->index); - -	attrs.phys.port_number = dp->index; -	memcpy(attrs.switch_id.id, id, len); -	attrs.switch_id.id_len = len; -	memset(dlp, 0, sizeof(*dlp)); - -	switch (dp->type) { -	case DSA_PORT_TYPE_UNUSED: -		attrs.flavour = DEVLINK_PORT_FLAVOUR_UNUSED; -		break; -	case DSA_PORT_TYPE_CPU: -		attrs.flavour = DEVLINK_PORT_FLAVOUR_CPU; -		break; -	case DSA_PORT_TYPE_DSA: -		attrs.flavour = DEVLINK_PORT_FLAVOUR_DSA; -		break; -	case DSA_PORT_TYPE_USER: -		attrs.flavour = DEVLINK_PORT_FLAVOUR_PHYSICAL; -		break; -	} - -	devlink_port_attrs_set(dlp, &attrs); -	err = devlink_port_register(dl, dlp, dp->index); - -	if (!err) -		dp->devlink_port_setup = true; - -	return err; -} -  static void dsa_port_teardown(struct dsa_port *dp)  {  	struct devlink_port *dlp = &dp->devlink_port; -	struct dsa_switch *ds = dp->ds;  	if (!dp->setup)  		return; -	if (ds->ops->port_teardown) -		ds->ops->port_teardown(ds, dp->index); -  	devlink_port_type_clear(dlp);  	switch (dp->type) { @@ -619,46 +636,15 @@ static void dsa_port_teardown(struct dsa_port *dp)  		break;  	} -	dp->setup = false; -} - -static void dsa_port_devlink_teardown(struct dsa_port *dp) -{ -	struct devlink_port *dlp = &dp->devlink_port; +	dsa_port_devlink_teardown(dp); -	if (dp->devlink_port_setup) -		devlink_port_unregister(dlp); -	dp->devlink_port_setup = false; +	dp->setup = false;  } -/* Destroy the current devlink port, and create a new one which has the UNUSED - * flavour. At this point, any call to ds->ops->port_setup has been already - * balanced out by a call to ds->ops->port_teardown, so we know that any - * devlink port regions the driver had are now unregistered. We then call its - * ds->ops->port_setup again, in order for the driver to re-create them on the - * new devlink port. - */ -static int dsa_port_reinit_as_unused(struct dsa_port *dp) +static int dsa_port_setup_as_unused(struct dsa_port *dp)  { -	struct dsa_switch *ds = dp->ds; -	int err; - -	dsa_port_devlink_teardown(dp);  	dp->type = DSA_PORT_TYPE_UNUSED; -	err = dsa_port_devlink_setup(dp); -	if (err) -		return err; - -	if (ds->ops->port_setup) { -		/* On error, leave the devlink port registered, -		 * dsa_switch_teardown will clean it up later. -		 */ -		err = ds->ops->port_setup(ds, dp->index); -		if (err) -			return err; -	} - -	return 0; +	return dsa_port_setup(dp);  }  static int dsa_devlink_info_get(struct devlink *dl, @@ -882,7 +868,6 @@ static int dsa_switch_setup(struct dsa_switch *ds)  {  	struct dsa_devlink_priv *dl_priv;  	struct device_node *dn; -	struct dsa_port *dp;  	int err;  	if (ds->setup) @@ -905,18 +890,9 @@ static int dsa_switch_setup(struct dsa_switch *ds)  	dl_priv = devlink_priv(ds->devlink);  	dl_priv->ds = ds; -	/* Setup devlink port instances now, so that the switch -	 * setup() can register regions etc, against the 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);  	if (err) -		goto unregister_devlink_ports; +		goto devlink_free;  	ds->configure_vlan_while_not_filtering = true; @@ -957,9 +933,7 @@ teardown:  		ds->ops->teardown(ds);  unregister_notifier:  	dsa_switch_unregister_notifier(ds); -unregister_devlink_ports: -	dsa_switch_for_each_port(dp, ds) -		dsa_port_devlink_teardown(dp); +devlink_free:  	devlink_free(ds->devlink);  	ds->devlink = NULL;  	return err; @@ -967,8 +941,6 @@ unregister_devlink_ports:  static void dsa_switch_teardown(struct dsa_switch *ds)  { -	struct dsa_port *dp; -  	if (!ds->setup)  		return; @@ -987,8 +959,6 @@ static void dsa_switch_teardown(struct dsa_switch *ds)  	dsa_switch_unregister_notifier(ds);  	if (ds->devlink) { -		dsa_switch_for_each_port(dp, ds) -			dsa_port_devlink_teardown(dp);  		devlink_free(ds->devlink);  		ds->devlink = NULL;  	} @@ -1041,7 +1011,7 @@ static int dsa_tree_setup_ports(struct dsa_switch_tree *dst)  		if (dsa_port_is_user(dp) || dsa_port_is_unused(dp)) {  			err = dsa_port_setup(dp);  			if (err) { -				err = dsa_port_reinit_as_unused(dp); +				err = dsa_port_setup_as_unused(dp);  				if (err)  					goto teardown;  			}  | 
