Netdev List
 help / color / mirror / Atom feed
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


  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