net: dsa: add support switches global DSCP priority mapping
Some switches like Microchip KSZ variants do not support per port DSCP priority configuration. Instead there is a global DSCP mapping table. To handle it, we will accept set/del request to any of user ports to make global configuration and update dcb app entries for all other ports. Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
ea1078d94c
commit
5f5109af47
@ -433,6 +433,11 @@ struct dsa_switch {
|
||||
*/
|
||||
u32 fdb_isolation:1;
|
||||
|
||||
/* Drivers that have global DSCP mapping settings must set this to
|
||||
* true to automatically apply the settings to all ports.
|
||||
*/
|
||||
u32 dscp_prio_mapping_is_global:1;
|
||||
|
||||
/* Listener for switch fabric events */
|
||||
struct notifier_block nb;
|
||||
|
||||
@ -586,6 +591,10 @@ static inline bool dsa_is_user_port(struct dsa_switch *ds, int p)
|
||||
dsa_switch_for_each_port((_dp), (_ds)) \
|
||||
if (dsa_port_is_user((_dp)))
|
||||
|
||||
#define dsa_switch_for_each_user_port_continue_reverse(_dp, _ds) \
|
||||
dsa_switch_for_each_port_continue_reverse((_dp), (_ds)) \
|
||||
if (dsa_port_is_user((_dp)))
|
||||
|
||||
#define dsa_switch_for_each_cpu_port(_dp, _ds) \
|
||||
dsa_switch_for_each_port((_dp), (_ds)) \
|
||||
if (dsa_port_is_cpu((_dp)))
|
||||
|
@ -2189,6 +2189,58 @@ dsa_user_dcbnl_set_default_prio(struct net_device *dev, struct dcb_app *app)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Update the DSCP prio entries on all user ports of the switch in case
|
||||
* the switch supports global DSCP prio instead of per port DSCP prios.
|
||||
*/
|
||||
static int dsa_user_dcbnl_ieee_global_dscp_setdel(struct net_device *dev,
|
||||
struct dcb_app *app, bool del)
|
||||
{
|
||||
int (*setdel)(struct net_device *dev, struct dcb_app *app);
|
||||
struct dsa_port *dp = dsa_user_to_port(dev);
|
||||
struct dsa_switch *ds = dp->ds;
|
||||
struct dsa_port *other_dp;
|
||||
int err, restore_err;
|
||||
|
||||
if (del)
|
||||
setdel = dcb_ieee_delapp;
|
||||
else
|
||||
setdel = dcb_ieee_setapp;
|
||||
|
||||
dsa_switch_for_each_user_port(other_dp, ds) {
|
||||
struct net_device *user = other_dp->user;
|
||||
|
||||
if (!user || user == dev)
|
||||
continue;
|
||||
|
||||
err = setdel(user, app);
|
||||
if (err)
|
||||
goto err_try_to_restore;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_try_to_restore:
|
||||
|
||||
/* Revert logic to restore previous state of app entries */
|
||||
if (!del)
|
||||
setdel = dcb_ieee_delapp;
|
||||
else
|
||||
setdel = dcb_ieee_setapp;
|
||||
|
||||
dsa_switch_for_each_user_port_continue_reverse(other_dp, ds) {
|
||||
struct net_device *user = other_dp->user;
|
||||
|
||||
if (!user || user == dev)
|
||||
continue;
|
||||
|
||||
restore_err = setdel(user, app);
|
||||
if (restore_err)
|
||||
netdev_err(user, "Failed to restore DSCP prio entry configuration\n");
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static int __maybe_unused
|
||||
dsa_user_dcbnl_add_dscp_prio(struct net_device *dev, struct dcb_app *app)
|
||||
{
|
||||
@ -2220,6 +2272,17 @@ dsa_user_dcbnl_add_dscp_prio(struct net_device *dev, struct dcb_app *app)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!ds->dscp_prio_mapping_is_global)
|
||||
return 0;
|
||||
|
||||
err = dsa_user_dcbnl_ieee_global_dscp_setdel(dev, app, false);
|
||||
if (err) {
|
||||
if (ds->ops->port_del_dscp_prio)
|
||||
ds->ops->port_del_dscp_prio(ds, port, dscp, new_prio);
|
||||
dcb_ieee_delapp(dev, app);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -2290,6 +2353,18 @@ dsa_user_dcbnl_del_dscp_prio(struct net_device *dev, struct dcb_app *app)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!ds->dscp_prio_mapping_is_global)
|
||||
return 0;
|
||||
|
||||
err = dsa_user_dcbnl_ieee_global_dscp_setdel(dev, app, true);
|
||||
if (err) {
|
||||
if (ds->ops->port_add_dscp_prio)
|
||||
ds->ops->port_add_dscp_prio(ds, port, dscp,
|
||||
app->priority);
|
||||
dcb_ieee_setapp(dev, app);
|
||||
return err;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user