diff options
author | Oleksij Rempel <o.rempel@pengutronix.de> | 2024-05-03 15:13:50 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2024-05-08 10:35:11 +0100 |
commit | c2e722657f18272a8b8711e94b29466f253715e6 (patch) | |
tree | f3460df4cbb6c1672cfd12d91698108d6c88c548 /drivers/net/dsa | |
parent | 5f5109af47535bc613c12a089dded425a373a12f (diff) |
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>
Diffstat (limited to 'drivers/net/dsa')
-rw-r--r-- | drivers/net/dsa/microchip/ksz_common.c | 3 | ||||
-rw-r--r-- | drivers/net/dsa/microchip/ksz_dcb.c | 60 | ||||
-rw-r--r-- | drivers/net/dsa/microchip/ksz_dcb.h | 2 |
3 files changed, 50 insertions, 15 deletions
diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index 996e8e893b66..bbf9925c98d9 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -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, }; diff --git a/drivers/net/dsa/microchip/ksz_dcb.c b/drivers/net/dsa/microchip/ksz_dcb.c index 80fb322de8f7..5e520c02afd7 100644 --- a/drivers/net/dsa/microchip/ksz_dcb.c +++ b/drivers/net/dsa/microchip/ksz_dcb.c @@ -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,19 +371,40 @@ 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; + ret = ksz_set_global_dscp_entry(dev, dscp, ipv); + } - if (dscp % per_reg == per_reg - 1) { - ret = ksz_write8(dev, reg + (dscp / per_reg), data); - if (ret) - return ret; + return 0; +} - data = 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 0; + return ksz_set_global_dscp_entry(dev, dscp, ipv); } /** diff --git a/drivers/net/dsa/microchip/ksz_dcb.h b/drivers/net/dsa/microchip/ksz_dcb.h index 254c0e7bdafc..e2065223ba90 100644 --- a/drivers/net/dsa/microchip/ksz_dcb.h +++ b/drivers/net/dsa/microchip/ksz_dcb.h @@ -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); |