[PATCH net-next 1/2] net: dsa: mv88e6xxx: use the hw tx queues

From: Cedric Jehasse via B4 Relay

Date: Fri May 22 2026 - 07:04:41 EST


From: Cedric Jehasse <cedric.jehasse@xxxxxxxxxx>

>From the datasheets i've looked at these switches have 4 or 8 transmit
queues per port.
There's a PRI field in the dsa tag used to indicate which egress queue
the frame is to be sent to.
This isn't done for vlan tagged frames because this would overwrite the
PCP value in the vlan tag (The PRI field in the dsa
tag is used as the PCP value in the vlan tag).

Signed-off-by: Cedric Jehasse <cedric.jehasse@xxxxxxxxxx>
---
drivers/net/dsa/mv88e6xxx/chip.c | 14 ++++++++++++++
drivers/net/dsa/mv88e6xxx/chip.h | 1 +
net/dsa/tag_dsa.c | 3 ++-
3 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 8ca5fd40df92..277efe24edf4 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -3979,6 +3979,7 @@ static int mv88e6xxx_setup(struct dsa_switch *ds)

chip->ds = ds;
ds->user_mii_bus = mv88e6xxx_default_mdio_bus(chip);
+ ds->num_tx_queues = chip->info->num_tx_queues;

/* Since virtual bridges are mapped in the PVT, the number we support
* depends on the physical switch topology. We need to let DSA figure
@@ -6051,6 +6052,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.num_ports = 11, /* 10 + Z80 */
.num_internal_phys = 9,
.num_gpio = 16,
+ .num_tx_queues = 8,
.max_vid = 8191,
.max_sid = 63,
.port_base_addr = 0x0,
@@ -6076,6 +6078,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.num_ports = 11, /* 10 + Z80 */
.num_internal_phys = 9,
.num_gpio = 16,
+ .num_tx_queues = 8,
.max_vid = 8191,
.max_sid = 63,
.port_base_addr = 0x0,
@@ -6125,6 +6128,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.num_ports = 11, /* 10 + Z80 */
.num_internal_phys = 8,
.internal_phys_offset = 1,
+ .num_tx_queues = 8,
.max_vid = 8191,
.max_sid = 63,
.port_base_addr = 0x0,
@@ -6151,6 +6155,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.num_internal_phys = 8,
.num_tcam_entries = 256,
.internal_phys_offset = 1,
+ .num_tx_queues = 8,
.max_vid = 8191,
.max_sid = 63,
.port_base_addr = 0x0,
@@ -6181,6 +6186,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.num_ports = 7,
.num_internal_phys = 2,
.invalid_port_mask = BIT(2) | BIT(3) | BIT(4),
+ .num_tx_queues = 4,
.max_vid = 4095,
.port_base_addr = 0x08,
.phy_base_addr = 0x00,
@@ -6205,6 +6211,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.num_ports = 7,
.num_internal_phys = 5,
.num_gpio = 15,
+ .num_tx_queues = 4,
.max_vid = 4095,
.max_sid = 63,
.port_base_addr = 0x10,
@@ -6230,6 +6237,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.num_databases = 64,
.num_ports = 7,
.num_internal_phys = 5,
+ .num_tx_queues = 4,
.max_vid = 4095,
.port_base_addr = 0x08,
.phy_base_addr = 0x00,
@@ -6282,6 +6290,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.num_internal_phys = 2,
.internal_phys_offset = 3,
.num_gpio = 15,
+ .num_tx_queues = 4,
.max_vid = 4095,
.max_sid = 63,
.port_base_addr = 0x10,
@@ -6310,6 +6319,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.num_internal_phys = 2,
.internal_phys_offset = 3,
.num_gpio = 15,
+ .num_tx_queues = 4,
.max_vid = 4095,
.max_sid = 63,
.port_base_addr = 0x10,
@@ -6414,6 +6424,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.num_ports = 7,
.num_internal_phys = 5,
.num_gpio = 15,
+ .num_tx_queues = 4,
.max_vid = 4095,
.max_sid = 63,
.port_base_addr = 0x10,
@@ -6468,6 +6479,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.num_internal_phys = 9,
.num_gpio = 16,
.num_tcam_entries = 256,
+ .num_tx_queues = 8,
.max_vid = 8191,
.max_sid = 63,
.port_base_addr = 0x0,
@@ -6495,6 +6507,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.num_ports = 11, /* 10 + Z80 */
.num_internal_phys = 9,
.num_gpio = 16,
+ .num_tx_queues = 8,
.max_vid = 8191,
.max_sid = 63,
.port_base_addr = 0x0,
@@ -6521,6 +6534,7 @@ static const struct mv88e6xxx_info mv88e6xxx_table[] = {
.num_ports = 11, /* 10 + Z80 */
.num_internal_phys = 8,
.num_tcam_entries = 256,
+ .num_tx_queues = 8,
.internal_phys_offset = 1,
.max_vid = 8191,
.max_sid = 63,
diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h
index cde71828e9d9..19d8eda19b78 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.h
+++ b/drivers/net/dsa/mv88e6xxx/chip.h
@@ -136,6 +136,7 @@ struct mv88e6xxx_info {
unsigned int num_internal_phys;
unsigned int num_gpio;
unsigned int num_tcam_entries;
+ unsigned int num_tx_queues;
unsigned int max_vid;
unsigned int max_sid;
unsigned int port_base_addr;
diff --git a/net/dsa/tag_dsa.c b/net/dsa/tag_dsa.c
index 2a2c4fb61a65..96c8fbedbd3b 100644
--- a/net/dsa/tag_dsa.c
+++ b/net/dsa/tag_dsa.c
@@ -179,6 +179,7 @@ static struct sk_buff *dsa_xmit_ll(struct sk_buff *skb, struct net_device *dev,
dsa_header[2] &= ~0x10;
}
} else {
+ u16 queue = skb_get_queue_mapping(skb) & 0x7;
u16 vid;

vid = br_dev ? MV88E6XXX_VID_BRIDGED : MV88E6XXX_VID_STANDALONE;
@@ -191,7 +192,7 @@ static struct sk_buff *dsa_xmit_ll(struct sk_buff *skb, struct net_device *dev,

dsa_header[0] = (cmd << 6) | tag_dev;
dsa_header[1] = tag_port << 3;
- dsa_header[2] = vid >> 8;
+ dsa_header[2] = (queue << 5) | vid >> 8;
dsa_header[3] = vid & 0xff;
}


--
2.43.0