* [PATCH net-next v1 0/8] net: dsa: realtek: rtl8365mb: DCB ingress QoS offload
@ 2026-10-02 11:58 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
` (8 more replies)
0 siblings, 9 replies; 19+ messages in thread
From: Oleksij Rempel @ 2026-10-02 11:58 UTC (permalink / raw)
To: Linus Walleij, Luiz Angelo Daros de Luca, Andrew Lunn,
Vladimir Oltean, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: Oleksij Rempel, kernel, linux-kernel, Alvin Šipraga, netdev,
Simon Horman
Add DCB-based ingress QoS offload for the RTL8365MB switch via the dcbnl
app interface: a per-port default priority, PCP trust, and DSCP trust.
It also adds the few net/core ieee8021q helpers the driver needs.
Nothing changes on the wire until an admin enables PCP or DSCP trust;
until then every frame takes the port default and lands on one queue.
Tested on an RTL8365MB-VC.
ETS scheduling and CPU-tag ingress pre-classification build on this and
will follow once it lands.
Oleksij Rempel (8):
net: ieee8021q: print traffic type and queue count with %u
net: ieee8021q: add pcp_to_tt()
net: ieee8021q: clarify the tt_to_tc() traffic-class mapping
net: ieee8021q: add tt_to_pcp()
net: dsa: realtek: rtl8365mb: store the egress queue count per chip
net: dsa: realtek: rtl8365mb: add QoS baseline and DCB default
priority
net: dsa: realtek: rtl8365mb: offload DCB apptrust
net: dsa: realtek: rtl8365mb: offload DCB DSCP-to-priority
drivers/net/dsa/realtek/Kconfig | 2 +
drivers/net/dsa/realtek/Makefile | 1 +
drivers/net/dsa/realtek/rtl8365mb_dcb.c | 589 +++++++++++++++++++++++
drivers/net/dsa/realtek/rtl8365mb_dcb.h | 29 ++
drivers/net/dsa/realtek/rtl8365mb_main.c | 33 ++
include/net/ieee8021q.h | 16 +-
net/core/ieee8021q_helpers.c | 115 ++++-
7 files changed, 768 insertions(+), 17 deletions(-)
create mode 100644 drivers/net/dsa/realtek/rtl8365mb_dcb.c
create mode 100644 drivers/net/dsa/realtek/rtl8365mb_dcb.h
--
2.47.3
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH net-next v1 1/8] net: ieee8021q: print traffic type and queue count with %u
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 ` 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
` (7 subsequent siblings)
8 siblings, 2 replies; 19+ messages in thread
From: Oleksij Rempel @ 2026-10-02 11:58 UTC (permalink / raw)
To: Linus Walleij, Luiz Angelo Daros de Luca, Andrew Lunn,
Vladimir Oltean, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: Oleksij Rempel, kernel, linux-kernel, Alvin Šipraga, netdev,
Simon Horman
Switch the out-of-range diagnostic in ieee8021q_tt_to_tc() from %d to
%u. The traffic class count num_queues is an unsigned int and the
traffic type is an enumeration, so printing them as unsigned matches
their types. The print sits on the range-check error path, which still
rejects a negative traffic type; %u only changes how an out-of-range
value is rendered, not which values are rejected.
Preparation for the inverse helper added next, which follows the same
convention.
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
net/core/ieee8021q_helpers.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/core/ieee8021q_helpers.c b/net/core/ieee8021q_helpers.c
index 669b357b73b2..bbacdfff9b4c 100644
--- a/net/core/ieee8021q_helpers.c
+++ b/net/core/ieee8021q_helpers.c
@@ -99,7 +99,7 @@ static const u8 ieee8021q_1queue_tt_tc_map[] = {
int ieee8021q_tt_to_tc(enum ieee8021q_traffic_type tt, unsigned int num_queues)
{
if (tt < 0 || tt >= IEEE8021Q_TT_MAX) {
- pr_err("Requested Traffic Type (%d) is out of range (%d)\n", tt,
+ pr_err("Requested Traffic Type (%u) is out of range (%u)\n", tt,
IEEE8021Q_TT_MAX);
return -EINVAL;
}
@@ -131,7 +131,7 @@ int ieee8021q_tt_to_tc(enum ieee8021q_traffic_type tt, unsigned int num_queues)
return ieee8021q_1queue_tt_tc_map[tt];
}
- pr_err("Invalid number of queues %d\n", num_queues);
+ pr_err("Invalid number of queues %u\n", num_queues);
return -EINVAL;
}
--
2.47.3
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH net-next v1 2/8] net: ieee8021q: add pcp_to_tt()
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 11:58 ` 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
` (6 subsequent siblings)
8 siblings, 1 reply; 19+ messages in thread
From: Oleksij Rempel @ 2026-10-02 11:58 UTC (permalink / raw)
To: Linus Walleij, Luiz Angelo Daros de Luca, Andrew Lunn,
Vladimir Oltean, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: Oleksij Rempel, kernel, linux-kernel, Alvin Šipraga, netdev,
Simon Horman
Add a helper that maps an IEEE 802.1Q Priority Code Point (PCP) to the
corresponding 802.1Q traffic type, complementing the existing
ietf_dscp_to_ieee8021q_tt().
It is very nearly an identity map, except that PCP 0 (Best Effort) and
PCP 1 (Background) are swapped: per 802.1Q-2022 (Annex I, Table I-2)
Background is a lower priority than Best Effort even though it carries
the higher PCP value. PCP 2..7 map straight through to the matching
traffic type, and values above 7 are rejected with -EINVAL. This decodes
the 8P0D encoding (Table I-7), where every PCP value is a priority and
none carries drop eligibility.
Drivers that classify ingress traffic by PCP need this to map into a
priority-ordered internal space without misordering Best Effort and
Background. The first consumer, the realtek rtl8365mb DSA driver, lands
later in this series.
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
include/net/ieee8021q.h | 10 +++++++--
net/core/ieee8021q_helpers.c | 41 ++++++++++++++++++++++++++++++++++++
2 files changed, 49 insertions(+), 2 deletions(-)
diff --git a/include/net/ieee8021q.h b/include/net/ieee8021q.h
index 8bfe903dd3d0..d24e4036577b 100644
--- a/include/net/ieee8021q.h
+++ b/include/net/ieee8021q.h
@@ -10,8 +10,8 @@
* enum ieee8021q_traffic_type - 802.1Q traffic type priority values (802.1Q-2022)
*
* @IEEE8021Q_TT_BK: Background
- * @IEEE8021Q_TT_BE: Best Effort (default). According to 802.1Q-2022, BE is 0
- * but has higher priority than BK which is 1.
+ * @IEEE8021Q_TT_BE: Best Effort (default). According to 802.1Q-2022 (Annex I,
+ * Table I-2), BE is 0 but has higher priority than BK which is 1.
* @IEEE8021Q_TT_EE: Excellent Effort
* @IEEE8021Q_TT_CA: Critical Applications
* @IEEE8021Q_TT_VI: Video, < 100 ms latency and jitter
@@ -38,6 +38,7 @@ enum ieee8021q_traffic_type {
#if IS_ENABLED(CONFIG_NET_IEEE8021Q_HELPERS)
int ietf_dscp_to_ieee8021q_tt(u8 dscp);
+int ieee8021q_pcp_to_tt(u8 pcp);
int ieee8021q_tt_to_tc(enum ieee8021q_traffic_type tt, unsigned int num_queues);
#else
@@ -47,6 +48,11 @@ static inline int ietf_dscp_to_ieee8021q_tt(u8 dscp)
return -EOPNOTSUPP;
}
+static inline int ieee8021q_pcp_to_tt(u8 pcp)
+{
+ return -EOPNOTSUPP;
+}
+
static inline int ieee8021q_tt_to_tc(enum ieee8021q_traffic_type tt,
unsigned int num_queues)
{
diff --git a/net/core/ieee8021q_helpers.c b/net/core/ieee8021q_helpers.c
index bbacdfff9b4c..a5bd5e039b47 100644
--- a/net/core/ieee8021q_helpers.c
+++ b/net/core/ieee8021q_helpers.c
@@ -222,3 +222,44 @@ int ietf_dscp_to_ieee8021q_tt(u8 dscp)
return SIMPLE_IETF_DSCP_TO_IEEE8021Q_TT(dscp);
}
EXPORT_SYMBOL_GPL(ietf_dscp_to_ieee8021q_tt);
+
+/**
+ * ieee8021q_pcp_to_tt - Map an IEEE 802.1Q PCP to a traffic type
+ * @pcp: IEEE 802.1Q Priority Code Point value
+ *
+ * Decode @pcp to its IEEE 802.1Q traffic type per Table I-7 ("Priority Code
+ * Point decoding") for the 8P0D encoding, where all eight PCP values are
+ * priorities and none carries drop eligibility. It is nearly the identity,
+ * except PCP 0 (Best Effort) and PCP 1 (Background) map to swapped traffic
+ * types: Background is lower priority than Best Effort despite the higher PCP
+ * value (Table I-2: BE = priority 0, BK = priority 1).
+ *
+ * The 7P1D/6P2D/5P3D encodings, whose lower PCP values carry drop eligibility,
+ * are the other rows of Table I-7 and are not decoded here.
+ *
+ * Return: the traffic type, or a negative value on error.
+ */
+int ieee8021q_pcp_to_tt(u8 pcp)
+{
+ switch (pcp) {
+ case 0:
+ return IEEE8021Q_TT_BE;
+ case 1:
+ return IEEE8021Q_TT_BK;
+ case 2:
+ return IEEE8021Q_TT_EE;
+ case 3:
+ return IEEE8021Q_TT_CA;
+ case 4:
+ return IEEE8021Q_TT_VI;
+ case 5:
+ return IEEE8021Q_TT_VO;
+ case 6:
+ return IEEE8021Q_TT_IC;
+ case 7:
+ return IEEE8021Q_TT_NC;
+ }
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(ieee8021q_pcp_to_tt);
--
2.47.3
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH net-next v1 3/8] net: ieee8021q: clarify the tt_to_tc() traffic-class mapping
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 11:58 ` [PATCH net-next v1 2/8] net: ieee8021q: add pcp_to_tt() Oleksij Rempel
@ 2026-10-02 11:58 ` 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
` (5 subsequent siblings)
8 siblings, 1 reply; 19+ messages in thread
From: Oleksij Rempel @ 2026-10-02 11:58 UTC (permalink / raw)
To: Linus Walleij, Luiz Angelo Daros de Luca, Andrew Lunn,
Vladimir Oltean, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: Oleksij Rempel, kernel, linux-kernel, Alvin Šipraga, netdev,
Simon Horman
Document that the tt_to_tc() traffic-class numbers are the pre-computed
composition of Table I-2 (traffic type -> priority) with Table 8-5
(priority -> traffic class). Note that Table 8-5 is the mapping for
implementations without the credit-based shaper, so the helper's scope
is clear; credit-based-shaper implementations use Table 34-1/34-2
instead.
The existing kdoc cited Annex I Table I-1 as the mapping basis, but
Table I-1 only partitions traffic types into classes; it does not assign
the class numbers.
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
net/core/ieee8021q_helpers.c | 30 +++++++++++++++++-------------
1 file changed, 17 insertions(+), 13 deletions(-)
diff --git a/net/core/ieee8021q_helpers.c b/net/core/ieee8021q_helpers.c
index a5bd5e039b47..520d86d592eb 100644
--- a/net/core/ieee8021q_helpers.c
+++ b/net/core/ieee8021q_helpers.c
@@ -12,10 +12,10 @@
compiletime_assert(ARRAY_SIZE(tbl) == IEEE8021Q_TT_MAX, \
#tbl " size mismatch")
-/* The following arrays map Traffic Types (TT) to traffic classes (TC) for
- * different number of queues as shown in the example provided by
- * IEEE 802.1Q-2022 in Annex I "I.3 Traffic type to traffic class mapping" and
- * Table I-1 "Traffic type to traffic class mapping".
+/* The following arrays map a traffic type (TT) to a traffic class (TC) for
+ * each supported number of queues. The mapping is the traffic-type -> priority
+ * -> traffic-class composition documented in the ieee8021q_tt_to_tc() kdoc
+ * below, reduced for the given number of queues.
*/
static const u8 ieee8021q_8queue_tt_tc_map[] = {
[IEEE8021Q_TT_BK] = 0,
@@ -84,17 +84,21 @@ static const u8 ieee8021q_1queue_tt_tc_map[] = {
};
/**
- * ieee8021q_tt_to_tc - Map IEEE 802.1Q Traffic Type to Traffic Class
- * @tt: IEEE 802.1Q Traffic Type
- * @num_queues: Number of queues
+ * ieee8021q_tt_to_tc - Map an IEEE 802.1Q traffic type to a traffic class
+ * @tt: IEEE 802.1Q traffic type
+ * @num_queues: number of traffic classes (queues) available, 1..8
*
- * This function maps an IEEE 802.1Q Traffic Type to a Traffic Class (TC) based
- * on the number of queues configured on the NIC. The mapping is based on the
- * example provided by IEEE 802.1Q-2022 in Annex I "I.3 Traffic type to traffic
- * class mapping" and Table I-1 "Traffic type to traffic class mapping".
+ * Return the traffic-class number for @tt. It is the pre-computed composition
+ * of two IEEE 802.1Q-2022 mappings:
*
- * Return: Traffic Class corresponding to the given Traffic Type or negative
- * value in case of error.
+ * traffic type --[Table I-2]--> priority --[Table 8-5]--> traffic class
+ *
+ * Table 8-5 is the priority-to-traffic-class mapping for implementations that
+ * do NOT support the credit-based shaper (8.6.8.2). Credit-based-shaper
+ * implementations use a different mapping (Table 34-1 for SR classes A and B,
+ * or Table 34-2 for SR class B only), which this helper does not implement.
+ *
+ * Return: the traffic class, or a negative value on error.
*/
int ieee8021q_tt_to_tc(enum ieee8021q_traffic_type tt, unsigned int num_queues)
{
--
2.47.3
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH net-next v1 4/8] net: ieee8021q: add tt_to_pcp()
2026-10-02 11:58 [PATCH net-next v1 0/8] net: dsa: realtek: rtl8365mb: DCB ingress QoS offload Oleksij Rempel
` (2 preceding siblings ...)
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-02 11:58 ` 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
` (4 subsequent siblings)
8 siblings, 1 reply; 19+ messages in thread
From: Oleksij Rempel @ 2026-10-02 11:58 UTC (permalink / raw)
To: Linus Walleij, Luiz Angelo Daros de Luca, Andrew Lunn,
Vladimir Oltean, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: Oleksij Rempel, kernel, linux-kernel, Alvin Šipraga, netdev,
Simon Horman
Add ieee8021q_tt_to_pcp(), the inverse of ieee8021q_pcp_to_tt(): it
encodes an 802.1Q traffic type back to its Priority Code Point, and
completes the pcp/tt helper family.
A driver that reseeds its PCP classifier through ieee8021q_pcp_to_tt()
stores traffic types in the hardware tables, while the dcbnl priority
ops exchange 802.1p priorities across the DSA boundary. Reading such a
table back therefore needs the reverse mapping to restore the 802.1p
value, which no existing helper provides. Because pcp_to_tt only
transposes Best Effort and Background and is the identity elsewhere the
two directions are numerically equal; provide tt_to_pcp as its own named
function so the read path does not decode a traffic type as if it were a
PCP.
The first user is the Realtek rtl8365mb DSA driver, whose dcbnl
get_default_prio and get_dscp_prio paths read back traffic types and
must return 802.1p priorities.
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
include/net/ieee8021q.h | 6 ++++++
net/core/ieee8021q_helpers.c | 40 ++++++++++++++++++++++++++++++++++++
2 files changed, 46 insertions(+)
diff --git a/include/net/ieee8021q.h b/include/net/ieee8021q.h
index d24e4036577b..b09572da0289 100644
--- a/include/net/ieee8021q.h
+++ b/include/net/ieee8021q.h
@@ -39,6 +39,7 @@ enum ieee8021q_traffic_type {
int ietf_dscp_to_ieee8021q_tt(u8 dscp);
int ieee8021q_pcp_to_tt(u8 pcp);
+int ieee8021q_tt_to_pcp(enum ieee8021q_traffic_type tt);
int ieee8021q_tt_to_tc(enum ieee8021q_traffic_type tt, unsigned int num_queues);
#else
@@ -53,6 +54,11 @@ static inline int ieee8021q_pcp_to_tt(u8 pcp)
return -EOPNOTSUPP;
}
+static inline int ieee8021q_tt_to_pcp(enum ieee8021q_traffic_type tt)
+{
+ return -EOPNOTSUPP;
+}
+
static inline int ieee8021q_tt_to_tc(enum ieee8021q_traffic_type tt,
unsigned int num_queues)
{
diff --git a/net/core/ieee8021q_helpers.c b/net/core/ieee8021q_helpers.c
index 520d86d592eb..205c11793473 100644
--- a/net/core/ieee8021q_helpers.c
+++ b/net/core/ieee8021q_helpers.c
@@ -267,3 +267,43 @@ int ieee8021q_pcp_to_tt(u8 pcp)
return -EINVAL;
}
EXPORT_SYMBOL_GPL(ieee8021q_pcp_to_tt);
+
+/**
+ * ieee8021q_tt_to_pcp - Map an IEEE 802.1Q traffic type to a PCP
+ * @tt: IEEE 802.1Q traffic type
+ *
+ * Encode @tt back to its IEEE 802.1Q Priority Code Point per Table I-7
+ * ("Priority Code Point decoding") for the 8P0D encoding, the inverse of
+ * ieee8021q_pcp_to_tt(). It is nearly the identity, except traffic types Best
+ * Effort and Background map to swapped PCP values: Best Effort is the default
+ * (PCP 0) despite being higher priority than Background (PCP 1) (Table I-2:
+ * BE = priority 0, BK = priority 1).
+ *
+ * Return: the PCP value, or a negative value on error.
+ */
+int ieee8021q_tt_to_pcp(enum ieee8021q_traffic_type tt)
+{
+ switch (tt) {
+ case IEEE8021Q_TT_BK:
+ return 1;
+ case IEEE8021Q_TT_BE:
+ return 0;
+ case IEEE8021Q_TT_EE:
+ return 2;
+ case IEEE8021Q_TT_CA:
+ return 3;
+ case IEEE8021Q_TT_VI:
+ return 4;
+ case IEEE8021Q_TT_VO:
+ return 5;
+ case IEEE8021Q_TT_IC:
+ return 6;
+ case IEEE8021Q_TT_NC:
+ return 7;
+ case IEEE8021Q_TT_MAX:
+ break;
+ }
+
+ return -EINVAL;
+}
+EXPORT_SYMBOL_GPL(ieee8021q_tt_to_pcp);
--
2.47.3
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH net-next v1 5/8] net: dsa: realtek: rtl8365mb: store the egress queue count per chip
2026-10-02 11:58 [PATCH net-next v1 0/8] net: dsa: realtek: rtl8365mb: DCB ingress QoS offload Oleksij Rempel
` (3 preceding siblings ...)
2026-10-02 11:58 ` [PATCH net-next v1 4/8] net: ieee8021q: add tt_to_pcp() Oleksij Rempel
@ 2026-10-02 11:58 ` Oleksij Rempel
2026-10-05 15:10 ` 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
` (3 subsequent siblings)
8 siblings, 1 reply; 19+ messages in thread
From: Oleksij Rempel @ 2026-10-02 11:58 UTC (permalink / raw)
To: Linus Walleij, Luiz Angelo Daros de Luca, Andrew Lunn,
Vladimir Oltean, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: Oleksij Rempel, kernel, linux-kernel, Alvin Šipraga, netdev,
Simon Horman
Store the number of egress queues in the per-chip info structure and
advertise it through ds->num_tx_queues, following the ksz driver
(struct ksz_chip_data.num_tx_queues).
The queue count is a per-chip hardware property, and this driver supports
several chips of the rtl8367c family. All currently-supported chips expose
eight queues, but keeping the count in chip_info lets the QoS code that
follows program the priority-to-queue map via the ieee8021q helpers for
whatever queue count a chip carries, so the 802.1Q collapse is correct
rather than hard-coded to eight.
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
drivers/net/dsa/realtek/rtl8365mb_main.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/drivers/net/dsa/realtek/rtl8365mb_main.c b/drivers/net/dsa/realtek/rtl8365mb_main.c
index 87ec924a0611..0924d31790e0 100644
--- a/drivers/net/dsa/realtek/rtl8365mb_main.c
+++ b/drivers/net/dsa/realtek/rtl8365mb_main.c
@@ -708,6 +708,7 @@ struct rtl8365mb_extint {
* @extints: available external interfaces
* @jam_table: chip-specific initialization jam table
* @jam_size: size of the chip's jam table
+ * @num_tx_queues: number of egress queues exposed by the chip
*
* These data are specific to a given chip in the family of switches supported
* by this driver. When adding support for another chip in the family, a new
@@ -720,6 +721,7 @@ struct rtl8365mb_chip_info {
const struct rtl8365mb_extint extints[RTL8365MB_MAX_NUM_EXTINTS];
const struct rtl8365mb_jam_tbl_entry *jam_table;
size_t jam_size;
+ unsigned int num_tx_queues;
};
/* Chip info for each supported switch in the family */
@@ -735,6 +737,7 @@ static const struct rtl8365mb_chip_info rtl8365mb_chip_infos[] = {
},
.jam_table = rtl8365mb_init_jam_8365mb_vc,
.jam_size = ARRAY_SIZE(rtl8365mb_init_jam_8365mb_vc),
+ .num_tx_queues = 8,
},
{
.name = "RTL8367S",
@@ -747,6 +750,7 @@ static const struct rtl8365mb_chip_info rtl8365mb_chip_infos[] = {
},
.jam_table = rtl8365mb_init_jam_8365mb_vc,
.jam_size = ARRAY_SIZE(rtl8365mb_init_jam_8365mb_vc),
+ .num_tx_queues = 8,
},
{
.name = "RTL8367SB",
@@ -761,6 +765,7 @@ static const struct rtl8365mb_chip_info rtl8365mb_chip_infos[] = {
},
.jam_table = rtl8365mb_init_jam_8365mb_vc,
.jam_size = ARRAY_SIZE(rtl8365mb_init_jam_8365mb_vc),
+ .num_tx_queues = 8,
},
{
.name = "RTL8367RB-VB",
@@ -774,6 +779,7 @@ static const struct rtl8365mb_chip_info rtl8365mb_chip_infos[] = {
},
.jam_table = rtl8365mb_init_jam_8365mb_vc,
.jam_size = ARRAY_SIZE(rtl8365mb_init_jam_8365mb_vc),
+ .num_tx_queues = 8,
},
};
@@ -3262,6 +3268,12 @@ static int rtl8365mb_setup(struct dsa_switch *ds)
goto out_teardown_irq;
}
+ /* The rtl8367c family this driver supports exposes a fixed number of
+ * egress queues per chip; advertise that count to DSA so the QoS code
+ * programs the priority-to-queue map for the right number of queues.
+ */
+ ds->num_tx_queues = mb->chip_info->num_tx_queues;
+
/* Start statistics counter polling */
ret = rtl8365mb_stats_setup(priv);
if (ret) {
--
2.47.3
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH net-next v1 6/8] net: dsa: realtek: rtl8365mb: add QoS baseline and DCB default priority
2026-10-02 11:58 [PATCH net-next v1 0/8] net: dsa: realtek: rtl8365mb: DCB ingress QoS offload Oleksij Rempel
` (4 preceding siblings ...)
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-02 11:58 ` 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
` (2 subsequent siblings)
8 siblings, 1 reply; 19+ messages in thread
From: Oleksij Rempel @ 2026-10-02 11:58 UTC (permalink / raw)
To: Linus Walleij, Luiz Angelo Daros de Luca, Andrew Lunn,
Vladimir Oltean, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: Oleksij Rempel, kernel, linux-kernel, Alvin Šipraga, netdev,
Simon Horman
Add rtl8365mb_dcb.c to establish a defined QoS baseline and offload the
DCB default priority.
The switch's internal priority is an opaque 3-bit value; give it the
meaning of an IEEE 802.1Q traffic type. The switch classifies from
several domains, each numbered on its own scale: the port default, PCP
and DSCP. A single traffic-type meaning lets each domain map onto the
internal priority with consistent ordering, so Best Effort outranks
Background rather than following the raw PCP number.
Program the baseline explicitly rather than trusting the chip reset
state: set the priority-to-queue map for the chip's queue count, remap
PCP to the internal priority, and give every one of the eight
priority-decision sources a defined weight. Only the port default is
trusted; PCP and DSCP stay untrusted until the admin opts in (apptrust,
added later), and every port defaults to Best Effort, so all traffic
lands on a single egress queue and the baseline has no user-visible
effect on its own.
Select DCB and the 802.1Q helpers following the microchip ksz driver, so
the DCB code needs no CONFIG_DCB guards.
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
drivers/net/dsa/realtek/Kconfig | 2 +
drivers/net/dsa/realtek/Makefile | 1 +
drivers/net/dsa/realtek/rtl8365mb_dcb.c | 287 +++++++++++++++++++++++
drivers/net/dsa/realtek/rtl8365mb_dcb.h | 20 ++
drivers/net/dsa/realtek/rtl8365mb_main.c | 15 ++
5 files changed, 325 insertions(+)
create mode 100644 drivers/net/dsa/realtek/rtl8365mb_dcb.c
create mode 100644 drivers/net/dsa/realtek/rtl8365mb_dcb.h
diff --git a/drivers/net/dsa/realtek/Kconfig b/drivers/net/dsa/realtek/Kconfig
index d6eb6713e5f6..934833adde58 100644
--- a/drivers/net/dsa/realtek/Kconfig
+++ b/drivers/net/dsa/realtek/Kconfig
@@ -33,6 +33,8 @@ config NET_DSA_REALTEK_RTL8365MB
tristate "Realtek RTL8365MB switch driver"
depends on NET_DSA_REALTEK_SMI || NET_DSA_REALTEK_MDIO
select NET_DSA_TAG_RTL8_4
+ select NET_IEEE8021Q_HELPERS
+ select DCB
help
Select to enable support for Realtek RTL8365MB-VC and RTL8367S.
diff --git a/drivers/net/dsa/realtek/Makefile b/drivers/net/dsa/realtek/Makefile
index 72bb42e80c95..052a924519e8 100644
--- a/drivers/net/dsa/realtek/Makefile
+++ b/drivers/net/dsa/realtek/Makefile
@@ -20,4 +20,5 @@ rtl8365mb-objs := rtl8365mb_main.o \
rtl8365mb_table.o \
rtl8365mb_vlan.o \
rtl8365mb_l2.o \
+ rtl8365mb_dcb.o \
# end of rtl8365mb-objs
diff --git a/drivers/net/dsa/realtek/rtl8365mb_dcb.c b/drivers/net/dsa/realtek/rtl8365mb_dcb.c
new file mode 100644
index 000000000000..f48e95ef3947
--- /dev/null
+++ b/drivers/net/dsa/realtek/rtl8365mb_dcb.c
@@ -0,0 +1,287 @@
+// SPDX-License-Identifier: GPL-2.0
+/* QoS and DCB configuration for the rtl8365mb switch family
+ *
+ * The internal priority is the common rail: every classifier writes onto it,
+ * and it is the 802.1Q traffic type.
+ *
+ * A queue is a traffic class. Priority is not the same as traffic class: the
+ * mapping is policy (Table 8-5 for non-CBS) and collapses 8 priorities onto nq
+ * queues when nq < 8; they only line up here because this is a non-CBS switch
+ * at 8 queues. The code therefore always maps through ieee8021q_tt_to_tc(), never
+ * assuming priority == queue.
+ */
+
+#include <linux/bitops.h>
+#include <linux/build_bug.h>
+#include <linux/regmap.h>
+#include <net/dsa.h>
+#include <net/ieee8021q.h>
+
+#include "realtek.h"
+#include "rtl8365mb_dcb.h"
+
+/* The chip's eight internal priorities carry 802.1Q traffic types, so the
+ * two axes must have the same cardinality.
+ */
+static_assert(RTL8365MB_NUM_IPMS == IEEE8021Q_TT_MAX);
+
+/* Per-port output-queue mapping index (selects the queue count). Four ports
+ * per register, 3-bit field. An N-queue configuration selects index N, except
+ * the full eight-queue configuration, which is encoded as index 0 (the field
+ * wraps modulo eight).
+ */
+#define RTL8365MB_QOS_PORT_QUEUE_NUMBER_REG(_p) (0x0900 + ((_p) >> 2))
+#define RTL8365MB_QOS_PORT_QUEUE_NUMBER_OFFSET(_p) (((_p) & 0x3) << 2)
+#define RTL8365MB_QOS_QMAP_IDX(_nq) ((_nq) & 0x7)
+
+/* Internal priority -> queue-id map. Eight tables (one per queue count),
+ * indexed [table][prio]; four priorities per register, 3-bit qid. An N-queue
+ * configuration uses table N-1 (1Q is table 0 at 0x0904, 8Q is table 7).
+ */
+#define RTL8365MB_QOS_PRI_TO_QID_TABLE(_nq) ((_nq) - 1)
+#define RTL8365MB_QOS_PRI_TO_QID_REG(_t, _pri) \
+ (0x0904 + ((_t) << 1) + ((_pri) >> 2))
+#define RTL8365MB_QOS_PRI_TO_QID_OFFSET(_pri) (((_pri) & 0x3) << 2)
+
+/* 802.1p (PCP) -> internal priority remap. Four priorities per register. */
+#define RTL8365MB_QOS_1Q_REMAP_REG(_pri) (0x0865 + ((_pri) >> 2))
+#define RTL8365MB_QOS_1Q_REMAP_OFFSET(_pri) (((_pri) & 0x3) << 2)
+
+/* Port-based (default) priority. Four ports per register, 3-bit. */
+#define RTL8365MB_QOS_PORT_PRI_REG(_p) (0x0877 + ((_p) >> 2))
+#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().
+ */
+#define RTL8365MB_QOS_DEFAULT_PRIO IEEE8021Q_TT_BE
+
+/* 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.
+ */
+#define RTL8365MB_QOS_PRIDEC_TBL0_REG(_s) (0x087B + ((_s) >> 1))
+#define RTL8365MB_QOS_PRIDEC_TBL1_REG(_s) (0x0885 + ((_s) >> 1))
+#define RTL8365MB_QOS_PRIDEC_OFFSET(_s) (((_s) & 0x1) << 3)
+
+/* Each port selects one of the two decision tables; one bit per port. */
+#define RTL8365MB_QOS_PRIDEC_IDX_REG 0x0889
+
+/* Priority-decision sources. The hardware numbers eight sources; this driver
+ * programs the three it uses by name and explicitly disables the rest. The
+ * hardware assigns these source ordinals: PORT=0, ACL=1 (unused), DSCP=2,
+ * 1Q=3, SVLAN=4 (unused), CVLAN=5 (unused), DA=6 (unused), SA=7 (unused).
+ */
+#define RTL8365MB_QOS_PRIDEC_PORT 0
+#define RTL8365MB_QOS_PRIDEC_DSCP 2
+#define RTL8365MB_QOS_PRIDEC_1Q 3
+#define RTL8365MB_QOS_PRIDEC_NUM_SRC 8
+
+/* Priority-decision weights. The baseline trusts only the port-based
+ * priority; every other source is disabled (weight 0). apptrust raises a
+ * trusted source's weight above the port default so that it wins.
+ */
+#define RTL8365MB_QOS_WEIGHT_UNTRUSTED 0
+#define RTL8365MB_QOS_WEIGHT_PORT 1
+
+/* The QoS priority and queue selectors are 3-bit register fields; derive a
+ * field's mask from its bit offset.
+ */
+static inline u32 rtl8365mb_qos_sel_field_mask(unsigned int off)
+{
+ return GENMASK(off + 2, off);
+}
+
+/* The priority-decision weight is an 8-bit register field; derive its mask
+ * from the field's bit offset, mirroring rtl8365mb_qos_sel_field_mask().
+ */
+static inline u32 rtl8365mb_qos_weight_field_mask(unsigned int off)
+{
+ return GENMASK(off + 7, off);
+}
+
+static int rtl8365mb_set_field(struct realtek_priv *priv, u32 reg, u32 mask,
+ u32 val)
+{
+ return regmap_update_bits(priv->map, reg, mask,
+ (val << __ffs(mask)) & mask);
+}
+
+static int rtl8365mb_get_field(struct realtek_priv *priv, u32 reg, u32 mask,
+ u32 *val)
+{
+ int ret;
+
+ ret = regmap_read(priv->map, reg, val);
+ if (ret)
+ return ret;
+
+ *val = (*val & mask) >> __ffs(mask);
+ return 0;
+}
+
+static u32 rtl8365mb_qos_pridec_reg(int table, int src)
+{
+ return table ? RTL8365MB_QOS_PRIDEC_TBL1_REG(src) :
+ RTL8365MB_QOS_PRIDEC_TBL0_REG(src);
+}
+
+static int rtl8365mb_qos_set_pridec(struct realtek_priv *priv, int table,
+ int src, u8 weight)
+{
+ int off = RTL8365MB_QOS_PRIDEC_OFFSET(src);
+
+ return rtl8365mb_set_field(priv, rtl8365mb_qos_pridec_reg(table, src),
+ rtl8365mb_qos_weight_field_mask(off), weight);
+}
+
+static int rtl8365mb_qos_setup_queues(struct realtek_priv *priv,
+ unsigned int nq)
+{
+ int table = RTL8365MB_QOS_PRI_TO_QID_TABLE(nq);
+ struct dsa_switch *ds = &priv->ds;
+ struct dsa_port *dp;
+ int tt, ret;
+
+ dsa_switch_for_each_port(dp, ds) {
+ u32 reg = RTL8365MB_QOS_PORT_QUEUE_NUMBER_REG(dp->index);
+ int off = RTL8365MB_QOS_PORT_QUEUE_NUMBER_OFFSET(dp->index);
+
+ ret = rtl8365mb_set_field(priv, reg,
+ rtl8365mb_qos_sel_field_mask(off),
+ RTL8365MB_QOS_QMAP_IDX(nq));
+ if (ret)
+ return ret;
+ }
+
+ for (tt = 0; tt < IEEE8021Q_TT_MAX; tt++) {
+ u32 reg = RTL8365MB_QOS_PRI_TO_QID_REG(table, tt);
+ int off = RTL8365MB_QOS_PRI_TO_QID_OFFSET(tt);
+ int tc = ieee8021q_tt_to_tc(tt, nq);
+
+ if (tc < 0)
+ return tc;
+
+ /* QID field holds the traffic class */
+ ret = rtl8365mb_set_field(priv, reg,
+ rtl8365mb_qos_sel_field_mask(off), tc);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+/* Map ingress PCP to the internal priority via its 802.1Q traffic type, so
+ * Best Effort (PCP 0) correctly outranks Background (PCP 1).
+ */
+static int rtl8365mb_qos_setup_pcp(struct realtek_priv *priv)
+{
+ int pcp, ret;
+
+ for (pcp = 0; pcp < IEEE_8021Q_MAX_PRIORITIES; pcp++) {
+ u32 reg = RTL8365MB_QOS_1Q_REMAP_REG(pcp);
+ int off = RTL8365MB_QOS_1Q_REMAP_OFFSET(pcp);
+ int tt = ieee8021q_pcp_to_tt(pcp);
+
+ if (tt < 0)
+ return tt;
+
+ ret = rtl8365mb_set_field(priv, reg,
+ rtl8365mb_qos_sel_field_mask(off), tt);
+ if (ret)
+ return ret;
+ }
+
+ return 0;
+}
+
+int rtl8365mb_dcb_init(struct dsa_switch *ds)
+{
+ struct realtek_priv *priv = ds->priv;
+ int table, ret;
+
+ /* The priority->queue table is a single switch-wide resource, shared by
+ * all ports (not per-port).
+ */
+ ret = rtl8365mb_qos_setup_queues(priv, ds->num_tx_queues);
+ if (ret)
+ return ret;
+
+ ret = rtl8365mb_qos_setup_pcp(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
+ * trusted table and steers ports to it on demand.
+ */
+ for (table = 0; table <= 1; table++) {
+ int src;
+
+ for (src = 0; src < RTL8365MB_QOS_PRIDEC_NUM_SRC; src++) {
+ u8 weight = src == RTL8365MB_QOS_PRIDEC_PORT ?
+ RTL8365MB_QOS_WEIGHT_PORT :
+ RTL8365MB_QOS_WEIGHT_UNTRUSTED;
+
+ ret = rtl8365mb_qos_set_pridec(priv, table, src, weight);
+ if (ret)
+ return ret;
+ }
+ }
+
+ return regmap_write(priv->map, RTL8365MB_QOS_PRIDEC_IDX_REG, 0);
+}
+
+int rtl8365mb_dcb_init_port(struct dsa_switch *ds, int port)
+{
+ int off = RTL8365MB_QOS_PORT_PRI_OFFSET(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
+ * so classification stays consistent once the admin opts a source in.
+ */
+ return rtl8365mb_set_field(priv, RTL8365MB_QOS_PORT_PRI_REG(port),
+ rtl8365mb_qos_sel_field_mask(off),
+ RTL8365MB_QOS_DEFAULT_PRIO);
+}
+
+int rtl8365mb_port_get_default_prio(struct dsa_switch *ds, int port)
+{
+ int off = RTL8365MB_QOS_PORT_PRI_OFFSET(port);
+ struct realtek_priv *priv = ds->priv;
+ u32 val;
+ int ret;
+
+ ret = rtl8365mb_get_field(priv, RTL8365MB_QOS_PORT_PRI_REG(port),
+ 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_set_default_prio(struct dsa_switch *ds, int port, u8 prio)
+{
+ int off = RTL8365MB_QOS_PORT_PRI_OFFSET(port);
+ struct realtek_priv *priv = ds->priv;
+ int tt;
+
+ 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_set_field(priv, RTL8365MB_QOS_PORT_PRI_REG(port),
+ rtl8365mb_qos_sel_field_mask(off), tt);
+}
diff --git a/drivers/net/dsa/realtek/rtl8365mb_dcb.h b/drivers/net/dsa/realtek/rtl8365mb_dcb.h
new file mode 100644
index 000000000000..4f8068dd3522
--- /dev/null
+++ b/drivers/net/dsa/realtek/rtl8365mb_dcb.h
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* QoS and DCB configuration for the rtl8365mb switch family */
+
+#ifndef _REALTEK_RTL8365MB_DCB_H
+#define _REALTEK_RTL8365MB_DCB_H
+
+#include <linux/types.h>
+#include <net/dsa.h>
+
+/* The switch has eight internal priorities (0..7). The egress queue count is
+ * a per-chip property; see struct rtl8365mb_chip_info::num_tx_queues.
+ */
+#define RTL8365MB_NUM_IPMS 8
+
+int rtl8365mb_dcb_init(struct dsa_switch *ds);
+int rtl8365mb_dcb_init_port(struct dsa_switch *ds, int port);
+int rtl8365mb_port_get_default_prio(struct dsa_switch *ds, int port);
+int rtl8365mb_port_set_default_prio(struct dsa_switch *ds, int port, 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 0924d31790e0..5a3f4328354e 100644
--- a/drivers/net/dsa/realtek/rtl8365mb_main.c
+++ b/drivers/net/dsa/realtek/rtl8365mb_main.c
@@ -108,6 +108,7 @@
#include "realtek-smi.h"
#include "realtek-mdio.h"
#include "rtl83xx.h"
+#include "rtl8365mb_dcb.h"
#include "rtl8365mb_l2.h"
#include "rtl8365mb_vlan.h"
@@ -3187,6 +3188,11 @@ static int rtl8365mb_setup(struct dsa_switch *ds)
if (ret)
goto out_teardown_irq;
+ /* Default the port QoS (default priority = Best Effort) */
+ ret = rtl8365mb_dcb_init_port(ds, dp->index);
+ if (ret)
+ goto out_teardown_irq;
+
/* Set up per-port private data */
p->priv = priv;
p->index = dp->index;
@@ -3274,6 +3280,13 @@ static int rtl8365mb_setup(struct dsa_switch *ds)
*/
ds->num_tx_queues = mb->chip_info->num_tx_queues;
+ /* Establish a defined QoS baseline: program the priority-to-queue map
+ * for the chip's queue count and trust only the port default priority.
+ */
+ ret = rtl8365mb_dcb_init(ds);
+ if (ret)
+ goto out_teardown_irq;
+
/* Start statistics counter polling */
ret = rtl8365mb_stats_setup(priv);
if (ret) {
@@ -3435,6 +3448,8 @@ static const struct dsa_switch_ops rtl8365mb_switch_ops = {
.port_bridge_leave = rtl83xx_port_bridge_leave,
.port_pre_bridge_flags = rtl8365mb_port_pre_bridge_flags,
.port_bridge_flags = rtl83xx_port_bridge_flags,
+ .port_get_default_prio = rtl8365mb_port_get_default_prio,
+ .port_set_default_prio = rtl8365mb_port_set_default_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
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH net-next v1 7/8] net: dsa: realtek: rtl8365mb: offload DCB apptrust
2026-10-02 11:58 [PATCH net-next v1 0/8] net: dsa: realtek: rtl8365mb: DCB ingress QoS offload Oleksij Rempel
` (5 preceding siblings ...)
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-02 11:58 ` Oleksij Rempel
2026-10-05 23:38 ` Linus Walleij
2026-10-02 11:58 ` [PATCH net-next v1 8/8] net: dsa: realtek: rtl8365mb: offload DCB DSCP-to-priority Oleksij Rempel
2026-10-05 15:03 ` [PATCH net-next v1 0/8] net: dsa: realtek: rtl8365mb: DCB ingress QoS offload Linus Walleij
8 siblings, 1 reply; 19+ messages in thread
From: Oleksij Rempel @ 2026-10-02 11:58 UTC (permalink / raw)
To: Linus Walleij, Luiz Angelo Daros de Luca, Andrew Lunn,
Vladimir Oltean, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: Oleksij Rempel, kernel, linux-kernel, Alvin Šipraga, netdev,
Simon Horman
Wire up port_get_apptrust/port_set_apptrust so the admin can choose,
through dcbnl, which ingress classification sources a port trusts for
its priority: 802.1p (PCP) and/or DSCP. Nothing but the port default is
trusted until this opts in.
The hardware exposes two priority-decision weight tables and a per-port
bit selecting between them. rtl8365mb_dcb_init() leaves both tables
trusting only the port priority; apptrust programs the second
("trusted") table with the requested PCP/DSCP weights and steers the
port to it, or back to the untrusted table when the selector list is
empty. This driver fixes the precedence to PCP > DSCP via the decision
weights, so the selector list is validated to be in that order.
Unlike switches with independent per-port trust bits, the trusted table
is a single switch-wide resource: all ports that trust something must
trust the same selectors. A request that conflicts with the selectors
another port is already using is refused with -EBUSY.
Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
---
drivers/net/dsa/realtek/rtl8365mb_dcb.c | 193 +++++++++++++++++++++++
drivers/net/dsa/realtek/rtl8365mb_dcb.h | 4 +
drivers/net/dsa/realtek/rtl8365mb_main.c | 2 +
3 files changed, 199 insertions(+)
diff --git a/drivers/net/dsa/realtek/rtl8365mb_dcb.c b/drivers/net/dsa/realtek/rtl8365mb_dcb.c
index f48e95ef3947..4afcae6e85a1 100644
--- a/drivers/net/dsa/realtek/rtl8365mb_dcb.c
+++ b/drivers/net/dsa/realtek/rtl8365mb_dcb.c
@@ -13,7 +13,9 @@
#include <linux/bitops.h>
#include <linux/build_bug.h>
+#include <linux/dcbnl.h>
#include <linux/regmap.h>
+#include <linux/string.h>
#include <net/dsa.h>
#include <net/ieee8021q.h>
@@ -66,6 +68,8 @@ static_assert(RTL8365MB_NUM_IPMS == IEEE8021Q_TT_MAX);
/* Each port selects one of the two decision tables; one bit per port. */
#define RTL8365MB_QOS_PRIDEC_IDX_REG 0x0889
+#define RTL8365MB_QOS_PRIDEC_TABLE_UNTRUSTED 0
+#define RTL8365MB_QOS_PRIDEC_TABLE_TRUSTED 1
/* Priority-decision sources. The hardware numbers eight sources; this driver
* programs the three it uses by name and explicitly disables the rest. The
@@ -84,6 +88,24 @@ static_assert(RTL8365MB_NUM_IPMS == IEEE8021Q_TT_MAX);
#define RTL8365MB_QOS_WEIGHT_UNTRUSTED 0
#define RTL8365MB_QOS_WEIGHT_PORT 1
+/* apptrust selectors this driver supports, in descending precedence. Each
+ * entry binds a dcbnl selector to the priority-decision source it enables, so
+ * this ordered table is the one place the fixed precedence lives.
+ */
+static const struct rtl8365mb_apptrust_map {
+ u8 sel; /* dcbnl apptrust selector */
+ u8 src; /* priority-decision source it enables */
+} rtl8365mb_apptrust_map[] = {
+ { DCB_APP_SEL_PCP, RTL8365MB_QOS_PRIDEC_1Q },
+ { IEEE_8021QAZ_APP_SEL_DSCP, RTL8365MB_QOS_PRIDEC_DSCP },
+};
+
+/* rtl8365mb_apptrust_weight() gives the first entry the top weight,
+ * RTL8365MB_QOS_WEIGHT_PORT + ARRAY_SIZE(rtl8365mb_apptrust_map); fail the
+ * build if adding a selector would raise it past the decision weight range.
+ */
+static_assert(RTL8365MB_QOS_WEIGHT_PORT + ARRAY_SIZE(rtl8365mb_apptrust_map) <= 7);
+
/* The QoS priority and queue selectors are 3-bit register fields; derive a
* field's mask from its bit offset.
*/
@@ -135,6 +157,22 @@ static int rtl8365mb_qos_set_pridec(struct realtek_priv *priv, int table,
rtl8365mb_qos_weight_field_mask(off), weight);
}
+static int rtl8365mb_qos_get_pridec(struct realtek_priv *priv, int table,
+ int src, u8 *weight)
+{
+ int off = RTL8365MB_QOS_PRIDEC_OFFSET(src);
+ u32 val;
+ int ret;
+
+ ret = rtl8365mb_get_field(priv, rtl8365mb_qos_pridec_reg(table, src),
+ rtl8365mb_qos_weight_field_mask(off), &val);
+ if (ret)
+ return ret;
+
+ *weight = val;
+ return 0;
+}
+
static int rtl8365mb_qos_setup_queues(struct realtek_priv *priv,
unsigned int nq)
{
@@ -285,3 +323,158 @@ int rtl8365mb_port_set_default_prio(struct dsa_switch *ds, int port, u8 prio)
return rtl8365mb_set_field(priv, RTL8365MB_QOS_PORT_PRI_REG(port),
rtl8365mb_qos_sel_field_mask(off), tt);
}
+
+/* Read which sources a decision table trusts (weight != 0), indexed like
+ * rtl8365mb_apptrust_map[].
+ */
+static int rtl8365mb_apptrust_read(struct realtek_priv *priv, int table,
+ bool *trust)
+{
+ int i, ret;
+
+ for (i = 0; i < ARRAY_SIZE(rtl8365mb_apptrust_map); i++) {
+ u8 weight;
+
+ ret = rtl8365mb_qos_get_pridec(priv, table,
+ rtl8365mb_apptrust_map[i].src,
+ &weight);
+ if (ret)
+ return ret;
+
+ trust[i] = weight != RTL8365MB_QOS_WEIGHT_UNTRUSTED;
+ }
+
+ return 0;
+}
+
+/* Validate the selector list and mark which table entries it trusts. This
+ * driver fixes the precedence via the decision weights, so the list must be in
+ * rtl8365mb_apptrust_map[] order.
+ */
+static int rtl8365mb_apptrust_parse(struct realtek_priv *priv, const u8 *sel,
+ int nsel, bool *trust)
+{
+ int i, prev = -1;
+
+ for (i = 0; i < ARRAY_SIZE(rtl8365mb_apptrust_map); i++)
+ trust[i] = false;
+
+ for (i = 0; i < nsel; i++) {
+ int idx;
+
+ for (idx = 0; idx < ARRAY_SIZE(rtl8365mb_apptrust_map); idx++)
+ if (sel[i] == rtl8365mb_apptrust_map[idx].sel)
+ break;
+
+ if (idx == ARRAY_SIZE(rtl8365mb_apptrust_map) || idx <= prev) {
+ dev_err(priv->dev,
+ "unsupported apptrust selector, or not in the driver's fixed precedence order\n");
+ return -EINVAL;
+ }
+ prev = idx;
+ trust[idx] = true;
+ }
+
+ return 0;
+}
+
+/* Trusted sources outrank the port default, and earlier entries in
+ * rtl8365mb_apptrust_map[] outrank later ones. Deriving the weight from the
+ * entry's position makes the table order the sole expression of precedence,
+ * so the order and the hardware weights cannot drift apart.
+ */
+static u8 rtl8365mb_apptrust_weight(unsigned int entry)
+{
+ return RTL8365MB_QOS_WEIGHT_PORT +
+ ARRAY_SIZE(rtl8365mb_apptrust_map) - entry;
+}
+
+int rtl8365mb_port_get_apptrust(struct dsa_switch *ds, int port, u8 *sel,
+ int *nsel)
+{
+ bool trust[ARRAY_SIZE(rtl8365mb_apptrust_map)];
+ struct realtek_priv *priv = ds->priv;
+ int ret, i;
+ u32 idx;
+
+ *nsel = 0;
+
+ ret = regmap_read(priv->map, RTL8365MB_QOS_PRIDEC_IDX_REG, &idx);
+ if (ret)
+ return ret;
+
+ /* On the untrusted table nothing but the port default is trusted. */
+ if (!(idx & BIT(port)))
+ return 0;
+
+ ret = rtl8365mb_apptrust_read(priv, RTL8365MB_QOS_PRIDEC_TABLE_TRUSTED,
+ trust);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < ARRAY_SIZE(rtl8365mb_apptrust_map); i++)
+ if (trust[i])
+ sel[(*nsel)++] = rtl8365mb_apptrust_map[i].sel;
+
+ return 0;
+}
+
+int rtl8365mb_port_set_apptrust(struct dsa_switch *ds, int port, const u8 *sel,
+ int nsel)
+{
+ bool trust[ARRAY_SIZE(rtl8365mb_apptrust_map)];
+ struct realtek_priv *priv = ds->priv;
+ bool any = false;
+ int ret, i;
+ u32 idx;
+
+ ret = rtl8365mb_apptrust_parse(priv, sel, nsel, trust);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < ARRAY_SIZE(rtl8365mb_apptrust_map); i++)
+ any |= trust[i];
+
+ ret = regmap_read(priv->map, RTL8365MB_QOS_PRIDEC_IDX_REG, &idx);
+ if (ret)
+ return ret;
+
+ /* Nothing trusted: point the port at the untrusted table. */
+ if (!any)
+ return rtl8365mb_set_field(priv, RTL8365MB_QOS_PRIDEC_IDX_REG,
+ BIT(port), 0);
+
+ /* The trusted table is a single switch-wide resource. If another port
+ * already uses it, this request must trust the same selectors.
+ */
+ if (idx & ~BIT(port)) {
+ bool other[ARRAY_SIZE(rtl8365mb_apptrust_map)];
+
+ ret = rtl8365mb_apptrust_read(priv,
+ RTL8365MB_QOS_PRIDEC_TABLE_TRUSTED,
+ other);
+ if (ret)
+ return ret;
+
+ if (memcmp(trust, other, sizeof(trust))) {
+ dev_err(priv->dev,
+ "trust profile is switch-wide; another port already trusts different sources\n");
+ return -EBUSY;
+ }
+ }
+
+ for (i = 0; i < ARRAY_SIZE(rtl8365mb_apptrust_map); i++) {
+ u8 weight = trust[i] ? rtl8365mb_apptrust_weight(i) :
+ RTL8365MB_QOS_WEIGHT_UNTRUSTED;
+
+ ret = rtl8365mb_qos_set_pridec(priv,
+ RTL8365MB_QOS_PRIDEC_TABLE_TRUSTED,
+ rtl8365mb_apptrust_map[i].src,
+ weight);
+ if (ret)
+ return ret;
+ }
+
+ return rtl8365mb_set_field(priv, RTL8365MB_QOS_PRIDEC_IDX_REG,
+ BIT(port), 1);
+}
diff --git a/drivers/net/dsa/realtek/rtl8365mb_dcb.h b/drivers/net/dsa/realtek/rtl8365mb_dcb.h
index 4f8068dd3522..156fa6e1c4fd 100644
--- a/drivers/net/dsa/realtek/rtl8365mb_dcb.h
+++ b/drivers/net/dsa/realtek/rtl8365mb_dcb.h
@@ -16,5 +16,9 @@ int rtl8365mb_dcb_init(struct dsa_switch *ds);
int rtl8365mb_dcb_init_port(struct dsa_switch *ds, int port);
int rtl8365mb_port_get_default_prio(struct dsa_switch *ds, int port);
int rtl8365mb_port_set_default_prio(struct dsa_switch *ds, int port, u8 prio);
+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);
#endif /* _REALTEK_RTL8365MB_DCB_H */
diff --git a/drivers/net/dsa/realtek/rtl8365mb_main.c b/drivers/net/dsa/realtek/rtl8365mb_main.c
index 5a3f4328354e..77f971abf783 100644
--- a/drivers/net/dsa/realtek/rtl8365mb_main.c
+++ b/drivers/net/dsa/realtek/rtl8365mb_main.c
@@ -3450,6 +3450,8 @@ static const struct dsa_switch_ops rtl8365mb_switch_ops = {
.port_bridge_flags = rtl83xx_port_bridge_flags,
.port_get_default_prio = rtl8365mb_port_get_default_prio,
.port_set_default_prio = rtl8365mb_port_set_default_prio,
+ .port_get_apptrust = rtl8365mb_port_get_apptrust,
+ .port_set_apptrust = rtl8365mb_port_set_apptrust,
.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
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH net-next v1 8/8] net: dsa: realtek: rtl8365mb: offload DCB DSCP-to-priority
2026-10-02 11:58 [PATCH net-next v1 0/8] net: dsa: realtek: rtl8365mb: DCB ingress QoS offload Oleksij Rempel
` (6 preceding siblings ...)
2026-10-02 11:58 ` [PATCH net-next v1 7/8] net: dsa: realtek: rtl8365mb: offload DCB apptrust Oleksij Rempel
@ 2026-10-02 11:58 ` Oleksij Rempel
2026-10-05 15:03 ` [PATCH net-next v1 0/8] net: dsa: realtek: rtl8365mb: DCB ingress QoS offload Linus Walleij
8 siblings, 0 replies; 19+ messages in thread
From: Oleksij Rempel @ 2026-10-02 11:58 UTC (permalink / raw)
To: Linus Walleij, Luiz Angelo Daros de Luca, Andrew Lunn,
Vladimir Oltean, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni
Cc: Oleksij Rempel, kernel, linux-kernel, Alvin Šipraga, netdev,
Simon Horman
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
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH net-next v1 1/8] net: ieee8021q: print traffic type and queue count with %u
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
1 sibling, 0 replies; 19+ messages in thread
From: Luiz Angelo Daros de Luca @ 2026-10-02 14:22 UTC (permalink / raw)
To: Oleksij Rempel
Cc: Linus Walleij, Andrew Lunn, Vladimir Oltean, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, kernel, linux-kernel,
Alvin Šipraga, netdev, Simon Horman
> Switch the out-of-range diagnostic in ieee8021q_tt_to_tc() from %d to
> %u. The traffic class count num_queues is an unsigned int and the
> traffic type is an enumeration, so printing them as unsigned matches
> their types. The print sits on the range-check error path, which still
> rejects a negative traffic type; %u only changes how an out-of-range
> value is rendered, not which values are rejected.
>
> Preparation for the inverse helper added next, which follows the same
> convention.
>
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Reviewed-by: Luiz Angelo Daros de Luca <luizluca@gmail.com>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH net-next v1 0/8] net: dsa: realtek: rtl8365mb: DCB ingress QoS offload
2026-10-02 11:58 [PATCH net-next v1 0/8] net: dsa: realtek: rtl8365mb: DCB ingress QoS offload Oleksij Rempel
` (7 preceding siblings ...)
2026-10-02 11:58 ` [PATCH net-next v1 8/8] net: dsa: realtek: rtl8365mb: offload DCB DSCP-to-priority Oleksij Rempel
@ 2026-10-05 15:03 ` Linus Walleij
8 siblings, 0 replies; 19+ messages in thread
From: Linus Walleij @ 2026-10-05 15:03 UTC (permalink / raw)
To: Oleksij Rempel
Cc: Luiz Angelo Daros de Luca, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
kernel, linux-kernel, Alvin Šipraga, netdev, Simon Horman
Hi Oleksij,
thanks for your patch!
On Fri, Oct 2, 2026 at 1:58 PM Oleksij Rempel <o.rempel@pengutronix.de> wrote:
> Add DCB-based ingress QoS offload for the RTL8365MB switch via the dcbnl
> app interface: a per-port default priority, PCP trust, and DSCP trust.
> It also adds the few net/core ieee8021q helpers the driver needs.
>
> Nothing changes on the wire until an admin enables PCP or DSCP trust;
> until then every frame takes the port default and lands on one queue.
>
> Tested on an RTL8365MB-VC.
>
> ETS scheduling and CPU-tag ingress pre-classification build on this and
> will follow once it lands.
>
> Oleksij Rempel (8):
> net: ieee8021q: print traffic type and queue count with %u
> net: ieee8021q: add pcp_to_tt()
> net: ieee8021q: clarify the tt_to_tc() traffic-class mapping
> net: ieee8021q: add tt_to_pcp()
> net: dsa: realtek: rtl8365mb: store the egress queue count per chip
> net: dsa: realtek: rtl8365mb: add QoS baseline and DCB default
> priority
> net: dsa: realtek: rtl8365mb: offload DCB apptrust
> net: dsa: realtek: rtl8365mb: offload DCB DSCP-to-priority
I have one major feedback on the series and it's pretty predictable:
the RTL8366RB has most of these features as well, so they
need to be added to the common helpers in rtl83xx.c and
realtek.h.
- RTL8366RB has the same type of traffic policy, albeit
with 6 queues per port rather than 8.
- Logic traffic queues are slightly different, RB uses
queues 0 & 5 for two queues, 0, 1 & 5 for three
and so on.
- The DSCP bits have slightly different bit layout so each
backend must deal with this.
- The apptrust in the RTL8366RB is *global* rather than
per-port so this could perhaps be handled in each back-end.
The global setting will even affect the CPU port.
If you add something like this to the realtek_ops in
realtek.h:
int (*qos_get_port_prio)(struct realtek_priv *priv, int port);
int (*qos_set_port_prio)(struct realtek_priv *priv, int port, u8 iprio);
int (*qos_set_pcp_prio)(struct realtek_priv *priv, u8 pcp, u8 iprio);
int (*qos_get_dscp_prio)(struct realtek_priv *priv, u8 dscp);
int (*qos_set_dscp_prio)(struct realtek_priv *priv, u8 dscp, u8 iprio);
int (*qos_set_port_num_queues)(struct realtek_priv *priv, int port,
unsigned int num_queues);
int (*qos_set_prio_tc)(struct realtek_priv *priv,
unsigned int num_queues, u8 iprio, u8 tc);
The getters would return an internal priority or a negative error.
Queue callbacks would own register encoding, table selection
and logical-TC-to-hardware-QID translation.
Common code (rtl83xx.c) could then provide:
- Default-priority get/set callbacks, including PCP <-> traffic-type
conversion.
- DSCP get/add/delete callbacks, including the series replacement
guard and restoration of the IETF default.
- Initialization of all eight PCP mappings and all 64 DSCP mappings.
- Priority-to-traffic-class initialization using ieee8021q_tt_to_tc().
- Per-port Best Effort initialization.
Both chip setups should expose their queue count through the
existing ds->num_tx_queues, and set ds->dscp_prio_mapping_is_global
when registering DSCP offload. There is no need to duplicate those
properties in another common structure.
Does this make sense?
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH net-next v1 1/8] net: ieee8021q: print traffic type and queue count with %u
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
1 sibling, 0 replies; 19+ messages in thread
From: Linus Walleij @ 2026-10-05 15:04 UTC (permalink / raw)
To: Oleksij Rempel
Cc: Luiz Angelo Daros de Luca, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
kernel, linux-kernel, Alvin Šipraga, netdev, Simon Horman
On Fri, Oct 2, 2026 at 1:58 PM Oleksij Rempel <o.rempel@pengutronix.de> wrote:
> Switch the out-of-range diagnostic in ieee8021q_tt_to_tc() from %d to
> %u. The traffic class count num_queues is an unsigned int and the
> traffic type is an enumeration, so printing them as unsigned matches
> their types. The print sits on the range-check error path, which still
> rejects a negative traffic type; %u only changes how an out-of-range
> value is rendered, not which values are rejected.
>
> Preparation for the inverse helper added next, which follows the same
> convention.
>
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Reviewed-by: Linus Walleij <linusw@kernel.org>
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH net-next v1 2/8] net: ieee8021q: add pcp_to_tt()
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
0 siblings, 0 replies; 19+ messages in thread
From: Linus Walleij @ 2026-10-05 15:06 UTC (permalink / raw)
To: Oleksij Rempel
Cc: Luiz Angelo Daros de Luca, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
kernel, linux-kernel, Alvin Šipraga, netdev, Simon Horman
On Fri, Oct 2, 2026 at 1:58 PM Oleksij Rempel <o.rempel@pengutronix.de> wrote:
> Add a helper that maps an IEEE 802.1Q Priority Code Point (PCP) to the
> corresponding 802.1Q traffic type, complementing the existing
> ietf_dscp_to_ieee8021q_tt().
>
> It is very nearly an identity map, except that PCP 0 (Best Effort) and
> PCP 1 (Background) are swapped: per 802.1Q-2022 (Annex I, Table I-2)
> Background is a lower priority than Best Effort even though it carries
> the higher PCP value. PCP 2..7 map straight through to the matching
> traffic type, and values above 7 are rejected with -EINVAL. This decodes
> the 8P0D encoding (Table I-7), where every PCP value is a priority and
> none carries drop eligibility.
>
> Drivers that classify ingress traffic by PCP need this to map into a
> priority-ordered internal space without misordering Best Effort and
> Background. The first consumer, the realtek rtl8365mb DSA driver, lands
> later in this series.
>
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
This looks very generally helpful.
Reviewed-by: Linus Walleij <linusw@kernel.org>
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH net-next v1 3/8] net: ieee8021q: clarify the tt_to_tc() traffic-class mapping
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
0 siblings, 0 replies; 19+ messages in thread
From: Linus Walleij @ 2026-10-05 15:07 UTC (permalink / raw)
To: Oleksij Rempel
Cc: Luiz Angelo Daros de Luca, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
kernel, linux-kernel, Alvin Šipraga, netdev, Simon Horman
On Fri, Oct 2, 2026 at 1:58 PM Oleksij Rempel <o.rempel@pengutronix.de> wrote:
> Document that the tt_to_tc() traffic-class numbers are the pre-computed
> composition of Table I-2 (traffic type -> priority) with Table 8-5
> (priority -> traffic class). Note that Table 8-5 is the mapping for
> implementations without the credit-based shaper, so the helper's scope
> is clear; credit-based-shaper implementations use Table 34-1/34-2
> instead.
>
> The existing kdoc cited Annex I Table I-1 as the mapping basis, but
> Table I-1 only partitions traffic types into classes; it does not assign
> the class numbers.
>
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Reviewed-by: Linus Walleij <linusw@kernel.org>
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH net-next v1 4/8] net: ieee8021q: add tt_to_pcp()
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
0 siblings, 0 replies; 19+ messages in thread
From: Linus Walleij @ 2026-10-05 15:08 UTC (permalink / raw)
To: Oleksij Rempel
Cc: Luiz Angelo Daros de Luca, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
kernel, linux-kernel, Alvin Šipraga, netdev, Simon Horman
On Fri, Oct 2, 2026 at 1:58 PM Oleksij Rempel <o.rempel@pengutronix.de> wrote:
> Add ieee8021q_tt_to_pcp(), the inverse of ieee8021q_pcp_to_tt(): it
> encodes an 802.1Q traffic type back to its Priority Code Point, and
> completes the pcp/tt helper family.
>
> A driver that reseeds its PCP classifier through ieee8021q_pcp_to_tt()
> stores traffic types in the hardware tables, while the dcbnl priority
> ops exchange 802.1p priorities across the DSA boundary. Reading such a
> table back therefore needs the reverse mapping to restore the 802.1p
> value, which no existing helper provides. Because pcp_to_tt only
> transposes Best Effort and Background and is the identity elsewhere the
> two directions are numerically equal; provide tt_to_pcp as its own named
> function so the read path does not decode a traffic type as if it were a
> PCP.
>
> The first user is the Realtek rtl8365mb DSA driver, whose dcbnl
> get_default_prio and get_dscp_prio paths read back traffic types and
> must return 802.1p priorities.
>
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
Perfect, this is very helpful stuff.
Reviewed-by: Linus Walleij <linusw@kernel.org>
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH net-next v1 5/8] net: dsa: realtek: rtl8365mb: store the egress queue count per chip
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
0 siblings, 1 reply; 19+ messages in thread
From: Linus Walleij @ 2026-10-05 15:10 UTC (permalink / raw)
To: Oleksij Rempel
Cc: Luiz Angelo Daros de Luca, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
kernel, linux-kernel, Alvin Šipraga, netdev, Simon Horman
On Fri, Oct 2, 2026 at 1:58 PM Oleksij Rempel <o.rempel@pengutronix.de> wrote:
> Store the number of egress queues in the per-chip info structure and
> advertise it through ds->num_tx_queues, following the ksz driver
> (struct ksz_chip_data.num_tx_queues).
>
> The queue count is a per-chip hardware property, and this driver supports
> several chips of the rtl8367c family. All currently-supported chips expose
> eight queues, but keeping the count in chip_info lets the QoS code that
> follows program the priority-to-queue map via the ieee8021q helpers for
> whatever queue count a chip carries, so the 802.1Q collapse is correct
> rather than hard-coded to eight.
>
> Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
RTL8366RB has 8 queues so it's fine to keep this separate
per-subdriver.
Reviewed-by: Linus Walleij <linusw@kernel.org>
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH net-next v1 5/8] net: dsa: realtek: rtl8365mb: store the egress queue count per chip
2026-10-05 15:10 ` Linus Walleij
@ 2026-10-05 15:12 ` Linus Walleij
0 siblings, 0 replies; 19+ messages in thread
From: Linus Walleij @ 2026-10-05 15:12 UTC (permalink / raw)
To: Oleksij Rempel
Cc: Luiz Angelo Daros de Luca, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
kernel, linux-kernel, Alvin Šipraga, netdev, Simon Horman
On Mon, Oct 5, 2026 at 5:10 PM Linus Walleij <linusw@kernel.org> wrote:
> On Fri, Oct 2, 2026 at 1:58 PM Oleksij Rempel <o.rempel@pengutronix.de> wrote:
>
> > Store the number of egress queues in the per-chip info structure and
> > advertise it through ds->num_tx_queues, following the ksz driver
> > (struct ksz_chip_data.num_tx_queues).
> >
> > The queue count is a per-chip hardware property, and this driver supports
> > several chips of the rtl8367c family. All currently-supported chips expose
> > eight queues, but keeping the count in chip_info lets the QoS code that
> > follows program the priority-to-queue map via the ieee8021q helpers for
> > whatever queue count a chip carries, so the 802.1Q collapse is correct
> > rather than hard-coded to eight.
> >
> > Signed-off-by: Oleksij Rempel <o.rempel@pengutronix.de>
>
> RTL8366RB has 8 queues so it's fine to keep this separate
> per-subdriver.
> Reviewed-by: Linus Walleij <linusw@kernel.org>
I meant RTL8366RB has 6 queues. Hm maybe you rather want to
store this in struct realtek_variant and have the core
helper instead?
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH net-next v1 6/8] net: dsa: realtek: rtl8365mb: add QoS baseline and DCB default priority
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
0 siblings, 0 replies; 19+ messages in thread
From: Linus Walleij @ 2026-10-05 23:18 UTC (permalink / raw)
To: Oleksij Rempel
Cc: Luiz Angelo Daros de Luca, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
kernel, linux-kernel, Alvin Šipraga, netdev, Simon Horman
Hi Oleksij,
thanks for your patch!
As mentioned I think the main logic of this DCB stuff needs to go into
common code.
Whether to use rtl83xx.c or create a new file rtl83xx-dcb.c with just this
QoS DCB stuff is up to you.
Some detailed comments:
On Fri, Oct 2, 2026 at 1:58 PM Oleksij Rempel <o.rempel@pengutronix.de> wrote:
> +#define RTL8365MB_QOS_QMAP_IDX(_nq) ((_nq) & 0x7)
> +
> +/* Internal priority -> queue-id map. Eight tables (one per queue count),
> + * indexed [table][prio]; four priorities per register, 3-bit qid. An N-queue
> + * configuration uses table N-1 (1Q is table 0 at 0x0904, 8Q is table 7).
> + */
> +#define RTL8365MB_QOS_PRI_TO_QID_TABLE(_nq) ((_nq) - 1)
> +#define RTL8365MB_QOS_PRI_TO_QID_REG(_t, _pri) \
> + (0x0904 + ((_t) << 1) + ((_pri) >> 2))
(...)
> +static int rtl8365mb_qos_setup_queues(struct realtek_priv *priv,
> + unsigned int nq)
> +{
> + int table = RTL8365MB_QOS_PRI_TO_QID_TABLE(nq);
Prio to qid table is nq-1
> + struct dsa_switch *ds = &priv->ds;
> + struct dsa_port *dp;
> + int tt, ret;
> +
> + dsa_switch_for_each_port(dp, ds) {
> + u32 reg = RTL8365MB_QOS_PORT_QUEUE_NUMBER_REG(dp->index);
> + int off = RTL8365MB_QOS_PORT_QUEUE_NUMBER_OFFSET(dp->index);
> +
> + ret = rtl8365mb_set_field(priv, reg,
> + rtl8365mb_qos_sel_field_mask(off),
> + RTL8365MB_QOS_QMAP_IDX(nq));
This sets qos port queue number to RTL8365MB_QOS_QMAP_IDX(nq)
which is nq & 7.
> + if (ret)
> + return ret;
> + }
> +
> + for (tt = 0; tt < IEEE8021Q_TT_MAX; tt++) {
> + u32 reg = RTL8365MB_QOS_PRI_TO_QID_REG(table, tt);
This finds the reg for table nq-1
> + int off = RTL8365MB_QOS_PRI_TO_QID_OFFSET(tt);
> + int tc = ieee8021q_tt_to_tc(tt, nq);
> +
> + if (tc < 0)
> + return tc;
> +
> + /* QID field holds the traffic class */
> + ret = rtl8365mb_set_field(priv, reg,
> + rtl8365mb_qos_sel_field_mask(off), tc);
> + if (ret)
> + return ret;
> + }
And sets it.
In a code dump I have for RTL8370 writes the same index into both registers,
so something like:
{
int qmapidx = RTL8365MB_QOS_QMAP_IDX(nq);
ret = rtl8365mb_set_field(priv, reg,
rtl8365mb_qos_sel_field_mask(off),
qmapidx);
(...)
for (tt = 0; tt < IEEE8021Q_TT_MAX; tt++) {
u32 reg = RTL8365MB_QOS_PRI_TO_QID_REG(qmapidx, tt);
int off = RTL8365MB_QOS_PRI_TO_QID_OFFSET(tt);
int tc = ieee8021q_tt_to_tc(tt, nq);
(...)
So we compute index once and use it both for port selection and
table programming.
Can you check this in the RTL8365MB manual, this old RTL8370 code
could be wrong but it's also the way RTL8366RB does things.
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH net-next v1 7/8] net: dsa: realtek: rtl8365mb: offload DCB apptrust
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
0 siblings, 0 replies; 19+ messages in thread
From: Linus Walleij @ 2026-10-05 23:38 UTC (permalink / raw)
To: Oleksij Rempel
Cc: Luiz Angelo Daros de Luca, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
kernel, linux-kernel, Alvin Šipraga, netdev, Simon Horman
Hi Oleksij,
thanks for your patch!
Again some potential to share code here, not going to
repeat myself from patch 0.
On Fri, Oct 2, 2026 at 1:59 PM Oleksij Rempel <o.rempel@pengutronix.de> wrote:
> +/* rtl8365mb_apptrust_weight() gives the first entry the top weight,
> + * RTL8365MB_QOS_WEIGHT_PORT + ARRAY_SIZE(rtl8365mb_apptrust_map); fail the
> + * build if adding a selector would raise it past the decision weight range.
(...)
> +/* Trusted sources outrank the port default, and earlier entries in
> + * rtl8365mb_apptrust_map[] outrank later ones. Deriving the weight from the
> + * entry's position makes the table order the sole expression of precedence,
> + * so the order and the hardware weights cannot drift apart.
> + */
> +static u8 rtl8365mb_apptrust_weight(unsigned int entry)
> +{
> + return RTL8365MB_QOS_WEIGHT_PORT +
> + ARRAY_SIZE(rtl8365mb_apptrust_map) - entry;
> +}
RTL8365MB_QOS_WEIGHT_PORT is 1.
The returned weights
will be 1 (default), 2 (DSCP), 3 (PCP)
if I understand correctly.
The RTL8370 source has some other opionions about this,
it writes a power-of-two value here, would be something like:
return BIT(ARRAY_SIZE(rtl8365mb_apptrust_map) - entry);
returning the weigths 1 (default), 2 (DSCP), 4 (PCP).
So for RTL8365MB this value lands in register 0x0886
for example if both sources are trusted as the value
0x0302. But for the RTL8370 (which uses another register)
the value is instead 0x0402 for both sources trusted.
Can you check this in the RTL8365MB manual because
the register usage overall seem very similar to
RTL8370.
Yours,
Linus Walleij
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2026-10-05 23:39 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
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-02 11:58 ` [PATCH net-next v1 8/8] net: dsa: realtek: rtl8365mb: offload DCB DSCP-to-priority Oleksij Rempel
2026-10-05 15:03 ` [PATCH net-next v1 0/8] net: dsa: realtek: rtl8365mb: DCB ingress QoS offload Linus Walleij
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®