From 57bb55c437374bf697faab7d3b32fb02b1b53b6b Mon Sep 17 00:00:00 2001 From: Robert Marko Date: Sat, 15 Aug 2026 16:19:15 +0200 Subject: [PATCH] qualcommax: qca_ppe: add port MTU change support DSA rejects MTU changes when the switch driver does not provide a port_change_mtu callback. Add the callback and program the PPE ingress MRU, unicast egress MTU and multicast egress MTU thresholds for the requested frame size. The PPE thresholds include the Ethernet header and space for up to two VLAN tags, so account for that overhead when converting the network device MTU. Initialize all three thresholds consistently during setup. Link: https://github.com/openwrt/openwrt/pull/24758 Signed-off-by: Robert Marko --- .../drivers/net/ethernet/qualcomm/qca_ppe.h | 4 ++- .../net/ethernet/qualcomm/qca_ppe_main.c | 33 ++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/target/linux/qualcommax/files/drivers/net/ethernet/qualcomm/qca_ppe.h b/target/linux/qualcommax/files/drivers/net/ethernet/qualcomm/qca_ppe.h index 87071dd7bea..e02150e447b 100644 --- a/target/linux/qualcommax/files/drivers/net/ethernet/qualcomm/qca_ppe.h +++ b/target/linux/qualcommax/files/drivers/net/ethernet/qualcomm/qca_ppe.h @@ -263,6 +263,7 @@ #define PPE_PORT_BRIDGE_CTRL_TXMAC_EN BIT(16) #define PPE_MC_MTU_CTRL(port) (PPE_L2_BASE + 0xa00 + (port) * 0x4) +#define PPE_MC_MTU_CTRL_MTU GENMASK(13, 0) #define PPE_MC_MTU_CTRL_TX_CNT_EN BIT(16) #define PPE_RFDB_TBL(idx) (PPE_L2_BASE + 0x1000 + (idx) * 0x8) @@ -278,6 +279,8 @@ #define PPE_VSI_TBL_STA_MOVE_LRN_EN BIT(3) #define PPE_MRU_MTU_CTRL(port, stride) (PPE_L2_BASE + 0x3000 + (port) * (stride)) +#define PPE_MRU_MTU_CTRL_MRU GENMASK(13, 0) +#define PPE_MRU_MTU_CTRL_MTU GENMASK(29, 16) #define PPE_MRU_MTU_CTRL_RX_CNT_EN BIT(0) #define PPE_MRU_MTU_CTRL_TX_CNT_EN BIT(1) @@ -420,7 +423,6 @@ #define PPE_VSI_MAX 32 #define PPE_VSI_INVALID U32_MAX #define PPE_DEFAULT_MTU 1514 -#define PPE_MTU_SHIFT 16 #define PPE_MAX_FRAME_SIZE 0x3000 #define PPE_AGE_UNIT_MS 8000 diff --git a/target/linux/qualcommax/files/drivers/net/ethernet/qualcomm/qca_ppe_main.c b/target/linux/qualcommax/files/drivers/net/ethernet/qualcomm/qca_ppe_main.c index c870bbf58d7..64c00d388a1 100644 --- a/target/linux/qualcommax/files/drivers/net/ethernet/qualcomm/qca_ppe_main.c +++ b/target/linux/qualcommax/files/drivers/net/ethernet/qualcomm/qca_ppe_main.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include "qca_ppe.h" @@ -434,11 +435,13 @@ static int qca_ppe_setup(struct dsa_switch *ds) { struct qca_ppe_priv *priv = ds_to_priv(ds); int num_ports = ds->num_ports; + u32 frame_size; u32 port_mask; u32 val; int i; port_mask = BIT(num_ports) - 1; + frame_size = PPE_DEFAULT_MTU + 2 * VLAN_HLEN; for (i = 0; i < num_ports; i++) priv->port_vsi[i] = PPE_VSI_INVALID; @@ -451,7 +454,13 @@ static int qca_ppe_setup(struct dsa_switch *ds) regmap_write(priv->regmap, PPE_MRU_MTU_CTRL(i, priv->data->mru_mtu_ctrl_stride), - PPE_DEFAULT_MTU | (PPE_DEFAULT_MTU << PPE_MTU_SHIFT)); + FIELD_PREP(PPE_MRU_MTU_CTRL_MRU, frame_size) | + FIELD_PREP(PPE_MRU_MTU_CTRL_MTU, frame_size)); + + regmap_update_bits(priv->regmap, PPE_MC_MTU_CTRL(i), + PPE_MC_MTU_CTRL_MTU, + FIELD_PREP(PPE_MC_MTU_CTRL_MTU, + frame_size)); if (i >= 1) regmap_write(priv->regmap, PPE_GMAC_MIB_CTRL(i - 1), @@ -512,6 +521,27 @@ static int qca_ppe_set_ageing_time(struct dsa_switch *ds, unsigned int msecs) return 0; } +static int qca_ppe_port_change_mtu(struct dsa_switch *ds, int port, + int new_mtu) +{ + struct qca_ppe_priv *priv = ds_to_priv(ds); + u32 frame_size = new_mtu + ETH_HLEN + 2 * VLAN_HLEN; + int ret; + + ret = regmap_update_bits(priv->regmap, + PPE_MRU_MTU_CTRL(port, + priv->data->mru_mtu_ctrl_stride), + PPE_MRU_MTU_CTRL_MRU | PPE_MRU_MTU_CTRL_MTU, + FIELD_PREP(PPE_MRU_MTU_CTRL_MRU, frame_size) | + FIELD_PREP(PPE_MRU_MTU_CTRL_MTU, frame_size)); + if (ret) + return ret; + + return regmap_update_bits(priv->regmap, PPE_MC_MTU_CTRL(port), + PPE_MC_MTU_CTRL_MTU, + FIELD_PREP(PPE_MC_MTU_CTRL_MTU, frame_size)); +} + static int qca_ppe_port_enable(struct dsa_switch *ds, int port, struct phy_device *phy) { @@ -1346,6 +1376,7 @@ static const struct dsa_switch_ops qca_ppe_ops = { .get_tag_protocol = qca_ppe_get_tag_protocol, .setup = qca_ppe_setup, .set_ageing_time = qca_ppe_set_ageing_time, + .port_change_mtu = qca_ppe_port_change_mtu, .port_enable = qca_ppe_port_enable, .port_disable = qca_ppe_port_disable, .port_stp_state_set = qca_ppe_port_stp_state_set,