* [PATCH net v2] net: stmmac: rebuild VLAN priority steering when filters change
@ 2026-11-04 18:51 James Hilliard
2026-11-04 18:53 ` netdev-bot+sinfo
2026-11-10 21:40 ` patchwork-bot+netdevbpf
0 siblings, 2 replies; 4+ messages in thread
From: James Hilliard @ 2026-11-04 18:51 UTC (permalink / raw)
To: Maxime Chevallier, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Maxime Coquelin, Alexandre Torgue
Cc: Piotr Wejman, Russell King, netdev, linux-arm-kernel,
linux-kernel, James Hilliard
The RX queue priority callbacks preserve previously assigned priorities.
Passing zero from tc_del_vlan_flow() therefore leaves the deleted rule's
priority mapped to its RX queue. Clearing the whole queue instead would
also remove priorities belonging to other installed rules.
Save each VLAN rule's priority and rebuild the complete per-queue masks
after insertion and deletion, starting from the platform assignments.
Resolve overlapping platform masks with the same last-queue-wins ordering
used during initialization.
Make the GMAC4 and XGMAC callbacks replace the target queue's mask while
retaining their exclusion of its priorities from other queues. Program a
priority's new destination before clearing its previous assignment.
Keep VLAN rules in programming order. Flower installs a replacement under
a new cookie before deleting the old one, so the newer assignment must
remain effective while both are present, including when an earlier array
slot is reused. Removing a rejected replacement restores the older rule,
and removing the last override restores the platform assignment.
VLAN and EtherType rules share the RFS array. Preserve an existing cookie's
steering type and reuse its entry without incrementing the rule count, so
replaying a rule cannot unlink an EtherType entry or leave a retyped VLAN
entry on the list.
Validate the selected RX queue before indexing the masks:
tc_classid_to_hwtc() checks the number of traffic classes, which can exceed
the number of RX queues. When rebuilding the masks, skip rules whose RX
queue was removed by ethtool so they cannot suppress the platform
assignment or an older rule targeting an active queue.
Found by code inspection while working on STMMAC reset/recovery fixes.
Host-side tests exercising the driver's VLAN rule handlers and priority
callbacks with mocked MMIO reproduce the stale mapping after deletion
and pass with this fix. No hardware testing was performed.
Fixes: b3da86d432b7 ("net: stmmac: fix rx queue priority assignment")
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
---
Changes in v2:
- Preserve RFS entry types on replay in both the VLAN and EtherType
handlers, keeping only VLAN entries on the priority list.
- Reuse installed EtherType entries without counting them again or
rejecting them against their own capacity limit.
- Skip removed RX queues when rebuilding masks, retaining active
platform assignments and older valid rules.
- Rebase onto net at 03897066069f.
- Link to v1: https://patch.msgid.link/20261102-submit-stmmac-vlan-prio-v1-v1-1-2b37767e4e08@gmail.com
---
drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c | 2 +
.../net/ethernet/stmicro/stmmac/dwxgmac2_core.c | 2 +
drivers/net/ethernet/stmicro/stmmac/stmmac.h | 4 +
drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c | 97 ++++++++++++++++------
4 files changed, 81 insertions(+), 24 deletions(-)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
index 259e2ebed8c1..efbe2ec4c213 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
@@ -126,6 +126,7 @@ static void dwmac4_rx_queue_priority(struct mac_device_info *hw,
* clear them from others queues
*/
if (queue < 4) {
+ ctrl2 &= ~GMAC_RXQCTRL_PSRQX_MASK(queue);
ctrl2 |= (prio << GMAC_RXQCTRL_PSRQX_SHIFT(queue)) &
GMAC_RXQCTRL_PSRQX_MASK(queue);
@@ -134,6 +135,7 @@ static void dwmac4_rx_queue_priority(struct mac_device_info *hw,
} else {
queue -= 4;
+ ctrl3 &= ~GMAC_RXQCTRL_PSRQX_MASK(queue);
ctrl3 |= (prio << GMAC_RXQCTRL_PSRQX_SHIFT(queue)) &
GMAC_RXQCTRL_PSRQX_MASK(queue);
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
index 1a88cbaed70c..7ad08651675e 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
@@ -119,6 +119,7 @@ static void dwxgmac2_rx_queue_prio(struct mac_device_info *hw, u32 prio,
* clear them from others queues
*/
if (queue < 4) {
+ ctrl2 &= ~XGMAC_PSRQ(queue);
ctrl2 |= (prio << XGMAC_PSRQ_SHIFT(queue)) &
XGMAC_PSRQ(queue);
@@ -127,6 +128,7 @@ static void dwxgmac2_rx_queue_prio(struct mac_device_info *hw, u32 prio,
} else {
queue -= 4;
+ ctrl3 &= ~XGMAC_PSRQ(queue);
ctrl3 |= (prio << XGMAC_PSRQ_SHIFT(queue)) &
XGMAC_PSRQ(queue);
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index b76acfe0d958..fcc395321816 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -14,6 +14,7 @@
#include <linux/clk.h>
#include <linux/hrtimer.h>
#include <linux/if_vlan.h>
+#include <linux/list.h>
#include <linux/stmmac.h>
#include <linux/phylink.h>
#include <linux/pci.h>
@@ -210,6 +211,8 @@ enum stmmac_rfs_type {
struct stmmac_rfs_entry {
unsigned long cookie;
u16 etype;
+ u8 vlan_prio;
+ struct list_head vlan_node;
int in_use;
int type;
int tc;
@@ -382,6 +385,7 @@ struct stmmac_priv {
unsigned int rfs_entries_cnt[STMMAC_RFS_T_MAX];
unsigned int rfs_entries_total;
struct stmmac_rfs_entry *rfs_entries;
+ struct list_head vlan_prio;
/* Pulse Per Second output */
struct stmmac_pps_cfg pps[STMMAC_PPS_MAX];
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
index 10b61fa2c27c..2ea3f433ff9b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
@@ -250,6 +250,8 @@ static int tc_rfs_init(struct stmmac_priv *priv)
if (!priv->rfs_entries)
return -ENOMEM;
+ INIT_LIST_HEAD(&priv->vlan_prio);
+
dev_info(priv->device, "Enabled RFS Flow TC (entries=%d)\n",
priv->rfs_entries_total);
@@ -685,6 +687,45 @@ static struct stmmac_rfs_entry *tc_find_rfs(struct stmmac_priv *priv,
#define VLAN_PRIO_FULL_MASK (0x07)
+static void tc_update_vlan_prio(struct stmmac_priv *priv, u8 prio)
+{
+ u8 prios[MTL_MAX_RX_QUEUES] = {};
+ struct stmmac_rfs_entry *entry;
+ unsigned int queue, i;
+
+ /* Restore platform assignments with the same precedence as setup. */
+ for (queue = 0; queue < priv->plat->rx_queues_to_use; queue++) {
+ if (!priv->plat->rx_queues_cfg[queue].use_prio)
+ continue;
+
+ prios[queue] = priv->plat->rx_queues_cfg[queue].prio;
+ for (i = 0; i < queue; i++)
+ prios[i] &= ~prios[queue];
+ }
+
+ /*
+ * Flower installs a replacement before destroying the old cookie.
+ * Preserve the latest assignment while both rules are present.
+ */
+ list_for_each_entry(entry, &priv->vlan_prio, vlan_node) {
+ /* The RX queue count may have been reduced with ethtool. */
+ if (entry->tc >= priv->plat->rx_queues_to_use)
+ continue;
+
+ for (queue = 0; queue < priv->plat->rx_queues_to_use; queue++)
+ prios[queue] &= ~entry->vlan_prio;
+ prios[entry->tc] |= entry->vlan_prio;
+ }
+
+ /* Install the new assignment before clearing the previous queue. */
+ for (queue = 0; queue < priv->plat->rx_queues_to_use; queue++)
+ if (prios[queue] & prio)
+ stmmac_rx_queue_prio(priv, priv->hw, prios[queue], queue);
+ for (queue = 0; queue < priv->plat->rx_queues_to_use; queue++)
+ if (!(prios[queue] & prio))
+ stmmac_rx_queue_prio(priv, priv->hw, prios[queue], queue);
+}
+
static int tc_add_vlan_flow(struct stmmac_priv *priv,
struct flow_cls_offload *cls)
{
@@ -694,13 +735,16 @@ static int tc_add_vlan_flow(struct stmmac_priv *priv,
int tc = tc_classid_to_hwtc(priv->dev, cls->classid);
struct flow_match_vlan match;
+ if (entry && entry->in_use && entry->type != STMMAC_RFS_T_VLAN)
+ return -EINVAL;
+
if (!entry) {
entry = tc_find_rfs(priv, cls, true);
if (!entry)
return -ENOENT;
}
- if (priv->rfs_entries_cnt[STMMAC_RFS_T_VLAN] >=
+ if (!entry->in_use && priv->rfs_entries_cnt[STMMAC_RFS_T_VLAN] >=
priv->rfs_entries_max[STMMAC_RFS_T_VLAN])
return -ENOENT;
@@ -708,7 +752,7 @@ static int tc_add_vlan_flow(struct stmmac_priv *priv,
if (!dissector_uses_key(dissector, FLOW_DISSECTOR_KEY_VLAN))
return -EINVAL;
- if (tc < 0) {
+ if (tc < 0 || tc >= priv->plat->rx_queues_to_use) {
netdev_err(priv->dev, "Invalid traffic class\n");
return -EINVAL;
}
@@ -724,13 +768,18 @@ static int tc_add_vlan_flow(struct stmmac_priv *priv,
}
prio = BIT(match.key->vlan_priority);
- stmmac_rx_queue_prio(priv, priv->hw, prio, tc);
+ if (entry->in_use)
+ list_del(&entry->vlan_node);
+ else
+ priv->rfs_entries_cnt[STMMAC_RFS_T_VLAN]++;
entry->in_use = true;
entry->cookie = cls->cookie;
entry->tc = tc;
entry->type = STMMAC_RFS_T_VLAN;
- priv->rfs_entries_cnt[STMMAC_RFS_T_VLAN]++;
+ entry->vlan_prio = prio;
+ list_add_tail(&entry->vlan_node, &priv->vlan_prio);
+ tc_update_vlan_prio(priv, entry->vlan_prio);
}
return 0;
@@ -744,14 +793,14 @@ static int tc_del_vlan_flow(struct stmmac_priv *priv,
if (!entry || !entry->in_use || entry->type != STMMAC_RFS_T_VLAN)
return -ENOENT;
- stmmac_rx_queue_prio(priv, priv->hw, 0, entry->tc);
-
+ list_del(&entry->vlan_node);
entry->in_use = false;
entry->cookie = 0;
entry->tc = 0;
entry->type = 0;
priv->rfs_entries_cnt[STMMAC_RFS_T_VLAN]--;
+ tc_update_vlan_prio(priv, entry->vlan_prio);
return 0;
}
@@ -784,6 +833,8 @@ static int tc_add_ethtype_flow(struct stmmac_priv *priv,
if (match.mask->n_proto) {
u16 etype = ntohs(match.key->n_proto);
+ enum stmmac_rfs_type type;
+ u8 packet;
if (match.mask->n_proto != ETHER_TYPE_FULL_MASK) {
netdev_err(priv->dev, "Only full mask is supported for EthType filter");
@@ -791,32 +842,30 @@ static int tc_add_ethtype_flow(struct stmmac_priv *priv,
}
switch (etype) {
case ETH_P_LLDP:
- if (priv->rfs_entries_cnt[STMMAC_RFS_T_LLDP] >=
- priv->rfs_entries_max[STMMAC_RFS_T_LLDP])
- return -ENOENT;
-
- entry->type = STMMAC_RFS_T_LLDP;
- priv->rfs_entries_cnt[STMMAC_RFS_T_LLDP]++;
-
- stmmac_rx_queue_routing(priv, priv->hw,
- PACKET_DCBCPQ, tc);
+ type = STMMAC_RFS_T_LLDP;
+ packet = PACKET_DCBCPQ;
break;
case ETH_P_1588:
- if (priv->rfs_entries_cnt[STMMAC_RFS_T_1588] >=
- priv->rfs_entries_max[STMMAC_RFS_T_1588])
- return -ENOENT;
-
- entry->type = STMMAC_RFS_T_1588;
- priv->rfs_entries_cnt[STMMAC_RFS_T_1588]++;
-
- stmmac_rx_queue_routing(priv, priv->hw,
- PACKET_PTPQ, tc);
+ type = STMMAC_RFS_T_1588;
+ packet = PACKET_PTPQ;
break;
default:
netdev_err(priv->dev, "EthType(0x%x) is not supported", etype);
return -EINVAL;
}
+ /* Replaying a cookie must preserve its steering type. */
+ if (entry->in_use) {
+ if (entry->type != type)
+ return -EINVAL;
+ } else {
+ if (priv->rfs_entries_cnt[type] >= priv->rfs_entries_max[type])
+ return -ENOENT;
+ priv->rfs_entries_cnt[type]++;
+ }
+
+ stmmac_rx_queue_routing(priv, priv->hw, packet, tc);
+ entry->type = type;
entry->in_use = true;
entry->cookie = cls->cookie;
entry->tc = tc;
---
base-commit: 03897066069fd47caf2908183edf3b22b822ea73
change-id: 20261102-submit-stmmac-vlan-prio-v1-8e5f674f1201
Best regards,
--
James Hilliard <james.hilliard1@gmail.com>
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH net v2] net: stmmac: rebuild VLAN priority steering when filters change
2026-11-04 18:51 [PATCH net v2] net: stmmac: rebuild VLAN priority steering when filters change James Hilliard
@ 2026-11-04 18:53 ` netdev-bot+sinfo
2026-11-04 18:55 ` James Hilliard
2026-11-10 21:40 ` patchwork-bot+netdevbpf
1 sibling, 1 reply; 4+ messages in thread
From: netdev-bot+sinfo @ 2026-11-04 18:53 UTC (permalink / raw)
To: James Hilliard
Cc: Maxime Chevallier, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Maxime Coquelin, Alexandre Torgue,
Piotr Wejman, Russell King, netdev, linux-arm-kernel,
linux-kernel
Hi!
This is an automated message. This series looks like a fix, but its
commit messages seem to be missing some information:
- What hardware the change was tested on. For driver fixes please
mention the device (and if relevant firmware version) used for
testing, or say that the change was not tested on real hardware.
Please do not repost the series just to address the above. Instead,
reply to this email with the missing information, so that reviewers
can take it into account. If the series needs another revision for
other reasons, please include the information in the commit messages
then.
The evaluation is done by an LLM so it may be wrong, if you think
that is the case please reply and explain.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH net v2] net: stmmac: rebuild VLAN priority steering when filters change
2026-11-04 18:53 ` netdev-bot+sinfo
@ 2026-11-04 18:55 ` James Hilliard
0 siblings, 0 replies; 4+ messages in thread
From: James Hilliard @ 2026-11-04 18:55 UTC (permalink / raw)
To: netdev-bot+sinfo
Cc: Maxime Chevallier, Andrew Lunn, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Maxime Coquelin, Alexandre Torgue,
Piotr Wejman, Russell King, netdev, linux-arm-kernel,
linux-kernel
On Wed, Nov 4, 2026 at 11:53 AM <netdev-bot+sinfo@kernel.org> wrote:
>
> Hi!
>
> This is an automated message. This series looks like a fix, but its
> commit messages seem to be missing some information:
>
> - What hardware the change was tested on. For driver fixes please
> mention the device (and if relevant firmware version) used for
> testing, or say that the change was not tested on real hardware.
As the commit message states:
No hardware testing was performed.
>
> Please do not repost the series just to address the above. Instead,
> reply to this email with the missing information, so that reviewers
> can take it into account. If the series needs another revision for
> other reasons, please include the information in the commit messages
> then.
>
> The evaluation is done by an LLM so it may be wrong, if you think
> that is the case please reply and explain.
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH net v2] net: stmmac: rebuild VLAN priority steering when filters change
2026-11-04 18:51 [PATCH net v2] net: stmmac: rebuild VLAN priority steering when filters change James Hilliard
2026-11-04 18:53 ` netdev-bot+sinfo
@ 2026-11-10 21:40 ` patchwork-bot+netdevbpf
1 sibling, 0 replies; 4+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-11-10 21:40 UTC (permalink / raw)
To: James Hilliard
Cc: maxime.chevallier, andrew+netdev, davem, edumazet, kuba, pabeni,
mcoquelin.stm32, alexandre.torgue, piotrwejman90, linux, netdev,
linux-arm-kernel, linux-kernel
Hello:
This patch was applied to netdev/net-next.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Wed, 04 Nov 2026 11:51:41 -0700 you wrote:
> The RX queue priority callbacks preserve previously assigned priorities.
> Passing zero from tc_del_vlan_flow() therefore leaves the deleted rule's
> priority mapped to its RX queue. Clearing the whole queue instead would
> also remove priorities belonging to other installed rules.
>
> Save each VLAN rule's priority and rebuild the complete per-queue masks
> after insertion and deletion, starting from the platform assignments.
> Resolve overlapping platform masks with the same last-queue-wins ordering
> used during initialization.
>
> [...]
Here is the summary with links:
- [net,v2] net: stmmac: rebuild VLAN priority steering when filters change
https://git.kernel.org/netdev/net-next/c/edf10f5c2513
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-11-10 21:40 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-04 18:51 [PATCH net v2] net: stmmac: rebuild VLAN priority steering when filters change James Hilliard
2026-11-04 18:53 ` netdev-bot+sinfo
2026-11-04 18:55 ` James Hilliard
2026-11-10 21:40 ` patchwork-bot+netdevbpf
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®