From f44218cd5e6a3d98b137344b808ee154117ce765 Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 17 Mar 2026 17:40:47 +0100 Subject: [PATCH] net: airoha: Reset PPE cpu port configuration in airoha_ppe_hw_init() Before this patch, the PPE cpu port configuration used for a specific GDM device was set just running ndo_init() callback during the device initialization. The selected PPE cpu port configuration depends on the QDMA block assigned to the GDM port. The QDMA block is selected according to the GDM port LAN/WAN configuration as specified in the commit '8737d7194d6d ("net: airoha: select QDMA block according LAN/WAN configuration"). However, the user selected PPE cpu port configuration can be different with respect to the one hardcoded in the NPU firmware binary. The hardcoded NPU PPE cpu port configuration is loaded initializing the PPE engine running the NPU ops ppe_init() callback in airoha_ppe_offload_setup routine (this is executed at runtime by the netfilter flowtable infrastructure during flow offloading). Reset the PPE cpu port configuration in airoha_ppe_hw_init routine in order to apply the user requested setup according to the device DTS. Please note this patch is fixing an issue not visible to the user (so we do not need to backport it) since airoha_eth driver currently supports just the internal phy available via the MT7530 DSA switch and there are no WAN interfaces officially supported since PCS/external phy is not merged mainline yet (it will be posted with following patches). Signed-off-by: Lorenzo Bianconi Reviewed-by: Simon Horman Link: https://patch.msgid.link/20260317-airoha-fix-ppe-def-cpu-v1-1-338533d8e234@kernel.org Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/airoha/airoha_eth.c | 28 +++++------------------ drivers/net/ethernet/airoha/airoha_eth.h | 2 ++ drivers/net/ethernet/airoha/airoha_ppe.c | 23 ++++++++++++++++++- drivers/net/ethernet/airoha/airoha_regs.h | 7 +++--- 4 files changed, 33 insertions(+), 27 deletions(-) diff --git a/drivers/net/ethernet/airoha/airoha_eth.c b/drivers/net/ethernet/airoha/airoha_eth.c index db9d9531711e..961325da833b 100644 --- a/drivers/net/ethernet/airoha/airoha_eth.c +++ b/drivers/net/ethernet/airoha/airoha_eth.c @@ -1755,8 +1755,7 @@ static int airoha_dev_init(struct net_device *dev) { struct airoha_gdm_port *port = netdev_priv(dev); struct airoha_eth *eth = port->eth; - u32 fe_cpu_port; - u8 ppe_id; + int i; /* QDMA0 is used for lan ports while QDMA1 is used for WAN ports */ port->qdma = ð->qdma[!airoha_is_lan_gdm_port(port)]; @@ -1774,28 +1773,13 @@ static int airoha_dev_init(struct net_device *dev) if (err) return err; } - fallthrough; - case AIROHA_GDM2_IDX: - if (airoha_ppe_is_enabled(eth, 1)) { - /* For PPE2 always use secondary cpu port. */ - fe_cpu_port = FE_PSE_PORT_CDM2; - ppe_id = 1; - break; - } - fallthrough; - default: { - u8 qdma_id = port->qdma - ð->qdma[0]; - - /* For PPE1 select cpu port according to the running QDMA. */ - fe_cpu_port = qdma_id ? FE_PSE_PORT_CDM2 : FE_PSE_PORT_CDM1; - ppe_id = 0; break; - } + default: + break; } - airoha_fe_rmw(eth, REG_PPE_DFT_CPORT0(ppe_id), - DFT_CPORT_MASK(port->id), - __field_prep(DFT_CPORT_MASK(port->id), fe_cpu_port)); + for (i = 0; i < eth->soc->num_ppe; i++) + airoha_ppe_set_cpu_port(port, i); return 0; } @@ -1898,7 +1882,7 @@ static u32 airoha_get_dsa_tag(struct sk_buff *skb, struct net_device *dev) #endif } -static int airoha_get_fe_port(struct airoha_gdm_port *port) +int airoha_get_fe_port(struct airoha_gdm_port *port) { struct airoha_qdma *qdma = port->qdma; struct airoha_eth *eth = qdma->eth; diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h index 8cfa94ec084a..7df4dbcd8861 100644 --- a/drivers/net/ethernet/airoha/airoha_eth.h +++ b/drivers/net/ethernet/airoha/airoha_eth.h @@ -646,9 +646,11 @@ static inline bool airoha_is_7583(struct airoha_eth *eth) return eth->soc->version == 0x7583; } +int airoha_get_fe_port(struct airoha_gdm_port *port); bool airoha_is_valid_gdm_port(struct airoha_eth *eth, struct airoha_gdm_port *port); +void airoha_ppe_set_cpu_port(struct airoha_gdm_port *port, u8 ppe_id); bool airoha_ppe_is_enabled(struct airoha_eth *eth, int index); void airoha_ppe_check_skb(struct airoha_ppe_dev *dev, struct sk_buff *skb, u16 hash, bool rx_wlan); diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c index ec5ce41dad80..7666b1d2f4f6 100644 --- a/drivers/net/ethernet/airoha/airoha_ppe.c +++ b/drivers/net/ethernet/airoha/airoha_ppe.c @@ -85,6 +85,20 @@ static u32 airoha_ppe_get_timestamp(struct airoha_ppe *ppe) return FIELD_GET(AIROHA_FOE_IB1_BIND_TIMESTAMP, timestamp); } +void airoha_ppe_set_cpu_port(struct airoha_gdm_port *port, u8 ppe_id) +{ + struct airoha_qdma *qdma = port->qdma; + u8 fport = airoha_get_fe_port(port); + struct airoha_eth *eth = qdma->eth; + u8 qdma_id = qdma - ð->qdma[0]; + u32 fe_cpu_port; + + fe_cpu_port = qdma_id ? FE_PSE_PORT_CDM2 : FE_PSE_PORT_CDM1; + airoha_fe_rmw(eth, REG_PPE_DFT_CPORT(ppe_id, fport), + DFT_CPORT_MASK(fport), + __field_prep(DFT_CPORT_MASK(fport), fe_cpu_port)); +} + static void airoha_ppe_hw_init(struct airoha_ppe *ppe) { u32 sram_ppe_num_data_entries = PPE_SRAM_NUM_ENTRIES, sram_num_entries; @@ -147,7 +161,9 @@ static void airoha_ppe_hw_init(struct airoha_ppe *ppe) airoha_fe_wr(eth, REG_PPE_HASH_SEED(i), PPE_HASH_SEED); - for (p = 0; p < ARRAY_SIZE(eth->ports); p++) + for (p = 0; p < ARRAY_SIZE(eth->ports); p++) { + struct airoha_gdm_port *port = eth->ports[p]; + airoha_fe_rmw(eth, REG_PPE_MTU(i, p), FP0_EGRESS_MTU_MASK | FP1_EGRESS_MTU_MASK, @@ -155,6 +171,11 @@ static void airoha_ppe_hw_init(struct airoha_ppe *ppe) AIROHA_MAX_MTU) | FIELD_PREP(FP1_EGRESS_MTU_MASK, AIROHA_MAX_MTU)); + if (!port) + continue; + + airoha_ppe_set_cpu_port(port, i); + } } } diff --git a/drivers/net/ethernet/airoha/airoha_regs.h b/drivers/net/ethernet/airoha/airoha_regs.h index 29878b954c77..436f3c8779c1 100644 --- a/drivers/net/ethernet/airoha/airoha_regs.h +++ b/drivers/net/ethernet/airoha/airoha_regs.h @@ -312,10 +312,9 @@ #define REG_PPE_HASH_SEED(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x244) #define PPE_HASH_SEED 0x12345678 -#define REG_PPE_DFT_CPORT0(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x248) -#define DFT_CPORT_MASK(_n) GENMASK(3 + ((_n) << 2), ((_n) << 2)) - -#define REG_PPE_DFT_CPORT1(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x24c) +#define REG_PPE_DFT_CPORT_BASE(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x248) +#define REG_PPE_DFT_CPORT(_m, _n) (REG_PPE_DFT_CPORT_BASE(_m) + (((_n) / 8) << 2)) +#define DFT_CPORT_MASK(_n) GENMASK(3 + (((_n) % 8) << 2), (((_n) % 8) << 2)) #define REG_PPE_TB_HASH_CFG(_n) (((_n) ? PPE2_BASE : PPE1_BASE) + 0x250) #define PPE_DRAM_HASH1_MODE_MASK GENMASK(31, 28) -- 2.47.3