[PATCH net-next v1 8/8] net: dsa: realtek: rtl8365mb: offload DCB DSCP-to-priority
flat view
COOLING5d
From: Oleksij Rempel <o.rempel@pengutronix.de>
Date: 2026-10-02 11:58:58
Also in:
lkml
Subsystem:
networking drivers, networking [dsa], realtek rtl83xx smi dsa router chips, the rest · Maintainers:
Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Andrew Lunn, Vladimir Oltean, Linus Walleij, Luiz Angelo Daros de Luca, Linus Torvalds
Wire up port_get_dscp_prio/port_add_dscp_prio/port_del_dscp_prio so dcbnl can program the DSCP-to-internal-priority mapping. The mapping only takes effect on ports that trust DSCP via apptrust, so it stays inert on the default (untrusted) configuration. The DSCP table is a single switch-wide resource, so set ds->dscp_prio_mapping_is_global and let the DSA core keep the app table consistent across ports; no per-port bookkeeping is needed. add and del write the global table; del reverts the entry to the standard IETF default for that DSCP (ietf_dscp_to_ieee8021q_tt()) and only when the table still holds the priority being removed, matching dcbnl's replace sequence. rtl8365mb_dcb_init() seeds the whole table with the same IETF mapping so the switch behaves predictably as soon as DSCP is trusted, rather than relying on the chip reset value. Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de> --- drivers/net/dsa/realtek/rtl8365mb_dcb.c | 113 ++++++++++++++++++++++- drivers/net/dsa/realtek/rtl8365mb_dcb.h | 5 + drivers/net/dsa/realtek/rtl8365mb_main.c | 4 + 3 files changed, 120 insertions(+), 2 deletions(-)
diff --git a/drivers/net/dsa/realtek/rtl8365mb_dcb.c b/drivers/net/dsa/realtek/rtl8365mb_dcb.c
index 4afcae6e85a1..091dc8189e73 100644
--- a/drivers/net/dsa/realtek/rtl8365mb_dcb.c
+++ b/drivers/net/dsa/realtek/rtl8365mb_dcb.c@@ -54,10 +54,16 @@ static_assert(RTL8365MB_NUM_IPMS == IEEE8021Q_TT_MAX); #define RTL8365MB_QOS_PORT_PRI_OFFSET(_p) (((_p) & 0x3) << 2) /* Default internal priority for unmarked traffic. Best Effort, to match what - * an untagged (PCP 0) frame resolves to via ieee8021q_pcp_to_tt(). + * an untagged (PCP 0) frame and a default-marked (DSCP CS0) frame resolve to + * via ieee8021q_pcp_to_tt() and ietf_dscp_to_ieee8021q_tt(). */ #define RTL8365MB_QOS_DEFAULT_PRIO IEEE8021Q_TT_BE +/* DSCP -> internal priority. Global table, four DSCP per register, 3-bit. */ +#define RTL8365MB_QOS_DSCP_PRI_REG(_d) (0x0867 + ((_d) >> 2)) +#define RTL8365MB_QOS_DSCP_PRI_OFFSET(_d) (((_d) & 0x3) << 2) +#define RTL8365MB_DSCP_MAX 64 + /* Priority-decision weight tables. Two tables (each port selects one), eight * sources, one 8-bit weight each, two sources per register. Higher weight * wins; a weight of zero disables the source.
@@ -142,6 +148,15 @@ static int rtl8365mb_get_field(struct realtek_priv *priv, u32 reg, u32 mask, return 0; } +static int rtl8365mb_qos_set_dscp_prio(struct realtek_priv *priv, u8 dscp, + u8 prio) +{ + int off = RTL8365MB_QOS_DSCP_PRI_OFFSET(dscp); + + return rtl8365mb_set_field(priv, RTL8365MB_QOS_DSCP_PRI_REG(dscp), + rtl8365mb_qos_sel_field_mask(off), prio); +} + static u32 rtl8365mb_qos_pridec_reg(int table, int src) { return table ? RTL8365MB_QOS_PRIDEC_TBL1_REG(src) :
@@ -234,6 +249,27 @@ static int rtl8365mb_qos_setup_pcp(struct realtek_priv *priv) return 0; } +/* Seed the DSCP -> priority table with the standard IETF mapping, so it is + * meaningful once a port opts in to trusting DSCP via apptrust. + */ +static int rtl8365mb_qos_setup_dscp(struct realtek_priv *priv) +{ + int dscp, ret; + + for (dscp = 0; dscp < RTL8365MB_DSCP_MAX; dscp++) { + int tt = ietf_dscp_to_ieee8021q_tt(dscp); + + if (tt < 0) + return tt; + + ret = rtl8365mb_qos_set_dscp_prio(priv, dscp, tt); + if (ret) + return ret; + } + + return 0; +} + int rtl8365mb_dcb_init(struct dsa_switch *ds) { struct realtek_priv *priv = ds->priv;
@@ -250,6 +286,10 @@ int rtl8365mb_dcb_init(struct dsa_switch *ds) if (ret) return ret; + ret = rtl8365mb_qos_setup_dscp(priv); + if (ret) + return ret; + /* Program every decision source in both tables rather than relying on * the reset state: only the port default carries weight, the other * seven sources are disabled. apptrust later raises the weights in the
@@ -278,7 +318,7 @@ int rtl8365mb_dcb_init_port(struct dsa_switch *ds, int port) struct realtek_priv *priv = ds->priv; /* All ports default to Best Effort: with no source trusted, every port - * treats its traffic as unmarked, matching the default PCP result + * treats its traffic as unmarked, matching the default PCP/DSCP result * so classification stays consistent once the admin opts a source in. */ return rtl8365mb_set_field(priv, RTL8365MB_QOS_PORT_PRI_REG(port),
@@ -324,6 +364,75 @@ int rtl8365mb_port_set_default_prio(struct dsa_switch *ds, int port, u8 prio) rtl8365mb_qos_sel_field_mask(off), tt); } +int rtl8365mb_port_get_dscp_prio(struct dsa_switch *ds, int port, u8 dscp) +{ + int off = RTL8365MB_QOS_DSCP_PRI_OFFSET(dscp); + struct realtek_priv *priv = ds->priv; + u32 val; + int ret; + + if (dscp >= RTL8365MB_DSCP_MAX) + return -EINVAL; + + ret = rtl8365mb_get_field(priv, RTL8365MB_QOS_DSCP_PRI_REG(dscp), + rtl8365mb_qos_sel_field_mask(off), &val); + if (ret) + return ret; + + /* The register holds the internal priority (an 802.1Q traffic type); + * dcbnl expects an 802.1p priority. + */ + return ieee8021q_tt_to_pcp(val); +} + +int rtl8365mb_port_add_dscp_prio(struct dsa_switch *ds, int port, u8 dscp, + u8 prio) +{ + struct realtek_priv *priv = ds->priv; + int tt; + + if (dscp >= RTL8365MB_DSCP_MAX) + return -EINVAL; + + if (prio >= IEEE_8021Q_MAX_PRIORITIES) + return -ERANGE; + + /* dcbnl passes an 802.1p priority; the register holds the internal + * priority (an 802.1Q traffic type). + */ + tt = ieee8021q_pcp_to_tt(prio); + if (tt < 0) + return tt; + + return rtl8365mb_qos_set_dscp_prio(priv, dscp, tt); +} + +int rtl8365mb_port_del_dscp_prio(struct dsa_switch *ds, int port, u8 dscp, + u8 prio) +{ + struct realtek_priv *priv = ds->priv; + int tt, ret; + + if (dscp >= RTL8365MB_DSCP_MAX) + return -EINVAL; + + /* dcbnl replaces an entry by adding the new one before deleting the + * old, so only revert if the table still holds the removed priority. + */ + ret = rtl8365mb_port_get_dscp_prio(ds, port, dscp); + if (ret < 0) + return ret; + if (ret != prio) + return 0; + + /* Revert to the standard IETF default mapping for this DSCP. */ + tt = ietf_dscp_to_ieee8021q_tt(dscp); + if (tt < 0) + return tt; + + return rtl8365mb_qos_set_dscp_prio(priv, dscp, tt); +} + /* Read which sources a decision table trusts (weight != 0), indexed like * rtl8365mb_apptrust_map[]. */
diff --git a/drivers/net/dsa/realtek/rtl8365mb_dcb.h b/drivers/net/dsa/realtek/rtl8365mb_dcb.h
index 156fa6e1c4fd..ebe6f1628734 100644
--- a/drivers/net/dsa/realtek/rtl8365mb_dcb.h
+++ b/drivers/net/dsa/realtek/rtl8365mb_dcb.h@@ -20,5 +20,10 @@ int rtl8365mb_port_get_apptrust(struct dsa_switch *ds, int port, u8 *sel, int *nsel); int rtl8365mb_port_set_apptrust(struct dsa_switch *ds, int port, const u8 *sel, int nsel); +int rtl8365mb_port_get_dscp_prio(struct dsa_switch *ds, int port, u8 dscp); +int rtl8365mb_port_add_dscp_prio(struct dsa_switch *ds, int port, u8 dscp, + u8 prio); +int rtl8365mb_port_del_dscp_prio(struct dsa_switch *ds, int port, u8 dscp, + u8 prio); #endif /* _REALTEK_RTL8365MB_DCB_H */
diff --git a/drivers/net/dsa/realtek/rtl8365mb_main.c b/drivers/net/dsa/realtek/rtl8365mb_main.c
index 77f971abf783..9fe87c295795 100644
--- a/drivers/net/dsa/realtek/rtl8365mb_main.c
+++ b/drivers/net/dsa/realtek/rtl8365mb_main.c@@ -3283,6 +3283,7 @@ static int rtl8365mb_setup(struct dsa_switch *ds) /* Establish a defined QoS baseline: program the priority-to-queue map * for the chip's queue count and trust only the port default priority. */ + ds->dscp_prio_mapping_is_global = true; ret = rtl8365mb_dcb_init(ds); if (ret) goto out_teardown_irq;
@@ -3452,6 +3453,9 @@ static const struct dsa_switch_ops rtl8365mb_switch_ops = { .port_set_default_prio = rtl8365mb_port_set_default_prio, .port_get_apptrust = rtl8365mb_port_get_apptrust, .port_set_apptrust = rtl8365mb_port_set_apptrust, + .port_get_dscp_prio = rtl8365mb_port_get_dscp_prio, + .port_add_dscp_prio = rtl8365mb_port_add_dscp_prio, + .port_del_dscp_prio = rtl8365mb_port_del_dscp_prio, .port_stp_state_set = rtl8365mb_port_stp_state_set, .port_fast_age = rtl83xx_port_fast_age, .port_fdb_add = rtl83xx_port_fdb_add,
--
2.47.3