* [PATCH net-next 0/2] net: dsa: mv88e6xxx: add support for dcb pcp app
@ 2026-06-04 8:30 Cedric Jehasse via B4 Relay
2026-06-04 8:30 ` [PATCH net-next 1/2] net: dsa: " Cedric Jehasse via B4 Relay
` (4 more replies)
0 siblings, 5 replies; 12+ messages in thread
From: Cedric Jehasse via B4 Relay @ 2026-06-04 8:30 UTC (permalink / raw)
To: Andrew Lunn, Vladimir Oltean, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Russell King
Cc: netdev, linux-kernel, Luke Howard, Cedric Jehasse, Cedric Jehasse
This patch series adds support for dcb pcp app to the mv88e6xxx
driver. The pcp app is there to configure pcp based queue
classification.
In the Marvell switches this is done by configuring the IEEE PRI Mapping
table. There are different hardware implementations of this table
depending on the switch:
* a global table
* the 6390 has one table per port
* the 6393 has one table for DEI=0, and another table for DEI=1 per port
For this the DSA framework needs to be extended. The implementation for
pcp-prio in the DSA framework is very similar to existing dcsp-prio
implementation.
There's another patch series [1] on the mailing list that uses the same
IEEE PRI Mapping table to implement MPQRIO. To me the dcb pcp app feels
like the natural way to configure the pcp to QPri mappings in the
switch.
[1] https://lore.kernel.org/netdev/20260602-mv88e6xxx-8021qat-mqprio-v2-0-72be14522e7c@padl.com/
Signed-off-by: Cedric Jehasse <cedric.jehasse@luminex.be>
---
Cedric Jehasse (2):
net: dsa: add support for dcb pcp app
net: dsa: mv88e6xxx: add support for dcb pcp app
drivers/net/dsa/mv88e6xxx/Makefile | 1 +
drivers/net/dsa/mv88e6xxx/chip.c | 36 ++++++
drivers/net/dsa/mv88e6xxx/chip.h | 17 +++
drivers/net/dsa/mv88e6xxx/dcb.c | 229 +++++++++++++++++++++++++++++++++++++
drivers/net/dsa/mv88e6xxx/dcb.h | 21 ++++
drivers/net/dsa/mv88e6xxx/port.c | 28 ++++-
drivers/net/dsa/mv88e6xxx/port.h | 8 ++
include/net/dsa.h | 10 ++
net/dsa/user.c | 126 ++++++++++++++++++--
9 files changed, 467 insertions(+), 9 deletions(-)
---
base-commit: 09942ddedcb960f9e78fd817ec33f501d1040c5b
change-id: 20260603-net-next-mv88e6xxx-pcp-prio-5752caa7926b
prerequisite-change-id: 20260430-net-next-mv88e6xxx-cbs-2121169caa68:v5
prerequisite-patch-id: 8ad59c43368d4639e0cabcc59a7f6e487560d3f7
prerequisite-patch-id: 88ee88bf34ac3631056bc92c6c6251c29cf7223c
Best regards,
--
Cedric Jehasse <cedric.jehasse@luminex.be>
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH net-next 1/2] net: dsa: add support for dcb pcp app
2026-06-04 8:30 [PATCH net-next 0/2] net: dsa: mv88e6xxx: add support for dcb pcp app Cedric Jehasse via B4 Relay
@ 2026-06-04 8:30 ` Cedric Jehasse via B4 Relay
2026-06-04 8:30 ` [PATCH net-next 2/2] net: dsa: mv88e6xxx: " Cedric Jehasse via B4 Relay
` (3 subsequent siblings)
4 siblings, 0 replies; 12+ messages in thread
From: Cedric Jehasse via B4 Relay @ 2026-06-04 8:30 UTC (permalink / raw)
To: Andrew Lunn, Vladimir Oltean, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Russell King
Cc: netdev, linux-kernel, Luke Howard, Cedric Jehasse, Cedric Jehasse
From: Cedric Jehasse <cedric.jehasse@luminex.be>
Set/get of dscp-prio map is already supported by dsa.
This adds support for set/get of pcp-prio map in a similar way.
Signed-off-by: Cedric Jehasse <cedric.jehasse@luminex.be>
---
include/net/dsa.h | 10 +++++
net/dsa/user.c | 126 +++++++++++++++++++++++++++++++++++++++++++++++++++---
2 files changed, 129 insertions(+), 7 deletions(-)
diff --git a/include/net/dsa.h b/include/net/dsa.h
index 8b6d34e8a6f0..05428c555ccd 100644
--- a/include/net/dsa.h
+++ b/include/net/dsa.h
@@ -447,6 +447,11 @@ struct dsa_switch {
*/
u32 dscp_prio_mapping_is_global:1;
+ /* Drivers that have global PCP mapping settings must set this to
+ * true to automatically apply the settings to all ports.
+ */
+ u32 pcp_prio_mapping_is_global:1;
+
/* Listener for switch fabric events */
struct notifier_block nb;
@@ -970,6 +975,11 @@ struct dsa_switch_ops {
u8 prio);
int (*port_del_dscp_prio)(struct dsa_switch *ds, int port, u8 dscp,
u8 prio);
+ int (*port_get_pcp_prio)(struct dsa_switch *ds, int port, u8 pcp);
+ int (*port_add_pcp_prio)(struct dsa_switch *ds, int port, u8 pcp,
+ u8 prio);
+ int (*port_del_pcp_prio)(struct dsa_switch *ds, int port, u8 pcp,
+ u8 prio);
int (*port_set_apptrust)(struct dsa_switch *ds, int port,
const u8 *sel, int nsel);
int (*port_get_apptrust)(struct dsa_switch *ds, int port, u8 *sel,
diff --git a/net/dsa/user.c b/net/dsa/user.c
index c4bd6fe90b45..aa6d030968b9 100644
--- a/net/dsa/user.c
+++ b/net/dsa/user.c
@@ -2238,11 +2238,11 @@ dsa_user_dcbnl_set_default_prio(struct net_device *dev, struct dcb_app *app)
return 0;
}
-/* Update the DSCP prio entries on all user ports of the switch in case
- * the switch supports global DSCP prio instead of per port DSCP prios.
+/* Update the APP entries on all user ports of the switch in case
+ * the switch supports global prio settings instead of per port prios.
*/
-static int dsa_user_dcbnl_ieee_global_dscp_setdel(struct net_device *dev,
- struct dcb_app *app, bool del)
+static int dsa_user_dcbnl_ieee_global_setdel(struct net_device *dev,
+ struct dcb_app *app, bool del)
{
int (*setdel)(struct net_device *dev, struct dcb_app *app);
struct dsa_port *dp = dsa_user_to_port(dev);
@@ -2284,7 +2284,7 @@ static int dsa_user_dcbnl_ieee_global_dscp_setdel(struct net_device *dev,
restore_err = setdel(user, app);
if (restore_err)
- netdev_err(user, "Failed to restore DSCP prio entry configuration\n");
+ netdev_err(user, "Failed to restore APP entry configuration\n");
}
return err;
@@ -2324,7 +2324,7 @@ dsa_user_dcbnl_add_dscp_prio(struct net_device *dev, struct dcb_app *app)
if (!ds->dscp_prio_mapping_is_global)
return 0;
- err = dsa_user_dcbnl_ieee_global_dscp_setdel(dev, app, false);
+ err = dsa_user_dcbnl_ieee_global_setdel(dev, app, false);
if (err) {
if (ds->ops->port_del_dscp_prio)
ds->ops->port_del_dscp_prio(ds, port, dscp, new_prio);
@@ -2335,6 +2335,54 @@ dsa_user_dcbnl_add_dscp_prio(struct net_device *dev, struct dcb_app *app)
return 0;
}
+static int __maybe_unused
+dsa_user_dcbnl_add_pcp_prio(struct net_device *dev, struct dcb_app *app)
+{
+ struct dsa_port *dp = dsa_user_to_port(dev);
+ struct dsa_switch *ds = dp->ds;
+ unsigned long mask, new_prio;
+ int err, port = dp->index;
+ u8 pcp = app->protocol;
+
+ if (!ds->ops->port_add_pcp_prio)
+ return -EOPNOTSUPP;
+
+ if (app->priority >= IEEE_8021QAZ_MAX_TCS)
+ return -EINVAL;
+
+ if (pcp >= 16) {
+ netdev_err(dev, "PCP APP entry with protocol value %u is invalid\n",
+ pcp);
+ return -EINVAL;
+ }
+
+ err = dcb_ieee_setapp(dev, app);
+ if (err)
+ return err;
+
+ mask = dcb_ieee_getapp_mask(dev, app);
+ new_prio = __fls(mask);
+
+ err = ds->ops->port_add_pcp_prio(ds, port, pcp, new_prio);
+ if (err) {
+ dcb_ieee_delapp(dev, app);
+ return err;
+ }
+
+ if (!ds->pcp_prio_mapping_is_global)
+ return 0;
+
+ err = dsa_user_dcbnl_ieee_global_setdel(dev, app, false);
+ if (err) {
+ if (ds->ops->port_del_pcp_prio)
+ ds->ops->port_del_pcp_prio(ds, port, pcp, new_prio);
+ dcb_ieee_delapp(dev, app);
+ return err;
+ }
+
+ return 0;
+}
+
static int __maybe_unused dsa_user_dcbnl_ieee_setapp(struct net_device *dev,
struct dcb_app *app)
{
@@ -2349,6 +2397,8 @@ static int __maybe_unused dsa_user_dcbnl_ieee_setapp(struct net_device *dev,
break;
case IEEE_8021QAZ_APP_SEL_DSCP:
return dsa_user_dcbnl_add_dscp_prio(dev, app);
+ case DCB_APP_SEL_PCP:
+ return dsa_user_dcbnl_add_pcp_prio(dev, app);
default:
return -EOPNOTSUPP;
}
@@ -2405,7 +2455,7 @@ dsa_user_dcbnl_del_dscp_prio(struct net_device *dev, struct dcb_app *app)
if (!ds->dscp_prio_mapping_is_global)
return 0;
- err = dsa_user_dcbnl_ieee_global_dscp_setdel(dev, app, true);
+ err = dsa_user_dcbnl_ieee_global_setdel(dev, app, true);
if (err) {
if (ds->ops->port_add_dscp_prio)
ds->ops->port_add_dscp_prio(ds, port, dscp,
@@ -2417,6 +2467,42 @@ dsa_user_dcbnl_del_dscp_prio(struct net_device *dev, struct dcb_app *app)
return 0;
}
+static int __maybe_unused
+dsa_user_dcbnl_del_pcp_prio(struct net_device *dev, struct dcb_app *app)
+{
+ struct dsa_port *dp = dsa_user_to_port(dev);
+ struct dsa_switch *ds = dp->ds;
+ int err, port = dp->index;
+ u8 pcp = app->protocol;
+
+ if (!ds->ops->port_del_pcp_prio)
+ return -EOPNOTSUPP;
+
+ err = dcb_ieee_delapp(dev, app);
+ if (err)
+ return err;
+
+ err = ds->ops->port_del_pcp_prio(ds, port, pcp, app->priority);
+ if (err) {
+ dcb_ieee_setapp(dev, app);
+ return err;
+ }
+
+ if (!ds->pcp_prio_mapping_is_global)
+ return 0;
+
+ err = dsa_user_dcbnl_ieee_global_setdel(dev, app, true);
+ if (err) {
+ if (ds->ops->port_add_pcp_prio)
+ ds->ops->port_add_pcp_prio(ds, port, pcp,
+ app->priority);
+ dcb_ieee_setapp(dev, app);
+ return err;
+ }
+
+ return 0;
+}
+
static int __maybe_unused dsa_user_dcbnl_ieee_delapp(struct net_device *dev,
struct dcb_app *app)
{
@@ -2431,6 +2517,8 @@ static int __maybe_unused dsa_user_dcbnl_ieee_delapp(struct net_device *dev,
break;
case IEEE_8021QAZ_APP_SEL_DSCP:
return dsa_user_dcbnl_del_dscp_prio(dev, app);
+ case DCB_APP_SEL_PCP:
+ return dsa_user_dcbnl_del_pcp_prio(dev, app);
default:
return -EOPNOTSUPP;
}
@@ -2486,6 +2574,30 @@ static int dsa_user_dcbnl_init(struct net_device *dev)
}
}
+ if (ds->ops->port_get_pcp_prio) {
+ int protocol;
+
+ for (protocol = 0; protocol < 16; protocol++) {
+ struct dcb_app app = {
+ .selector = DCB_APP_SEL_PCP,
+ .protocol = protocol,
+ };
+ int prio;
+
+ prio = ds->ops->port_get_pcp_prio(ds, port, protocol);
+ if (prio == -EOPNOTSUPP)
+ continue;
+ if (prio < 0)
+ return prio;
+
+ app.priority = prio;
+
+ err = dcb_ieee_setapp(dev, &app);
+ if (err)
+ return err;
+ }
+ }
+
return 0;
}
--
2.43.0
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH net-next 2/2] net: dsa: mv88e6xxx: add support for dcb pcp app
2026-06-04 8:30 [PATCH net-next 0/2] net: dsa: mv88e6xxx: add support for dcb pcp app Cedric Jehasse via B4 Relay
2026-06-04 8:30 ` [PATCH net-next 1/2] net: dsa: " Cedric Jehasse via B4 Relay
@ 2026-06-04 8:30 ` Cedric Jehasse via B4 Relay
2026-06-04 10:37 ` [PATCH net-next 0/2] " Luke Howard
` (2 subsequent siblings)
4 siblings, 0 replies; 12+ messages in thread
From: Cedric Jehasse via B4 Relay @ 2026-06-04 8:30 UTC (permalink / raw)
To: Andrew Lunn, Vladimir Oltean, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Russell King
Cc: netdev, linux-kernel, Luke Howard, Cedric Jehasse, Cedric Jehasse
From: Cedric Jehasse <cedric.jehasse@luminex.be>
Implement the DSA pcp_prio hooks to support the dcb pcp app.
In the Marvell switches this is done by configuring the IEEE PRI Mapping
table. There are different hardware implementations of this table
depending on the switch:
* a global table
* the 6390 has one table per port
* the 6393 has one table for DEI=0, and another table for DEI=1 per port
Example command:
dcb app replace dev p1 pcp-prio 7nd:3
Signed-off-by: Cedric Jehasse <cedric.jehasse@luminex.be>
---
drivers/net/dsa/mv88e6xxx/Makefile | 1 +
drivers/net/dsa/mv88e6xxx/chip.c | 36 ++++++
drivers/net/dsa/mv88e6xxx/chip.h | 17 +++
drivers/net/dsa/mv88e6xxx/dcb.c | 229 +++++++++++++++++++++++++++++++++++++
drivers/net/dsa/mv88e6xxx/dcb.h | 21 ++++
drivers/net/dsa/mv88e6xxx/port.c | 28 ++++-
drivers/net/dsa/mv88e6xxx/port.h | 8 ++
7 files changed, 338 insertions(+), 2 deletions(-)
diff --git a/drivers/net/dsa/mv88e6xxx/Makefile b/drivers/net/dsa/mv88e6xxx/Makefile
index b0b08c6f159c..6eb9be4d934a 100644
--- a/drivers/net/dsa/mv88e6xxx/Makefile
+++ b/drivers/net/dsa/mv88e6xxx/Makefile
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_NET_DSA_MV88E6XXX) += mv88e6xxx.o
mv88e6xxx-objs := chip.o
+mv88e6xxx-objs += dcb.o
mv88e6xxx-objs += devlink.o
mv88e6xxx-objs += global1.o
mv88e6xxx-objs += global1_atu.o
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 5bbf5e69de9a..e12b84e42a93 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -35,6 +35,7 @@
#include <net/pkt_sched.h>
#include "chip.h"
+#include "dcb.h"
#include "devlink.h"
#include "global1.h"
#include "global2.h"
@@ -4258,6 +4259,7 @@ static const struct mv88e6xxx_ops mv88e6085_ops = {
.stu_loadpurge = mv88e6352_g1_stu_loadpurge,
.phylink_get_caps = mv88e6185_phylink_get_caps,
.set_max_frame_size = mv88e6185_g1_set_max_frame_size,
+ .dcb_ops = &mv88e6352_dcb_ops,
};
static const struct mv88e6xxx_ops mv88e6095_ops = {
@@ -4290,6 +4292,7 @@ static const struct mv88e6xxx_ops mv88e6095_ops = {
.phylink_get_caps = mv88e6095_phylink_get_caps,
.pcs_ops = &mv88e6185_pcs_ops,
.set_max_frame_size = mv88e6185_g1_set_max_frame_size,
+ .dcb_ops = &mv88e6352_dcb_ops,
};
static const struct mv88e6xxx_ops mv88e6097_ops = {
@@ -4337,6 +4340,7 @@ static const struct mv88e6xxx_ops mv88e6097_ops = {
.stu_getnext = mv88e6352_g1_stu_getnext,
.stu_loadpurge = mv88e6352_g1_stu_loadpurge,
.set_max_frame_size = mv88e6185_g1_set_max_frame_size,
+ .dcb_ops = &mv88e6352_dcb_ops,
};
static const struct mv88e6xxx_ops mv88e6123_ops = {
@@ -4378,6 +4382,7 @@ static const struct mv88e6xxx_ops mv88e6123_ops = {
.stu_loadpurge = mv88e6352_g1_stu_loadpurge,
.phylink_get_caps = mv88e6185_phylink_get_caps,
.set_max_frame_size = mv88e6185_g1_set_max_frame_size,
+ .dcb_ops = &mv88e6352_dcb_ops,
};
static const struct mv88e6xxx_ops mv88e6131_ops = {
@@ -4418,6 +4423,7 @@ static const struct mv88e6xxx_ops mv88e6131_ops = {
.vtu_getnext = mv88e6185_g1_vtu_getnext,
.vtu_loadpurge = mv88e6185_g1_vtu_loadpurge,
.phylink_get_caps = mv88e6185_phylink_get_caps,
+ .dcb_ops = &mv88e6352_dcb_ops,
};
static const struct mv88e6xxx_ops mv88e6141_ops = {
@@ -4481,6 +4487,7 @@ static const struct mv88e6xxx_ops mv88e6141_ops = {
.serdes_get_regs = mv88e6390_serdes_get_regs,
.phylink_get_caps = mv88e6341_phylink_get_caps,
.pcs_ops = &mv88e6390_pcs_ops,
+ .dcb_ops = &mv88e6352_dcb_ops,
};
static const struct mv88e6xxx_ops mv88e6161_ops = {
@@ -4529,6 +4536,7 @@ static const struct mv88e6xxx_ops mv88e6161_ops = {
.ptp_ops = &mv88e6165_ptp_ops,
.phylink_get_caps = mv88e6185_phylink_get_caps,
.set_max_frame_size = mv88e6185_g1_set_max_frame_size,
+ .dcb_ops = &mv88e6352_dcb_ops,
};
static const struct mv88e6xxx_ops mv88e6165_ops = {
@@ -4566,6 +4574,7 @@ static const struct mv88e6xxx_ops mv88e6165_ops = {
.avb_ops = &mv88e6165_avb_ops,
.ptp_ops = &mv88e6165_ptp_ops,
.phylink_get_caps = mv88e6185_phylink_get_caps,
+ .dcb_ops = &mv88e6352_dcb_ops,
};
static const struct mv88e6xxx_ops mv88e6171_ops = {
@@ -4612,6 +4621,7 @@ static const struct mv88e6xxx_ops mv88e6171_ops = {
.stu_getnext = mv88e6352_g1_stu_getnext,
.stu_loadpurge = mv88e6352_g1_stu_loadpurge,
.phylink_get_caps = mv88e6351_phylink_get_caps,
+ .dcb_ops = &mv88e6352_dcb_ops,
};
static const struct mv88e6xxx_ops mv88e6172_ops = {
@@ -4669,6 +4679,7 @@ static const struct mv88e6xxx_ops mv88e6172_ops = {
.gpio_ops = &mv88e6352_gpio_ops,
.phylink_get_caps = mv88e6352_phylink_get_caps,
.pcs_ops = &mv88e6352_pcs_ops,
+ .dcb_ops = &mv88e6352_dcb_ops,
};
static const struct mv88e6xxx_ops mv88e6175_ops = {
@@ -4715,6 +4726,7 @@ static const struct mv88e6xxx_ops mv88e6175_ops = {
.stu_getnext = mv88e6352_g1_stu_getnext,
.stu_loadpurge = mv88e6352_g1_stu_loadpurge,
.phylink_get_caps = mv88e6351_phylink_get_caps,
+ .dcb_ops = &mv88e6352_dcb_ops,
};
static const struct mv88e6xxx_ops mv88e6176_ops = {
@@ -4773,6 +4785,7 @@ static const struct mv88e6xxx_ops mv88e6176_ops = {
.gpio_ops = &mv88e6352_gpio_ops,
.phylink_get_caps = mv88e6352_phylink_get_caps,
.pcs_ops = &mv88e6352_pcs_ops,
+ .dcb_ops = &mv88e6352_dcb_ops,
};
static const struct mv88e6xxx_ops mv88e6185_ops = {
@@ -4811,6 +4824,7 @@ static const struct mv88e6xxx_ops mv88e6185_ops = {
.phylink_get_caps = mv88e6185_phylink_get_caps,
.pcs_ops = &mv88e6185_pcs_ops,
.set_max_frame_size = mv88e6185_g1_set_max_frame_size,
+ .dcb_ops = &mv88e6352_dcb_ops,
};
static const struct mv88e6xxx_ops mv88e6190_ops = {
@@ -4830,6 +4844,7 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
.port_set_speed_duplex = mv88e6390_port_set_speed_duplex,
.port_max_speed_mode = mv88e6390_port_max_speed_mode,
.port_tag_remap = mv88e6390_port_tag_remap,
+ .dcb_ops = &mv88e6390_dcb_ops,
.port_set_policy = mv88e6352_port_set_policy,
.port_set_frame_mode = mv88e6351_port_set_frame_mode,
.port_set_ucast_flood = mv88e6352_port_set_ucast_flood,
@@ -4931,6 +4946,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
.gpio_ops = &mv88e6352_gpio_ops,
.phylink_get_caps = mv88e6390x_phylink_get_caps,
.pcs_ops = &mv88e6390_pcs_ops,
+ .dcb_ops = &mv88e6390_dcb_ops,
};
static const struct mv88e6xxx_ops mv88e6191_ops = {
@@ -4990,6 +5006,7 @@ static const struct mv88e6xxx_ops mv88e6191_ops = {
.ptp_ops = &mv88e6352_ptp_ops,
.phylink_get_caps = mv88e6390_phylink_get_caps,
.pcs_ops = &mv88e6390_pcs_ops,
+ .dcb_ops = &mv88e6390_dcb_ops,
};
static const struct mv88e6xxx_ops mv88e6240_ops = {
@@ -5051,6 +5068,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
.ptp_ops = &mv88e6352_ptp_ops,
.phylink_get_caps = mv88e6352_phylink_get_caps,
.pcs_ops = &mv88e6352_pcs_ops,
+ .dcb_ops = &mv88e6352_dcb_ops,
};
static const struct mv88e6xxx_ops mv88e6250_ops = {
@@ -5096,6 +5114,7 @@ static const struct mv88e6xxx_ops mv88e6250_ops = {
.ptp_ops = &mv88e6352_ptp_ops,
.phylink_get_caps = mv88e6250_phylink_get_caps,
.set_max_frame_size = mv88e6185_g1_set_max_frame_size,
+ .dcb_ops = &mv88e6352_dcb_ops,
};
static const struct mv88e6xxx_ops mv88e6290_ops = {
@@ -5158,6 +5177,7 @@ static const struct mv88e6xxx_ops mv88e6290_ops = {
.phylink_get_caps = mv88e6390_phylink_get_caps,
.pcs_ops = &mv88e6390_pcs_ops,
.tcam_ops = &mv88e6390_tcam_ops,
+ .dcb_ops = &mv88e6390_dcb_ops,
};
static const struct mv88e6xxx_ops mv88e6320_ops = {
@@ -5211,6 +5231,7 @@ static const struct mv88e6xxx_ops mv88e6320_ops = {
.avb_ops = &mv88e6352_avb_ops,
.ptp_ops = &mv88e6352_ptp_ops,
.phylink_get_caps = mv88e632x_phylink_get_caps,
+ .dcb_ops = &mv88e6352_dcb_ops,
};
static const struct mv88e6xxx_ops mv88e6321_ops = {
@@ -5263,6 +5284,7 @@ static const struct mv88e6xxx_ops mv88e6321_ops = {
.avb_ops = &mv88e6352_avb_ops,
.ptp_ops = &mv88e6352_ptp_ops,
.phylink_get_caps = mv88e632x_phylink_get_caps,
+ .dcb_ops = &mv88e6352_dcb_ops,
};
static const struct mv88e6xxx_ops mv88e6341_ops = {
@@ -5329,6 +5351,7 @@ static const struct mv88e6xxx_ops mv88e6341_ops = {
.serdes_get_regs = mv88e6390_serdes_get_regs,
.phylink_get_caps = mv88e6341_phylink_get_caps,
.pcs_ops = &mv88e6390_pcs_ops,
+ .dcb_ops = &mv88e6352_dcb_ops,
};
static const struct mv88e6xxx_ops mv88e6350_ops = {
@@ -5375,6 +5398,7 @@ static const struct mv88e6xxx_ops mv88e6350_ops = {
.stu_getnext = mv88e6352_g1_stu_getnext,
.stu_loadpurge = mv88e6352_g1_stu_loadpurge,
.phylink_get_caps = mv88e6351_phylink_get_caps,
+ .dcb_ops = &mv88e6352_dcb_ops,
};
static const struct mv88e6xxx_ops mv88e6351_ops = {
@@ -5423,6 +5447,7 @@ static const struct mv88e6xxx_ops mv88e6351_ops = {
.avb_ops = &mv88e6352_avb_ops,
.ptp_ops = &mv88e6352_ptp_ops,
.phylink_get_caps = mv88e6351_phylink_get_caps,
+ .dcb_ops = &mv88e6352_dcb_ops,
};
static const struct mv88e6xxx_ops mv88e6352_ops = {
@@ -5487,6 +5512,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
.serdes_get_regs = mv88e6352_serdes_get_regs,
.phylink_get_caps = mv88e6352_phylink_get_caps,
.pcs_ops = &mv88e6352_pcs_ops,
+ .dcb_ops = &mv88e6352_dcb_ops,
};
static const struct mv88e6xxx_ops mv88e6390_ops = {
@@ -5553,6 +5579,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
.phylink_get_caps = mv88e6390_phylink_get_caps,
.pcs_ops = &mv88e6390_pcs_ops,
.tcam_ops = &mv88e6390_tcam_ops,
+ .dcb_ops = &mv88e6390_dcb_ops,
};
static const struct mv88e6xxx_ops mv88e6390x_ops = {
@@ -5618,6 +5645,7 @@ static const struct mv88e6xxx_ops mv88e6390x_ops = {
.ptp_ops = &mv88e6390_ptp_ops,
.phylink_get_caps = mv88e6390x_phylink_get_caps,
.pcs_ops = &mv88e6390_pcs_ops,
+ .dcb_ops = &mv88e6390_dcb_ops,
};
static const struct mv88e6xxx_ops mv88e6393x_ops = {
@@ -5684,6 +5712,7 @@ static const struct mv88e6xxx_ops mv88e6393x_ops = {
.phylink_get_caps = mv88e6393x_phylink_get_caps,
.pcs_ops = &mv88e6393x_pcs_ops,
.tcam_ops = &mv88e6393_tcam_ops,
+ .dcb_ops = &mv88e6393x_dcb_ops,
};
static const struct mv88e6xxx_qav_info mv88e6352_qav_info = {
@@ -7385,6 +7414,9 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
.port_hwtstamp_get = mv88e6xxx_port_hwtstamp_get,
.port_txtstamp = mv88e6xxx_port_txtstamp,
.port_rxtstamp = mv88e6xxx_port_rxtstamp,
+ .port_get_pcp_prio = mv88e6xxx_port_get_pcp_prio,
+ .port_add_pcp_prio = mv88e6xxx_port_add_pcp_prio,
+ .port_del_pcp_prio = mv88e6xxx_port_del_pcp_prio,
.port_setup_tc = mv88e6xxx_port_setup_tc,
.cls_flower_add = mv88e6xxx_cls_flower_add,
.cls_flower_del = mv88e6xxx_cls_flower_del,
@@ -7402,6 +7434,7 @@ static const struct dsa_switch_ops mv88e6xxx_switch_ops = {
static int mv88e6xxx_register_switch(struct mv88e6xxx_chip *chip)
{
+ const struct mv88e6xxx_dcb_ops *dcb_ops = chip->info->ops->dcb_ops;
struct device *dev = chip->dev;
struct dsa_switch *ds;
@@ -7418,6 +7451,9 @@ static int mv88e6xxx_register_switch(struct mv88e6xxx_chip *chip)
ds->ageing_time_min = chip->info->age_time_coeff;
ds->ageing_time_max = chip->info->age_time_coeff * U8_MAX;
+ ds->pcp_prio_mapping_is_global = dcb_ops &&
+ dcb_ops->global_get_pcp_prio;
+
/* Some chips support up to 32, but that requires enabling the
* 5-bit port mode, which we do not support. 640k^W16 ought to
* be enough for anyone.
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index e563cfe8ab2a..1aa77b643924 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -211,6 +211,7 @@ struct mv88e6xxx_stu_entry {
};
struct mv88e6xxx_bus_ops;
+struct mv88e6xxx_dcb_ops;
struct mv88e6xxx_irq_ops;
struct mv88e6xxx_gpio_ops;
struct mv88e6xxx_avb_ops;
@@ -728,6 +729,9 @@ struct mv88e6xxx_ops {
/* Ternary Content Addressable Memory operations */
const struct mv88e6xxx_tcam_ops *tcam_ops;
+
+ /* Data Center Bridging operations */
+ const struct mv88e6xxx_dcb_ops *dcb_ops;
};
struct mv88e6xxx_irq_ops {
@@ -779,6 +783,19 @@ struct mv88e6xxx_avb_ops {
u16 data);
};
+struct mv88e6xxx_dcb_ops {
+ /* Get/set the chip's global PCP to queue priority mapping */
+ int (*global_get_pcp_prio)(struct mv88e6xxx_chip *chip, u8 pcp);
+ int (*global_set_pcp_prio)(struct mv88e6xxx_chip *chip, u8 pcp,
+ u8 prio);
+
+ /* Get/set a port's PCP to queue priority mapping */
+ int (*port_get_pcp_prio)(struct mv88e6xxx_chip *chip, int port,
+ u8 pcp);
+ int (*port_set_pcp_prio)(struct mv88e6xxx_chip *chip, int port,
+ u8 pcp, u8 prio);
+};
+
struct mv88e6xxx_ptp_ops {
u64 (*clock_read)(struct cyclecounter *cc);
int (*ptp_enable)(struct ptp_clock_info *ptp,
diff --git a/drivers/net/dsa/mv88e6xxx/dcb.c b/drivers/net/dsa/mv88e6xxx/dcb.c
new file mode 100644
index 000000000000..0a3099cdf388
--- /dev/null
+++ b/drivers/net/dsa/mv88e6xxx/dcb.c
@@ -0,0 +1,229 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+// Copyright (c) 2026 Luminex Network Intelligence
+
+#include "chip.h"
+#include "dcb.h"
+#include "global1.h"
+#include "port.h"
+
+static int mv88e6352_get_pcp_prio(struct mv88e6xxx_chip *chip, u8 pcp)
+{
+ u16 val;
+ int err;
+
+ /* These devices have no mapping table for frames with DEI bit set */
+ if (pcp >= 8)
+ return -EOPNOTSUPP;
+
+ err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_IEEE_PRI, &val);
+ if (err)
+ return err;
+
+ return (val >> (pcp * 2)) & 3;
+}
+
+static int mv88e6352_set_pcp_prio(struct mv88e6xxx_chip *chip, u8 pcp, u8 prio)
+{
+ u16 val;
+ int err;
+
+ /* These devices have no mapping table for frames with DEI bit set */
+ if (pcp >= 8)
+ return -EOPNOTSUPP;
+
+ if (prio >= 4)
+ return -EINVAL;
+
+ err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_IEEE_PRI, &val);
+ if (err)
+ return err;
+
+ val &= ~(3 << (pcp * 2));
+ val |= prio << (pcp * 2);
+
+ return mv88e6xxx_g1_write(chip, MV88E6XXX_G1_IEEE_PRI, val);
+}
+
+static int mv88e639x_port_ieeepmt_pcp_entry(u8 pcp, bool has_dei,
+ u16 *table, u8 *ptr)
+{
+ if (pcp >= 16)
+ return -EINVAL;
+
+ /* not all devices have a table for mapping with DEI bit set */
+ if (pcp >= 8 && !has_dei)
+ return -EOPNOTSUPP;
+
+ *table = pcp >= 8 ?
+ MV88E6393X_PORT_IEEE_PRIO_MAP_TABLE_INGRESS_PCP_DEI :
+ MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_INGRESS_PCP;
+ *ptr = pcp & 7;
+
+ return 0;
+}
+
+static int mv88e639x_port_get_pcp_prio(struct mv88e6xxx_chip *chip, int port,
+ u8 pcp, bool has_dei)
+{
+ u16 val, table;
+ u8 ptr;
+ int err;
+
+ err = mv88e639x_port_ieeepmt_pcp_entry(pcp, has_dei, &table, &ptr);
+ if (err)
+ return err;
+
+ err = mv88e6xxx_port_ieeepmt_read(chip, port, table, ptr, &val);
+ if (err)
+ return err;
+
+ if (val & MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_QPRI_DIS)
+ return -EOPNOTSUPP;
+
+ return (val & MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_QPRI_MASK)
+ >> MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_QPRI_SHIFT;
+}
+
+static int mv88e639x_port_set_pcp_prio(struct mv88e6xxx_chip *chip, int port,
+ u8 pcp, u8 prio, bool has_dei)
+{
+ u16 val, table;
+ u8 ptr;
+ int err;
+
+ if (prio >= 8)
+ return -EINVAL;
+
+ err = mv88e639x_port_ieeepmt_pcp_entry(pcp, has_dei, &table, &ptr);
+ if (err)
+ return err;
+
+ err = mv88e6xxx_port_ieeepmt_read(chip, port, table, ptr, &val);
+ if (err)
+ return err;
+
+ val &= ~MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_QPRI_DIS;
+ val &= ~MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_QPRI_MASK;
+ val |= (prio << MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_QPRI_SHIFT) &
+ MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_QPRI_MASK;
+
+ return mv88e6xxx_port_ieeepmt_write(chip, port, table, ptr, val);
+}
+
+static int mv88e6390_port_get_pcp_prio(struct mv88e6xxx_chip *chip, int port,
+ u8 pcp)
+{
+ return mv88e639x_port_get_pcp_prio(chip, port, pcp, false);
+}
+
+static int mv88e6390_port_set_pcp_prio(struct mv88e6xxx_chip *chip, int port,
+ u8 pcp, u8 prio)
+{
+ return mv88e639x_port_set_pcp_prio(chip, port, pcp, prio, false);
+}
+
+static int mv88e6393x_port_get_pcp_prio(struct mv88e6xxx_chip *chip, int port,
+ u8 pcp)
+{
+ return mv88e639x_port_get_pcp_prio(chip, port, pcp, true);
+}
+
+static int mv88e6393x_port_set_pcp_prio(struct mv88e6xxx_chip *chip, int port,
+ u8 pcp, u8 prio)
+{
+ return mv88e639x_port_set_pcp_prio(chip, port, pcp, prio, true);
+}
+
+const struct mv88e6xxx_dcb_ops mv88e6352_dcb_ops = {
+ .global_get_pcp_prio = mv88e6352_get_pcp_prio,
+ .global_set_pcp_prio = mv88e6352_set_pcp_prio,
+};
+
+const struct mv88e6xxx_dcb_ops mv88e6390_dcb_ops = {
+ .port_get_pcp_prio = mv88e6390_port_get_pcp_prio,
+ .port_set_pcp_prio = mv88e6390_port_set_pcp_prio,
+};
+
+const struct mv88e6xxx_dcb_ops mv88e6393x_dcb_ops = {
+ .port_get_pcp_prio = mv88e6393x_port_get_pcp_prio,
+ .port_set_pcp_prio = mv88e6393x_port_set_pcp_prio,
+};
+
+static int mv88e6xxx_dcb_get_pcp_prio(struct mv88e6xxx_chip *chip, int port,
+ u8 pcp)
+{
+ const struct mv88e6xxx_dcb_ops *dcb_ops = chip->info->ops->dcb_ops;
+
+ if (!dcb_ops)
+ return -EOPNOTSUPP;
+
+ if (dcb_ops->port_get_pcp_prio)
+ return dcb_ops->port_get_pcp_prio(chip, port, pcp);
+
+ if (dcb_ops->global_get_pcp_prio)
+ return dcb_ops->global_get_pcp_prio(chip, pcp);
+
+ return -EOPNOTSUPP;
+}
+
+static int mv88e6xxx_dcb_set_pcp_prio(struct mv88e6xxx_chip *chip, int port,
+ u8 pcp, u8 prio)
+{
+ const struct mv88e6xxx_dcb_ops *dcb_ops = chip->info->ops->dcb_ops;
+
+ if (!dcb_ops)
+ return -EOPNOTSUPP;
+
+ if (dcb_ops->port_set_pcp_prio)
+ return dcb_ops->port_set_pcp_prio(chip, port, pcp, prio);
+
+ if (dcb_ops->global_set_pcp_prio)
+ return dcb_ops->global_set_pcp_prio(chip, pcp, prio);
+
+ return -EOPNOTSUPP;
+}
+
+int mv88e6xxx_port_get_pcp_prio(struct dsa_switch *ds, int port, u8 pcp)
+{
+ struct mv88e6xxx_chip *chip = ds->priv;
+ int err;
+
+ mv88e6xxx_reg_lock(chip);
+ err = mv88e6xxx_dcb_get_pcp_prio(chip, port, pcp);
+ mv88e6xxx_reg_unlock(chip);
+
+ return err;
+}
+
+int mv88e6xxx_port_add_pcp_prio(struct dsa_switch *ds, int port, u8 pcp,
+ u8 prio)
+{
+ struct mv88e6xxx_chip *chip = ds->priv;
+ int err;
+
+ if (prio >= 8)
+ return -EINVAL;
+
+ mv88e6xxx_reg_lock(chip);
+ err = mv88e6xxx_dcb_set_pcp_prio(chip, port, pcp, prio);
+ mv88e6xxx_reg_unlock(chip);
+
+ return err;
+}
+
+int mv88e6xxx_port_del_pcp_prio(struct dsa_switch *ds, int port, u8 pcp,
+ u8 prio)
+{
+ struct mv88e6xxx_chip *chip = ds->priv;
+ int err = 0;
+
+ mv88e6xxx_reg_lock(chip);
+ if (mv88e6xxx_dcb_get_pcp_prio(chip, port, pcp) != prio)
+ goto unlock;
+
+ err = mv88e6xxx_dcb_set_pcp_prio(chip, port, pcp, 0);
+
+unlock:
+ mv88e6xxx_reg_unlock(chip);
+ return err;
+}
diff --git a/drivers/net/dsa/mv88e6xxx/dcb.h b/drivers/net/dsa/mv88e6xxx/dcb.h
new file mode 100644
index 000000000000..7a2124ec23ba
--- /dev/null
+++ b/drivers/net/dsa/mv88e6xxx/dcb.h
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * Marvell 88E6xxx Switch DCB support
+ */
+
+#ifndef _MV88E6XXX_DCB_H_
+#define _MV88E6XXX_DCB_H_
+
+#include "chip.h"
+
+extern const struct mv88e6xxx_dcb_ops mv88e6352_dcb_ops;
+extern const struct mv88e6xxx_dcb_ops mv88e6390_dcb_ops;
+extern const struct mv88e6xxx_dcb_ops mv88e6393x_dcb_ops;
+
+int mv88e6xxx_port_get_pcp_prio(struct dsa_switch *ds, int port, u8 pcp);
+int mv88e6xxx_port_add_pcp_prio(struct dsa_switch *ds, int port, u8 pcp,
+ u8 prio);
+int mv88e6xxx_port_del_pcp_prio(struct dsa_switch *ds, int port, u8 pcp,
+ u8 prio);
+
+#endif /* _MV88E6XXX_DCB_H_ */
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index 23d1435db0d8..a8e2f8910b0a 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -1641,8 +1641,8 @@ int mv88e6095_port_tag_remap(struct mv88e6xxx_chip *chip, int port)
0x7654);
}
-static int mv88e6xxx_port_ieeepmt_write(struct mv88e6xxx_chip *chip,
- int port, u16 table, u8 ptr, u16 data)
+int mv88e6xxx_port_ieeepmt_write(struct mv88e6xxx_chip *chip,
+ int port, u16 table, u8 ptr, u16 data)
{
u16 reg;
@@ -1654,6 +1654,30 @@ static int mv88e6xxx_port_ieeepmt_write(struct mv88e6xxx_chip *chip,
MV88E6390_PORT_IEEE_PRIO_MAP_TABLE, reg);
}
+int mv88e6xxx_port_ieeepmt_read(struct mv88e6xxx_chip *chip, int port,
+ u16 table, u8 ptr, u16 *data)
+{
+ u16 reg;
+ int err;
+
+ reg = table |
+ (ptr << __bf_shf(MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_PTR_MASK));
+
+ err = mv88e6xxx_port_write(chip, port,
+ MV88E6390_PORT_IEEE_PRIO_MAP_TABLE, reg);
+ if (err)
+ return err;
+
+ err = mv88e6xxx_port_read(chip, port,
+ MV88E6390_PORT_IEEE_PRIO_MAP_TABLE, ®);
+ if (err)
+ return err;
+
+ *data = reg & MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_DATA_MASK;
+
+ return 0;
+}
+
int mv88e6390_port_tag_remap(struct mv88e6xxx_chip *chip, int port)
{
int err, i;
diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h
index cf8655a13729..8bf0f3cbc4f0 100644
--- a/drivers/net/dsa/mv88e6xxx/port.h
+++ b/drivers/net/dsa/mv88e6xxx/port.h
@@ -457,11 +457,15 @@
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_PCP 0x1000
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_PCP 0x2000
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_PCP 0x3000
+#define MV88E6393X_PORT_IEEE_PRIO_MAP_TABLE_INGRESS_PCP_DEI 0x4000
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_GREEN_DSCP 0x5000
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_YELLOW_DSCP 0x6000
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_EGRESS_AVB_DSCP 0x7000
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_PTR_MASK 0x0e00
#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_DATA_MASK 0x01ff
+#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_QPRI_DIS 0x0080
+#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_QPRI_MASK 0x0070
+#define MV88E6390_PORT_IEEE_PRIO_MAP_TABLE_QPRI_SHIFT 4
/* Offset 0x18: Port IEEE Priority Remapping Registers (0-3) */
#define MV88E6095_PORT_IEEE_PRIO_REMAP_0123 0x18
@@ -543,6 +547,10 @@ int mv88e6xxx_port_set_8021q_mode(struct mv88e6xxx_chip *chip, int port,
u16 mode);
int mv88e6095_port_tag_remap(struct mv88e6xxx_chip *chip, int port);
int mv88e6390_port_tag_remap(struct mv88e6xxx_chip *chip, int port);
+int mv88e6xxx_port_ieeepmt_write(struct mv88e6xxx_chip *chip,
+ int port, u16 table, u8 ptr, u16 data);
+int mv88e6xxx_port_ieeepmt_read(struct mv88e6xxx_chip *chip, int port,
+ u16 table, u8 ptr, u16 *data);
int mv88e6xxx_port_set_egress_mode(struct mv88e6xxx_chip *chip, int port,
enum mv88e6xxx_egress_mode mode);
int mv88e6085_port_set_frame_mode(struct mv88e6xxx_chip *chip, int port,
--
2.43.0
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH net-next 0/2] net: dsa: mv88e6xxx: add support for dcb pcp app
2026-06-04 8:30 [PATCH net-next 0/2] net: dsa: mv88e6xxx: add support for dcb pcp app Cedric Jehasse via B4 Relay
2026-06-04 8:30 ` [PATCH net-next 1/2] net: dsa: " Cedric Jehasse via B4 Relay
2026-06-04 8:30 ` [PATCH net-next 2/2] net: dsa: mv88e6xxx: " Cedric Jehasse via B4 Relay
@ 2026-06-04 10:37 ` Luke Howard
2026-06-04 12:01 ` Cedric Jehasse
2026-06-05 1:14 ` Luke Howard
2026-06-07 3:12 ` Luke Howard
4 siblings, 1 reply; 12+ messages in thread
From: Luke Howard @ 2026-06-04 10:37 UTC (permalink / raw)
To: cedric.jehasse
Cc: Andrew Lunn, Vladimir Oltean, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Russell King, netdev,
linux-kernel, Cedric Jehasse
> On 4 Jun 2026, at 6:30 pm, Cedric Jehasse via B4 Relay <devnull+cedric.jehasse.luminex.be@kernel.org> wrote:
>
> There's another patch series [1] on the mailing list that uses the same
> IEEE PRI Mapping table to implement MPQRIO. To me the dcb pcp app feels
> like the natural way to configure the pcp to QPri mappings in the
> switch
I’m not familiar with the API or user tools, but the fact it supports both global and ingress mappings makes it seem like a better option, agreed.
It seems like we maybe could support MQPRIO properly with TCAM but perhaps that isn’t really necessary (certainly not for my all-ports-in-bridge use case, where there isn’t a distinction between ingress and egress priority mappings).
I still need to find a similarly natural way to expose the switch’s AVB capabilities / 802.1Qat admission control. Perhaps there is none and it will need to remain a local patch.
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH net-next 0/2] net: dsa: mv88e6xxx: add support for dcb pcp app
2026-06-04 10:37 ` [PATCH net-next 0/2] " Luke Howard
@ 2026-06-04 12:01 ` Cedric Jehasse
2026-06-04 22:51 ` Luke Howard
0 siblings, 1 reply; 12+ messages in thread
From: Cedric Jehasse @ 2026-06-04 12:01 UTC (permalink / raw)
To: Luke Howard
Cc: cedric.jehasse, Andrew Lunn, Vladimir Oltean, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Russell King, netdev, linux-kernel
On Thu, Jun 04, 2026 at 08:37:17PM +1000, Luke Howard wrote:
> I still need to find a similarly natural way to expose the switch’s AVB capabilities / 802.1Qat admission control. Perhaps there is none and it will need to remain a local patch.
There's a devlink port param command. I've been wondering if this could be used
to set a port's AvbMode. However:
* at the moment there are no drivers supporting this.
eg. devlink_nl_port_param_set_doit and other return this isn't supported
* i don't know if AvbMode is a valid use for devlink port param, and if it
would get accepted
Cedric
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH net-next 0/2] net: dsa: mv88e6xxx: add support for dcb pcp app
2026-06-04 12:01 ` Cedric Jehasse
@ 2026-06-04 22:51 ` Luke Howard
2026-06-04 23:21 ` Andrew Lunn
0 siblings, 1 reply; 12+ messages in thread
From: Luke Howard @ 2026-06-04 22:51 UTC (permalink / raw)
To: Cedric Jehasse
Cc: cedric.jehasse, Andrew Lunn, Vladimir Oltean, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Russell King, netdev, linux-kernel
Hi Cedric,
> On 4 Jun 2026, at 10:01 pm, Cedric Jehasse <cedric.jehasse@gmail.com> wrote:
>
> On Thu, Jun 04, 2026 at 08:37:17PM +1000, Luke Howard wrote:
>> I still need to find a similarly natural way to expose the switch’s AVB capabilities / 802.1Qat admission control. Perhaps there is none and it will need to remain a local patch.
>
> There's a devlink port param command. I've been wondering if this could be used
> to set a port's AvbMode. However:
> * at the moment there are no drivers supporting this.
> eg. devlink_nl_port_param_set_doit and other return this isn't supported
> * i don't know if AvbMode is a valid use for devlink port param, and if it
> would get accepted
mv88e6xxx already exposes the ATU_hash driver-specific devlink parameter, so there is a precedent which augurs well.
A per-port AVB mode devlink could configure:
- AVB mode to enhanced
- iso ptrs to number of enabled ports * N (currently we use N=64)
- enabling interpreting AVB_NRL entries as AVB with G1_ATU_CTL_MAC_AVB
The leaves two issues:
- if at least one port has AVB mode set, we could install permanent MDB entries as AVB_NRL. But here we have the old problem, that AVB mode is on the ingress port, whereas MDB entries are on the egress port.
- also the AVB FPri and QPri values would need to be configured, either via another devlink parameter or MQPRIO
This approach would integrate well with your CBS and DCB patches. Having said that, AVB mode could likely be reimplemented with TCAM, and (assuming an SRP daemon that knew how to install those flower entries) that might be a more portable and idiomatic solution. I am not sure how it would perform compared to the native AVB admission control in the switch.
Luke
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH net-next 0/2] net: dsa: mv88e6xxx: add support for dcb pcp app
2026-06-04 22:51 ` Luke Howard
@ 2026-06-04 23:21 ` Andrew Lunn
2026-06-05 1:13 ` Luke Howard
0 siblings, 1 reply; 12+ messages in thread
From: Andrew Lunn @ 2026-06-04 23:21 UTC (permalink / raw)
To: Luke Howard
Cc: Cedric Jehasse, cedric.jehasse, Vladimir Oltean, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Russell King, netdev, linux-kernel
On Fri, Jun 05, 2026 at 08:51:56AM +1000, Luke Howard wrote:
> Hi Cedric,
>
> > On 4 Jun 2026, at 10:01 pm, Cedric Jehasse <cedric.jehasse@gmail.com> wrote:
> >
> > On Thu, Jun 04, 2026 at 08:37:17PM +1000, Luke Howard wrote:
> >> I still need to find a similarly natural way to expose the switch’s AVB capabilities / 802.1Qat admission control. Perhaps there is none and it will need to remain a local patch.
> >
> > There's a devlink port param command. I've been wondering if this could be used
> > to set a port's AvbMode. However:
> > * at the moment there are no drivers supporting this.
> > eg. devlink_nl_port_param_set_doit and other return this isn't supported
> > * i don't know if AvbMode is a valid use for devlink port param, and if it
> > would get accepted
>
> mv88e6xxx already exposes the ATU_hash driver-specific devlink parameter, so there is a precedent which augurs well.
>
> A per-port AVB mode devlink could configure:
>
> - AVB mode to enhanced
> - iso ptrs to number of enabled ports * N (currently we use N=64)
> - enabling interpreting AVB_NRL entries as AVB with G1_ATU_CTL_MAC_AVB
I don't know enough about AVB, so this might not apply here....
What does the pure software version of AVB look like? Is there a need
to configure these parameters? If not, why not? If there is, what API
is currently used?
Ideally, the user should not need to know if some functionality has
been accelerated by offloading it to hardware. They just configure it
using the standard Linux model of the feature.
Andrew
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH net-next 0/2] net: dsa: mv88e6xxx: add support for dcb pcp app
2026-06-04 23:21 ` Andrew Lunn
@ 2026-06-05 1:13 ` Luke Howard
2026-06-05 12:05 ` Luke Howard
0 siblings, 1 reply; 12+ messages in thread
From: Luke Howard @ 2026-06-05 1:13 UTC (permalink / raw)
To: Andrew Lunn
Cc: Cedric Jehasse, cedric.jehasse, Vladimir Oltean, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Russell King, netdev, linux-kernel, Max Hunter, Kieran Tyrrell,
Nikolay Aleksandrov
Hi Andrew,
> I don't know enough about AVB, so this might not apply here....
>
> What does the pure software version of AVB look like? Is there a need
> to configure these parameters? If not, why not? If there is, what API
> is currently used?
Qdisc configuration for AVB is described here [1] albeit with reversed numbering of TCs. CBS parameters are usually managed dynamically by SRP (in user space), but static configuration as shown in the link would be common for automative AVB/TSN.
> Ideally, the user should not need to know if some functionality has
> been accelerated by offloading it to hardware. They just configure it
> using the standard Linux model of the feature.
Absolutely, and that was the model I used when building a SRP daemon, which I first tested with the software bridge and some i210s.
One issue is that AVB is typically configured using MQPRIO, which configures egress queue mapping. The Marvell switches support ingress queue mapping (the subject of this patch), although there is a special case for AVB traffic which does allow for egress queue mapping.
The main issue is that inbound frames belonging to AVB TCs that do _not_ have a SRP-managed DA must be dropped. This permits those queues’ CBS bandwidth to be reserved for AVB streams.Marvell implements this with the STATIC_AVB_NRL entry state, combined with an ingress port flag that enables the packet filtering.
My patch mapped the Marvell model to the software bridge, i.e. new IFLA_BRPORT and MDB flags. However, Nikolay (correctly) points out that these are unidiomatic for Linux.
My understanding is that these should likely be managed with tc-flower. The SRP daemon would manage tc-flower entries along with the MDB when an AVB stream is admitted. Unfortunately, implemetning this in mv88e6xxx would be more complicated: it would either require intercepting the tc-flower requests and mapping them to native AVB admission control (which may be fragile), or adding PCP/DA matching to the TCAM implementation (which may not be sufficiently performant, more research is needed).
Luke
[1] https://tsn.readthedocs.io/avb.html
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH net-next 0/2] net: dsa: mv88e6xxx: add support for dcb pcp app
2026-06-04 8:30 [PATCH net-next 0/2] net: dsa: mv88e6xxx: add support for dcb pcp app Cedric Jehasse via B4 Relay
` (2 preceding siblings ...)
2026-06-04 10:37 ` [PATCH net-next 0/2] " Luke Howard
@ 2026-06-05 1:14 ` Luke Howard
2026-06-07 3:12 ` Luke Howard
4 siblings, 0 replies; 12+ messages in thread
From: Luke Howard @ 2026-06-05 1:14 UTC (permalink / raw)
To: cedric.jehasse
Cc: Andrew Lunn, Vladimir Oltean, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Russell King, netdev,
linux-kernel, Cedric Jehasse
> On 4 Jun 2026, at 6:30 pm, Cedric Jehasse via B4 Relay <devnull+cedric.jehasse.luminex.be@kernel.org> wrote:
>
> This patch series adds support for dcb pcp app to the mv88e6xxx
> driver. The pcp app is there to configure pcp based queue
> classification.
Somehow these patches didn’t arrive in my inbox, but (looking on lore) they all LGTM.
The only comments I had:
- whether you might use IEEE_8021Q_MAX_PRIORITIES instead of 8 (this requires importing dcbnl.h though)
- the user might infer the ‘prio’ parameter name means we are remapping frame priorities rather than assigning to a queue. Perhaps it could have a different name?
Luke
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH net-next 0/2] net: dsa: mv88e6xxx: add support for dcb pcp app
2026-06-05 1:13 ` Luke Howard
@ 2026-06-05 12:05 ` Luke Howard
0 siblings, 0 replies; 12+ messages in thread
From: Luke Howard @ 2026-06-05 12:05 UTC (permalink / raw)
To: Andrew Lunn
Cc: Cedric Jehasse, cedric.jehasse, Vladimir Oltean, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Simon Horman,
Russell King, netdev, linux-kernel, Max Hunter, Kieran Tyrrell,
Nikolay Aleksandrov
> On 5 Jun 2026, at 11:13 am, Luke Howard <lukeh@padl.com> wrote:
>
>> Ideally, the user should not need to know if some functionality has
>> been accelerated by offloading it to hardware. They just configure it
>> using the standard Linux model of the feature.
>
> Absolutely, and that was the model I used when building a SRP daemon, which I first tested with the software bridge and some i210s.
Which does beg the question why I hadn’t considered the admission control issue when originally implementing against the software bridge. That’s my bad, and perhaps had I discovered tc-flower earlier I would have a different mental model of how to map this to mv88e6xxx.
Also whilst the admission control is necessary to correctly implement 802.1Qat and pass the Avnu test suites, it might not matter for many networks.
I will think about how to implement these semantics with tc-flower/TCAM, likely after I take a look at submitting your DSA in-band/Marvell RMU patches.
Luke
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH net-next 0/2] net: dsa: mv88e6xxx: add support for dcb pcp app
2026-06-04 8:30 [PATCH net-next 0/2] net: dsa: mv88e6xxx: add support for dcb pcp app Cedric Jehasse via B4 Relay
` (3 preceding siblings ...)
2026-06-05 1:14 ` Luke Howard
@ 2026-06-07 3:12 ` Luke Howard
2026-06-08 21:22 ` Luke Howard
4 siblings, 1 reply; 12+ messages in thread
From: Luke Howard @ 2026-06-07 3:12 UTC (permalink / raw)
To: cedric.jehasse
Cc: Andrew Lunn, Vladimir Oltean, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Russell King, netdev,
linux-kernel, Cedric Jehasse
> On 4 Jun 2026, at 6:30 pm, Cedric Jehasse via B4 Relay <devnull+cedric.jehasse.luminex.be@kernel.org> wrote:
>
> To me the dcb pcp app feels like the natural way to configure the pcp to QPri mappings in the switch.
Revisiting this, I think the DCB PCP to PRIO mapping should instead configure the Port IEEE Priority Remapping registers (6352) or Ingress PCP mapping (6390). There’s nothing in dcb-app(8) that suggests to me that PRIO implies queue just because the PCP selector was used.
This is a bit unfortunate as configuring the PCP to QPri would be useful. But we could get the same end result by mapping to FPri and accepting the default FPri/QPri mapping.
(The 6352 data sheet is confusing when it refers to the IEEE-PRI register setting the “frame’s priority”, but the width of the field implies it is indeed QPri.)
I do (now) agree that MQPRIO is not the place to configure this.
Luke
^ permalink raw reply [flat|nested] 12+ messages in thread
* Re: [PATCH net-next 0/2] net: dsa: mv88e6xxx: add support for dcb pcp app
2026-06-07 3:12 ` Luke Howard
@ 2026-06-08 21:22 ` Luke Howard
0 siblings, 0 replies; 12+ messages in thread
From: Luke Howard @ 2026-06-08 21:22 UTC (permalink / raw)
To: cedric.jehasse
Cc: Andrew Lunn, Vladimir Oltean, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Simon Horman, Russell King, netdev,
linux-kernel, Cedric Jehasse
> On 7 Jun 2026, at 13:12, Luke Howard <lukeh@padl.com> wrote:
>
>
>
>> On 4 Jun 2026, at 6:30 pm, Cedric Jehasse via B4 Relay <devnull+cedric.jehasse.luminex.be@kernel.org> wrote:
>>
>> To me the dcb pcp app feels like the natural way to configure the pcp to QPri mappings in the switch.
>
> Revisiting this, I think the DCB PCP to PRIO mapping should instead configure the Port IEEE Priority Remapping registers (6352) or Ingress PCP mapping (6390). There’s nothing in dcb-app(8) that suggests to me that PRIO implies queue just because the PCP selector was used.
I’m wrong, DCB priorities are not PCP priorities, the closest analogue is QPri. Comment withdrawn.
Luke
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2026-06-08 21:22 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-04 8:30 [PATCH net-next 0/2] net: dsa: mv88e6xxx: add support for dcb pcp app Cedric Jehasse via B4 Relay
2026-06-04 8:30 ` [PATCH net-next 1/2] net: dsa: " Cedric Jehasse via B4 Relay
2026-06-04 8:30 ` [PATCH net-next 2/2] net: dsa: mv88e6xxx: " Cedric Jehasse via B4 Relay
2026-06-04 10:37 ` [PATCH net-next 0/2] " Luke Howard
2026-06-04 12:01 ` Cedric Jehasse
2026-06-04 22:51 ` Luke Howard
2026-06-04 23:21 ` Andrew Lunn
2026-06-05 1:13 ` Luke Howard
2026-06-05 12:05 ` Luke Howard
2026-06-05 1:14 ` Luke Howard
2026-06-07 3:12 ` Luke Howard
2026-06-08 21:22 ` Luke Howard
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox