From: Oleksij Rempel <o.rempel@pengutronix.de>
To: Linus Walleij <linusw@kernel.org>,
Luiz Angelo Daros de Luca <luizluca@gmail.com>,
Andrew Lunn <andrew@lunn.ch>, Vladimir Oltean <olteanv@gmail.com>,
"David S. Miller" <davem@davemloft.net>,
Eric Dumazet <edumazet@kernel.org>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>
Cc: "Oleksij Rempel" <o.rempel@pengutronix.de>,
kernel@pengutronix.de, linux-kernel@vger.kernel.org,
"Alvin Šipraga" <alvin.sipraga@analog.com>,
netdev@vger.kernel.org, "Simon Horman" <horms@kernel.org>
Subject: [PATCH net-next v1 8/8] net: dsa: realtek: rtl8365mb: offload DCB DSCP-to-priority
Date: Fri, 2 Oct 2026 13:58:50 +0200 [thread overview]
Message-ID: <20261002115850.962676-9-o.rempel@pengutronix.de> (raw)
In-Reply-To: <20261002115850.962676-1-o.rempel@pengutronix.de>
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
next prev parent reply other threads:[~2026-10-02 11:58 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-02 11:58 [PATCH net-next v1 0/8] net: dsa: realtek: rtl8365mb: DCB ingress QoS offload Oleksij Rempel
2026-10-02 11:58 ` [PATCH net-next v1 1/8] net: ieee8021q: print traffic type and queue count with %u Oleksij Rempel
2026-10-02 14:22 ` Luiz Angelo Daros de Luca
2026-10-05 15:04 ` Linus Walleij
2026-10-02 11:58 ` [PATCH net-next v1 2/8] net: ieee8021q: add pcp_to_tt() Oleksij Rempel
2026-10-05 15:06 ` Linus Walleij
2026-10-02 11:58 ` [PATCH net-next v1 3/8] net: ieee8021q: clarify the tt_to_tc() traffic-class mapping Oleksij Rempel
2026-10-05 15:07 ` Linus Walleij
2026-10-02 11:58 ` [PATCH net-next v1 4/8] net: ieee8021q: add tt_to_pcp() Oleksij Rempel
2026-10-05 15:08 ` Linus Walleij
2026-10-02 11:58 ` [PATCH net-next v1 5/8] net: dsa: realtek: rtl8365mb: store the egress queue count per chip Oleksij Rempel
2026-10-05 15:10 ` Linus Walleij
2026-10-05 15:12 ` Linus Walleij
2026-10-02 11:58 ` [PATCH net-next v1 6/8] net: dsa: realtek: rtl8365mb: add QoS baseline and DCB default priority Oleksij Rempel
2026-10-05 23:18 ` Linus Walleij
2026-10-02 11:58 ` [PATCH net-next v1 7/8] net: dsa: realtek: rtl8365mb: offload DCB apptrust Oleksij Rempel
2026-10-05 23:38 ` Linus Walleij
2026-10-06 13:43 ` netdev-bot+sashiko
2026-10-02 11:58 ` Oleksij Rempel [this message]
2026-10-06 13:43 ` [PATCH net-next v1 8/8] net: dsa: realtek: rtl8365mb: offload DCB DSCP-to-priority netdev-bot+sashiko
2026-10-05 15:03 ` [PATCH net-next v1 0/8] net: dsa: realtek: rtl8365mb: DCB ingress QoS offload Linus Walleij
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261002115850.962676-9-o.rempel@pengutronix.de \
--to=o.rempel@pengutronix.de \
--cc=alvin.sipraga@analog.com \
--cc=andrew@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@kernel.org \
--cc=horms@kernel.org \
--cc=kernel@pengutronix.de \
--cc=kuba@kernel.org \
--cc=linusw@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=luizluca@gmail.com \
--cc=netdev@vger.kernel.org \
--cc=olteanv@gmail.com \
--cc=pabeni@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox