summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorOleksij Rempel <o.rempel@pengutronix.de>2024-05-03 15:13:50 +0200
committerDavid S. Miller <davem@davemloft.net>2024-05-08 10:35:11 +0100
commitc2e722657f18272a8b8711e94b29466f253715e6 (patch)
treef3460df4cbb6c1672cfd12d91698108d6c88c548
parent5f5109af47535bc613c12a089dded425a373a12f (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>
-rw-r--r--drivers/net/dsa/microchip/ksz_common.c3
-rw-r--r--drivers/net/dsa/microchip/ksz_dcb.c60
-rw-r--r--drivers/net/dsa/microchip/ksz_dcb.h2
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, &reg, &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, &reg, &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);