* [PATCH net 1/5] net: dsa: mt7530: fix FDB entries not aging out with short timeout
2026-05-05 14:15 [PATCH net 0/5] net: dsa: mt7530: assorted fixes Daniel Golle
@ 2026-05-05 14:16 ` Daniel Golle
2026-05-05 14:16 ` [PATCH net 2/5] net: dsa: mt7530: preserve VLAN tags on trapped link-local frames Daniel Golle
` (3 subsequent siblings)
4 siblings, 0 replies; 9+ messages in thread
From: Daniel Golle @ 2026-05-05 14:16 UTC (permalink / raw)
To: Chester A. Unal, Daniel Golle, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Matthias Brugger, AngeloGioacchino Del Regno, DENG Qingfang,
Florian Fainelli, Arınç ÜNAL, Sean Wang, netdev,
linux-kernel, linux-arm-kernel, linux-mediatek
When setting a low ageing time such as 10 seconds, the algorithm in
mt7530_set_ageing_time() finds AGE_CNT=0 and AGE_UNIT=9 as the first
exact match (starting the search from tmp_age_count=0).
On the MT7530/MT7531 hardware, the per-entry aging counter is
initialized to AGE_CNT when a MAC address is learned. With AGE_CNT=0,
new entries start with a counter value of 0, which the hardware treats
as "already aged" and never removes, effectively disabling aging.
Fix this by starting the search from tmp_age_count=1 to ensure entries
always have a non-zero initial aging counter. For a 10-second ageing
time this yields AGE_CNT=1 and AGE_UNIT=4 instead: the timer ticks
every 5 seconds and entries are removed after 2 ticks.
Fixes: ea6d5c924e39 ("net: dsa: mt7530: support setting ageing time")
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/net/dsa/mt7530.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 44d670904ad8..b1903da7d500 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -1027,8 +1027,12 @@ mt7530_set_ageing_time(struct dsa_switch *ds, unsigned int msecs)
if (secs < 1 || secs > (AGE_CNT_MAX + 1) * (AGE_UNIT_MAX + 1))
return -ERANGE;
- /* iterate through all possible age_count to find the closest pair */
- for (tmp_age_count = 0; tmp_age_count <= AGE_CNT_MAX; ++tmp_age_count) {
+ /* Iterate through all possible age_count values to find the closest
+ * pair. Start from 1 because the per-entry aging counter is
+ * initialized to AGE_CNT and a value of 0 means the entry will
+ * never be aged out.
+ */
+ for (tmp_age_count = 1; tmp_age_count <= AGE_CNT_MAX; ++tmp_age_count) {
unsigned int tmp_age_unit = secs / (tmp_age_count + 1) - 1;
if (tmp_age_unit <= AGE_UNIT_MAX) {
--
2.54.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH net 2/5] net: dsa: mt7530: preserve VLAN tags on trapped link-local frames
2026-05-05 14:15 [PATCH net 0/5] net: dsa: mt7530: assorted fixes Daniel Golle
2026-05-05 14:16 ` [PATCH net 1/5] net: dsa: mt7530: fix FDB entries not aging out with short timeout Daniel Golle
@ 2026-05-05 14:16 ` Daniel Golle
2026-05-05 15:37 ` Chester A. Unal
2026-05-05 14:16 ` [PATCH net 3/5] net: dsa: mt7530: fix CPU port VLAN not being reset to unaware Daniel Golle
` (2 subsequent siblings)
4 siblings, 1 reply; 9+ messages in thread
From: Daniel Golle @ 2026-05-05 14:16 UTC (permalink / raw)
To: Chester A. Unal, Daniel Golle, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Matthias Brugger, AngeloGioacchino Del Regno, DENG Qingfang,
Florian Fainelli, Arınç ÜNAL, Sean Wang, netdev,
linux-kernel, linux-arm-kernel, linux-mediatek
The BPC, RGAC1 and RGAC2 registers control the handling of link-local
frames with reserved MAC DAs (01:80:C2:00:00:0x). These frames are
correctly trapped to the CPU port, but the egress VLAN tag attribute was
set to MT7530_VLAN_EG_UNTAGGED which causes the switch to strip any
VLAN tags from trapped frames before they reach the CPU.
This causes VLAN-tagged link-local frames (STP BPDUs, LLDP, PTP Peer
Delay Requests) to arrive at the CPU without their VLAN tag, so they
are delivered to the base network interface instead of the VLAN
sub-interface. The DSA local_termination selftest confirms this: all
link-local protocol tests on VLAN upper interfaces fail.
Set the EG_TAG attribute to MT7530_VLAN_EG_DISABLED (system default)
so that the switch does not modify VLAN tags in trapped frames. This
way VLAN-tagged frames retain their original tag and are delivered to
the correct VLAN sub-interface, matching the behavior of non-trapped
frames which pass through without VLAN tag modification.
Fixes: 69ddba9d170b ("net: dsa: mt7530: fix handling of all link-local frames")
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/net/dsa/mt7530.c | 27 +++++++++++++++------------
1 file changed, 15 insertions(+), 12 deletions(-)
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index b1903da7d500..a696c8736982 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -1300,37 +1300,40 @@ static void mt7530_setup_port5(struct dsa_switch *ds, phy_interface_t interface)
static void
mt753x_trap_frames(struct mt7530_priv *priv)
{
- /* Trap 802.1X PAE frames and BPDUs to the CPU port(s) and egress them
- * VLAN-untagged.
+ /* Trap 802.1X PAE frames and BPDUs to the CPU port(s) and egress
+ * them with the EG_TAG attribute set to disabled (system default)
+ * so that any VLAN tags in the frame are not modified by the
+ * switch egress VLAN tag processing. This preserves VLAN tags
+ * for reception on VLAN sub-interfaces.
*/
mt7530_rmw(priv, MT753X_BPC,
PAE_BPDU_FR | PAE_EG_TAG_MASK | PAE_PORT_FW_MASK |
BPDU_EG_TAG_MASK | BPDU_PORT_FW_MASK,
- PAE_BPDU_FR | PAE_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
+ PAE_BPDU_FR | PAE_EG_TAG(MT7530_VLAN_EG_DISABLED) |
PAE_PORT_FW(TO_CPU_FW_CPU_ONLY) |
- BPDU_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
+ BPDU_EG_TAG(MT7530_VLAN_EG_DISABLED) |
TO_CPU_FW_CPU_ONLY);
- /* Trap frames with :01 and :02 MAC DAs to the CPU port(s) and egress
- * them VLAN-untagged.
+ /* Trap frames with :01 and :02 MAC DAs to the CPU port(s) and
+ * egress them with EG_TAG disabled.
*/
mt7530_rmw(priv, MT753X_RGAC1,
R02_BPDU_FR | R02_EG_TAG_MASK | R02_PORT_FW_MASK |
R01_BPDU_FR | R01_EG_TAG_MASK | R01_PORT_FW_MASK,
- R02_BPDU_FR | R02_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
+ R02_BPDU_FR | R02_EG_TAG(MT7530_VLAN_EG_DISABLED) |
R02_PORT_FW(TO_CPU_FW_CPU_ONLY) | R01_BPDU_FR |
- R01_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
+ R01_EG_TAG(MT7530_VLAN_EG_DISABLED) |
TO_CPU_FW_CPU_ONLY);
- /* Trap frames with :03 and :0E MAC DAs to the CPU port(s) and egress
- * them VLAN-untagged.
+ /* Trap frames with :03 and :0E MAC DAs to the CPU port(s) and
+ * egress them with EG_TAG disabled.
*/
mt7530_rmw(priv, MT753X_RGAC2,
R0E_BPDU_FR | R0E_EG_TAG_MASK | R0E_PORT_FW_MASK |
R03_BPDU_FR | R03_EG_TAG_MASK | R03_PORT_FW_MASK,
- R0E_BPDU_FR | R0E_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
+ R0E_BPDU_FR | R0E_EG_TAG(MT7530_VLAN_EG_DISABLED) |
R0E_PORT_FW(TO_CPU_FW_CPU_ONLY) | R03_BPDU_FR |
- R03_EG_TAG(MT7530_VLAN_EG_UNTAGGED) |
+ R03_EG_TAG(MT7530_VLAN_EG_DISABLED) |
TO_CPU_FW_CPU_ONLY);
}
--
2.54.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* Re: [PATCH net 2/5] net: dsa: mt7530: preserve VLAN tags on trapped link-local frames
2026-05-05 14:16 ` [PATCH net 2/5] net: dsa: mt7530: preserve VLAN tags on trapped link-local frames Daniel Golle
@ 2026-05-05 15:37 ` Chester A. Unal
2026-05-05 16:03 ` Daniel Golle
0 siblings, 1 reply; 9+ messages in thread
From: Chester A. Unal @ 2026-05-05 15:37 UTC (permalink / raw)
To: Daniel Golle, Andrew Lunn, Vladimir Oltean, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, Matthias Brugger,
AngeloGioacchino Del Regno, DENG Qingfang, Florian Fainelli,
Arınç ÜNAL, Sean Wang, netdev, linux-kernel,
linux-arm-kernel, linux-mediatek
Hey Daniel.
On 05/05/2026 15:16, Daniel Golle wrote:
> The BPC, RGAC1 and RGAC2 registers control the handling of link-local
> frames with reserved MAC DAs (01:80:C2:00:00:0x). These frames are
> correctly trapped to the CPU port, but the egress VLAN tag attribute was
> set to MT7530_VLAN_EG_UNTAGGED which causes the switch to strip any
> VLAN tags from trapped frames before they reach the CPU.
>
> This causes VLAN-tagged link-local frames (STP BPDUs, LLDP, PTP Peer
> Delay Requests) to arrive at the CPU without their VLAN tag, so they
> are delivered to the base network interface instead of the VLAN
> sub-interface. The DSA local_termination selftest confirms this: all
> link-local protocol tests on VLAN upper interfaces fail.
>
> Set the EG_TAG attribute to MT7530_VLAN_EG_DISABLED (system default)
> so that the switch does not modify VLAN tags in trapped frames. This
> way VLAN-tagged frames retain their original tag and are delivered to
> the correct VLAN sub-interface, matching the behavior of non-trapped
> frames which pass through without VLAN tag modification.
>
> Fixes: 69ddba9d170b ("net: dsa: mt7530: fix handling of all link-local frames")
> Signed-off-by: Daniel Golle <daniel@makrotopia.org>
Thank you for this patch. Could you please confirm that it conforms to the
findings documented on this patch log?
https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/commit/?id=e8bf353577f382c7066c661fed41b2adc0fc7c40
Cheers.
Chester A.
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH net 2/5] net: dsa: mt7530: preserve VLAN tags on trapped link-local frames
2026-05-05 15:37 ` Chester A. Unal
@ 2026-05-05 16:03 ` Daniel Golle
2026-05-05 16:12 ` Chester A. Unal
0 siblings, 1 reply; 9+ messages in thread
From: Daniel Golle @ 2026-05-05 16:03 UTC (permalink / raw)
To: Chester A. Unal
Cc: Andrew Lunn, Vladimir Oltean, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Matthias Brugger,
AngeloGioacchino Del Regno, DENG Qingfang, Florian Fainelli,
Arınç ÜNAL, Sean Wang, netdev, linux-kernel,
linux-arm-kernel, linux-mediatek
On Tue, May 05, 2026 at 03:37:29PM +0000, Chester A. Unal wrote:
> Hey Daniel.
>
> On 05/05/2026 15:16, Daniel Golle wrote:
> > The BPC, RGAC1 and RGAC2 registers control the handling of link-local
> > frames with reserved MAC DAs (01:80:C2:00:00:0x). These frames are
> > correctly trapped to the CPU port, but the egress VLAN tag attribute was
> > set to MT7530_VLAN_EG_UNTAGGED which causes the switch to strip any
> > VLAN tags from trapped frames before they reach the CPU.
> >
> > This causes VLAN-tagged link-local frames (STP BPDUs, LLDP, PTP Peer
> > Delay Requests) to arrive at the CPU without their VLAN tag, so they
> > are delivered to the base network interface instead of the VLAN
> > sub-interface. The DSA local_termination selftest confirms this: all
> > link-local protocol tests on VLAN upper interfaces fail.
> >
> > Set the EG_TAG attribute to MT7530_VLAN_EG_DISABLED (system default)
> > so that the switch does not modify VLAN tags in trapped frames. This
> > way VLAN-tagged frames retain their original tag and are delivered to
> > the correct VLAN sub-interface, matching the behavior of non-trapped
> > frames which pass through without VLAN tag modification.
> >
> > Fixes: 69ddba9d170b ("net: dsa: mt7530: fix handling of all link-local frames")
> > Signed-off-by: Daniel Golle <daniel@makrotopia.org>
>
> Thank you for this patch. Could you please confirm that it conforms to the
> findings documented on this patch log?
>
> https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/commit/?id=e8bf353577f382c7066c661fed41b2adc0fc7c40
Yes. Combining VLAN CTAG and DSA tag into single "mess" tag is what the
MT7530 hardware does, and also what tag_mtk.c expects, and mtk_eth_soc
"special tag" feature handles well.
I've found, addressed and verified all the issues in the series using
the DSA selftests in tools/testing/selftest/drivers/net/dsa, ie. running
bridge_vlan_aware.sh, bridge_vlan_unaware.sh and local_termination.sh
in a loop, and random order, on BPi-R3 (MT7531) and BPi-R4 (MT7988).
With the series applied many of the previously failing tests are now
passing.
^ permalink raw reply [flat|nested] 9+ messages in thread* Re: [PATCH net 2/5] net: dsa: mt7530: preserve VLAN tags on trapped link-local frames
2026-05-05 16:03 ` Daniel Golle
@ 2026-05-05 16:12 ` Chester A. Unal
0 siblings, 0 replies; 9+ messages in thread
From: Chester A. Unal @ 2026-05-05 16:12 UTC (permalink / raw)
To: Daniel Golle
Cc: Andrew Lunn, Vladimir Oltean, David S. Miller, Eric Dumazet,
Jakub Kicinski, Paolo Abeni, Matthias Brugger,
AngeloGioacchino Del Regno, DENG Qingfang, Florian Fainelli,
Arınç ÜNAL, Sean Wang, netdev, linux-kernel,
linux-arm-kernel, linux-mediatek
On 05/05/2026 17:03, Daniel Golle wrote:
> On Tue, May 05, 2026 at 03:37:29PM +0000, Chester A. Unal wrote:
>> Hey Daniel.
>>
>> On 05/05/2026 15:16, Daniel Golle wrote:
>>> The BPC, RGAC1 and RGAC2 registers control the handling of link-local
>>> frames with reserved MAC DAs (01:80:C2:00:00:0x). These frames are
>>> correctly trapped to the CPU port, but the egress VLAN tag attribute was
>>> set to MT7530_VLAN_EG_UNTAGGED which causes the switch to strip any
>>> VLAN tags from trapped frames before they reach the CPU.
>>>
>>> This causes VLAN-tagged link-local frames (STP BPDUs, LLDP, PTP Peer
>>> Delay Requests) to arrive at the CPU without their VLAN tag, so they
>>> are delivered to the base network interface instead of the VLAN
>>> sub-interface. The DSA local_termination selftest confirms this: all
>>> link-local protocol tests on VLAN upper interfaces fail.
>>>
>>> Set the EG_TAG attribute to MT7530_VLAN_EG_DISABLED (system default)
>>> so that the switch does not modify VLAN tags in trapped frames. This
>>> way VLAN-tagged frames retain their original tag and are delivered to
>>> the correct VLAN sub-interface, matching the behavior of non-trapped
>>> frames which pass through without VLAN tag modification.
>>>
>>> Fixes: 69ddba9d170b ("net: dsa: mt7530: fix handling of all link-local frames")
>>> Signed-off-by: Daniel Golle <daniel@makrotopia.org>
>>
>> Thank you for this patch. Could you please confirm that it conforms to the
>> findings documented on this patch log?
>>
>> https://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next.git/commit/?id=e8bf353577f382c7066c661fed41b2adc0fc7c40
>
> Yes. Combining VLAN CTAG and DSA tag into single "mess" tag is what the
> MT7530 hardware does, and also what tag_mtk.c expects, and mtk_eth_soc
> "special tag" feature handles well.
>
> I've found, addressed and verified all the issues in the series using
> the DSA selftests in tools/testing/selftest/drivers/net/dsa, ie. running
> bridge_vlan_aware.sh, bridge_vlan_unaware.sh and local_termination.sh
> in a loop, and random order, on BPi-R3 (MT7531) and BPi-R4 (MT7988).
>
> With the series applied many of the previously failing tests are now
> passing.
Great to hear!
Acked-by: Chester A. Unal <chester.a.unal@arinc9.com>
Chester A.
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH net 3/5] net: dsa: mt7530: fix CPU port VLAN not being reset to unaware
2026-05-05 14:15 [PATCH net 0/5] net: dsa: mt7530: assorted fixes Daniel Golle
2026-05-05 14:16 ` [PATCH net 1/5] net: dsa: mt7530: fix FDB entries not aging out with short timeout Daniel Golle
2026-05-05 14:16 ` [PATCH net 2/5] net: dsa: mt7530: preserve VLAN tags on trapped link-local frames Daniel Golle
@ 2026-05-05 14:16 ` Daniel Golle
2026-05-05 14:16 ` [PATCH net 4/5] net: dsa: mt7530: clear flood flags on bridge leave Daniel Golle
2026-05-05 14:16 ` [PATCH net 5/5] net: dsa: mt7530: untag VLAN-aware bridge PVID Daniel Golle
4 siblings, 0 replies; 9+ messages in thread
From: Daniel Golle @ 2026-05-05 14:16 UTC (permalink / raw)
To: Chester A. Unal, Daniel Golle, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Matthias Brugger, AngeloGioacchino Del Regno, DENG Qingfang,
Florian Fainelli, Arınç ÜNAL, Sean Wang, netdev,
linux-kernel, linux-arm-kernel, linux-mediatek
After a VLAN-aware bridge is destroyed, creating any VLAN-unaware
bridge loses all connectivity. The VID 0 VLAN table entry used by
VLAN-unaware ports in FALLBACK mode gets corrupted during VLAN-aware
operation: mt7530_hw_vlan_add() overwrites its EG_CON flag with
VTAG_EN and bridge teardown removes ports from its PORT_MEM.
The cleanup code that should restore it never runs because the current
port's dp->vlan_filtering flag is still true when checked (DSA updates
it only after the driver callback returns). Even when restored, the
deferred VLAN deletion events from the switchdev workqueue can corrupt
VID 0 again after the restoration.
Skip the current port in the all_user_ports_removed check, call
mt7530_setup_vlan0() to restore the VID 0 entry, and protect VID 0
from being modified by bridge VLAN operations in port_vlan_add and
port_vlan_del since it is managed exclusively by mt7530_setup_vlan0().
Remove the CPU port PCR and PVC register writes which were clobbering
PORT_VLAN mode and VLAN_ATTR with wrong values.
Fixes: 83163f7dca56 ("net: dsa: mediatek: add VLAN support for MT7530")
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/net/dsa/mt7530.c | 111 ++++++++++++++++++++++-----------------
1 file changed, 62 insertions(+), 49 deletions(-)
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index a696c8736982..7cd8566a31e6 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -1623,6 +1623,49 @@ mt7530_port_bridge_join(struct dsa_switch *ds, int port,
return 0;
}
+static int
+mt7530_vlan_cmd(struct mt7530_priv *priv, enum mt7530_vlan_cmd cmd, u16 vid)
+{
+ struct mt7530_dummy_poll p;
+ u32 val;
+ int ret;
+
+ val = VTCR_BUSY | VTCR_FUNC(cmd) | vid;
+ mt7530_write(priv, MT7530_VTCR, val);
+
+ INIT_MT7530_DUMMY_POLL(&p, priv, MT7530_VTCR);
+ ret = readx_poll_timeout(_mt7530_read, &p, val,
+ !(val & VTCR_BUSY), 20, 20000);
+ if (ret < 0) {
+ dev_err(priv->dev, "poll timeout\n");
+ return ret;
+ }
+
+ val = mt7530_read(priv, MT7530_VTCR);
+ if (val & VTCR_INVALID) {
+ dev_err(priv->dev, "read VTCR invalid\n");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int
+mt7530_setup_vlan0(struct mt7530_priv *priv)
+{
+ u32 val;
+
+ /* Validate the entry with independent learning, keep the original
+ * ingress tag attribute.
+ */
+ val = IVL_MAC | EG_CON | PORT_MEM(MT7530_ALL_MEMBERS) | FID(FID_BRIDGED) |
+ VLAN_VALID;
+ mt7530_write(priv, MT7530_VAWD1, val);
+ mt7530_write(priv, MT7530_VAWD2, 0);
+
+ return mt7530_vlan_cmd(priv, MT7530_VTCR_WR_VID, 0);
+}
+
static void
mt7530_port_set_vlan_unaware(struct dsa_switch *ds, int port)
{
@@ -1648,6 +1691,8 @@ mt7530_port_set_vlan_unaware(struct dsa_switch *ds, int port)
G0_PORT_VID_DEF);
for (i = 0; i < priv->ds->num_ports; i++) {
+ if (i == port)
+ continue;
if (dsa_is_user_port(ds, i) &&
dsa_port_is_vlan_filtering(dsa_to_port(ds, i))) {
all_user_ports_removed = false;
@@ -1659,13 +1704,9 @@ mt7530_port_set_vlan_unaware(struct dsa_switch *ds, int port)
* the CPU port get out of VLAN filtering mode.
*/
if (all_user_ports_removed) {
- struct dsa_port *dp = dsa_to_port(ds, port);
- struct dsa_port *cpu_dp = dp->cpu_dp;
-
- mt7530_write(priv, MT7530_PCR_P(cpu_dp->index),
- PCR_MATRIX(dsa_user_ports(priv->ds)));
- mt7530_write(priv, MT7530_PVC_P(cpu_dp->index), PORT_SPEC_TAG
- | PVC_EG_TAG(MT7530_VLAN_EG_CONSISTENT));
+ mutex_lock(&priv->reg_mutex);
+ mt7530_setup_vlan0(priv);
+ mutex_unlock(&priv->reg_mutex);
}
}
@@ -1853,33 +1894,6 @@ mt7530_port_mdb_del(struct dsa_switch *ds, int port,
return ret;
}
-static int
-mt7530_vlan_cmd(struct mt7530_priv *priv, enum mt7530_vlan_cmd cmd, u16 vid)
-{
- struct mt7530_dummy_poll p;
- u32 val;
- int ret;
-
- val = VTCR_BUSY | VTCR_FUNC(cmd) | vid;
- mt7530_write(priv, MT7530_VTCR, val);
-
- INIT_MT7530_DUMMY_POLL(&p, priv, MT7530_VTCR);
- ret = readx_poll_timeout(_mt7530_read, &p, val,
- !(val & VTCR_BUSY), 20, 20000);
- if (ret < 0) {
- dev_err(priv->dev, "poll timeout\n");
- return ret;
- }
-
- val = mt7530_read(priv, MT7530_VTCR);
- if (val & VTCR_INVALID) {
- dev_err(priv->dev, "read VTCR invalid\n");
- return -EINVAL;
- }
-
- return 0;
-}
-
static int
mt7530_port_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
struct netlink_ext_ack *extack)
@@ -1984,21 +1998,6 @@ mt7530_hw_vlan_update(struct mt7530_priv *priv, u16 vid,
mt7530_vlan_cmd(priv, MT7530_VTCR_WR_VID, vid);
}
-static int
-mt7530_setup_vlan0(struct mt7530_priv *priv)
-{
- u32 val;
-
- /* Validate the entry with independent learning, keep the original
- * ingress tag attribute.
- */
- val = IVL_MAC | EG_CON | PORT_MEM(MT7530_ALL_MEMBERS) | FID(FID_BRIDGED) |
- VLAN_VALID;
- mt7530_write(priv, MT7530_VAWD1, val);
-
- return mt7530_vlan_cmd(priv, MT7530_VTCR_WR_VID, 0);
-}
-
static int
mt7530_port_vlan_add(struct dsa_switch *ds, int port,
const struct switchdev_obj_port_vlan *vlan,
@@ -2011,9 +2010,18 @@ mt7530_port_vlan_add(struct dsa_switch *ds, int port,
mutex_lock(&priv->reg_mutex);
+ /* VID 0 is managed exclusively by mt7530_setup_vlan0() for
+ * VLAN-unaware bridge operation. Don't let the bridge overwrite
+ * its EG_CON flag with VTAG_EN and corrupt PORT_MEM.
+ */
+ if (vlan->vid == 0)
+ goto skip_vlan_table;
+
mt7530_hw_vlan_entry_init(&new_entry, port, untagged);
mt7530_hw_vlan_update(priv, vlan->vid, &new_entry, mt7530_hw_vlan_add);
+skip_vlan_table:
+
if (pvid) {
priv->ports[port].pvid = vlan->vid;
@@ -2053,10 +2061,15 @@ mt7530_port_vlan_del(struct dsa_switch *ds, int port,
mutex_lock(&priv->reg_mutex);
+ /* VID 0 is managed exclusively by mt7530_setup_vlan0(). */
+ if (vlan->vid == 0)
+ goto skip_vlan_table;
+
mt7530_hw_vlan_entry_init(&target_entry, port, 0);
mt7530_hw_vlan_update(priv, vlan->vid, &target_entry,
mt7530_hw_vlan_del);
+skip_vlan_table:
/* PVID is being restored to the default whenever the PVID port
* is being removed from the VLAN.
*/
--
2.54.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH net 4/5] net: dsa: mt7530: clear flood flags on bridge leave
2026-05-05 14:15 [PATCH net 0/5] net: dsa: mt7530: assorted fixes Daniel Golle
` (2 preceding siblings ...)
2026-05-05 14:16 ` [PATCH net 3/5] net: dsa: mt7530: fix CPU port VLAN not being reset to unaware Daniel Golle
@ 2026-05-05 14:16 ` Daniel Golle
2026-05-05 14:16 ` [PATCH net 5/5] net: dsa: mt7530: untag VLAN-aware bridge PVID Daniel Golle
4 siblings, 0 replies; 9+ messages in thread
From: Daniel Golle @ 2026-05-05 14:16 UTC (permalink / raw)
To: Chester A. Unal, Daniel Golle, Andrew Lunn, Vladimir Oltean,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
Matthias Brugger, AngeloGioacchino Del Regno, DENG Qingfang,
Florian Fainelli, Arınç ÜNAL, Sean Wang, netdev,
linux-kernel, linux-arm-kernel, linux-mediatek
Flood flags set by port_bridge_flags persist after a port leaves the
bridge, causing unknown unicast to be forwarded to standalone ports.
Clear UNU_FFP, UNM_FFP and BC_FFP in port_bridge_leave so that the
port returns to its initial state without flooding.
Fixes: 5a30833b9a16 ("net: dsa: mt7530: support MDB and bridge flag operations")
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/net/dsa/mt7530.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 7cd8566a31e6..2e5337186800 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -1767,6 +1767,11 @@ mt7530_port_bridge_leave(struct dsa_switch *ds, int port,
mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK,
MT7530_PORT_MATRIX_MODE);
+ /* Clear flood flags so they don't persist across bridge leave */
+ mt7530_clear(priv, MT753X_MFC,
+ UNU_FFP(BIT(port)) | UNM_FFP(BIT(port)) |
+ BC_FFP(BIT(port)));
+
mutex_unlock(&priv->reg_mutex);
}
--
2.54.0
^ permalink raw reply related [flat|nested] 9+ messages in thread* [PATCH net 5/5] net: dsa: mt7530: untag VLAN-aware bridge PVID
2026-05-05 14:15 [PATCH net 0/5] net: dsa: mt7530: assorted fixes Daniel Golle
` (3 preceding siblings ...)
2026-05-05 14:16 ` [PATCH net 4/5] net: dsa: mt7530: clear flood flags on bridge leave Daniel Golle
@ 2026-05-05 14:16 ` Daniel Golle
4 siblings, 0 replies; 9+ messages in thread
From: Daniel Golle @ 2026-05-05 14:16 UTC (permalink / raw)
To: Chester A. Unal, Daniel Golle, Edward Parker, Andrew Lunn,
Vladimir Oltean, David S. Miller, Eric Dumazet, Jakub Kicinski,
Paolo Abeni, Matthias Brugger, AngeloGioacchino Del Regno,
DENG Qingfang, Florian Fainelli, Arınç ÜNAL,
Sean Wang, netdev, linux-kernel, linux-arm-kernel, linux-mediatek
From: Edward Parker <edward@topnotchit.com>
With bridge VLAN filtering enabled on a port configured as untagged
member of the bridge PVID, ingress untagged frames do not reach the
corresponding bridge VLAN upper interface (br-lan.<vid>). ARP and
similar traffic is visible on the physical port but not delivered
to the VLAN sub-interface.
The MT7530/MT7531 forwards frames to the CPU port with the user
port's PVID tag applied even when the frame ingressed untagged on
the wire, because the CPU port is set to MT7530_VLAN_EG_CONSISTENT
and is a tagged member of the VLAN entry created for the bridge
VLAN. The DSA core then sees a hwaccel-tagged frame whose VID
matches the port's PVID, which the bridge does not treat as the
untagged-on-the-wire frame that the user expects.
Set ds->untag_vlan_aware_bridge_pvid in the mt7530 and mt7531
setup paths so the DSA core strips that hwaccel tag in software
when the parsed VID matches the bridge port's PVID, restoring the
on-the-wire frame as the bridge expects to see it.
Link: https://github.com/openwrt/openwrt/issues/18576
Fixes: 83163f7dca56 ("net: dsa: mediatek: add VLAN support for MT7530")
Signed-off-by: Edward Parker <edward@topnotchit.com>
[daniel@makrotopia.org: improve commit message]
Signed-off-by: Daniel Golle <daniel@makrotopia.org>
---
drivers/net/dsa/mt7530.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/dsa/mt7530.c b/drivers/net/dsa/mt7530.c
index 2e5337186800..4b7e5398b211 100644
--- a/drivers/net/dsa/mt7530.c
+++ b/drivers/net/dsa/mt7530.c
@@ -2452,6 +2452,7 @@ mt7530_setup(struct dsa_switch *ds)
}
ds->assisted_learning_on_cpu_port = true;
+ ds->untag_vlan_aware_bridge_pvid = true;
ds->mtu_enforcement_ingress = true;
if (priv->id == ID_MT7530) {
@@ -2641,6 +2642,7 @@ mt7531_setup_common(struct dsa_switch *ds)
int ret, i;
ds->assisted_learning_on_cpu_port = true;
+ ds->untag_vlan_aware_bridge_pvid = true;
ds->mtu_enforcement_ingress = true;
mt753x_trap_frames(priv);
--
2.54.0
^ permalink raw reply related [flat|nested] 9+ messages in thread