]> git.ipfire.org Git - thirdparty/openwrt.git/commitdiff
airoha: backport upstream patch for AN7583 Ethernet support 20489/head
authorChristian Marangi <ansuelsmth@gmail.com>
Tue, 21 Oct 2025 21:12:07 +0000 (23:12 +0200)
committerChristian Marangi <ansuelsmth@gmail.com>
Wed, 22 Oct 2025 10:31:21 +0000 (12:31 +0200)
Backport upstream patch for AN7583 Ethernet support. While at it also
backport some additional fixes required to apply the AN7583 patches
cleanly.

Refresh all affected patch automatically (aside from the XSI patch that
changed the implementation)

Link: https://github.com/openwrt/openwrt/pull/20489
Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
28 files changed:
target/linux/airoha/patches-6.12/092-v6.18-net-airoha-Avoid-Wflex-array-member-not-at-end-warni.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/093-v6.18-net-airoha-Fix-PPE_IP_PROTO_CHK-register-definitions.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/094-v6.18-net-airoha-npu-Add-a-NPU-callback-to-initialize-flow.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/095-v6.19-net-airoha-Fix-loopback-mode-configuration-for-GDM2-.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/096-v6.19-net-airoha-Add-missing-stats-to-ethtool_eth_mac_stat.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/097-v6.19-net-airoha-Add-get_link-ethtool-callback.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/098-v6.19-net-airoha-Take-into-account-out-of-order-tx-complet.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/099-01-v6.19-net-airoha-ppe-Dynamically-allocate-foe_check_time-a.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/099-02-v6.19-net-airoha-Add-airoha_ppe_get_num_stats_entries-and-.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/099-03-v6.19-net-airoha-Add-airoha_eth_soc_data-struct.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/099-04-v6.19-net-airoha-Generalize-airoha_ppe2_is_enabled-routine.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/099-05-v6.19-net-airoha-ppe-Move-PPE-memory-info-in-airoha_eth_so.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/099-06-v6.19-net-airoha-ppe-Remove-airoha_ppe_is_enabled-where-no.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/099-07-v6.19-net-airoha-ppe-Configure-SRAM-PPE-entries-via-the-cp.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/099-08-v6.19-net-airoha-ppe-Flush-PPE-SRAM-table-during-PPE-setup.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/099-09-v6.19-net-airoha-Select-default-ppe-cpu-port-in-airoha_dev.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/099-10-v6.19-net-airoha-Refactor-src-port-configuration-in-airhoh.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/099-11-v6.19-net-airoha-ppe-Do-not-use-magic-numbers-in-airoha_pp.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/099-12-v6.19-net-airoha-Add-AN7583-SoC-support.patch [new file with mode: 0644]
target/linux/airoha/patches-6.12/116-02-net-airoha-deassert-XSI-line-on-hw-init.patch
target/linux/airoha/patches-6.12/116-03-net-airoha-add-reference-for-SPORT-GDM4-in-qdma_get_.patch
target/linux/airoha/patches-6.12/116-05-net-airoha-drop-redundant-GDM3-4-define.patch
target/linux/airoha/patches-6.12/116-06-net-airoha-add-initial-fixup-for-GDM3-4-port-support.patch
target/linux/airoha/patches-6.12/116-07-airoha-ethernet-drop-xsi-mac-reset.patch
target/linux/airoha/patches-6.12/116-08-net-phylink-add-.pcs_link_down-PCS-OP.patch
target/linux/airoha/patches-6.12/116-10-net-airoha-add-phylink-support-for-GDM2-4.patch
target/linux/airoha/patches-6.12/604-02-net-ethernet-airoha-define-sport-value-for-GDM3.patch
target/linux/airoha/patches-6.12/606-net-airoha-disable-external-phy-code-if-PCS_AIROHA-i.patch

