mirror of
https://github.com/torvalds/linux
synced 2024-10-06 19:34:19 +00:00
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;
|
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 */
|
/* Listener for switch fabric events */
|
||||||
struct notifier_block nb;
|
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)) \
|
dsa_switch_for_each_port((_dp), (_ds)) \
|
||||||
if (dsa_port_is_user((_dp)))
|
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) \
|
#define dsa_switch_for_each_cpu_port(_dp, _ds) \
|
||||||
dsa_switch_for_each_port((_dp), (_ds)) \
|
dsa_switch_for_each_port((_dp), (_ds)) \
|
||||||
if (dsa_port_is_cpu((_dp)))
|
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;
|
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
|
static int __maybe_unused
|
||||||
dsa_user_dcbnl_add_dscp_prio(struct net_device *dev, struct dcb_app *app)
|
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;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2290,6 +2353,18 @@ dsa_user_dcbnl_del_dscp_prio(struct net_device *dev, struct dcb_app *app)
|
||||||
return err;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue