[PATCH net-next v2 10/12] net: dsa: rzn1-a5psw: Add fixed frame length workaround for management port
From: Prabhakar
Date: Thu Oct 01 2026 - 12:06:03 EST
From: Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx>
The ETHSW IP used in SoCs such as RZ/T2H and RZ/N2H has a hardware issue
where the internal mgmt_tag_vld signal is asserted as a level instead of
a single-cycle pulse. This causes the frame length counter on the
management (CPU) port to over-increment, so valid frames are falsely
detected as oversized and dropped.
The recommended workaround is to program the maximum frame length
register (FRM_LENGTH) of the management port with a fixed, large value.
Add a management_port_fixed_frame_len member to struct a5psw_of_data to
hold the SoC-specific value. When it is set, program A5PSW_FRM_LENGTH
for the CPU port with this value in a5psw_setup(), and skip updating
FRM_LENGTH for the CPU port in a5psw_port_change_mtu() so that MTU
changes do not override the workaround.
No functional change for existing SoCs, which leave the value unset.
Signed-off-by: Lad Prabhakar <prabhakar.mahadev-lad.rj@xxxxxxxxxxxxxx>
---
v1->v2:
- Added info about the IP issue and the workaround.
- Updated commit message
---
drivers/net/dsa/rzn1_a5psw.c | 18 +++++++++++++++++-
drivers/net/dsa/rzn1_a5psw.h | 3 +++
2 files changed, 20 insertions(+), 1 deletion(-)
diff --git a/drivers/net/dsa/rzn1_a5psw.c b/drivers/net/dsa/rzn1_a5psw.c
index 0b0b4055e615..ce931442d49f 100644
--- a/drivers/net/dsa/rzn1_a5psw.c
+++ b/drivers/net/dsa/rzn1_a5psw.c
@@ -209,8 +209,13 @@ static int a5psw_port_enable(struct dsa_switch *ds, int port,
static int a5psw_port_change_mtu(struct dsa_switch *ds, int port, int new_mtu)
{
struct a5psw *a5psw = ds->priv;
+ struct a5psw_of_data *of_data = a5psw->of_data;
+
+ if (dsa_is_cpu_port(ds, port) && of_data->management_port_fixed_frame_len)
+ return 0;
new_mtu += ETH_HLEN + A5PSW_EXTRA_MTU_LEN + ETH_FCS_LEN;
+
a5psw_reg_writel(a5psw, A5PSW_FRM_LENGTH(port), new_mtu);
return 0;
@@ -990,8 +995,19 @@ static int a5psw_setup(struct dsa_switch *ds)
if (dsa_port_is_unused(dp))
continue;
- /* Enable egress flooding and learning for CPU port */
if (dsa_port_is_cpu(dp)) {
+ /*
+ * Workaround for ETHSW IP issue, mgmt_tag_vld is asserted as a level
+ * instead of a single-cycle pulse, causing the frame length counter
+ * to over-increment and trigger false oversize frame drops.
+ * The recommended workaround is to set the maximum frame
+ * length on the management port.
+ */
+ if (a5psw->of_data->management_port_fixed_frame_len)
+ a5psw_reg_writel(a5psw, A5PSW_FRM_LENGTH(port),
+ a5psw->of_data->management_port_fixed_frame_len);
+
+ /* Enable egress flooding and learning for CPU port */
a5psw_flooding_set_resolution(a5psw, port, true);
a5psw_port_learning_set(a5psw, port, true);
}
diff --git a/drivers/net/dsa/rzn1_a5psw.h b/drivers/net/dsa/rzn1_a5psw.h
index e952afd95dca..5bec33b23079 100644
--- a/drivers/net/dsa/rzn1_a5psw.h
+++ b/drivers/net/dsa/rzn1_a5psw.h
@@ -237,12 +237,15 @@ union lk_data {
* @npcs: Number of PCS connected to the switch
* @cpu_port: CPU port number
* @tag_proto: DSA tag protocol used by the switch
+ * @management_port_fixed_frame_len: Fixed frame length for the management
+ * port to account for the HW issue.
*/
struct a5psw_of_data {
unsigned int nports;
unsigned int npcs;
unsigned int cpu_port;
enum dsa_tag_protocol tag_proto;
+ unsigned int management_port_fixed_frame_len;
};
/**
--
2.55.0