diff --git a/target/linux/airoha/patches-6.12/092-v6.18-net-airoha-Avoid-Wflex-array-member-not-at-end-warni.patch b/target/linux/airoha/patches-6.12/092-v6.18-net-airoha-Avoid-Wflex-array-member-not-at-end-warni.patch
new file mode 100644 (file)
index 0000000..5e52a3b
--- /dev/null
@@ -0,0 +1,45 @@
+From 09630ab91d840416b0178f3660afa4eebce24286 Mon Sep 17 00:00:00 2001
+From: "Gustavo A. R. Silva" <gustavoars@kernel.org>
+Date: Mon, 22 Sep 2025 16:08:21 +0200
+Subject: [PATCH] net: airoha: Avoid -Wflex-array-member-not-at-end warning
+
+-Wflex-array-member-not-at-end was introduced in GCC-14, and we are
+getting ready to enable it, globally.
+
+Move the conflicting declaration to the end of the corresponding
+structure. Notice that `struct airoha_foe_entry` is a flexible
+structure, this is a structure that contains a flexible-array
+member.
+
+Fix the following warning:
+
+drivers/net/ethernet/airoha/airoha_eth.h:474:33: warning: structure containing a flexible array member is not at the end of another structure [-Wflex-array-member-not-at-end]
+
+Signed-off-by: Gustavo A. R. Silva <gustavoars@kernel.org>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/aNFYVYLXQDqm4yxb@kspp
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/ethernet/airoha/airoha_eth.h | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/ethernet/airoha/airoha_eth.h
++++ b/drivers/net/ethernet/airoha/airoha_eth.h
+@@ -471,7 +471,6 @@ struct airoha_flow_table_entry {
+               };
+       };
+-      struct airoha_foe_entry data;
+       struct hlist_node l2_subflow_node; /* PPE L2 subflow entry */
+       u32 hash;
+@@ -480,6 +479,9 @@ struct airoha_flow_table_entry {
+       struct rhash_head node;
+       unsigned long cookie;
++
++      /* Must be last --ends in a flexible-array member. */
++      struct airoha_foe_entry data;
+ };
+ struct airoha_wdma_info {
diff --git a/target/linux/airoha/patches-6.12/093-v6.18-net-airoha-Fix-PPE_IP_PROTO_CHK-register-definitions.patch b/target/linux/airoha/patches-6.12/093-v6.18-net-airoha-Fix-PPE_IP_PROTO_CHK-register-definitions.patch
new file mode 100644 (file)
index 0000000..31cd950
--- /dev/null
@@ -0,0 +1,29 @@
+From e156dd6b856fa462430d875b0d4cd281ecd66c23 Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Thu, 18 Sep 2025 08:59:41 +0200
+Subject: [PATCH] net: airoha: Fix PPE_IP_PROTO_CHK register definitions
+
+Fix typo in PPE_IP_PROTO_CHK_IPV4_MASK and PPE_IP_PROTO_CHK_IPV6_MASK
+register mask definitions. This is not a real problem since this
+register is not actually used in the current codebase.
+
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/ethernet/airoha/airoha_regs.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/ethernet/airoha/airoha_regs.h
++++ b/drivers/net/ethernet/airoha/airoha_regs.h
+@@ -237,8 +237,8 @@
+ #define PPE_FLOW_CFG_IP4_TCP_FRAG_MASK                BIT(6)
+ #define REG_PPE_IP_PROTO_CHK(_n)              (((_n) ? PPE2_BASE : PPE1_BASE) + 0x208)
+-#define PPE_IP_PROTO_CHK_IPV4_MASK            GENMASK(15, 0)
+-#define PPE_IP_PROTO_CHK_IPV6_MASK            GENMASK(31, 16)
++#define PPE_IP_PROTO_CHK_IPV4_MASK            GENMASK(31, 16)
++#define PPE_IP_PROTO_CHK_IPV6_MASK            GENMASK(15, 0)
+ #define REG_PPE_TB_CFG(_n)                    (((_n) ? PPE2_BASE : PPE1_BASE) + 0x21c)
+ #define PPE_SRAM_TB_NUM_ENTRY_MASK            GENMASK(26, 24)
diff --git a/target/linux/airoha/patches-6.12/094-v6.18-net-airoha-npu-Add-a-NPU-callback-to-initialize-flow.patch b/target/linux/airoha/patches-6.12/094-v6.18-net-airoha-npu-Add-a-NPU-callback-to-initialize-flow.patch
new file mode 100644 (file)
index 0000000..021ec0c
--- /dev/null
@@ -0,0 +1,159 @@
+From 105ce7ad57e492b75ab40f2dc591db645fadbaa2 Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Wed, 24 Sep 2025 23:14:53 +0200
+Subject: [PATCH] net: airoha: npu: Add a NPU callback to initialize flow stats
+
+Introduce a NPU callback to initialize flow stats and remove NPU stats
+initialization from airoha_npu_get routine. Add num_stats_entries to
+airoha_npu_ppe_stats_setup routine.
+This patch makes the code more readable since NPU statistic are now
+initialized on demand by the NPU consumer (at the moment NPU statistic
+are configured just by the airoha_eth driver).
+Moreover this patch allows the NPU consumer (PPE module) to explicitly
+enable/disable NPU flow stats.
+
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20250924-airoha-npu-init-stats-callback-v1-1-88bdf3c941b2@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/ethernet/airoha/airoha_npu.c  | 24 ++++++-----------------
+ drivers/net/ethernet/airoha/airoha_ppe.c  | 19 ++++++++++++------
+ include/linux/soc/airoha/airoha_offload.h |  7 ++++---
+ 3 files changed, 23 insertions(+), 27 deletions(-)
+
+--- a/drivers/net/ethernet/airoha/airoha_npu.c
++++ b/drivers/net/ethernet/airoha/airoha_npu.c
+@@ -379,15 +379,13 @@ out:
+       return err;
+ }
+-static int airoha_npu_stats_setup(struct airoha_npu *npu,
+-                                dma_addr_t foe_stats_addr)
++static int airoha_npu_ppe_stats_setup(struct airoha_npu *npu,
++                                    dma_addr_t foe_stats_addr,
++                                    u32 num_stats_entries)
+ {
+-      int err, size = PPE_STATS_NUM_ENTRIES * sizeof(*npu->stats);
++      int err, size = num_stats_entries * sizeof(*npu->stats);
+       struct ppe_mbox_data *ppe_data;
+-      if (!size) /* flow stats are disabled */
+-              return 0;
+-
+       ppe_data = kzalloc(sizeof(*ppe_data), GFP_ATOMIC);
+       if (!ppe_data)
+               return -ENOMEM;
+@@ -542,7 +540,7 @@ static void airoha_npu_wlan_irq_disable(
+       regmap_clear_bits(npu->regmap, REG_IRQ_RXDONE(q), NPU_IRQ_RX_MASK(q));
+ }
+-struct airoha_npu *airoha_npu_get(struct device *dev, dma_addr_t *stats_addr)
++struct airoha_npu *airoha_npu_get(struct device *dev)
+ {
+       struct platform_device *pdev;
+       struct device_node *np;
+@@ -580,17 +578,6 @@ struct airoha_npu *airoha_npu_get(struct
+               goto error_module_put;
+       }
+-      if (stats_addr) {
+-              int err;
+-
+-              err = airoha_npu_stats_setup(npu, *stats_addr);
+-              if (err) {
+-                      dev_err(dev, "failed to allocate npu stats buffer\n");
+-                      npu = ERR_PTR(err);
+-                      goto error_module_put;
+-              }
+-      }
+-
+       return npu;
+ error_module_put:
+@@ -643,6 +630,7 @@ static int airoha_npu_probe(struct platf
+       npu->dev = dev;
+       npu->ops.ppe_init = airoha_npu_ppe_init;
+       npu->ops.ppe_deinit = airoha_npu_ppe_deinit;
++      npu->ops.ppe_init_stats = airoha_npu_ppe_stats_setup;
+       npu->ops.ppe_flush_sram_entries = airoha_npu_ppe_flush_sram_entries;
+       npu->ops.ppe_foe_commit_entry = airoha_npu_foe_commit_entry;
+       npu->ops.wlan_init_reserved_memory = airoha_npu_wlan_init_memory;
+--- a/drivers/net/ethernet/airoha/airoha_ppe.c
++++ b/drivers/net/ethernet/airoha/airoha_ppe.c
+@@ -1243,12 +1243,11 @@ static int airoha_ppe_flush_sram_entries
+ static struct airoha_npu *airoha_ppe_npu_get(struct airoha_eth *eth)
+ {
+-      struct airoha_npu *npu = airoha_npu_get(eth->dev,
+-                                              &eth->ppe->foe_stats_dma);
++      struct airoha_npu *npu = airoha_npu_get(eth->dev);
+       if (IS_ERR(npu)) {
+               request_module("airoha-npu");
+-              npu = airoha_npu_get(eth->dev, &eth->ppe->foe_stats_dma);
++              npu = airoha_npu_get(eth->dev);
+       }
+       return npu;
+@@ -1257,6 +1256,7 @@ static struct airoha_npu *airoha_ppe_npu
+ static int airoha_ppe_offload_setup(struct airoha_eth *eth)
+ {
+       struct airoha_npu *npu = airoha_ppe_npu_get(eth);
++      struct airoha_ppe *ppe = eth->ppe;
+       int err;
+       if (IS_ERR(npu))
+@@ -1266,12 +1266,19 @@ static int airoha_ppe_offload_setup(stru
+       if (err)
+               goto error_npu_put;
+-      airoha_ppe_hw_init(eth->ppe);
+-      err = airoha_ppe_flush_sram_entries(eth->ppe, npu);
++      if (PPE_STATS_NUM_ENTRIES) {
++              err = npu->ops.ppe_init_stats(npu, ppe->foe_stats_dma,
++                                            PPE_STATS_NUM_ENTRIES);
++              if (err)
++                      goto error_npu_put;
++      }
++
++      airoha_ppe_hw_init(ppe);
++      err = airoha_ppe_flush_sram_entries(ppe, npu);
+       if (err)
+               goto error_npu_put;
+-      airoha_ppe_foe_flow_stats_reset(eth->ppe, npu);
++      airoha_ppe_foe_flow_stats_reset(ppe, npu);
+       rcu_assign_pointer(eth->npu, npu);
+       synchronize_rcu();
+--- a/include/linux/soc/airoha/airoha_offload.h
++++ b/include/linux/soc/airoha/airoha_offload.h
+@@ -181,6 +181,8 @@ struct airoha_npu {
+       struct {
+               int (*ppe_init)(struct airoha_npu *npu);
+               int (*ppe_deinit)(struct airoha_npu *npu);
++              int (*ppe_init_stats)(struct airoha_npu *npu,
++                                    dma_addr_t addr, u32 num_stats_entries);
+               int (*ppe_flush_sram_entries)(struct airoha_npu *npu,
+                                             dma_addr_t foe_addr,
+                                             int sram_num_entries);
+@@ -206,7 +208,7 @@ struct airoha_npu {
+ };
+ #if (IS_BUILTIN(CONFIG_NET_AIROHA_NPU) || IS_MODULE(CONFIG_NET_AIROHA_NPU))
+-struct airoha_npu *airoha_npu_get(struct device *dev, dma_addr_t *stats_addr);
++struct airoha_npu *airoha_npu_get(struct device *dev);
+ void airoha_npu_put(struct airoha_npu *npu);
+ static inline int airoha_npu_wlan_init_reserved_memory(struct airoha_npu *npu)
+@@ -256,8 +258,7 @@ static inline void airoha_npu_wlan_disab
+       npu->ops.wlan_disable_irq(npu, q);
+ }
+ #else
+-static inline struct airoha_npu *airoha_npu_get(struct device *dev,
+-                                              dma_addr_t *foe_stats_addr)
++static inline struct airoha_npu *airoha_npu_get(struct device *dev)
+ {
+       return NULL;
+ }
diff --git a/target/linux/airoha/patches-6.12/095-v6.19-net-airoha-Fix-loopback-mode-configuration-for-GDM2-.patch b/target/linux/airoha/patches-6.12/095-v6.19-net-airoha-Fix-loopback-mode-configuration-for-GDM2-.patch
new file mode 100644 (file)
index 0000000..5c3fcc0
--- /dev/null
@@ -0,0 +1,43 @@
+From fea8cdf6738a8b25fccbb7b109b440795a0892cb Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Wed, 8 Oct 2025 11:27:43 +0200
+Subject: [PATCH] net: airoha: Fix loopback mode configuration for GDM2 port
+
+Add missing configuration for loopback mode in airhoha_set_gdm2_loopback
+routine.
+
+Fixes: 9cd451d414f6e ("net: airoha: Add loopback support for GDM2")
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
+Link: https://patch.msgid.link/20251008-airoha-loopback-mode-fix-v2-1-045694fe7f60@kernel.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+---
+ drivers/net/ethernet/airoha/airoha_eth.c  | 4 +++-
+ drivers/net/ethernet/airoha/airoha_regs.h | 3 +++
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/ethernet/airoha/airoha_eth.c
++++ b/drivers/net/ethernet/airoha/airoha_eth.c
+@@ -1715,7 +1715,9 @@ static void airhoha_set_gdm2_loopback(st
+       airoha_fe_wr(eth, REG_GDM_RXCHN_EN(2), 0xffff);
+       airoha_fe_rmw(eth, REG_GDM_LPBK_CFG(2),
+                     LPBK_CHAN_MASK | LPBK_MODE_MASK | LPBK_EN_MASK,
+-                    FIELD_PREP(LPBK_CHAN_MASK, chan) | LPBK_EN_MASK);
++                    FIELD_PREP(LPBK_CHAN_MASK, chan) |
++                    LBK_GAP_MODE_MASK | LBK_LEN_MODE_MASK |
++                    LBK_CHAN_MODE_MASK | LPBK_EN_MASK);
+       airoha_fe_rmw(eth, REG_GDM_LEN_CFG(2),
+                     GDM_SHORT_LEN_MASK | GDM_LONG_LEN_MASK,
+                     FIELD_PREP(GDM_SHORT_LEN_MASK, 60) |
+--- a/drivers/net/ethernet/airoha/airoha_regs.h
++++ b/drivers/net/ethernet/airoha/airoha_regs.h
+@@ -151,6 +151,9 @@
+ #define LPBK_LEN_MASK                 GENMASK(23, 10)
+ #define LPBK_CHAN_MASK                        GENMASK(8, 4)
+ #define LPBK_MODE_MASK                        GENMASK(3, 1)
++#define LBK_GAP_MODE_MASK             BIT(3)
++#define LBK_LEN_MODE_MASK             BIT(2)
++#define LBK_CHAN_MODE_MASK            BIT(1)
+ #define LPBK_EN_MASK                  BIT(0)
+ #define REG_GDM_TXCHN_EN(_n)          (GDM_BASE(_n) + 0x24)
diff --git a/target/linux/airoha/patches-6.12/096-v6.19-net-airoha-Add-missing-stats-to-ethtool_eth_mac_stat.patch b/target/linux/airoha/patches-6.12/096-v6.19-net-airoha-Add-missing-stats-to-ethtool_eth_mac_stat.patch
new file mode 100644 (file)
index 0000000..66d72de
--- /dev/null
@@ -0,0 +1,34 @@
+From 331f8a8bea22aecf99437f3561453a85f40026de Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Mon, 13 Oct 2025 16:29:41 +0200
+Subject: [PATCH] net: airoha: Add missing stats to ethtool_eth_mac_stats
+
+Add the following stats to ethtool ethtool_eth_mac_stats stats:
+- FramesTransmittedOK
+- OctetsTransmittedOK
+- FramesReceivedOK
+- OctetsReceivedOK
+
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://patch.msgid.link/20251013-airoha-ethtool-improvements-v1-1-fdd1c6fc9be1@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/ethernet/airoha/airoha_eth.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+--- a/drivers/net/ethernet/airoha/airoha_eth.c
++++ b/drivers/net/ethernet/airoha/airoha_eth.c
+@@ -2027,8 +2027,12 @@ static void airoha_ethtool_get_mac_stats
+       airoha_update_hw_stats(port);
+       do {
+               start = u64_stats_fetch_begin(&port->stats.syncp);
++              stats->FramesTransmittedOK = port->stats.tx_ok_pkts;
++              stats->OctetsTransmittedOK = port->stats.tx_ok_bytes;
+               stats->MulticastFramesXmittedOK = port->stats.tx_multicast;
+               stats->BroadcastFramesXmittedOK = port->stats.tx_broadcast;
++              stats->FramesReceivedOK = port->stats.rx_ok_pkts;
++              stats->OctetsReceivedOK = port->stats.rx_ok_bytes;
+               stats->BroadcastFramesReceivedOK = port->stats.rx_broadcast;
+       } while (u64_stats_fetch_retry(&port->stats.syncp, start));
+ }
diff --git a/target/linux/airoha/patches-6.12/097-v6.19-net-airoha-Add-get_link-ethtool-callback.patch b/target/linux/airoha/patches-6.12/097-v6.19-net-airoha-Add-get_link-ethtool-callback.patch
new file mode 100644 (file)
index 0000000..7d78bd6
--- /dev/null
@@ -0,0 +1,25 @@
+From fc4fed9054ef5b5269d4395dd9db36fe98fce9e3 Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Mon, 13 Oct 2025 16:29:42 +0200
+Subject: [PATCH] net: airoha: Add get_link ethtool callback
+
+Set get_link ethtool callback to ethtool_op_get_link routine.
+
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Link: https://patch.msgid.link/20251013-airoha-ethtool-improvements-v1-2-fdd1c6fc9be1@kernel.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/ethernet/airoha/airoha_eth.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+--- a/drivers/net/ethernet/airoha/airoha_eth.c
++++ b/drivers/net/ethernet/airoha/airoha_eth.c
+@@ -2775,6 +2775,7 @@ static const struct ethtool_ops airoha_e
+       .get_drvinfo            = airoha_ethtool_get_drvinfo,
+       .get_eth_mac_stats      = airoha_ethtool_get_mac_stats,
+       .get_rmon_stats         = airoha_ethtool_get_rmon_stats,
++      .get_link               = ethtool_op_get_link,
+ };
+ static int airoha_metadata_dst_alloc(struct airoha_gdm_port *port)
diff --git a/target/linux/airoha/patches-6.12/098-v6.19-net-airoha-Take-into-account-out-of-order-tx-complet.patch b/target/linux/airoha/patches-6.12/098-v6.19-net-airoha-Take-into-account-out-of-order-tx-complet.patch
new file mode 100644 (file)
index 0000000..46432b2
--- /dev/null
@@ -0,0 +1,54 @@
+From bd5afca115f181c85f992d42a57cd497bc823ccb Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Sun, 12 Oct 2025 11:19:44 +0200
+Subject: [PATCH] net: airoha: Take into account out-of-order tx completions in
+ airoha_dev_xmit()
+
+Completion napi can free out-of-order tx descriptors if hw QoS is
+enabled and packets with different priority are queued to same DMA ring.
+Take into account possible out-of-order reports checking if the tx queue
+is full using circular buffer head/tail pointer instead of the number of
+queued packets.
+
+Fixes: 23020f0493270 ("net: airoha: Introduce ethernet support for EN7581 SoC")
+Suggested-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Link: https://patch.msgid.link/20251012-airoha-tx-busy-queue-v2-1-a600b08bab2d@kernel.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+---
+ drivers/net/ethernet/airoha/airoha_eth.c | 16 +++++++++++++++-
+ 1 file changed, 15 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/ethernet/airoha/airoha_eth.c
++++ b/drivers/net/ethernet/airoha/airoha_eth.c
+@@ -1878,6 +1878,20 @@ static u32 airoha_get_dsa_tag(struct sk_
+ #endif
+ }
++static bool airoha_dev_tx_queue_busy(struct airoha_queue *q, u32 nr_frags)
++{
++      u32 tail = q->tail <= q->head ? q->tail + q->ndesc : q->tail;
++      u32 index = q->head + nr_frags;
++
++      /* completion napi can free out-of-order tx descriptors if hw QoS is
++       * enabled and packets with different priorities are queued to the same
++       * DMA ring. Take into account possible out-of-order reports checking
++       * if the tx queue is full using circular buffer head/tail pointers
++       * instead of the number of queued packets.
++       */
++      return index >= tail;
++}
++
+ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
+                                  struct net_device *dev)
+ {
+@@ -1931,7 +1945,7 @@ static netdev_tx_t airoha_dev_xmit(struc
+       txq = netdev_get_tx_queue(dev, qid);
+       nr_frags = 1 + skb_shinfo(skb)->nr_frags;
+-      if (q->queued + nr_frags > q->ndesc) {
++      if (airoha_dev_tx_queue_busy(q, nr_frags)) {
+               /* not enough space in the queue */
+               netif_tx_stop_queue(txq);
+               spin_unlock_bh(&q->lock);
diff --git a/target/linux/airoha/patches-6.12/099-01-v6.19-net-airoha-ppe-Dynamically-allocate-foe_check_time-a.patch b/target/linux/airoha/patches-6.12/099-01-v6.19-net-airoha-ppe-Dynamically-allocate-foe_check_time-a.patch
new file mode 100644 (file)
index 0000000..3d4b0cf
--- /dev/null
@@ -0,0 +1,43 @@
+From 6d5b601d52a27aafff555b480e538507901c672c Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Fri, 17 Oct 2025 11:06:11 +0200
+Subject: [PATCH 01/12] net: airoha: ppe: Dynamically allocate foe_check_time
+ array in airoha_ppe struct
+
+This is a preliminary patch to properly enable PPE support for AN7583
+SoC.
+
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Link: https://patch.msgid.link/20251017-an7583-eth-support-v3-2-f28319666667@kernel.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+---
+ drivers/net/ethernet/airoha/airoha_eth.h | 2 +-
+ drivers/net/ethernet/airoha/airoha_ppe.c | 5 +++++
+ 2 files changed, 6 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/ethernet/airoha/airoha_eth.h
++++ b/drivers/net/ethernet/airoha/airoha_eth.h
+@@ -554,7 +554,7 @@ struct airoha_ppe {
+       struct rhashtable l2_flows;
+       struct hlist_head *foe_flow;
+-      u16 foe_check_time[PPE_NUM_ENTRIES];
++      u16 *foe_check_time;
+       struct airoha_foe_stats *foe_stats;
+       dma_addr_t foe_stats_dma;
+--- a/drivers/net/ethernet/airoha/airoha_ppe.c
++++ b/drivers/net/ethernet/airoha/airoha_ppe.c
+@@ -1440,6 +1440,11 @@ int airoha_ppe_init(struct airoha_eth *e
+                       return -ENOMEM;
+       }
++      ppe->foe_check_time = devm_kzalloc(eth->dev, PPE_NUM_ENTRIES,
++                                         GFP_KERNEL);
++      if (!ppe->foe_check_time)
++              return -ENOMEM;
++
+       err = rhashtable_init(&eth->flow_table, &airoha_flow_table_params);
+       if (err)
+               return err;
diff --git a/target/linux/airoha/patches-6.12/099-02-v6.19-net-airoha-Add-airoha_ppe_get_num_stats_entries-and-.patch b/target/linux/airoha/patches-6.12/099-02-v6.19-net-airoha-Add-airoha_ppe_get_num_stats_entries-and-.patch
new file mode 100644 (file)
index 0000000..6733331
--- /dev/null
@@ -0,0 +1,239 @@
+From 15f357cd4581ce6e02e5e97719320600783140ec Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Fri, 17 Oct 2025 11:06:12 +0200
+Subject: [PATCH 02/12] net: airoha: Add airoha_ppe_get_num_stats_entries() and
+ airoha_ppe_get_num_total_stats_entries()
+
+Introduce airoha_ppe_get_num_stats_entries and
+airoha_ppe_get_num_total_stats_entries routines in order to make the
+code more readable controlling if CONFIG_NET_AIROHA_FLOW_STATS is
+enabled or disabled.
+Modify airoha_ppe_foe_get_flow_stats_index routine signature relying on
+airoha_ppe_get_num_total_stats_entries().
+
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Link: https://patch.msgid.link/20251017-an7583-eth-support-v3-3-f28319666667@kernel.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+---
+ drivers/net/ethernet/airoha/airoha_eth.h |  10 +--
+ drivers/net/ethernet/airoha/airoha_ppe.c | 101 ++++++++++++++++++-----
+ 2 files changed, 81 insertions(+), 30 deletions(-)
+
+--- a/drivers/net/ethernet/airoha/airoha_eth.h
++++ b/drivers/net/ethernet/airoha/airoha_eth.h
+@@ -50,15 +50,9 @@
+ #define PPE_NUM                               2
+ #define PPE1_SRAM_NUM_ENTRIES         (8 * 1024)
+-#define PPE_SRAM_NUM_ENTRIES          (2 * PPE1_SRAM_NUM_ENTRIES)
+-#ifdef CONFIG_NET_AIROHA_FLOW_STATS
++#define PPE_SRAM_NUM_ENTRIES          (PPE_NUM * PPE1_SRAM_NUM_ENTRIES)
+ #define PPE1_STATS_NUM_ENTRIES                (4 * 1024)
+-#else
+-#define PPE1_STATS_NUM_ENTRIES                0
+-#endif /* CONFIG_NET_AIROHA_FLOW_STATS */
+-#define PPE_STATS_NUM_ENTRIES         (2 * PPE1_STATS_NUM_ENTRIES)
+-#define PPE1_SRAM_NUM_DATA_ENTRIES    (PPE1_SRAM_NUM_ENTRIES - PPE1_STATS_NUM_ENTRIES)
+-#define PPE_SRAM_NUM_DATA_ENTRIES     (2 * PPE1_SRAM_NUM_DATA_ENTRIES)
++#define PPE_STATS_NUM_ENTRIES         (PPE_NUM * PPE1_STATS_NUM_ENTRIES)
+ #define PPE_DRAM_NUM_ENTRIES          (16 * 1024)
+ #define PPE_NUM_ENTRIES                       (PPE_SRAM_NUM_ENTRIES + PPE_DRAM_NUM_ENTRIES)
+ #define PPE_HASH_MASK                 (PPE_NUM_ENTRIES - 1)
+--- a/drivers/net/ethernet/airoha/airoha_ppe.c
++++ b/drivers/net/ethernet/airoha/airoha_ppe.c
+@@ -32,6 +32,24 @@ static const struct rhashtable_params ai
+       .automatic_shrinking = true,
+ };
++static int airoha_ppe_get_num_stats_entries(struct airoha_ppe *ppe)
++{
++      if (!IS_ENABLED(CONFIG_NET_AIROHA_FLOW_STATS))
++              return -EOPNOTSUPP;
++
++      return PPE1_STATS_NUM_ENTRIES;
++}
++
++static int airoha_ppe_get_total_num_stats_entries(struct airoha_ppe *ppe)
++{
++      int num_stats = airoha_ppe_get_num_stats_entries(ppe);
++
++      if (num_stats > 0)
++              num_stats = num_stats * PPE_NUM;
++
++      return num_stats;
++}
++
+ static bool airoha_ppe2_is_enabled(struct airoha_eth *eth)
+ {
+       return airoha_fe_rr(eth, REG_PPE_GLO_CFG(1)) & PPE_GLO_CFG_EN_MASK;
+@@ -48,7 +66,7 @@ static void airoha_ppe_hw_init(struct ai
+ {
+       u32 sram_tb_size, sram_num_entries, dram_num_entries;
+       struct airoha_eth *eth = ppe->eth;
+-      int i;
++      int i, sram_num_stats_entries;
+       sram_tb_size = PPE_SRAM_NUM_ENTRIES * sizeof(struct airoha_foe_entry);
+       dram_num_entries = PPE_RAM_NUM_ENTRIES_SHIFT(PPE_DRAM_NUM_ENTRIES);
+@@ -103,8 +121,13 @@ static void airoha_ppe_hw_init(struct ai
+       }
+       if (airoha_ppe2_is_enabled(eth)) {
+-              sram_num_entries =
+-                      PPE_RAM_NUM_ENTRIES_SHIFT(PPE1_SRAM_NUM_DATA_ENTRIES);
++              sram_num_entries = PPE1_SRAM_NUM_ENTRIES;
++              sram_num_stats_entries =
++                      airoha_ppe_get_num_stats_entries(ppe);
++              if (sram_num_stats_entries > 0)
++                      sram_num_entries -= sram_num_stats_entries;
++              sram_num_entries = PPE_RAM_NUM_ENTRIES_SHIFT(sram_num_entries);
++
+               airoha_fe_rmw(eth, REG_PPE_TB_CFG(0),
+                             PPE_SRAM_TB_NUM_ENTRY_MASK |
+                             PPE_DRAM_TB_NUM_ENTRY_MASK,
+@@ -120,8 +143,13 @@ static void airoha_ppe_hw_init(struct ai
+                             FIELD_PREP(PPE_DRAM_TB_NUM_ENTRY_MASK,
+                                        dram_num_entries));
+       } else {
+-              sram_num_entries =
+-                      PPE_RAM_NUM_ENTRIES_SHIFT(PPE_SRAM_NUM_DATA_ENTRIES);
++              sram_num_entries = PPE_SRAM_NUM_ENTRIES;
++              sram_num_stats_entries =
++                      airoha_ppe_get_total_num_stats_entries(ppe);
++              if (sram_num_stats_entries > 0)
++                      sram_num_entries -= sram_num_stats_entries;
++              sram_num_entries = PPE_RAM_NUM_ENTRIES_SHIFT(sram_num_entries);
++
+               airoha_fe_rmw(eth, REG_PPE_TB_CFG(0),
+                             PPE_SRAM_TB_NUM_ENTRY_MASK |
+                             PPE_DRAM_TB_NUM_ENTRY_MASK,
+@@ -480,13 +508,21 @@ static u32 airoha_ppe_foe_get_entry_hash
+       return hash;
+ }
+-static u32 airoha_ppe_foe_get_flow_stats_index(struct airoha_ppe *ppe, u32 hash)
++static int airoha_ppe_foe_get_flow_stats_index(struct airoha_ppe *ppe,
++                                             u32 hash, u32 *index)
+ {
+-      if (!airoha_ppe2_is_enabled(ppe->eth))
+-              return hash;
++      int ppe_num_stats_entries;
++
++      ppe_num_stats_entries = airoha_ppe_get_total_num_stats_entries(ppe);
++      if (ppe_num_stats_entries < 0)
++              return ppe_num_stats_entries;
++
++      *index = hash;
++      if (airoha_ppe2_is_enabled(ppe->eth) &&
++          hash >= ppe_num_stats_entries)
++              *index = *index - PPE_STATS_NUM_ENTRIES;
+-      return hash >= PPE_STATS_NUM_ENTRIES ? hash - PPE1_STATS_NUM_ENTRIES
+-                                           : hash;
++      return 0;
+ }
+ static void airoha_ppe_foe_flow_stat_entry_reset(struct airoha_ppe *ppe,
+@@ -500,9 +536,13 @@ static void airoha_ppe_foe_flow_stat_ent
+ static void airoha_ppe_foe_flow_stats_reset(struct airoha_ppe *ppe,
+                                           struct airoha_npu *npu)
+ {
+-      int i;
++      int i, ppe_num_stats_entries;
++
++      ppe_num_stats_entries = airoha_ppe_get_total_num_stats_entries(ppe);
++      if (ppe_num_stats_entries < 0)
++              return;
+-      for (i = 0; i < PPE_STATS_NUM_ENTRIES; i++)
++      for (i = 0; i < ppe_num_stats_entries; i++)
+               airoha_ppe_foe_flow_stat_entry_reset(ppe, npu, i);
+ }
+@@ -513,10 +553,17 @@ static void airoha_ppe_foe_flow_stats_up
+ {
+       int type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, hwe->ib1);
+       u32 index, pse_port, val, *data, *ib2, *meter;
++      int ppe_num_stats_entries;
+       u8 nbq;
+-      index = airoha_ppe_foe_get_flow_stats_index(ppe, hash);
+-      if (index >= PPE_STATS_NUM_ENTRIES)
++      ppe_num_stats_entries = airoha_ppe_get_total_num_stats_entries(ppe);
++      if (ppe_num_stats_entries < 0)
++              return;
++
++      if (airoha_ppe_foe_get_flow_stats_index(ppe, hash, &index))
++              return;
++
++      if (index >= ppe_num_stats_entries)
+               return;
+       if (type == PPE_PKT_TYPE_BRIDGE) {
+@@ -1158,11 +1205,19 @@ static int airoha_ppe_flow_offload_destr
+ void airoha_ppe_foe_entry_get_stats(struct airoha_ppe *ppe, u32 hash,
+                                   struct airoha_foe_stats64 *stats)
+ {
+-      u32 index = airoha_ppe_foe_get_flow_stats_index(ppe, hash);
+       struct airoha_eth *eth = ppe->eth;
++      int ppe_num_stats_entries;
+       struct airoha_npu *npu;
++      u32 index;
++
++      ppe_num_stats_entries = airoha_ppe_get_total_num_stats_entries(ppe);
++      if (ppe_num_stats_entries < 0)
++              return;
+-      if (index >= PPE_STATS_NUM_ENTRIES)
++      if (airoha_ppe_foe_get_flow_stats_index(ppe, hash, &index))
++              return;
++
++      if (index >= ppe_num_stats_entries)
+               return;
+       rcu_read_lock();
+@@ -1257,7 +1312,7 @@ static int airoha_ppe_offload_setup(stru
+ {
+       struct airoha_npu *npu = airoha_ppe_npu_get(eth);
+       struct airoha_ppe *ppe = eth->ppe;
+-      int err;
++      int err, ppe_num_stats_entries;
+       if (IS_ERR(npu))
+               return PTR_ERR(npu);
+@@ -1266,9 +1321,10 @@ static int airoha_ppe_offload_setup(stru
+       if (err)
+               goto error_npu_put;
+-      if (PPE_STATS_NUM_ENTRIES) {
++      ppe_num_stats_entries = airoha_ppe_get_total_num_stats_entries(ppe);
++      if (ppe_num_stats_entries > 0) {
+               err = npu->ops.ppe_init_stats(npu, ppe->foe_stats_dma,
+-                                            PPE_STATS_NUM_ENTRIES);
++                                            ppe_num_stats_entries);
+               if (err)
+                       goto error_npu_put;
+       }
+@@ -1405,8 +1461,8 @@ EXPORT_SYMBOL_GPL(airoha_ppe_put_dev);
+ int airoha_ppe_init(struct airoha_eth *eth)
+ {
++      int foe_size, err, ppe_num_stats_entries;
+       struct airoha_ppe *ppe;
+-      int foe_size, err;
+       ppe = devm_kzalloc(eth->dev, sizeof(*ppe), GFP_KERNEL);
+       if (!ppe)
+@@ -1431,8 +1487,9 @@ int airoha_ppe_init(struct airoha_eth *e
+       if (!ppe->foe_flow)
+               return -ENOMEM;
+-      foe_size = PPE_STATS_NUM_ENTRIES * sizeof(*ppe->foe_stats);
+-      if (foe_size) {
++      ppe_num_stats_entries = airoha_ppe_get_total_num_stats_entries(ppe);
++      if (ppe_num_stats_entries > 0) {
++              foe_size = ppe_num_stats_entries * sizeof(*ppe->foe_stats);
+               ppe->foe_stats = dmam_alloc_coherent(eth->dev, foe_size,
+                                                    &ppe->foe_stats_dma,
+                                                    GFP_KERNEL);
diff --git a/target/linux/airoha/patches-6.12/099-03-v6.19-net-airoha-Add-airoha_eth_soc_data-struct.patch b/target/linux/airoha/patches-6.12/099-03-v6.19-net-airoha-Add-airoha_eth_soc_data-struct.patch
new file mode 100644 (file)
index 0000000..9035e21
--- /dev/null
@@ -0,0 +1,152 @@
+From 5863b4e065e2253ef05684f728a04e4972046bcb Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Fri, 17 Oct 2025 11:06:13 +0200
+Subject: [PATCH 03/12] net: airoha: Add airoha_eth_soc_data struct
+
+Introduce airoha_eth_soc_data struct to contain differences between
+various SoC. Move XSI reset names in airoha_eth_soc_data. This is a
+preliminary patch to enable AN7583 ethernet controller support in
+airoha-eth driver.
+
+Co-developed-by: Christian Marangi <ansuelsmth@gmail.com>
+Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Link: https://patch.msgid.link/20251017-an7583-eth-support-v3-4-f28319666667@kernel.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+---
+ drivers/net/ethernet/airoha/airoha_eth.c | 42 +++++++++++++++++++-----
+ drivers/net/ethernet/airoha/airoha_eth.h | 17 ++++++++--
+ 2 files changed, 48 insertions(+), 11 deletions(-)
+
+--- a/drivers/net/ethernet/airoha/airoha_eth.c
++++ b/drivers/net/ethernet/airoha/airoha_eth.c
+@@ -1392,8 +1392,7 @@ static int airoha_hw_init(struct platfor
+       int err, i;
+       /* disable xsi */
+-      err = reset_control_bulk_assert(ARRAY_SIZE(eth->xsi_rsts),
+-                                      eth->xsi_rsts);
++      err = reset_control_bulk_assert(eth->soc->num_xsi_rsts, eth->xsi_rsts);
+       if (err)
+               return err;
+@@ -2927,6 +2926,7 @@ free_metadata_dst:
+ static int airoha_probe(struct platform_device *pdev)
+ {
++      struct reset_control_bulk_data *xsi_rsts;
+       struct device_node *np;
+       struct airoha_eth *eth;
+       int i, err;
+@@ -2935,6 +2935,10 @@ static int airoha_probe(struct platform_
+       if (!eth)
+               return -ENOMEM;
++      eth->soc = of_device_get_match_data(&pdev->dev);
++      if (!eth->soc)
++              return -EINVAL;
++
+       eth->dev = &pdev->dev;
+       err = dma_set_mask_and_coherent(eth->dev, DMA_BIT_MASK(32));
+@@ -2959,13 +2963,18 @@ static int airoha_probe(struct platform_
+               return err;
+       }
+-      eth->xsi_rsts[0].id = "xsi-mac";
+-      eth->xsi_rsts[1].id = "hsi0-mac";
+-      eth->xsi_rsts[2].id = "hsi1-mac";
+-      eth->xsi_rsts[3].id = "hsi-mac";
+-      eth->xsi_rsts[4].id = "xfp-mac";
++      xsi_rsts = devm_kzalloc(eth->dev,
++                              eth->soc->num_xsi_rsts * sizeof(*xsi_rsts),
++                              GFP_KERNEL);
++      if (err)
++              return err;
++
++      eth->xsi_rsts = xsi_rsts;
++      for (i = 0; i < eth->soc->num_xsi_rsts; i++)
++              eth->xsi_rsts[i].id = eth->soc->xsi_rsts_names[i];
++
+       err = devm_reset_control_bulk_get_exclusive(eth->dev,
+-                                                  ARRAY_SIZE(eth->xsi_rsts),
++                                                  eth->soc->num_xsi_rsts,
+                                                   eth->xsi_rsts);
+       if (err) {
+               dev_err(eth->dev, "failed to get bulk xsi reset lines\n");
+@@ -3052,8 +3061,23 @@ static void airoha_remove(struct platfor
+       platform_set_drvdata(pdev, NULL);
+ }
++static const char * const en7581_xsi_rsts_names[] = {
++      "xsi-mac",
++      "hsi0-mac",
++      "hsi1-mac",
++      "hsi-mac",
++      "xfp-mac",
++};
++
++static const struct airoha_eth_soc_data en7581_soc_data = {
++      .version = 0x7581,
++      .xsi_rsts_names = en7581_xsi_rsts_names,
++      .num_xsi_rsts = ARRAY_SIZE(en7581_xsi_rsts_names),
++      .num_ppe = 2,
++};
++
+ static const struct of_device_id of_airoha_match[] = {
+-      { .compatible = "airoha,en7581-eth" },
++      { .compatible = "airoha,en7581-eth", .data = &en7581_soc_data },
+       { /* sentinel */ }
+ };
+ MODULE_DEVICE_TABLE(of, of_airoha_match);
+--- a/drivers/net/ethernet/airoha/airoha_eth.h
++++ b/drivers/net/ethernet/airoha/airoha_eth.h
+@@ -21,7 +21,6 @@
+ #define AIROHA_MAX_NUM_IRQ_BANKS      4
+ #define AIROHA_MAX_DSA_PORTS          7
+ #define AIROHA_MAX_NUM_RSTS           3
+-#define AIROHA_MAX_NUM_XSI_RSTS               5
+ #define AIROHA_MAX_MTU                        9216
+ #define AIROHA_MAX_PACKET_SIZE                2048
+ #define AIROHA_NUM_QOS_CHANNELS               4
+@@ -556,9 +555,18 @@ struct airoha_ppe {
+       struct dentry *debugfs_dir;
+ };
++struct airoha_eth_soc_data {
++      u16 version;
++      const char * const *xsi_rsts_names;
++      int num_xsi_rsts;
++      int num_ppe;
++};
++
+ struct airoha_eth {
+       struct device *dev;
++      const struct airoha_eth_soc_data *soc;
++
+       unsigned long state;
+       void __iomem *fe_regs;
+@@ -568,7 +576,7 @@ struct airoha_eth {
+       struct rhashtable flow_table;
+       struct reset_control_bulk_data rsts[AIROHA_MAX_NUM_RSTS];
+-      struct reset_control_bulk_data xsi_rsts[AIROHA_MAX_NUM_XSI_RSTS];
++      struct reset_control_bulk_data *xsi_rsts;
+       struct net_device *napi_dev;
+@@ -611,6 +619,11 @@ static inline bool airhoa_is_lan_gdm_por
+       return port->id == 1;
+ }
++static inline bool airoha_is_7581(struct airoha_eth *eth)
++{
++      return eth->soc->version == 0x7581;
++}
++
+ bool airoha_is_valid_gdm_port(struct airoha_eth *eth,
+                             struct airoha_gdm_port *port);
diff --git a/target/linux/airoha/patches-6.12/099-04-v6.19-net-airoha-Generalize-airoha_ppe2_is_enabled-routine.patch b/target/linux/airoha/patches-6.12/099-04-v6.19-net-airoha-Generalize-airoha_ppe2_is_enabled-routine.patch
new file mode 100644 (file)
index 0000000..e82ce24
--- /dev/null
@@ -0,0 +1,147 @@
+From ef9449f080b61920cdc3d3106f8ffc2d9ba8b861 Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Fri, 17 Oct 2025 11:06:14 +0200
+Subject: [PATCH 04/12] net: airoha: Generalize airoha_ppe2_is_enabled routine
+
+Rename airoha_ppe2_is_enabled() in airoha_ppe_is_enabled() and
+generalize it in order to check if each PPE module is enabled.
+Rely on airoha_ppe_is_enabled routine to properly initialize PPE for
+AN7583 SoC since AN7583 does not support PPE2.
+
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Link: https://patch.msgid.link/20251017-an7583-eth-support-v3-5-f28319666667@kernel.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+---
+ drivers/net/ethernet/airoha/airoha_eth.c | 32 ++++++++++++++++--------
+ drivers/net/ethernet/airoha/airoha_eth.h |  1 +
+ drivers/net/ethernet/airoha/airoha_ppe.c | 17 +++++++------
+ 3 files changed, 32 insertions(+), 18 deletions(-)
+
+--- a/drivers/net/ethernet/airoha/airoha_eth.c
++++ b/drivers/net/ethernet/airoha/airoha_eth.c
+@@ -297,8 +297,11 @@ static void airoha_fe_pse_ports_init(str
+       int q;
+       all_rsv = airoha_fe_get_pse_all_rsv(eth);
+-      /* hw misses PPE2 oq rsv */
+-      all_rsv += PSE_RSV_PAGES * pse_port_num_queues[FE_PSE_PORT_PPE2];
++      if (airoha_ppe_is_enabled(eth, 1)) {
++              /* hw misses PPE2 oq rsv */
++              all_rsv += PSE_RSV_PAGES *
++                         pse_port_num_queues[FE_PSE_PORT_PPE2];
++      }
+       airoha_fe_set(eth, REG_FE_PSE_BUF_SET, all_rsv);
+       /* CMD1 */
+@@ -335,13 +338,17 @@ static void airoha_fe_pse_ports_init(str
+       for (q = 4; q < pse_port_num_queues[FE_PSE_PORT_CDM4]; q++)
+               airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_CDM4, q,
+                                        PSE_QUEUE_RSV_PAGES);
+-      /* PPE2 */
+-      for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_PPE2]; q++) {
+-              if (q < pse_port_num_queues[FE_PSE_PORT_PPE2] / 2)
+-                      airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_PPE2, q,
+-                                               PSE_QUEUE_RSV_PAGES);
+-              else
+-                      airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_PPE2, q, 0);
++      if (airoha_ppe_is_enabled(eth, 1)) {
++              /* PPE2 */
++              for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_PPE2]; q++) {
++                      if (q < pse_port_num_queues[FE_PSE_PORT_PPE2] / 2)
++                              airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_PPE2,
++                                                       q,
++                                                       PSE_QUEUE_RSV_PAGES);
++                      else
++                              airoha_fe_set_pse_oq_rsv(eth, FE_PSE_PORT_PPE2,
++                                                       q, 0);
++              }
+       }
+       /* GMD4 */
+       for (q = 0; q < pse_port_num_queues[FE_PSE_PORT_GDM4]; q++)
+@@ -1767,8 +1774,11 @@ static int airoha_dev_init(struct net_de
+                       airhoha_set_gdm2_loopback(port);
+               fallthrough;
+       case 2:
+-              pse_port = FE_PSE_PORT_PPE2;
+-              break;
++              if (airoha_ppe_is_enabled(eth, 1)) {
++                      pse_port = FE_PSE_PORT_PPE2;
++                      break;
++              }
++              fallthrough;
+       default:
+               pse_port = FE_PSE_PORT_PPE1;
+               break;
+--- a/drivers/net/ethernet/airoha/airoha_eth.h
++++ b/drivers/net/ethernet/airoha/airoha_eth.h
+@@ -627,6 +627,7 @@ static inline bool airoha_is_7581(struct
+ bool airoha_is_valid_gdm_port(struct airoha_eth *eth,
+                             struct airoha_gdm_port *port);
++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);
+ int airoha_ppe_setup_tc_block_cb(struct airoha_ppe_dev *dev, void *type_data);
+--- a/drivers/net/ethernet/airoha/airoha_ppe.c
++++ b/drivers/net/ethernet/airoha/airoha_ppe.c
+@@ -50,9 +50,12 @@ static int airoha_ppe_get_total_num_stat
+       return num_stats;
+ }
+-static bool airoha_ppe2_is_enabled(struct airoha_eth *eth)
++bool airoha_ppe_is_enabled(struct airoha_eth *eth, int index)
+ {
+-      return airoha_fe_rr(eth, REG_PPE_GLO_CFG(1)) & PPE_GLO_CFG_EN_MASK;
++      if (index >= eth->soc->num_ppe)
++              return false;
++
++      return airoha_fe_rr(eth, REG_PPE_GLO_CFG(index)) & PPE_GLO_CFG_EN_MASK;
+ }
+ static u32 airoha_ppe_get_timestamp(struct airoha_ppe *ppe)
+@@ -120,7 +123,7 @@ static void airoha_ppe_hw_init(struct ai
+                                                AIROHA_MAX_MTU));
+       }
+-      if (airoha_ppe2_is_enabled(eth)) {
++      if (airoha_ppe_is_enabled(eth, 1)) {
+               sram_num_entries = PPE1_SRAM_NUM_ENTRIES;
+               sram_num_stats_entries =
+                       airoha_ppe_get_num_stats_entries(ppe);
+@@ -518,7 +521,7 @@ static int airoha_ppe_foe_get_flow_stats
+               return ppe_num_stats_entries;
+       *index = hash;
+-      if (airoha_ppe2_is_enabled(ppe->eth) &&
++      if (airoha_ppe_is_enabled(ppe->eth, 1) &&
+           hash >= ppe_num_stats_entries)
+               *index = *index - PPE_STATS_NUM_ENTRIES;
+@@ -613,7 +616,7 @@ airoha_ppe_foe_get_entry_locked(struct a
+               u32 val;
+               int i;
+-              ppe2 = airoha_ppe2_is_enabled(ppe->eth) &&
++              ppe2 = airoha_ppe_is_enabled(ppe->eth, 1) &&
+                      hash >= PPE1_SRAM_NUM_ENTRIES;
+               airoha_fe_wr(ppe->eth, REG_PPE_RAM_CTRL(ppe2),
+                            FIELD_PREP(PPE_SRAM_CTRL_ENTRY_MASK, hash) |
+@@ -691,7 +694,7 @@ static int airoha_ppe_foe_commit_entry(s
+       if (hash < PPE_SRAM_NUM_ENTRIES) {
+               dma_addr_t addr = ppe->foe_dma + hash * sizeof(*hwe);
+-              bool ppe2 = airoha_ppe2_is_enabled(eth) &&
++              bool ppe2 = airoha_ppe_is_enabled(eth, 1) &&
+                           hash >= PPE1_SRAM_NUM_ENTRIES;
+               err = npu->ops.ppe_foe_commit_entry(npu, addr, sizeof(*hwe),
+@@ -1286,7 +1289,7 @@ static int airoha_ppe_flush_sram_entries
+       int i, sram_num_entries = PPE_SRAM_NUM_ENTRIES;
+       struct airoha_foe_entry *hwe = ppe->foe;
+-      if (airoha_ppe2_is_enabled(ppe->eth))
++      if (airoha_ppe_is_enabled(ppe->eth, 1))
+               sram_num_entries = sram_num_entries / 2;
+       for (i = 0; i < sram_num_entries; i++)
diff --git a/target/linux/airoha/patches-6.12/099-05-v6.19-net-airoha-ppe-Move-PPE-memory-info-in-airoha_eth_so.patch b/target/linux/airoha/patches-6.12/099-05-v6.19-net-airoha-ppe-Move-PPE-memory-info-in-airoha_eth_so.patch
new file mode 100644 (file)
index 0000000..2382a21
--- /dev/null
@@ -0,0 +1,359 @@
+From 5bd1d1fd48ea9f8300b211540d946899c7f96480 Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Fri, 17 Oct 2025 11:06:15 +0200
+Subject: [PATCH 05/12] net: airoha: ppe: Move PPE memory info in
+ airoha_eth_soc_data struct
+
+AN7583 SoC runs a single PPE device while EN7581 runs two of them.
+Moreover PPE SRAM in AN7583 SoC is reduced to 8K (while SRAM is 16K on
+EN7581). Take into account PPE memory layout during PPE configuration.
+
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Link: https://patch.msgid.link/20251017-an7583-eth-support-v3-6-f28319666667@kernel.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+---
+ drivers/net/ethernet/airoha/airoha_eth.h      |  10 +-
+ drivers/net/ethernet/airoha/airoha_ppe.c      | 133 +++++++++---------
+ .../net/ethernet/airoha/airoha_ppe_debugfs.c  |   3 +-
+ 3 files changed, 70 insertions(+), 76 deletions(-)
+
+--- a/drivers/net/ethernet/airoha/airoha_eth.h
++++ b/drivers/net/ethernet/airoha/airoha_eth.h
+@@ -47,14 +47,9 @@
+ #define QDMA_METER_IDX(_n)            ((_n) & 0xff)
+ #define QDMA_METER_GROUP(_n)          (((_n) >> 8) & 0x3)
+-#define PPE_NUM                               2
+-#define PPE1_SRAM_NUM_ENTRIES         (8 * 1024)
+-#define PPE_SRAM_NUM_ENTRIES          (PPE_NUM * PPE1_SRAM_NUM_ENTRIES)
+-#define PPE1_STATS_NUM_ENTRIES                (4 * 1024)
+-#define PPE_STATS_NUM_ENTRIES         (PPE_NUM * PPE1_STATS_NUM_ENTRIES)
++#define PPE_SRAM_NUM_ENTRIES          (8 * 1024)
++#define PPE_STATS_NUM_ENTRIES         (4 * 1024)
+ #define PPE_DRAM_NUM_ENTRIES          (16 * 1024)
+-#define PPE_NUM_ENTRIES                       (PPE_SRAM_NUM_ENTRIES + PPE_DRAM_NUM_ENTRIES)
+-#define PPE_HASH_MASK                 (PPE_NUM_ENTRIES - 1)
+ #define PPE_ENTRY_SIZE                        80
+ #define PPE_RAM_NUM_ENTRIES_SHIFT(_n) (__ffs((_n) >> 10))
+@@ -634,6 +629,7 @@ int airoha_ppe_setup_tc_block_cb(struct
+ int airoha_ppe_init(struct airoha_eth *eth);
+ void airoha_ppe_deinit(struct airoha_eth *eth);
+ void airoha_ppe_init_upd_mem(struct airoha_gdm_port *port);
++u32 airoha_ppe_get_total_num_entries(struct airoha_ppe *ppe);
+ struct airoha_foe_entry *airoha_ppe_foe_get_entry(struct airoha_ppe *ppe,
+                                                 u32 hash);
+ void airoha_ppe_foe_entry_get_stats(struct airoha_ppe *ppe, u32 hash,
+--- a/drivers/net/ethernet/airoha/airoha_ppe.c
++++ b/drivers/net/ethernet/airoha/airoha_ppe.c
+@@ -37,19 +37,36 @@ static int airoha_ppe_get_num_stats_entr
+       if (!IS_ENABLED(CONFIG_NET_AIROHA_FLOW_STATS))
+               return -EOPNOTSUPP;
+-      return PPE1_STATS_NUM_ENTRIES;
++      return PPE_STATS_NUM_ENTRIES;
+ }
+ static int airoha_ppe_get_total_num_stats_entries(struct airoha_ppe *ppe)
+ {
+       int num_stats = airoha_ppe_get_num_stats_entries(ppe);
+-      if (num_stats > 0)
+-              num_stats = num_stats * PPE_NUM;
++      if (num_stats > 0) {
++              struct airoha_eth *eth = ppe->eth;
++
++              num_stats = num_stats * eth->soc->num_ppe;
++      }
+       return num_stats;
+ }
++static u32 airoha_ppe_get_total_sram_num_entries(struct airoha_ppe *ppe)
++{
++      struct airoha_eth *eth = ppe->eth;
++
++      return PPE_SRAM_NUM_ENTRIES * eth->soc->num_ppe;
++}
++
++u32 airoha_ppe_get_total_num_entries(struct airoha_ppe *ppe)
++{
++      u32 sram_num_entries = airoha_ppe_get_total_sram_num_entries(ppe);
++
++      return sram_num_entries + PPE_DRAM_NUM_ENTRIES;
++}
++
+ bool airoha_ppe_is_enabled(struct airoha_eth *eth, int index)
+ {
+       if (index >= eth->soc->num_ppe)
+@@ -67,14 +84,22 @@ static u32 airoha_ppe_get_timestamp(stru
+ static void airoha_ppe_hw_init(struct airoha_ppe *ppe)
+ {
+-      u32 sram_tb_size, sram_num_entries, dram_num_entries;
++      u32 sram_ppe_num_data_entries = PPE_SRAM_NUM_ENTRIES, sram_num_entries;
++      u32 sram_tb_size, dram_num_entries;
+       struct airoha_eth *eth = ppe->eth;
+       int i, sram_num_stats_entries;
+-      sram_tb_size = PPE_SRAM_NUM_ENTRIES * sizeof(struct airoha_foe_entry);
++      sram_num_entries = airoha_ppe_get_total_sram_num_entries(ppe);
++      sram_tb_size = sram_num_entries * sizeof(struct airoha_foe_entry);
+       dram_num_entries = PPE_RAM_NUM_ENTRIES_SHIFT(PPE_DRAM_NUM_ENTRIES);
+-      for (i = 0; i < PPE_NUM; i++) {
++      sram_num_stats_entries = airoha_ppe_get_num_stats_entries(ppe);
++      if (sram_num_stats_entries > 0)
++              sram_ppe_num_data_entries -= sram_num_stats_entries;
++      sram_ppe_num_data_entries =
++              PPE_RAM_NUM_ENTRIES_SHIFT(sram_ppe_num_data_entries);
++
++      for (i = 0; i < eth->soc->num_ppe; i++) {
+               int p;
+               airoha_fe_wr(eth, REG_PPE_TB_BASE(i),
+@@ -106,10 +131,16 @@ static void airoha_ppe_hw_init(struct ai
+               airoha_fe_rmw(eth, REG_PPE_TB_CFG(i),
+                             PPE_TB_CFG_SEARCH_MISS_MASK |
++                            PPE_SRAM_TB_NUM_ENTRY_MASK |
++                            PPE_DRAM_TB_NUM_ENTRY_MASK |
+                             PPE_TB_CFG_KEEPALIVE_MASK |
+                             PPE_TB_ENTRY_SIZE_MASK,
+                             FIELD_PREP(PPE_TB_CFG_SEARCH_MISS_MASK, 3) |
+-                            FIELD_PREP(PPE_TB_ENTRY_SIZE_MASK, 0));
++                            FIELD_PREP(PPE_TB_ENTRY_SIZE_MASK, 0) |
++                            FIELD_PREP(PPE_SRAM_TB_NUM_ENTRY_MASK,
++                                       sram_ppe_num_data_entries) |
++                            FIELD_PREP(PPE_DRAM_TB_NUM_ENTRY_MASK,
++                                       dram_num_entries));
+               airoha_fe_wr(eth, REG_PPE_HASH_SEED(i), PPE_HASH_SEED);
+@@ -122,45 +153,6 @@ static void airoha_ppe_hw_init(struct ai
+                                     FIELD_PREP(FP1_EGRESS_MTU_MASK,
+                                                AIROHA_MAX_MTU));
+       }
+-
+-      if (airoha_ppe_is_enabled(eth, 1)) {
+-              sram_num_entries = PPE1_SRAM_NUM_ENTRIES;
+-              sram_num_stats_entries =
+-                      airoha_ppe_get_num_stats_entries(ppe);
+-              if (sram_num_stats_entries > 0)
+-                      sram_num_entries -= sram_num_stats_entries;
+-              sram_num_entries = PPE_RAM_NUM_ENTRIES_SHIFT(sram_num_entries);
+-
+-              airoha_fe_rmw(eth, REG_PPE_TB_CFG(0),
+-                            PPE_SRAM_TB_NUM_ENTRY_MASK |
+-                            PPE_DRAM_TB_NUM_ENTRY_MASK,
+-                            FIELD_PREP(PPE_SRAM_TB_NUM_ENTRY_MASK,
+-                                       sram_num_entries) |
+-                            FIELD_PREP(PPE_DRAM_TB_NUM_ENTRY_MASK,
+-                                       dram_num_entries));
+-              airoha_fe_rmw(eth, REG_PPE_TB_CFG(1),
+-                            PPE_SRAM_TB_NUM_ENTRY_MASK |
+-                            PPE_DRAM_TB_NUM_ENTRY_MASK,
+-                            FIELD_PREP(PPE_SRAM_TB_NUM_ENTRY_MASK,
+-                                       sram_num_entries) |
+-                            FIELD_PREP(PPE_DRAM_TB_NUM_ENTRY_MASK,
+-                                       dram_num_entries));
+-      } else {
+-              sram_num_entries = PPE_SRAM_NUM_ENTRIES;
+-              sram_num_stats_entries =
+-                      airoha_ppe_get_total_num_stats_entries(ppe);
+-              if (sram_num_stats_entries > 0)
+-                      sram_num_entries -= sram_num_stats_entries;
+-              sram_num_entries = PPE_RAM_NUM_ENTRIES_SHIFT(sram_num_entries);
+-
+-              airoha_fe_rmw(eth, REG_PPE_TB_CFG(0),
+-                            PPE_SRAM_TB_NUM_ENTRY_MASK |
+-                            PPE_DRAM_TB_NUM_ENTRY_MASK,
+-                            FIELD_PREP(PPE_SRAM_TB_NUM_ENTRY_MASK,
+-                                       sram_num_entries) |
+-                            FIELD_PREP(PPE_DRAM_TB_NUM_ENTRY_MASK,
+-                                       dram_num_entries));
+-      }
+ }
+ static void airoha_ppe_flow_mangle_eth(const struct flow_action_entry *act, void *eth)
+@@ -459,9 +451,11 @@ static int airoha_ppe_foe_entry_set_ipv6
+       return 0;
+ }
+-static u32 airoha_ppe_foe_get_entry_hash(struct airoha_foe_entry *hwe)
++static u32 airoha_ppe_foe_get_entry_hash(struct airoha_ppe *ppe,
++                                       struct airoha_foe_entry *hwe)
+ {
+       int type = FIELD_GET(AIROHA_FOE_IB1_BIND_PACKET_TYPE, hwe->ib1);
++      u32 ppe_hash_mask = airoha_ppe_get_total_num_entries(ppe) - 1;
+       u32 hash, hv1, hv2, hv3;
+       switch (type) {
+@@ -499,14 +493,14 @@ static u32 airoha_ppe_foe_get_entry_hash
+       case PPE_PKT_TYPE_IPV6_6RD:
+       default:
+               WARN_ON_ONCE(1);
+-              return PPE_HASH_MASK;
++              return ppe_hash_mask;
+       }
+       hash = (hv1 & hv2) | ((~hv1) & hv3);
+       hash = (hash >> 24) | ((hash & 0xffffff) << 8);
+       hash ^= hv1 ^ hv2 ^ hv3;
+       hash ^= hash >> 16;
+-      hash &= PPE_NUM_ENTRIES - 1;
++      hash &= ppe_hash_mask;
+       return hash;
+ }
+@@ -607,9 +601,11 @@ static void airoha_ppe_foe_flow_stats_up
+ static struct airoha_foe_entry *
+ airoha_ppe_foe_get_entry_locked(struct airoha_ppe *ppe, u32 hash)
+ {
++      u32 sram_num_entries = airoha_ppe_get_total_sram_num_entries(ppe);
++
+       lockdep_assert_held(&ppe_lock);
+-      if (hash < PPE_SRAM_NUM_ENTRIES) {
++      if (hash < sram_num_entries) {
+               u32 *hwe = ppe->foe + hash * sizeof(struct airoha_foe_entry);
+               struct airoha_eth *eth = ppe->eth;
+               bool ppe2;
+@@ -617,7 +613,7 @@ airoha_ppe_foe_get_entry_locked(struct a
+               int i;
+               ppe2 = airoha_ppe_is_enabled(ppe->eth, 1) &&
+-                     hash >= PPE1_SRAM_NUM_ENTRIES;
++                     hash >= PPE_SRAM_NUM_ENTRIES;
+               airoha_fe_wr(ppe->eth, REG_PPE_RAM_CTRL(ppe2),
+                            FIELD_PREP(PPE_SRAM_CTRL_ENTRY_MASK, hash) |
+                            PPE_SRAM_CTRL_REQ_MASK);
+@@ -668,6 +664,7 @@ static int airoha_ppe_foe_commit_entry(s
+                                      struct airoha_foe_entry *e,
+                                      u32 hash, bool rx_wlan)
+ {
++      u32 sram_num_entries = airoha_ppe_get_total_sram_num_entries(ppe);
+       struct airoha_foe_entry *hwe = ppe->foe + hash * sizeof(*hwe);
+       u32 ts = airoha_ppe_get_timestamp(ppe);
+       struct airoha_eth *eth = ppe->eth;
+@@ -692,10 +689,10 @@ static int airoha_ppe_foe_commit_entry(s
+       if (!rx_wlan)
+               airoha_ppe_foe_flow_stats_update(ppe, npu, hwe, hash);
+-      if (hash < PPE_SRAM_NUM_ENTRIES) {
++      if (hash < sram_num_entries) {
+               dma_addr_t addr = ppe->foe_dma + hash * sizeof(*hwe);
+               bool ppe2 = airoha_ppe_is_enabled(eth, 1) &&
+-                          hash >= PPE1_SRAM_NUM_ENTRIES;
++                          hash >= PPE_SRAM_NUM_ENTRIES;
+               err = npu->ops.ppe_foe_commit_entry(npu, addr, sizeof(*hwe),
+                                                   hash, ppe2);
+@@ -822,7 +819,7 @@ static void airoha_ppe_foe_insert_entry(
+       if (state == AIROHA_FOE_STATE_BIND)
+               goto unlock;
+-      index = airoha_ppe_foe_get_entry_hash(hwe);
++      index = airoha_ppe_foe_get_entry_hash(ppe, hwe);
+       hlist_for_each_entry_safe(e, n, &ppe->foe_flow[index], list) {
+               if (e->type == FLOW_TYPE_L2_SUBFLOW) {
+                       state = FIELD_GET(AIROHA_FOE_IB1_BIND_STATE, hwe->ib1);
+@@ -882,7 +879,7 @@ static int airoha_ppe_foe_flow_commit_en
+       if (type == PPE_PKT_TYPE_BRIDGE)
+               return airoha_ppe_foe_l2_flow_commit_entry(ppe, e);
+-      hash = airoha_ppe_foe_get_entry_hash(&e->data);
++      hash = airoha_ppe_foe_get_entry_hash(ppe, &e->data);
+       e->type = FLOW_TYPE_L4;
+       e->hash = 0xffff;
+@@ -1286,17 +1283,15 @@ static int airoha_ppe_flow_offload_cmd(s
+ static int airoha_ppe_flush_sram_entries(struct airoha_ppe *ppe,
+                                        struct airoha_npu *npu)
+ {
+-      int i, sram_num_entries = PPE_SRAM_NUM_ENTRIES;
++      u32 sram_num_entries = airoha_ppe_get_total_sram_num_entries(ppe);
+       struct airoha_foe_entry *hwe = ppe->foe;
++      int i;
+-      if (airoha_ppe_is_enabled(ppe->eth, 1))
+-              sram_num_entries = sram_num_entries / 2;
+-
+-      for (i = 0; i < sram_num_entries; i++)
++      for (i = 0; i < PPE_SRAM_NUM_ENTRIES; i++)
+               memset(&hwe[i], 0, sizeof(*hwe));
+       return npu->ops.ppe_flush_sram_entries(npu, ppe->foe_dma,
+-                                             PPE_SRAM_NUM_ENTRIES);
++                                             sram_num_entries);
+ }
+ static struct airoha_npu *airoha_ppe_npu_get(struct airoha_eth *eth)
+@@ -1372,9 +1367,10 @@ void airoha_ppe_check_skb(struct airoha_
+                         u16 hash, bool rx_wlan)
+ {
+       struct airoha_ppe *ppe = dev->priv;
++      u32 ppe_hash_mask = airoha_ppe_get_total_num_entries(ppe) - 1;
+       u16 now, diff;
+-      if (hash > PPE_HASH_MASK)
++      if (hash > ppe_hash_mask)
+               return;
+       now = (u16)jiffies;
+@@ -1465,6 +1461,7 @@ EXPORT_SYMBOL_GPL(airoha_ppe_put_dev);
+ int airoha_ppe_init(struct airoha_eth *eth)
+ {
+       int foe_size, err, ppe_num_stats_entries;
++      u32 ppe_num_entries;
+       struct airoha_ppe *ppe;
+       ppe = devm_kzalloc(eth->dev, sizeof(*ppe), GFP_KERNEL);
+@@ -1474,18 +1471,18 @@ int airoha_ppe_init(struct airoha_eth *e
+       ppe->dev.ops.setup_tc_block_cb = airoha_ppe_setup_tc_block_cb;
+       ppe->dev.ops.check_skb = airoha_ppe_check_skb;
+       ppe->dev.priv = ppe;
++      ppe->eth = eth;
++      eth->ppe = ppe;
+-      foe_size = PPE_NUM_ENTRIES * sizeof(struct airoha_foe_entry);
++      ppe_num_entries = airoha_ppe_get_total_num_entries(ppe);
++      foe_size = ppe_num_entries * sizeof(struct airoha_foe_entry);
+       ppe->foe = dmam_alloc_coherent(eth->dev, foe_size, &ppe->foe_dma,
+                                      GFP_KERNEL);
+       if (!ppe->foe)
+               return -ENOMEM;
+-      ppe->eth = eth;
+-      eth->ppe = ppe;
+-
+       ppe->foe_flow = devm_kzalloc(eth->dev,
+-                                   PPE_NUM_ENTRIES * sizeof(*ppe->foe_flow),
++                                   ppe_num_entries * sizeof(*ppe->foe_flow),
+                                    GFP_KERNEL);
+       if (!ppe->foe_flow)
+               return -ENOMEM;
+@@ -1500,7 +1497,7 @@ int airoha_ppe_init(struct airoha_eth *e
+                       return -ENOMEM;
+       }
+-      ppe->foe_check_time = devm_kzalloc(eth->dev, PPE_NUM_ENTRIES,
++      ppe->foe_check_time = devm_kzalloc(eth->dev, ppe_num_entries,
+                                          GFP_KERNEL);
+       if (!ppe->foe_check_time)
+               return -ENOMEM;
+--- a/drivers/net/ethernet/airoha/airoha_ppe_debugfs.c
++++ b/drivers/net/ethernet/airoha/airoha_ppe_debugfs.c
+@@ -53,9 +53,10 @@ static int airoha_ppe_debugfs_foe_show(s
+               [AIROHA_FOE_STATE_FIN] = "FIN",
+       };
+       struct airoha_ppe *ppe = m->private;
++      u32 ppe_num_entries = airoha_ppe_get_total_num_entries(ppe);
+       int i;
+-      for (i = 0; i < PPE_NUM_ENTRIES; i++) {
++      for (i = 0; i < ppe_num_entries; i++) {
+               const char *state_str, *type_str = "UNKNOWN";
+               void *src_addr = NULL, *dest_addr = NULL;
+               u16 *src_port = NULL, *dest_port = NULL;
diff --git a/target/linux/airoha/patches-6.12/099-06-v6.19-net-airoha-ppe-Remove-airoha_ppe_is_enabled-where-no.patch b/target/linux/airoha/patches-6.12/099-06-v6.19-net-airoha-ppe-Remove-airoha_ppe_is_enabled-where-no.patch
new file mode 100644 (file)
index 0000000..18b92fb
--- /dev/null
@@ -0,0 +1,58 @@
+From 41139125f5c70e0f66f0cc4ac1b3a62f5801ab42 Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Fri, 17 Oct 2025 11:06:16 +0200
+Subject: [PATCH 06/12] net: airoha: ppe: Remove airoha_ppe_is_enabled() where
+ not necessary
+
+Now each PPE has always PPE_STATS_NUM_ENTRIES entries so we do not need
+to run airoha_ppe_is_enabled routine to check if the hash refers to
+PPE1 or PPE2.
+
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Link: https://patch.msgid.link/20251017-an7583-eth-support-v3-7-f28319666667@kernel.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+---
+ drivers/net/ethernet/airoha/airoha_ppe.c | 13 ++++---------
+ 1 file changed, 4 insertions(+), 9 deletions(-)
+
+--- a/drivers/net/ethernet/airoha/airoha_ppe.c
++++ b/drivers/net/ethernet/airoha/airoha_ppe.c
+@@ -514,10 +514,8 @@ static int airoha_ppe_foe_get_flow_stats
+       if (ppe_num_stats_entries < 0)
+               return ppe_num_stats_entries;
+-      *index = hash;
+-      if (airoha_ppe_is_enabled(ppe->eth, 1) &&
+-          hash >= ppe_num_stats_entries)
+-              *index = *index - PPE_STATS_NUM_ENTRIES;
++      *index = hash >= ppe_num_stats_entries ? hash - PPE_STATS_NUM_ENTRIES
++                                             : hash;
+       return 0;
+ }
+@@ -607,13 +605,11 @@ airoha_ppe_foe_get_entry_locked(struct a
+       if (hash < sram_num_entries) {
+               u32 *hwe = ppe->foe + hash * sizeof(struct airoha_foe_entry);
++              bool ppe2 = hash >= PPE_SRAM_NUM_ENTRIES;
+               struct airoha_eth *eth = ppe->eth;
+-              bool ppe2;
+               u32 val;
+               int i;
+-              ppe2 = airoha_ppe_is_enabled(ppe->eth, 1) &&
+-                     hash >= PPE_SRAM_NUM_ENTRIES;
+               airoha_fe_wr(ppe->eth, REG_PPE_RAM_CTRL(ppe2),
+                            FIELD_PREP(PPE_SRAM_CTRL_ENTRY_MASK, hash) |
+                            PPE_SRAM_CTRL_REQ_MASK);
+@@ -691,8 +687,7 @@ static int airoha_ppe_foe_commit_entry(s
+       if (hash < sram_num_entries) {
+               dma_addr_t addr = ppe->foe_dma + hash * sizeof(*hwe);
+-              bool ppe2 = airoha_ppe_is_enabled(eth, 1) &&
+-                          hash >= PPE_SRAM_NUM_ENTRIES;
++              bool ppe2 = hash >= PPE_SRAM_NUM_ENTRIES;
+               err = npu->ops.ppe_foe_commit_entry(npu, addr, sizeof(*hwe),
+                                                   hash, ppe2);
diff --git a/target/linux/airoha/patches-6.12/099-07-v6.19-net-airoha-ppe-Configure-SRAM-PPE-entries-via-the-cp.patch b/target/linux/airoha/patches-6.12/099-07-v6.19-net-airoha-ppe-Configure-SRAM-PPE-entries-via-the-cp.patch
new file mode 100644 (file)
index 0000000..60b4ee1
--- /dev/null
@@ -0,0 +1,65 @@
+From 306b78f5035af4bd011753c5a6b12812515caa6c Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Fri, 17 Oct 2025 11:06:17 +0200
+Subject: [PATCH 07/12] net: airoha: ppe: Configure SRAM PPE entries via the
+ cpu
+
+Introduce airoha_ppe_foe_commit_sram_entry routine in order to configure
+the SRAM PPE entries directly via the CPU instead of using the NPU APIs.
+This is a preliminary patch to enable netfilter flowtable hw offload for
+AN7583 SoC.
+
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Link: https://patch.msgid.link/20251017-an7583-eth-support-v3-8-f28319666667@kernel.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+---
+ drivers/net/ethernet/airoha/airoha_ppe.c | 30 ++++++++++++++++++------
+ 1 file changed, 23 insertions(+), 7 deletions(-)
+
+--- a/drivers/net/ethernet/airoha/airoha_ppe.c
++++ b/drivers/net/ethernet/airoha/airoha_ppe.c
+@@ -656,6 +656,27 @@ static bool airoha_ppe_foe_compare_entry
+       return !memcmp(&e->data.d, &hwe->d, len - sizeof(hwe->ib1));
+ }
++static int airoha_ppe_foe_commit_sram_entry(struct airoha_ppe *ppe, u32 hash)
++{
++      struct airoha_foe_entry *hwe = ppe->foe + hash * sizeof(*hwe);
++      bool ppe2 = hash >= PPE_SRAM_NUM_ENTRIES;
++      u32 *ptr = (u32 *)hwe, val;
++      int i;
++
++      for (i = 0; i < sizeof(*hwe) / sizeof(*ptr); i++)
++              airoha_fe_wr(ppe->eth, REG_PPE_RAM_ENTRY(ppe2, i), ptr[i]);
++
++      wmb();
++      airoha_fe_wr(ppe->eth, REG_PPE_RAM_CTRL(ppe2),
++                   FIELD_PREP(PPE_SRAM_CTRL_ENTRY_MASK, hash) |
++                   PPE_SRAM_CTRL_WR_MASK | PPE_SRAM_CTRL_REQ_MASK);
++
++      return read_poll_timeout_atomic(airoha_fe_rr, val,
++                                      val & PPE_SRAM_CTRL_ACK_MASK,
++                                      10, 100, false, ppe->eth,
++                                      REG_PPE_RAM_CTRL(ppe2));
++}
++
+ static int airoha_ppe_foe_commit_entry(struct airoha_ppe *ppe,
+                                      struct airoha_foe_entry *e,
+                                      u32 hash, bool rx_wlan)
+@@ -685,13 +706,8 @@ static int airoha_ppe_foe_commit_entry(s
+       if (!rx_wlan)
+               airoha_ppe_foe_flow_stats_update(ppe, npu, hwe, hash);
+-      if (hash < sram_num_entries) {
+-              dma_addr_t addr = ppe->foe_dma + hash * sizeof(*hwe);
+-              bool ppe2 = hash >= PPE_SRAM_NUM_ENTRIES;
+-
+-              err = npu->ops.ppe_foe_commit_entry(npu, addr, sizeof(*hwe),
+-                                                  hash, ppe2);
+-      }
++      if (hash < sram_num_entries)
++              err = airoha_ppe_foe_commit_sram_entry(ppe, hash);
+ unlock:
+       rcu_read_unlock();
diff --git a/target/linux/airoha/patches-6.12/099-08-v6.19-net-airoha-ppe-Flush-PPE-SRAM-table-during-PPE-setup.patch b/target/linux/airoha/patches-6.12/099-08-v6.19-net-airoha-ppe-Flush-PPE-SRAM-table-during-PPE-setup.patch
new file mode 100644 (file)
index 0000000..24eccca
--- /dev/null
@@ -0,0 +1,71 @@
+From 620d7b91aadbd4eb930895b07e34f0a155a9d3c1 Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Fri, 17 Oct 2025 11:06:18 +0200
+Subject: [PATCH 08/12] net: airoha: ppe: Flush PPE SRAM table during PPE setup
+
+Rely on airoha_ppe_foe_commit_sram_entry routine to flush SRAM PPE table
+entries. This patch allow moving PPE SRAM flush during PPE setup and
+avoid dumping uninitialized values via the debugfs if no entries are
+offloaded yet.
+
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Link: https://patch.msgid.link/20251017-an7583-eth-support-v3-9-f28319666667@kernel.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+---
+ drivers/net/ethernet/airoha/airoha_ppe.c | 24 ++++++++++++++----------
+ 1 file changed, 14 insertions(+), 10 deletions(-)
+
+--- a/drivers/net/ethernet/airoha/airoha_ppe.c
++++ b/drivers/net/ethernet/airoha/airoha_ppe.c
+@@ -1291,18 +1291,22 @@ static int airoha_ppe_flow_offload_cmd(s
+       return -EOPNOTSUPP;
+ }
+-static int airoha_ppe_flush_sram_entries(struct airoha_ppe *ppe,
+-                                       struct airoha_npu *npu)
++static int airoha_ppe_flush_sram_entries(struct airoha_ppe *ppe)
+ {
+       u32 sram_num_entries = airoha_ppe_get_total_sram_num_entries(ppe);
+       struct airoha_foe_entry *hwe = ppe->foe;
+-      int i;
++      int i, err = 0;
++
++      for (i = 0; i < sram_num_entries; i++) {
++              int err;
+-      for (i = 0; i < PPE_SRAM_NUM_ENTRIES; i++)
+               memset(&hwe[i], 0, sizeof(*hwe));
++              err = airoha_ppe_foe_commit_sram_entry(ppe, i);
++              if (err)
++                      break;
++      }
+-      return npu->ops.ppe_flush_sram_entries(npu, ppe->foe_dma,
+-                                             sram_num_entries);
++      return err;
+ }
+ static struct airoha_npu *airoha_ppe_npu_get(struct airoha_eth *eth)
+@@ -1339,10 +1343,6 @@ static int airoha_ppe_offload_setup(stru
+       }
+       airoha_ppe_hw_init(ppe);
+-      err = airoha_ppe_flush_sram_entries(ppe, npu);
+-      if (err)
+-              goto error_npu_put;
+-
+       airoha_ppe_foe_flow_stats_reset(ppe, npu);
+       rcu_assign_pointer(eth->npu, npu);
+@@ -1513,6 +1513,10 @@ int airoha_ppe_init(struct airoha_eth *e
+       if (!ppe->foe_check_time)
+               return -ENOMEM;
++      err = airoha_ppe_flush_sram_entries(ppe);
++      if (err)
++              return err;
++
+       err = rhashtable_init(&eth->flow_table, &airoha_flow_table_params);
+       if (err)
+               return err;
diff --git a/target/linux/airoha/patches-6.12/099-09-v6.19-net-airoha-Select-default-ppe-cpu-port-in-airoha_dev.patch b/target/linux/airoha/patches-6.12/099-09-v6.19-net-airoha-Select-default-ppe-cpu-port-in-airoha_dev.patch
new file mode 100644 (file)
index 0000000..c6ecbdb
--- /dev/null
@@ -0,0 +1,91 @@
+From c71a7a861ef02aa2bebb18c2f3385aa3f19094e0 Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Fri, 17 Oct 2025 11:06:19 +0200
+Subject: [PATCH 09/12] net: airoha: Select default ppe cpu port in
+ airoha_dev_init()
+
+Select the PPE default cpu port in airoha_dev_init routine.
+This patch allows to distribute the load between the two available cpu
+ports (FE_PSE_PORT_CDM1 and FE_PSE_PORT_CDM2) if the device is running a
+single PPE module (e.g. 7583) selecting the cpu port based on the use
+QDMA device. For multi-PPE device (e.g. 7581) assign FE_PSE_PORT_CDM1 to
+PPE1 and FE_PSE_PORT_CDM2 to PPE2.
+
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Link: https://patch.msgid.link/20251017-an7583-eth-support-v3-10-f28319666667@kernel.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+---
+ drivers/net/ethernet/airoha/airoha_eth.c | 38 ++++++++++--------------
+ 1 file changed, 16 insertions(+), 22 deletions(-)
+
+--- a/drivers/net/ethernet/airoha/airoha_eth.c
++++ b/drivers/net/ethernet/airoha/airoha_eth.c
+@@ -531,25 +531,6 @@ static int airoha_fe_init(struct airoha_
+       /* disable IFC by default */
+       airoha_fe_clear(eth, REG_FE_CSR_IFC_CFG, FE_IFC_EN_MASK);
+-      airoha_fe_wr(eth, REG_PPE_DFT_CPORT0(0),
+-                   FIELD_PREP(DFT_CPORT_MASK(7), FE_PSE_PORT_CDM1) |
+-                   FIELD_PREP(DFT_CPORT_MASK(6), FE_PSE_PORT_CDM1) |
+-                   FIELD_PREP(DFT_CPORT_MASK(5), FE_PSE_PORT_CDM1) |
+-                   FIELD_PREP(DFT_CPORT_MASK(4), FE_PSE_PORT_CDM1) |
+-                   FIELD_PREP(DFT_CPORT_MASK(3), FE_PSE_PORT_CDM1) |
+-                   FIELD_PREP(DFT_CPORT_MASK(2), FE_PSE_PORT_CDM1) |
+-                   FIELD_PREP(DFT_CPORT_MASK(1), FE_PSE_PORT_CDM1) |
+-                   FIELD_PREP(DFT_CPORT_MASK(0), FE_PSE_PORT_CDM1));
+-      airoha_fe_wr(eth, REG_PPE_DFT_CPORT0(1),
+-                   FIELD_PREP(DFT_CPORT_MASK(7), FE_PSE_PORT_CDM2) |
+-                   FIELD_PREP(DFT_CPORT_MASK(6), FE_PSE_PORT_CDM2) |
+-                   FIELD_PREP(DFT_CPORT_MASK(5), FE_PSE_PORT_CDM2) |
+-                   FIELD_PREP(DFT_CPORT_MASK(4), FE_PSE_PORT_CDM2) |
+-                   FIELD_PREP(DFT_CPORT_MASK(3), FE_PSE_PORT_CDM2) |
+-                   FIELD_PREP(DFT_CPORT_MASK(2), FE_PSE_PORT_CDM2) |
+-                   FIELD_PREP(DFT_CPORT_MASK(1), FE_PSE_PORT_CDM2) |
+-                   FIELD_PREP(DFT_CPORT_MASK(0), FE_PSE_PORT_CDM2));
+-
+       /* enable 1:N vlan action, init vlan table */
+       airoha_fe_set(eth, REG_MC_VLAN_EN, MC_VLAN_EN_MASK);
+@@ -1761,8 +1742,10 @@ static void airhoha_set_gdm2_loopback(st
+ static int airoha_dev_init(struct net_device *dev)
+ {
+       struct airoha_gdm_port *port = netdev_priv(dev);
+-      struct airoha_eth *eth = port->qdma->eth;
+-      u32 pse_port;
++      struct airoha_qdma *qdma = port->qdma;
++      struct airoha_eth *eth = qdma->eth;
++      u32 pse_port, fe_cpu_port;
++      u8 ppe_id;
+       airoha_set_macaddr(port, dev->dev_addr);
+@@ -1775,16 +1758,27 @@ static int airoha_dev_init(struct net_de
+               fallthrough;
+       case 2:
+               if (airoha_ppe_is_enabled(eth, 1)) {
++                      /* For PPE2 always use secondary cpu port. */
++                      fe_cpu_port = FE_PSE_PORT_CDM2;
+                       pse_port = FE_PSE_PORT_PPE2;
+                       break;
+               }
+               fallthrough;
+-      default:
++      default: {
++              u8 qdma_id = qdma - &eth->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;
+               pse_port = FE_PSE_PORT_PPE1;
+               break;
+       }
++      }
+       airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(port->id), pse_port);
++      ppe_id = pse_port == FE_PSE_PORT_PPE2 ? 1 : 0;
++      airoha_fe_rmw(eth, REG_PPE_DFT_CPORT0(ppe_id),
++                    DFT_CPORT_MASK(port->id),
++                    fe_cpu_port << __ffs(DFT_CPORT_MASK(port->id)));
+       return 0;
+ }
diff --git a/target/linux/airoha/patches-6.12/099-10-v6.19-net-airoha-Refactor-src-port-configuration-in-airhoh.patch b/target/linux/airoha/patches-6.12/099-10-v6.19-net-airoha-Refactor-src-port-configuration-in-airhoh.patch
new file mode 100644 (file)
index 0000000..cec0798
--- /dev/null
@@ -0,0 +1,202 @@
+From 9d5b5219f672c80bed4d4e15f0068e648cdca43b Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Fri, 17 Oct 2025 11:06:20 +0200
+Subject: [PATCH 10/12] net: airoha: Refactor src port configuration in
+ airhoha_set_gdm2_loopback
+
+AN7583 chipset relies on different definitions for source-port
+identifier used for hw offloading. In order to support hw offloading
+in AN7583 controller, refactor src port configuration in
+airhoha_set_gdm2_loopback routine and introduce get_src_port_id
+callback.
+
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Link: https://patch.msgid.link/20251017-an7583-eth-support-v3-11-f28319666667@kernel.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+---
+ drivers/net/ethernet/airoha/airoha_eth.c  | 82 ++++++++++++++++-------
+ drivers/net/ethernet/airoha/airoha_eth.h  | 18 +++--
+ drivers/net/ethernet/airoha/airoha_regs.h |  6 +-
+ 3 files changed, 73 insertions(+), 33 deletions(-)
+
+--- a/drivers/net/ethernet/airoha/airoha_eth.c
++++ b/drivers/net/ethernet/airoha/airoha_eth.c
+@@ -1687,13 +1687,17 @@ static int airoha_dev_set_macaddr(struct
+       return 0;
+ }
+-static void airhoha_set_gdm2_loopback(struct airoha_gdm_port *port)
++static int airhoha_set_gdm2_loopback(struct airoha_gdm_port *port)
+ {
+-      u32 pse_port = port->id == 3 ? FE_PSE_PORT_GDM3 : FE_PSE_PORT_GDM4;
++      u32 val, pse_port, chan = port->id == AIROHA_GDM3_IDX ? 4 : 0;
+       struct airoha_eth *eth = port->qdma->eth;
+-      u32 chan = port->id == 3 ? 4 : 0;
++      /* XXX: handle XSI_USB_PORT and XSI_PCE1_PORT */
++      u32 nbq = port->id == AIROHA_GDM3_IDX ? 4 : 0;
++      int src_port;
+       /* Forward the traffic to the proper GDM port */
++      pse_port = port->id == AIROHA_GDM3_IDX ? FE_PSE_PORT_GDM3
++                                             : FE_PSE_PORT_GDM4;
+       airoha_set_gdm_port_fwd_cfg(eth, REG_GDM_FWD_CFG(2), pse_port);
+       airoha_fe_clear(eth, REG_GDM_FWD_CFG(2), GDM_STRIP_CRC);
+@@ -1714,29 +1718,25 @@ static void airhoha_set_gdm2_loopback(st
+       airoha_fe_clear(eth, REG_FE_VIP_PORT_EN, BIT(2));
+       airoha_fe_clear(eth, REG_FE_IFC_PORT_EN, BIT(2));
+-      if (port->id == 3) {
+-              /* FIXME: handle XSI_PCE1_PORT */
+-              airoha_fe_rmw(eth, REG_FE_WAN_PORT,
+-                            WAN1_EN_MASK | WAN1_MASK | WAN0_MASK,
+-                            FIELD_PREP(WAN0_MASK, HSGMII_LAN_PCIE0_SRCPORT));
+-              airoha_fe_rmw(eth,
+-                            REG_SP_DFT_CPORT(HSGMII_LAN_PCIE0_SRCPORT >> 3),
+-                            SP_CPORT_PCIE0_MASK,
+-                            FIELD_PREP(SP_CPORT_PCIE0_MASK,
+-                                       FE_PSE_PORT_CDM2));
+-      } else {
+-              /* FIXME: handle XSI_USB_PORT */
++      src_port = eth->soc->ops.get_src_port_id(port, nbq);
++      if (src_port < 0)
++              return src_port;
++
++      airoha_fe_rmw(eth, REG_FE_WAN_PORT,
++                    WAN1_EN_MASK | WAN1_MASK | WAN0_MASK,
++                    FIELD_PREP(WAN0_MASK, src_port));
++      val = src_port & SP_CPORT_DFT_MASK;
++      airoha_fe_rmw(eth,
++                    REG_SP_DFT_CPORT(src_port >> fls(SP_CPORT_DFT_MASK)),
++                    SP_CPORT_MASK(val),
++                    FE_PSE_PORT_CDM2 << __ffs(SP_CPORT_MASK(val)));
++
++      if (port->id != AIROHA_GDM3_IDX)
+               airoha_fe_rmw(eth, REG_SRC_PORT_FC_MAP6,
+                             FC_ID_OF_SRC_PORT24_MASK,
+                             FIELD_PREP(FC_ID_OF_SRC_PORT24_MASK, 2));
+-              airoha_fe_rmw(eth, REG_FE_WAN_PORT,
+-                            WAN1_EN_MASK | WAN1_MASK | WAN0_MASK,
+-                            FIELD_PREP(WAN0_MASK, HSGMII_LAN_ETH_SRCPORT));
+-              airoha_fe_rmw(eth,
+-                            REG_SP_DFT_CPORT(HSGMII_LAN_ETH_SRCPORT >> 3),
+-                            SP_CPORT_ETH_MASK,
+-                            FIELD_PREP(SP_CPORT_ETH_MASK, FE_PSE_PORT_CDM2));
+-      }
++
++      return 0;
+ }
+ static int airoha_dev_init(struct net_device *dev)
+@@ -1753,8 +1753,13 @@ static int airoha_dev_init(struct net_de
+       case 3:
+       case 4:
+               /* If GDM2 is active we can't enable loopback */
+-              if (!eth->ports[1])
+-                      airhoha_set_gdm2_loopback(port);
++              if (!eth->ports[1]) {
++                      int err;
++
++                      err = airhoha_set_gdm2_loopback(port);
++                      if (err)
++                              return err;
++              }
+               fallthrough;
+       case 2:
+               if (airoha_ppe_is_enabled(eth, 1)) {
+@@ -3073,11 +3078,38 @@ static const char * const en7581_xsi_rst
+       "xfp-mac",
+ };
++static int airoha_en7581_get_src_port_id(struct airoha_gdm_port *port, int nbq)
++{
++      switch (port->id) {
++      case 3:
++              /* 7581 SoC supports PCIe serdes on GDM3 port */
++              if (nbq == 4)
++                      return HSGMII_LAN_7581_PCIE0_SRCPORT;
++              if (nbq == 5)
++                      return HSGMII_LAN_7581_PCIE1_SRCPORT;
++              break;
++      case 4:
++              /* 7581 SoC supports eth and usb serdes on GDM4 port */
++              if (!nbq)
++                      return HSGMII_LAN_7581_ETH_SRCPORT;
++              if (nbq == 1)
++                      return HSGMII_LAN_7581_USB_SRCPORT;
++              break;
++      default:
++              break;
++      }
++
++      return -EINVAL;
++}
++
+ static const struct airoha_eth_soc_data en7581_soc_data = {
+       .version = 0x7581,
+       .xsi_rsts_names = en7581_xsi_rsts_names,
+       .num_xsi_rsts = ARRAY_SIZE(en7581_xsi_rsts_names),
+       .num_ppe = 2,
++      .ops = {
++              .get_src_port_id = airoha_en7581_get_src_port_id,
++      },
+ };
+ static const struct of_device_id of_airoha_match[] = {
+--- a/drivers/net/ethernet/airoha/airoha_eth.h
++++ b/drivers/net/ethernet/airoha/airoha_eth.h
+@@ -67,10 +67,10 @@ enum {
+ };
+ enum {
+-      HSGMII_LAN_PCIE0_SRCPORT = 0x16,
+-      HSGMII_LAN_PCIE1_SRCPORT,
+-      HSGMII_LAN_ETH_SRCPORT,
+-      HSGMII_LAN_USB_SRCPORT,
++      HSGMII_LAN_7581_PCIE0_SRCPORT   = 0x16,
++      HSGMII_LAN_7581_PCIE1_SRCPORT,
++      HSGMII_LAN_7581_ETH_SRCPORT,
++      HSGMII_LAN_7581_USB_SRCPORT,
+ };
+ enum {
+@@ -99,6 +99,13 @@ enum {
+       CRSN_25 = 0x19,
+ };
++enum airoha_gdm_index {
++      AIROHA_GDM1_IDX = 1,
++      AIROHA_GDM2_IDX = 2,
++      AIROHA_GDM3_IDX = 3,
++      AIROHA_GDM4_IDX = 4,
++};
++
+ enum {
+       FE_PSE_PORT_CDM1,
+       FE_PSE_PORT_GDM1,
+@@ -555,6 +562,9 @@ struct airoha_eth_soc_data {
+       const char * const *xsi_rsts_names;
+       int num_xsi_rsts;
+       int num_ppe;
++      struct {
++              int (*get_src_port_id)(struct airoha_gdm_port *port, int nbq);
++      } ops;
+ };
+ struct airoha_eth {
+--- a/drivers/net/ethernet/airoha/airoha_regs.h
++++ b/drivers/net/ethernet/airoha/airoha_regs.h
+@@ -383,10 +383,8 @@
+ #define REG_MC_VLAN_DATA              0x2108
+ #define REG_SP_DFT_CPORT(_n)          (0x20e0 + ((_n) << 2))
+-#define SP_CPORT_PCIE1_MASK           GENMASK(31, 28)
+-#define SP_CPORT_PCIE0_MASK           GENMASK(27, 24)
+-#define SP_CPORT_USB_MASK             GENMASK(7, 4)
+-#define SP_CPORT_ETH_MASK             GENMASK(7, 4)
++#define SP_CPORT_DFT_MASK             GENMASK(2, 0)
++#define SP_CPORT_MASK(_n)             GENMASK(3 + ((_n) << 2), ((_n) << 2))
+ #define REG_SRC_PORT_FC_MAP6          0x2298
+ #define FC_ID_OF_SRC_PORT27_MASK      GENMASK(28, 24)
diff --git a/target/linux/airoha/patches-6.12/099-11-v6.19-net-airoha-ppe-Do-not-use-magic-numbers-in-airoha_pp.patch b/target/linux/airoha/patches-6.12/099-11-v6.19-net-airoha-ppe-Do-not-use-magic-numbers-in-airoha_pp.patch
new file mode 100644 (file)
index 0000000..93e7f5e
--- /dev/null
@@ -0,0 +1,29 @@
+From 63f283d36b1fb06b55ae609a1f679544f5f66057 Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Fri, 17 Oct 2025 11:06:21 +0200
+Subject: [PATCH 11/12] net: airoha: ppe: Do not use magic numbers in
+ airoha_ppe_foe_get_entry_locked()
+
+Explicit the size of entries pointed by hwe pointer in
+airoha_ppe_foe_get_entry_locked routine
+
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Link: https://patch.msgid.link/20251017-an7583-eth-support-v3-12-f28319666667@kernel.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+---
+ drivers/net/ethernet/airoha/airoha_ppe.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/ethernet/airoha/airoha_ppe.c
++++ b/drivers/net/ethernet/airoha/airoha_ppe.c
+@@ -619,7 +619,8 @@ airoha_ppe_foe_get_entry_locked(struct a
+                                            REG_PPE_RAM_CTRL(ppe2)))
+                       return NULL;
+-              for (i = 0; i < sizeof(struct airoha_foe_entry) / 4; i++)
++              for (i = 0; i < sizeof(struct airoha_foe_entry) / sizeof(*hwe);
++                   i++)
+                       hwe[i] = airoha_fe_rr(eth,
+                                             REG_PPE_RAM_ENTRY(ppe2, i));
+       }
diff --git a/target/linux/airoha/patches-6.12/099-12-v6.19-net-airoha-Add-AN7583-SoC-support.patch b/target/linux/airoha/patches-6.12/099-12-v6.19-net-airoha-Add-AN7583-SoC-support.patch
new file mode 100644 (file)
index 0000000..7f34a05
--- /dev/null
@@ -0,0 +1,185 @@
+From e4e5ce823bdd4601bd75ae7c206ae35e7c2fa60b Mon Sep 17 00:00:00 2001
+From: Lorenzo Bianconi <lorenzo@kernel.org>
+Date: Fri, 17 Oct 2025 11:06:22 +0200
+Subject: [PATCH 12/12] net: airoha: Add AN7583 SoC support
+
+Introduce support for AN7583 ethernet controller to airoha-eth dirver.
+
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
+Link: https://patch.msgid.link/20251017-an7583-eth-support-v3-13-f28319666667@kernel.org
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+---
+ drivers/net/ethernet/airoha/airoha_eth.c | 68 ++++++++++++++++++++++--
+ drivers/net/ethernet/airoha/airoha_eth.h | 11 ++++
+ drivers/net/ethernet/airoha/airoha_ppe.c |  3 ++
+ 3 files changed, 77 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/ethernet/airoha/airoha_eth.c
++++ b/drivers/net/ethernet/airoha/airoha_eth.c
+@@ -1689,10 +1689,8 @@ static int airoha_dev_set_macaddr(struct
+ static int airhoha_set_gdm2_loopback(struct airoha_gdm_port *port)
+ {
+-      u32 val, pse_port, chan = port->id == AIROHA_GDM3_IDX ? 4 : 0;
+       struct airoha_eth *eth = port->qdma->eth;
+-      /* XXX: handle XSI_USB_PORT and XSI_PCE1_PORT */
+-      u32 nbq = port->id == AIROHA_GDM3_IDX ? 4 : 0;
++      u32 val, pse_port, chan, nbq;
+       int src_port;
+       /* Forward the traffic to the proper GDM port */
+@@ -1704,6 +1702,8 @@ static int airhoha_set_gdm2_loopback(str
+       /* Enable GDM2 loopback */
+       airoha_fe_wr(eth, REG_GDM_TXCHN_EN(2), 0xffffffff);
+       airoha_fe_wr(eth, REG_GDM_RXCHN_EN(2), 0xffff);
++
++      chan = port->id == AIROHA_GDM3_IDX ? airoha_is_7581(eth) ? 4 : 3 : 0;
+       airoha_fe_rmw(eth, REG_GDM_LPBK_CFG(2),
+                     LPBK_CHAN_MASK | LPBK_MODE_MASK | LPBK_EN_MASK,
+                     FIELD_PREP(LPBK_CHAN_MASK, chan) |
+@@ -1718,6 +1718,8 @@ static int airhoha_set_gdm2_loopback(str
+       airoha_fe_clear(eth, REG_FE_VIP_PORT_EN, BIT(2));
+       airoha_fe_clear(eth, REG_FE_IFC_PORT_EN, BIT(2));
++      /* XXX: handle XSI_USB_PORT and XSI_PCE1_PORT */
++      nbq = port->id == AIROHA_GDM3_IDX && airoha_is_7581(eth) ? 4 : 0;
+       src_port = eth->soc->ops.get_src_port_id(port, nbq);
+       if (src_port < 0)
+               return src_port;
+@@ -1731,7 +1733,7 @@ static int airhoha_set_gdm2_loopback(str
+                     SP_CPORT_MASK(val),
+                     FE_PSE_PORT_CDM2 << __ffs(SP_CPORT_MASK(val)));
+-      if (port->id != AIROHA_GDM3_IDX)
++      if (port->id != AIROHA_GDM3_IDX && airoha_is_7581(eth))
+               airoha_fe_rmw(eth, REG_SRC_PORT_FC_MAP6,
+                             FC_ID_OF_SRC_PORT24_MASK,
+                             FIELD_PREP(FC_ID_OF_SRC_PORT24_MASK, 2));
+@@ -1900,6 +1902,22 @@ static bool airoha_dev_tx_queue_busy(str
+       return index >= tail;
+ }
++static int airoha_get_fe_port(struct airoha_gdm_port *port)
++{
++      struct airoha_qdma *qdma = port->qdma;
++      struct airoha_eth *eth = qdma->eth;
++
++      switch (eth->soc->version) {
++      case 0x7583:
++              return port->id == AIROHA_GDM3_IDX ? FE_PSE_PORT_GDM3
++                                                 : port->id;
++      case 0x7581:
++      default:
++              return port->id == AIROHA_GDM4_IDX ? FE_PSE_PORT_GDM4
++                                                 : port->id;
++      }
++}
++
+ static netdev_tx_t airoha_dev_xmit(struct sk_buff *skb,
+                                  struct net_device *dev)
+ {
+@@ -1940,7 +1958,7 @@ static netdev_tx_t airoha_dev_xmit(struc
+               }
+       }
+-      fport = port->id == 4 ? FE_PSE_PORT_GDM4 : port->id;
++      fport = airoha_get_fe_port(port);
+       msg1 = FIELD_PREP(QDMA_ETH_TXMSG_FPORT_MASK, fport) |
+              FIELD_PREP(QDMA_ETH_TXMSG_METER_MASK, 0x7f);
+@@ -3102,6 +3120,35 @@ static int airoha_en7581_get_src_port_id
+       return -EINVAL;
+ }
++static const char * const an7583_xsi_rsts_names[] = {
++      "xsi-mac",
++      "hsi0-mac",
++      "hsi1-mac",
++      "xfp-mac",
++};
++
++static int airoha_an7583_get_src_port_id(struct airoha_gdm_port *port, int nbq)
++{
++      switch (port->id) {
++      case 3:
++              /* 7583 SoC supports eth serdes on GDM3 port */
++              if (!nbq)
++                      return HSGMII_LAN_7583_ETH_SRCPORT;
++              break;
++      case 4:
++              /* 7583 SoC supports PCIe and USB serdes on GDM4 port */
++              if (!nbq)
++                      return HSGMII_LAN_7583_PCIE_SRCPORT;
++              if (nbq == 1)
++                      return HSGMII_LAN_7583_USB_SRCPORT;
++              break;
++      default:
++              break;
++      }
++
++      return -EINVAL;
++}
++
+ static const struct airoha_eth_soc_data en7581_soc_data = {
+       .version = 0x7581,
+       .xsi_rsts_names = en7581_xsi_rsts_names,
+@@ -3112,8 +3159,19 @@ static const struct airoha_eth_soc_data
+       },
+ };
++static const struct airoha_eth_soc_data an7583_soc_data = {
++      .version = 0x7583,
++      .xsi_rsts_names = an7583_xsi_rsts_names,
++      .num_xsi_rsts = ARRAY_SIZE(an7583_xsi_rsts_names),
++      .num_ppe = 1,
++      .ops = {
++              .get_src_port_id = airoha_an7583_get_src_port_id,
++      },
++};
++
+ static const struct of_device_id of_airoha_match[] = {
+       { .compatible = "airoha,en7581-eth", .data = &en7581_soc_data },
++      { .compatible = "airoha,an7583-eth", .data = &an7583_soc_data },
+       { /* sentinel */ }
+ };
+ MODULE_DEVICE_TABLE(of, of_airoha_match);
+--- a/drivers/net/ethernet/airoha/airoha_eth.h
++++ b/drivers/net/ethernet/airoha/airoha_eth.h
+@@ -74,6 +74,12 @@ enum {
+ };
+ enum {
++      HSGMII_LAN_7583_ETH_SRCPORT     = 0x16,
++      HSGMII_LAN_7583_PCIE_SRCPORT    = 0x18,
++      HSGMII_LAN_7583_USB_SRCPORT,
++};
++
++enum {
+       XSI_PCIE0_VIP_PORT_MASK = BIT(22),
+       XSI_PCIE1_VIP_PORT_MASK = BIT(23),
+       XSI_USB_VIP_PORT_MASK   = BIT(25),
+@@ -629,6 +635,11 @@ static inline bool airoha_is_7581(struct
+       return eth->soc->version == 0x7581;
+ }
++static inline bool airoha_is_7583(struct airoha_eth *eth)
++{
++      return eth->soc->version == 0x7583;
++}
++
+ bool airoha_is_valid_gdm_port(struct airoha_eth *eth,
+                             struct airoha_gdm_port *port);
+--- a/drivers/net/ethernet/airoha/airoha_ppe.c
++++ b/drivers/net/ethernet/airoha/airoha_ppe.c
+@@ -37,6 +37,9 @@ static int airoha_ppe_get_num_stats_entr
+       if (!IS_ENABLED(CONFIG_NET_AIROHA_FLOW_STATS))
+               return -EOPNOTSUPP;
++      if (airoha_is_7583(ppe->eth))
++              return -EOPNOTSUPP;
++
+       return PPE_STATS_NUM_ENTRIES;
+ }
index 7537f659f9d2c3259148917332e7e4d1c00b8e95..85af65e3b41061642e57190b549b4efcfc85b053 100644 (file)
@@ -13,11 +13,11 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
 
 --- a/drivers/net/ethernet/airoha/airoha_eth.c
 +++ b/drivers/net/ethernet/airoha/airoha_eth.c
-@@ -1401,6 +1401,10 @@ static int airoha_hw_init(struct platfor
+@@ -1388,6 +1388,10 @@ static int airoha_hw_init(struct platfor
        if (err)
                return err;
  
-+      err = reset_control_bulk_deassert(ARRAY_SIZE(eth->xsi_rsts), eth->xsi_rsts);
++      err = reset_control_bulk_deassert(eth->soc->num_xsi_rsts, eth->xsi_rsts);
 +      if (err)
 +              return err;
 +
index b620ec62b9b84c881e73b7417c40a18bbbda2f0c..cf6520dd53bcacdaef4e29f4418f56180a336f9b 100644 (file)
@@ -16,7 +16,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
 
 --- a/drivers/net/ethernet/airoha/airoha_eth.c
 +++ b/drivers/net/ethernet/airoha/airoha_eth.c
-@@ -605,8 +605,11 @@ static int airoha_qdma_get_gdm_port(stru
+@@ -593,8 +593,11 @@ static int airoha_qdma_get_gdm_port(stru
  
        sport = FIELD_GET(QDMA_ETH_RXMSG_SPORT_MASK, msg1);
        switch (sport) {
index 4cc1d6c6fcfeaa9350b3f3ee72a4020b9841852e..a52ee91ed9d6b89af667d43db064959cdaf2a59a 100644 (file)
@@ -15,7 +15,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
 
 --- a/drivers/net/ethernet/airoha/airoha_eth.c
 +++ b/drivers/net/ethernet/airoha/airoha_eth.c
-@@ -507,8 +507,8 @@ static int airoha_fe_init(struct airoha_
+@@ -514,8 +514,8 @@ static int airoha_fe_init(struct airoha_
                      FIELD_PREP(IP_ASSEMBLE_PORT_MASK, 0) |
                      FIELD_PREP(IP_ASSEMBLE_NBQ_MASK, 22));
  
@@ -36,7 +36,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
  #define GDM_DROP_CRC_ERR              BIT(23)
  #define GDM_IP4_CKSUM                 BIT(22)
  #define GDM_TCP_CKSUM                 BIT(21)
-@@ -349,13 +350,6 @@
+@@ -352,13 +353,6 @@
  #define MBI_RX_AGE_SEL_MASK           GENMASK(26, 25)
  #define MBI_TX_AGE_SEL_MASK           GENMASK(18, 17)
  
index 4af027568872718be0c8967e582f2ebabb54d8a1..7e3ee7a9e88f3a2d92b85889280d84a1ced66471 100644 (file)
@@ -15,7 +15,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
 
 --- a/drivers/net/ethernet/airoha/airoha_eth.c
 +++ b/drivers/net/ethernet/airoha/airoha_eth.c
-@@ -507,8 +507,10 @@ static int airoha_fe_init(struct airoha_
+@@ -514,8 +514,10 @@ static int airoha_fe_init(struct airoha_
                      FIELD_PREP(IP_ASSEMBLE_PORT_MASK, 0) |
                      FIELD_PREP(IP_ASSEMBLE_NBQ_MASK, 22));
  
@@ -28,7 +28,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
  
        airoha_fe_crsn_qsel_init(eth);
  
-@@ -1643,7 +1645,8 @@ static int airoha_dev_open(struct net_de
+@@ -1630,7 +1632,8 @@ static int airoha_dev_open(struct net_de
        if (err)
                return err;
  
index 3e9a92db6b5ad6474aff71e9498f626e1195731e..be23e27ce0ed3143bd707073df40d14e3b9d9392 100644 (file)
@@ -15,30 +15,19 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
 
 --- a/drivers/net/ethernet/airoha/airoha_eth.c
 +++ b/drivers/net/ethernet/airoha/airoha_eth.c
-@@ -2948,11 +2948,10 @@ static int airoha_probe(struct platform_
-               return err;
-       }
+@@ -3099,7 +3099,6 @@ static void airoha_remove(struct platfor
+ }
  
--      eth->xsi_rsts[0].id = "xsi-mac";
--      eth->xsi_rsts[1].id = "hsi0-mac";
--      eth->xsi_rsts[2].id = "hsi1-mac";
--      eth->xsi_rsts[3].id = "hsi-mac";
--      eth->xsi_rsts[4].id = "xfp-mac";
-+      eth->xsi_rsts[0].id = "hsi0-mac";
-+      eth->xsi_rsts[1].id = "hsi1-mac";
-+      eth->xsi_rsts[2].id = "hsi-mac";
-+      eth->xsi_rsts[3].id = "xfp-mac";
-       err = devm_reset_control_bulk_get_exclusive(eth->dev,
-                                                   ARRAY_SIZE(eth->xsi_rsts),
-                                                   eth->xsi_rsts);
---- a/drivers/net/ethernet/airoha/airoha_eth.h
-+++ b/drivers/net/ethernet/airoha/airoha_eth.h
-@@ -21,7 +21,7 @@
- #define AIROHA_MAX_NUM_IRQ_BANKS      4
- #define AIROHA_MAX_DSA_PORTS          7
- #define AIROHA_MAX_NUM_RSTS           3
--#define AIROHA_MAX_NUM_XSI_RSTS               5
-+#define AIROHA_MAX_NUM_XSI_RSTS               4
- #define AIROHA_MAX_MTU                        9216
- #define AIROHA_MAX_PACKET_SIZE                2048
- #define AIROHA_NUM_QOS_CHANNELS               4
+ static const char * const en7581_xsi_rsts_names[] = {
+-      "xsi-mac",
+       "hsi0-mac",
+       "hsi1-mac",
+       "hsi-mac",
+@@ -3131,7 +3130,6 @@ static int airoha_en7581_get_src_port_id
+ }
+ static const char * const an7583_xsi_rsts_names[] = {
+-      "xsi-mac",
+       "hsi0-mac",
+       "hsi1-mac",
+       "xfp-mac",
index 151decb8a8c8a4a4678adca9dec115901b89ad8d..7f5dcc7bd3f684bad0726805d64eee74e78edf64 100644 (file)
@@ -22,8 +22,8 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
 
 --- a/drivers/net/phy/phylink.c
 +++ b/drivers/net/phy/phylink.c
-@@ -1041,6 +1041,12 @@ static void phylink_pcs_link_up(struct p
-               pcs->ops->pcs_link_up(pcs, neg_mode, interface, speed, duplex);
+@@ -1088,6 +1088,12 @@ static unsigned int phylink_inband_caps(
+       return phylink_pcs_inband_caps(pcs, interface);
  }
  
 +static void phylink_pcs_link_down(struct phylink_pcs *pcs)
@@ -35,18 +35,18 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
  static void phylink_pcs_poll_stop(struct phylink *pl)
  {
        if (pl->cfg_link_an_mode == MLO_AN_INBAND)
-@@ -1454,6 +1460,8 @@ static void phylink_link_down(struct phy
+@@ -1642,6 +1648,8 @@ static void phylink_link_down(struct phy
  
        if (ndev)
                netif_carrier_off(ndev);
 +      phylink_pcs_link_down(pl->pcs);
 +
-       pl->mac_ops->mac_link_down(pl->config, pl->cur_link_an_mode,
+       pl->mac_ops->mac_link_down(pl->config, pl->act_link_an_mode,
                                   pl->cur_interface);
        phylink_info(pl, "Link is Down\n");
 --- a/include/linux/phylink.h
 +++ b/include/linux/phylink.h
-@@ -430,6 +430,7 @@ struct phylink_pcs {
+@@ -431,6 +431,7 @@ struct phylink_pcs {
   *               (where necessary).
   * @pcs_pre_init: configure PCS components necessary for MAC hardware
   *                initialization e.g. RX clock for stmmac.
@@ -54,7 +54,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
   */
  struct phylink_pcs_ops {
        int (*pcs_validate)(struct phylink_pcs *pcs, unsigned long *supported,
-@@ -450,6 +451,7 @@ struct phylink_pcs_ops {
+@@ -453,6 +454,7 @@ struct phylink_pcs_ops {
        void (*pcs_link_up)(struct phylink_pcs *pcs, unsigned int neg_mode,
                            phy_interface_t interface, int speed, int duplex);
        int (*pcs_pre_init)(struct phylink_pcs *pcs);
index 68671eb496cd7ce24b2cd0e6d6406b49eb08fbc3..fd01dcda99bd34a0da04d811e84e238a4933c84d 100644 (file)
@@ -35,7 +35,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
  static void airoha_set_macaddr(struct airoha_gdm_port *port, const u8 *addr)
  {
        struct airoha_eth *eth = port->qdma->eth;
-@@ -1640,6 +1646,17 @@ static int airoha_dev_open(struct net_de
+@@ -1627,6 +1633,17 @@ static int airoha_dev_open(struct net_de
        struct airoha_gdm_port *port = netdev_priv(dev);
        struct airoha_qdma *qdma = port->qdma;
  
@@ -53,7 +53,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
        netif_tx_start_all_queues(dev);
        err = airoha_set_vip_for_gdm_port(port, true);
        if (err)
-@@ -1693,6 +1710,11 @@ static int airoha_dev_stop(struct net_de
+@@ -1680,6 +1697,11 @@ static int airoha_dev_stop(struct net_de
                }
        }
  
@@ -65,8 +65,8 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
        return 0;
  }
  
-@@ -2781,6 +2803,20 @@ static const struct ethtool_ops airoha_e
-       .get_rmon_stats         = airoha_ethtool_get_rmon_stats,
+@@ -2828,6 +2850,20 @@ static const struct ethtool_ops airoha_e
+       .get_link               = ethtool_op_get_link,
  };
  
 +static struct phylink_pcs *airoha_phylink_mac_select_pcs(struct phylink_config *config,
@@ -86,7 +86,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
  static int airoha_metadata_dst_alloc(struct airoha_gdm_port *port)
  {
        int i;
-@@ -2825,6 +2861,99 @@ bool airoha_is_valid_gdm_port(struct air
+@@ -2872,6 +2908,99 @@ bool airoha_is_valid_gdm_port(struct air
        return false;
  }
  
@@ -186,7 +186,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
  static int airoha_alloc_gdm_port(struct airoha_eth *eth,
                                 struct device_node *np, int index)
  {
-@@ -2903,6 +3032,12 @@ static int airoha_alloc_gdm_port(struct
+@@ -2950,6 +3079,12 @@ static int airoha_alloc_gdm_port(struct
        if (err)
                return err;
  
@@ -199,7 +199,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
        err = register_netdev(dev);
        if (err)
                goto free_metadata_dst;
-@@ -3006,6 +3141,10 @@ error_hw_cleanup:
+@@ -3064,6 +3199,10 @@ error_hw_cleanup:
                if (port && port->dev->reg_state == NETREG_REGISTERED) {
                        unregister_netdev(port->dev);
                        airoha_metadata_dst_free(port);
@@ -210,7 +210,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
                }
        }
        free_netdev(eth->napi_dev);
-@@ -3033,6 +3172,10 @@ static void airoha_remove(struct platfor
+@@ -3091,6 +3230,10 @@ static void airoha_remove(struct platfor
                airoha_dev_stop(port->dev);
                unregister_netdev(port->dev);
                airoha_metadata_dst_free(port);
@@ -223,7 +223,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
  
 --- a/drivers/net/ethernet/airoha/airoha_eth.h
 +++ b/drivers/net/ethernet/airoha/airoha_eth.h
-@@ -528,6 +528,10 @@ struct airoha_gdm_port {
+@@ -531,6 +531,10 @@ struct airoha_gdm_port {
        struct net_device *dev;
        int id;
  
@@ -236,7 +236,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
        DECLARE_BITMAP(qos_sq_bmap, AIROHA_NUM_QOS_CHANNELS);
 --- a/drivers/net/ethernet/airoha/airoha_regs.h
 +++ b/drivers/net/ethernet/airoha/airoha_regs.h
-@@ -361,6 +361,18 @@
+@@ -364,6 +364,18 @@
  #define IP_FRAGMENT_PORT_MASK         GENMASK(8, 5)
  #define IP_FRAGMENT_NBQ_MASK          GENMASK(4, 0)
  
index 0fa14de3ee5e78ad5fc7d32a0d15c62e8f486d57..5270c26e99e8e2725948dd707bc40bba90e2f1c1 100644 (file)
@@ -14,7 +14,7 @@ Signed-off-by: Christian Marangi <ansuelsmth@gmail.com>
 
 --- a/drivers/net/ethernet/airoha/airoha_eth.c
 +++ b/drivers/net/ethernet/airoha/airoha_eth.c
-@@ -616,6 +616,9 @@ static int airoha_qdma_get_gdm_port(stru
+@@ -604,6 +604,9 @@ static int airoha_qdma_get_gdm_port(stru
        case 0x18:
                port = 3; /* GDM4 */
                break;
index 370e9a755012768c0de1dda6777ccfe97012ebcd..563ef641a5d3136628bc644af9451c082ff06416 100644 (file)
@@ -28,7 +28,7 @@ Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
  
  static void airoha_set_macaddr(struct airoha_gdm_port *port, const u8 *addr)
  {
-@@ -1649,6 +1651,7 @@ static int airoha_dev_open(struct net_de
+@@ -1636,6 +1638,7 @@ static int airoha_dev_open(struct net_de
        struct airoha_gdm_port *port = netdev_priv(dev);
        struct airoha_qdma *qdma = port->qdma;
  
@@ -36,7 +36,7 @@ Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
        if (airhoa_is_phy_external(port)) {
                err = phylink_of_phy_connect(port->phylink, dev->dev.of_node, 0);
                if (err) {
-@@ -1659,6 +1662,7 @@ static int airoha_dev_open(struct net_de
+@@ -1646,6 +1649,7 @@ static int airoha_dev_open(struct net_de
  
                phylink_start(port->phylink);
        }
@@ -44,7 +44,7 @@ Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
  
        netif_tx_start_all_queues(dev);
        err = airoha_set_vip_for_gdm_port(port, true);
-@@ -1713,10 +1717,12 @@ static int airoha_dev_stop(struct net_de
+@@ -1700,10 +1704,12 @@ static int airoha_dev_stop(struct net_de
                }
        }
  
@@ -57,15 +57,15 @@ Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
  
        return 0;
  }
-@@ -2806,6 +2812,7 @@ static const struct ethtool_ops airoha_e
-       .get_rmon_stats         = airoha_ethtool_get_rmon_stats,
+@@ -2853,6 +2859,7 @@ static const struct ethtool_ops airoha_e
+       .get_link               = ethtool_op_get_link,
  };
  
 +#if defined(CONFIG_PCS_AIROHA)
  static struct phylink_pcs *airoha_phylink_mac_select_pcs(struct phylink_config *config,
                                                         phy_interface_t interface)
  {
-@@ -2819,6 +2826,7 @@ static void airoha_mac_config(struct phy
+@@ -2866,6 +2873,7 @@ static void airoha_mac_config(struct phy
                              const struct phylink_link_state *state)
  {
  }
@@ -73,7 +73,7 @@ Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
  
  static int airoha_metadata_dst_alloc(struct airoha_gdm_port *port)
  {
-@@ -2864,6 +2872,7 @@ bool airoha_is_valid_gdm_port(struct air
+@@ -2911,6 +2919,7 @@ bool airoha_is_valid_gdm_port(struct air
        return false;
  }
  
@@ -81,7 +81,7 @@ Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
  static void airoha_mac_link_up(struct phylink_config *config, struct phy_device *phy,
                               unsigned int mode, phy_interface_t interface,
                               int speed, int duplex, bool tx_pause, bool rx_pause)
-@@ -2956,6 +2965,7 @@ static int airoha_setup_phylink(struct n
+@@ -3003,6 +3012,7 @@ static int airoha_setup_phylink(struct n
  
        return 0;
  }
@@ -89,7 +89,7 @@ Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
  
  static int airoha_alloc_gdm_port(struct airoha_eth *eth,
                                 struct device_node *np, int index)
-@@ -3035,11 +3045,13 @@ static int airoha_alloc_gdm_port(struct
+@@ -3082,11 +3092,13 @@ static int airoha_alloc_gdm_port(struct
        if (err)
                return err;
  
@@ -103,7 +103,7 @@ Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
  
        err = register_netdev(dev);
        if (err)
-@@ -3144,10 +3156,12 @@ error_hw_cleanup:
+@@ -3202,10 +3214,12 @@ error_hw_cleanup:
                if (port && port->dev->reg_state == NETREG_REGISTERED) {
                        unregister_netdev(port->dev);
                        airoha_metadata_dst_free(port);
@@ -116,7 +116,7 @@ Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
                }
        }
        free_netdev(eth->napi_dev);
-@@ -3175,10 +3189,12 @@ static void airoha_remove(struct platfor
+@@ -3233,10 +3247,12 @@ static void airoha_remove(struct platfor
                airoha_dev_stop(port->dev);
                unregister_netdev(port->dev);
                airoha_metadata_dst_free(port);
@@ -131,7 +131,7 @@ Signed-off-by: Mikhail Kshevetskiy <mikhail.kshevetskiy@iopsys.eu>
  
 --- a/drivers/net/ethernet/airoha/airoha_eth.h
 +++ b/drivers/net/ethernet/airoha/airoha_eth.h
-@@ -528,9 +528,11 @@ struct airoha_gdm_port {
+@@ -531,9 +531,11 @@ struct airoha_gdm_port {
        struct net_device *dev;
        int id;