net: dsa: microchip: add support DSCP priority mapping
Microchip KSZ and LAN variants do not have per port DSCP priority configuration. Instead there is a global DSCP mapping table. This patch provides write access to this global DSCP map. In case entry is "deleted", we map corresponding DSCP entry to a best effort prio, which is expected to be the default priority for all untagged traffic. Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
5f5109af47
commit
c2e722657f
@ -2360,6 +2360,7 @@ static int ksz_setup(struct dsa_switch *ds)
|
||||
ksz_init_mib_timer(dev);
|
||||
|
||||
ds->configure_vlan_while_not_filtering = false;
|
||||
ds->dscp_prio_mapping_is_global = true;
|
||||
|
||||
if (dev->dev_ops->setup) {
|
||||
ret = dev->dev_ops->setup(ds);
|
||||
@ -3989,6 +3990,8 @@ static const struct dsa_switch_ops ksz_switch_ops = {
|
||||
.port_get_default_prio = ksz_port_get_default_prio,
|
||||
.port_set_default_prio = ksz_port_set_default_prio,
|
||||
.port_get_dscp_prio = ksz_port_get_dscp_prio,
|
||||
.port_add_dscp_prio = ksz_port_add_dscp_prio,
|
||||
.port_del_dscp_prio = ksz_port_del_dscp_prio,
|
||||
.port_get_apptrust = ksz_port_get_apptrust,
|
||||
.port_set_apptrust = ksz_port_set_apptrust,
|
||||
};
|
||||
|
@ -310,6 +310,19 @@ int ksz_port_get_dscp_prio(struct dsa_switch *ds, int port, u8 dscp)
|
||||
return (data >> shift) & mask;
|
||||
}
|
||||
|
||||
static int ksz_set_global_dscp_entry(struct ksz_device *dev, u8 dscp, u8 ipv)
|
||||
{
|
||||
int reg, per_reg, shift;
|
||||
u8 mask;
|
||||
|
||||
ksz_get_dscp_prio_reg(dev, ®, &per_reg, &mask);
|
||||
|
||||
shift = (dscp % per_reg) * (8 / per_reg);
|
||||
|
||||
return ksz_rmw8(dev, reg + (dscp / per_reg), mask << shift,
|
||||
ipv << shift);
|
||||
}
|
||||
|
||||
/**
|
||||
* ksz_init_global_dscp_map - Initializes the global DSCP-to-priority mapping
|
||||
* @dev: Pointer to the KSZ switch device structure
|
||||
@ -321,9 +334,7 @@ int ksz_port_get_dscp_prio(struct dsa_switch *ds, int port, u8 dscp)
|
||||
*/
|
||||
static int ksz_init_global_dscp_map(struct ksz_device *dev)
|
||||
{
|
||||
int reg, per_reg, ret, dscp;
|
||||
u8 data = 0;
|
||||
u8 mask;
|
||||
int ret, dscp;
|
||||
|
||||
/* On KSZ9xxx variants, DSCP remapping is disabled by default.
|
||||
* Enable to have, predictable and reproducible behavior across
|
||||
@ -337,10 +348,8 @@ static int ksz_init_global_dscp_map(struct ksz_device *dev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ksz_get_dscp_prio_reg(dev, ®, &per_reg, &mask);
|
||||
|
||||
for (dscp = 0; dscp < DSCP_MAX; dscp++) {
|
||||
int ipv, shift, tt;
|
||||
int ipv, tt;
|
||||
|
||||
/* Map DSCP to Traffic Type, which is corresponding to the
|
||||
* Internal Priority Value (IPV) in the switch.
|
||||
@ -362,21 +371,42 @@ static int ksz_init_global_dscp_map(struct ksz_device *dev)
|
||||
if (ipv < 0)
|
||||
return ipv;
|
||||
|
||||
shift = (dscp % per_reg) * (8 / per_reg);
|
||||
data |= (ipv & mask) << shift;
|
||||
|
||||
if (dscp % per_reg == per_reg - 1) {
|
||||
ret = ksz_write8(dev, reg + (dscp / per_reg), data);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
data = 0;
|
||||
}
|
||||
ret = ksz_set_global_dscp_entry(dev, dscp, ipv);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ksz_port_add_dscp_prio(struct dsa_switch *ds, int port, u8 dscp, u8 prio)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
|
||||
if (prio >= dev->info->num_ipvs)
|
||||
return -ERANGE;
|
||||
|
||||
return ksz_set_global_dscp_entry(dev, dscp, prio);
|
||||
}
|
||||
|
||||
int ksz_port_del_dscp_prio(struct dsa_switch *ds, int port, u8 dscp, u8 prio)
|
||||
{
|
||||
struct ksz_device *dev = ds->priv;
|
||||
int ipv;
|
||||
|
||||
if (ksz_port_get_dscp_prio(ds, port, dscp) != prio)
|
||||
return 0;
|
||||
|
||||
if (is_ksz8(dev)) {
|
||||
ipv = ieee8021q_tt_to_tc(IEEE8021Q_TT_BE,
|
||||
dev->info->num_tx_queues);
|
||||
if (ipv < 0)
|
||||
return ipv;
|
||||
} else {
|
||||
ipv = IEEE8021Q_TT_BE;
|
||||
}
|
||||
|
||||
return ksz_set_global_dscp_entry(dev, dscp, ipv);
|
||||
}
|
||||
|
||||
/**
|
||||
* ksz_apptrust_error - Prints an error message for an invalid apptrust selector
|
||||
* @dev: Pointer to the KSZ switch device structure
|
||||
|
@ -11,6 +11,8 @@
|
||||
int ksz_port_get_default_prio(struct dsa_switch *ds, int port);
|
||||
int ksz_port_set_default_prio(struct dsa_switch *ds, int port, u8 prio);
|
||||
int ksz_port_get_dscp_prio(struct dsa_switch *ds, int port, u8 dscp);
|
||||
int ksz_port_add_dscp_prio(struct dsa_switch *ds, int port, u8 dscp, u8 prio);
|
||||
int ksz_port_del_dscp_prio(struct dsa_switch *ds, int port, u8 dscp, u8 prio);
|
||||
int ksz_port_set_apptrust(struct dsa_switch *ds, int port,
|
||||
const unsigned char *sel,
|
||||
int nsel);
|
||||
|
Loading…
x
Reference in New Issue
Block a user