* [PATCH net] net: airoha: keep PPE offload when NPU refuses flow stats
@ 2026-10-08 9:48 SAYANTAN NANDY
2026-10-08 9:55 ` netdev-bot+sinfo
` (2 more replies)
0 siblings, 3 replies; 5+ messages in thread
From: SAYANTAN NANDY @ 2026-10-08 9:48 UTC (permalink / raw)
To: netdev
Cc: lorenzo, andrew+netdev, linux-arm-kernel, linux-mediatek,
bread.hsu, sayantan.nandy, SAYANTAN NANDY
From: Chad Monroe <chad@monroe.io>
With flow stats enabled, PPE offload setup requests flow statistics
from the NPU. If the running NPU firmware does not support flow
counters, the request fails and the current setup path aborts PPE
offload.
Treat flow statistics as an optional capability so that a failure to
set up the counters does not prevent normal PPE offload. Record
whether flow statistics are available and continue PPE initialization
when the NPU refuses the flow-statistics request.
Also treat a zero NPU statistics address returned by the firmware as a
refusal. A zero address does not provide a usable counter region and
must not be passed to the address mapping path.
When flow statistics are unavailable, PPE continues to operate
without NPU flow counters while retaining normal offload functionality.
This combines the original SmartRG/Airoha fixes for:
- keeping PPE offload active when the NPU refuses flow statistics
- treating a zero NPU statistics address as a flow-statistics refusal
Based on the original SmartRG/Airoha work by Chad Monroe:
5ce96ab ("SDG-9458: keep PPE offload when NPU refuses flow stats")
0ad8528 ("SDG-9458: airoha: treat a zero NPU stats address as a refusal")
Fixes: b81e0f2b58be ("net: airoha: Add FLOW_CLS_STATS callback support")
Signed-off-by: Chad Monroe <chad@monroe.io>
Signed-off-by: SAYANTAN NANDY <sayantann11@gmail.com>
---
drivers/net/ethernet/airoha/airoha_eth.h | 1 +
drivers/net/ethernet/airoha/airoha_npu.c | 8 ++++++++
drivers/net/ethernet/airoha/airoha_ppe.c | 20 +++++++++++++-------
drivers/net/ethernet/airoha/airoha_regs.h | 2 ++
4 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
index 8277c1c87bb3..bd5a94fce843 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.h
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
@@ -617,6 +617,7 @@ struct airoha_ppe {
void *foe;
dma_addr_t foe_dma;
+ bool flow_stats;
struct rhashtable l2_flows;
diff --git a/drivers/net/ethernet/airoha/airoha_npu.c b/drivers/net/ethernet/airoha/airoha_npu.c
index 4d3195eb00f7..b32a01dbe06b 100644
--- a/drivers/net/ethernet/airoha/airoha_npu.c
+++ b/drivers/net/ethernet/airoha/airoha_npu.c
@@ -450,6 +450,14 @@ static int airoha_npu_ppe_stats_setup(struct airoha_npu *npu,
if (err)
goto out;
+ /* The firmware reports success with a zero address when its SRAM
+ * pool has no room left for the counters.
+ */
+ if (!ppe_data->stats_info.npu_stats_addr) {
+ err = -ENOSPC;
+ goto out;
+ }
+
npu->stats = devm_ioremap(npu->dev,
ppe_data->stats_info.npu_stats_addr,
size);
diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
index 92611802801e..fbc200614de3 100644
--- a/drivers/net/ethernet/airoha/airoha_ppe.c
+++ b/drivers/net/ethernet/airoha/airoha_ppe.c
@@ -37,10 +37,7 @@ static const struct rhashtable_params airoha_l2_flow_table_params = {
static int airoha_ppe_get_num_stats_entries(struct airoha_ppe *ppe)
{
- if (!IS_ENABLED(CONFIG_NET_AIROHA_FLOW_STATS))
- return -EOPNOTSUPP;
-
- if (airoha_is_7583(ppe->eth))
+ if (!ppe->flow_stats)
return -EOPNOTSUPP;
return PPE_STATS_NUM_ENTRIES;
@@ -144,6 +141,10 @@ static void airoha_ppe_hw_init(struct airoha_ppe *ppe)
sram_ppe_num_data_entries =
PPE_RAM_NUM_ENTRIES_SHIFT(sram_ppe_num_data_entries);
+ if (ppe->flow_stats)
+ airoha_fe_rmw(eth, PSE_FC_CFG, PSE_PORT6_SHARE_DIS,
+ FIELD_PREP(PSE_PORT6_SHARE_DIS, 0));
+
for (i = 0; i < eth->soc->num_ppe; i++) {
airoha_fe_wr(eth, REG_PPE_TB_BASE(i),
ppe->foe_dma + sram_tb_size);
@@ -1456,10 +1457,13 @@ static int airoha_ppe_offload_setup(struct airoha_eth *eth)
if (ppe_num_stats_entries > 0) {
err = npu->ops.ppe_init_stats(npu, ppe->foe_stats_dma,
ppe_num_stats_entries);
- if (err)
- goto error_npu_put;
+ if (err) {
+ dev_warn(eth->dev,
+ "NPU firmware refused flow stats setup (%d), offload runs without flow counters\n",
+ err);
+ ppe->flow_stats = false;
+ }
}
-
airoha_ppe_hw_init(ppe);
airoha_ppe_foe_flow_stats_reset(ppe, npu);
@@ -1608,6 +1612,8 @@ int airoha_ppe_init(struct airoha_eth *eth)
ppe->dev.priv = ppe;
ppe->eth = eth;
eth->ppe = ppe;
+ ppe->flow_stats = IS_ENABLED(CONFIG_NET_AIROHA_FLOW_STATS) &&
+ !airoha_is_7583(eth);
ppe_num_entries = airoha_ppe_get_total_num_entries(ppe);
foe_size = ppe_num_entries * sizeof(struct airoha_foe_entry);
diff --git a/drivers/net/ethernet/airoha/airoha_regs.h b/drivers/net/ethernet/airoha/airoha_regs.h
index 442b48c9b991..aee06c058586 100644
--- a/drivers/net/ethernet/airoha/airoha_regs.h
+++ b/drivers/net/ethernet/airoha/airoha_regs.h
@@ -72,6 +72,8 @@
#define PSE_CFG_OQ_RSV_MASK GENMASK(13, 0)
#define PSE_FQ_CFG 0x008c
+#define PSE_FC_CFG 0x0098
+#define PSE_PORT6_SHARE_DIS BIT(22)
#define PSE_FQ_LIMIT_MASK GENMASK(14, 0)
#define REG_FE_PSE_BUF_SET 0x0090
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH net] net: airoha: keep PPE offload when NPU refuses flow stats
2026-10-08 9:48 [PATCH net] net: airoha: keep PPE offload when NPU refuses flow stats SAYANTAN NANDY
@ 2026-10-08 9:55 ` netdev-bot+sinfo
2026-10-08 10:44 ` Lorenzo Bianconi
2026-10-09 5:03 ` [PATCH net v2] " SAYANTAN NANDY
2 siblings, 0 replies; 5+ messages in thread
From: netdev-bot+sinfo @ 2026-10-08 9:55 UTC (permalink / raw)
To: SAYANTAN NANDY
Cc: netdev, lorenzo, andrew+netdev, linux-arm-kernel, linux-mediatek,
bread.hsu, sayantan.nandy
Hi!
This is an automated message. This series looks like a fix, but its
commit messages seem to be missing some information:
- What hardware the change was tested on. For driver fixes please
mention the device (and if relevant firmware version) used for
testing, or say that the change was not tested on real hardware.
Please do not repost the series just to address the above. Instead,
reply to this email with the missing information, so that reviewers
can take it into account. If the series needs another revision for
other reasons, please include the information in the commit messages
then.
The evaluation is done by an LLM so it may be wrong, if you think
that is the case please reply and explain.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH net] net: airoha: keep PPE offload when NPU refuses flow stats
2026-10-08 9:48 [PATCH net] net: airoha: keep PPE offload when NPU refuses flow stats SAYANTAN NANDY
2026-10-08 9:55 ` netdev-bot+sinfo
@ 2026-10-08 10:44 ` Lorenzo Bianconi
2026-10-09 5:03 ` [PATCH net v2] " SAYANTAN NANDY
2 siblings, 0 replies; 5+ messages in thread
From: Lorenzo Bianconi @ 2026-10-08 10:44 UTC (permalink / raw)
To: SAYANTAN NANDY
Cc: netdev, andrew+netdev, linux-arm-kernel, linux-mediatek,
bread.hsu, sayantan.nandy
[-- Attachment #1: Type: text/plain, Size: 5874 bytes --]
On Oct 08, SAYANTAN NANDY wrote:
> From: Chad Monroe <chad@monroe.io>
>
> With flow stats enabled, PPE offload setup requests flow statistics
> from the NPU. If the running NPU firmware does not support flow
> counters, the request fails and the current setup path aborts PPE
> offload.
>
> Treat flow statistics as an optional capability so that a failure to
> set up the counters does not prevent normal PPE offload. Record
> whether flow statistics are available and continue PPE initialization
> when the NPU refuses the flow-statistics request.
>
> Also treat a zero NPU statistics address returned by the firmware as a
> refusal. A zero address does not provide a usable counter region and
> must not be passed to the address mapping path.
>
> When flow statistics are unavailable, PPE continues to operate
> without NPU flow counters while retaining normal offload functionality.
>
> This combines the original SmartRG/Airoha fixes for:
> - keeping PPE offload active when the NPU refuses flow statistics
> - treating a zero NPU statistics address as a flow-statistics refusal
>
> Based on the original SmartRG/Airoha work by Chad Monroe:
> 5ce96ab ("SDG-9458: keep PPE offload when NPU refuses flow stats")
> 0ad8528 ("SDG-9458: airoha: treat a zero NPU stats address as a refusal")
> Fixes: b81e0f2b58be ("net: airoha: Add FLOW_CLS_STATS callback support")
> Signed-off-by: Chad Monroe <chad@monroe.io>
> Signed-off-by: SAYANTAN NANDY <sayantann11@gmail.com>
> ---
> drivers/net/ethernet/airoha/airoha_eth.h | 1 +
> drivers/net/ethernet/airoha/airoha_npu.c | 8 ++++++++
> drivers/net/ethernet/airoha/airoha_ppe.c | 20 +++++++++++++-------
> drivers/net/ethernet/airoha/airoha_regs.h | 2 ++
> 4 files changed, 24 insertions(+), 7 deletions(-)
>
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
> index 8277c1c87bb3..bd5a94fce843 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.h
> +++ b/drivers/net/ethernet/airoha/airoha_eth.h
> @@ -617,6 +617,7 @@ struct airoha_ppe {
>
> void *foe;
> dma_addr_t foe_dma;
> + bool flow_stats;
I agree naming is hard, but I guess we could a more meaningful name, like flow_stats_cap. What do you think?
>
> struct rhashtable l2_flows;
>
> diff --git a/drivers/net/ethernet/airoha/airoha_npu.c b/drivers/net/ethernet/airoha/airoha_npu.c
> index 4d3195eb00f7..b32a01dbe06b 100644
> --- a/drivers/net/ethernet/airoha/airoha_npu.c
> +++ b/drivers/net/ethernet/airoha/airoha_npu.c
> @@ -450,6 +450,14 @@ static int airoha_npu_ppe_stats_setup(struct airoha_npu *npu,
> if (err)
> goto out;
>
> + /* The firmware reports success with a zero address when its SRAM
> + * pool has no room left for the counters.
> + */
> + if (!ppe_data->stats_info.npu_stats_addr) {
can it really happen? I guess dmam_alloc_coherent() in airoha_ppe_init()
should fail in this case, right?
> + err = -ENOSPC;
> + goto out;
> + }
> +
> npu->stats = devm_ioremap(npu->dev,
> ppe_data->stats_info.npu_stats_addr,
> size);
> diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
> index 92611802801e..fbc200614de3 100644
> --- a/drivers/net/ethernet/airoha/airoha_ppe.c
> +++ b/drivers/net/ethernet/airoha/airoha_ppe.c
> @@ -37,10 +37,7 @@ static const struct rhashtable_params airoha_l2_flow_table_params = {
>
> static int airoha_ppe_get_num_stats_entries(struct airoha_ppe *ppe)
> {
> - if (!IS_ENABLED(CONFIG_NET_AIROHA_FLOW_STATS))
> - return -EOPNOTSUPP;
> -
> - if (airoha_is_7583(ppe->eth))
> + if (!ppe->flow_stats)
> return -EOPNOTSUPP;
>
> return PPE_STATS_NUM_ENTRIES;
> @@ -144,6 +141,10 @@ static void airoha_ppe_hw_init(struct airoha_ppe *ppe)
> sram_ppe_num_data_entries =
> PPE_RAM_NUM_ENTRIES_SHIFT(sram_ppe_num_data_entries);
>
> + if (ppe->flow_stats)
> + airoha_fe_rmw(eth, PSE_FC_CFG, PSE_PORT6_SHARE_DIS,
> + FIELD_PREP(PSE_PORT6_SHARE_DIS, 0));
can you please provide more details about it, why is it needed?
Moreover, I guess you could use airoha_fe_clear() here.
> +
> for (i = 0; i < eth->soc->num_ppe; i++) {
> airoha_fe_wr(eth, REG_PPE_TB_BASE(i),
> ppe->foe_dma + sram_tb_size);
> @@ -1456,10 +1457,13 @@ static int airoha_ppe_offload_setup(struct airoha_eth *eth)
> if (ppe_num_stats_entries > 0) {
> err = npu->ops.ppe_init_stats(npu, ppe->foe_stats_dma,
> ppe_num_stats_entries);
> - if (err)
> - goto error_npu_put;
> + if (err) {
> + dev_warn(eth->dev,
> + "NPU firmware refused flow stats setup (%d), offload runs without flow counters\n",
> + err);
can you please try to respect the 79 column width? (I still have old habits :))
> + ppe->flow_stats = false;
> + }
> }
> -
> airoha_ppe_hw_init(ppe);
> airoha_ppe_foe_flow_stats_reset(ppe, npu);
>
> @@ -1608,6 +1612,8 @@ int airoha_ppe_init(struct airoha_eth *eth)
> ppe->dev.priv = ppe;
> ppe->eth = eth;
> eth->ppe = ppe;
> + ppe->flow_stats = IS_ENABLED(CONFIG_NET_AIROHA_FLOW_STATS) &&
> + !airoha_is_7583(eth);
>
> ppe_num_entries = airoha_ppe_get_total_num_entries(ppe);
> foe_size = ppe_num_entries * sizeof(struct airoha_foe_entry);
> diff --git a/drivers/net/ethernet/airoha/airoha_regs.h b/drivers/net/ethernet/airoha/airoha_regs.h
> index 442b48c9b991..aee06c058586 100644
> --- a/drivers/net/ethernet/airoha/airoha_regs.h
> +++ b/drivers/net/ethernet/airoha/airoha_regs.h
> @@ -72,6 +72,8 @@
> #define PSE_CFG_OQ_RSV_MASK GENMASK(13, 0)
>
> #define PSE_FQ_CFG 0x008c
> +#define PSE_FC_CFG 0x0098
> +#define PSE_PORT6_SHARE_DIS BIT(22)
> #define PSE_FQ_LIMIT_MASK GENMASK(14, 0)
>
> #define REG_FE_PSE_BUF_SET 0x0090
> --
> 2.43.0
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread* [PATCH net v2] net: airoha: keep PPE offload when NPU refuses flow stats
2026-10-08 9:48 [PATCH net] net: airoha: keep PPE offload when NPU refuses flow stats SAYANTAN NANDY
2026-10-08 9:55 ` netdev-bot+sinfo
2026-10-08 10:44 ` Lorenzo Bianconi
@ 2026-10-09 5:03 ` SAYANTAN NANDY
2026-10-09 7:44 ` Lorenzo Bianconi
2 siblings, 1 reply; 5+ messages in thread
From: SAYANTAN NANDY @ 2026-10-09 5:03 UTC (permalink / raw)
To: netdev
Cc: lorenzo, andrew+netdev, linux-arm-kernel, linux-mediatek,
bread.hsu, sayantan.nandy, SAYANTAN NANDY
From: Chad Monroe <chad@monroe.io>
With flow stats enabled, PPE offload setup requests flow statistics
from the NPU. If the running NPU firmware does not support flow
counters, the request fails and the current setup path aborts PPE
offload.
Treat flow statistics as an optional capability so that a failure to
set up the counters does not prevent normal PPE offload. Record
whether flow statistics are available and continue PPE initialization
when the NPU refuses the flow-statistics request.
Also treat a zero NPU statistics address returned by the firmware as a
refusal. The host-side DMA buffer (foe_stats_dma) is allocated by
dmam_alloc_coherent() in airoha_ppe_init() from system memory. The NPU
statistics address (npu_stats_addr) is a separate allocation from the
NPU firmware's internal SRAM pool. When that pool is exhausted, the
firmware replies with success and npu_stats_addr = 0. A zero address
does not provide a usable counter region and must not be passed to
devm_ioremap().
When flow stats are available, clear PSE_PORT6_SHARE_DIS so that PSE
port 6 (CDM3 path to the NPU) participates in shared-buffer flow
control, which the counter traffic path needs.
When flow statistics are unavailable, PPE continues to operate without
NPU flow counters while retaining normal offload functionality.
This combines the original SmartRG/Airoha fixes for:
- keeping PPE offload active when the NPU refuses flow statistics
- treating a zero NPU statistics address as a flow-statistics refusal
Based on the original SmartRG/Airoha work by Chad Monroe:
5ce96ab ("SDG-9458: keep PPE offload when NPU refuses flow stats")
0ad8528 ("SDG-9458: airoha: treat a zero NPU stats address as a refusal")
Fixes: b81e0f2b58be ("net: airoha: Add FLOW_CLS_STATS callback support")
Tested-on: AN7581 with MT7992
Signed-off-by: Chad Monroe <chad@monroe.io>
Signed-off-by: SAYANTAN NANDY <sayantann11@gmail.com>
---
Changes since v1:
- Rename flow_stats to flow_stats_cap (Lorenzo).
- Explain that npu_stats_addr is an NPU firmware SRAM allocation,
distinct from the host-side foe_stats_dma buffer (Lorenzo).
- Explain why PSE_PORT6_SHARE_DIS is cleared for counter traffic
(Lorenzo).
- Use airoha_fe_clear() and shorten the warning message (Lorenzo).
- Add hardware testing information requested by netdev-bot.
drivers/net/ethernet/airoha/airoha_eth.h | 1 +
drivers/net/ethernet/airoha/airoha_npu.c | 8 ++++++++
drivers/net/ethernet/airoha/airoha_ppe.c | 17 +++++++++++------
drivers/net/ethernet/airoha/airoha_regs.h | 2 ++
4 files changed, 22 insertions(+), 6 deletions(-)
diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
index 8277c1c87bb3..da4a3ba69e3c 100644
--- a/drivers/net/ethernet/airoha/airoha_eth.h
+++ b/drivers/net/ethernet/airoha/airoha_eth.h
@@ -617,6 +617,7 @@ struct airoha_ppe {
void *foe;
dma_addr_t foe_dma;
+ bool flow_stats_cap;
struct rhashtable l2_flows;
diff --git a/drivers/net/ethernet/airoha/airoha_npu.c b/drivers/net/ethernet/airoha/airoha_npu.c
index 4d3195eb00f7..b32a01dbe06b 100644
--- a/drivers/net/ethernet/airoha/airoha_npu.c
+++ b/drivers/net/ethernet/airoha/airoha_npu.c
@@ -450,6 +450,14 @@ static int airoha_npu_ppe_stats_setup(struct airoha_npu *npu,
if (err)
goto out;
+ /* The firmware reports success with a zero address when its SRAM
+ * pool has no room left for the counters.
+ */
+ if (!ppe_data->stats_info.npu_stats_addr) {
+ err = -ENOSPC;
+ goto out;
+ }
+
npu->stats = devm_ioremap(npu->dev,
ppe_data->stats_info.npu_stats_addr,
size);
diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
index 92611802801e..0957f331478a 100644
--- a/drivers/net/ethernet/airoha/airoha_ppe.c
+++ b/drivers/net/ethernet/airoha/airoha_ppe.c
@@ -37,10 +37,7 @@ static const struct rhashtable_params airoha_l2_flow_table_params = {
static int airoha_ppe_get_num_stats_entries(struct airoha_ppe *ppe)
{
- if (!IS_ENABLED(CONFIG_NET_AIROHA_FLOW_STATS))
- return -EOPNOTSUPP;
-
- if (airoha_is_7583(ppe->eth))
+ if (!ppe->flow_stats_cap)
return -EOPNOTSUPP;
return PPE_STATS_NUM_ENTRIES;
@@ -144,6 +141,9 @@ static void airoha_ppe_hw_init(struct airoha_ppe *ppe)
sram_ppe_num_data_entries =
PPE_RAM_NUM_ENTRIES_SHIFT(sram_ppe_num_data_entries);
+ if (ppe->flow_stats_cap)
+ airoha_fe_clear(eth, PSE_FC_CFG, PSE_PORT6_SHARE_DIS);
+
for (i = 0; i < eth->soc->num_ppe; i++) {
airoha_fe_wr(eth, REG_PPE_TB_BASE(i),
ppe->foe_dma + sram_tb_size);
@@ -1456,8 +1456,11 @@ static int airoha_ppe_offload_setup(struct airoha_eth *eth)
if (ppe_num_stats_entries > 0) {
err = npu->ops.ppe_init_stats(npu, ppe->foe_stats_dma,
ppe_num_stats_entries);
- if (err)
- goto error_npu_put;
+ if (err) {
+ dev_warn(eth->dev, "NPU refused flow stats (%d)\n",
+ err);
+ ppe->flow_stats_cap = false;
+ }
}
airoha_ppe_hw_init(ppe);
@@ -1608,6 +1611,8 @@ int airoha_ppe_init(struct airoha_eth *eth)
ppe->dev.priv = ppe;
ppe->eth = eth;
eth->ppe = ppe;
+ ppe->flow_stats_cap = IS_ENABLED(CONFIG_NET_AIROHA_FLOW_STATS) &&
+ !airoha_is_7583(eth);
ppe_num_entries = airoha_ppe_get_total_num_entries(ppe);
foe_size = ppe_num_entries * sizeof(struct airoha_foe_entry);
diff --git a/drivers/net/ethernet/airoha/airoha_regs.h b/drivers/net/ethernet/airoha/airoha_regs.h
index 442b48c9b991..aee06c058586 100644
--- a/drivers/net/ethernet/airoha/airoha_regs.h
+++ b/drivers/net/ethernet/airoha/airoha_regs.h
@@ -72,6 +72,8 @@
#define PSE_CFG_OQ_RSV_MASK GENMASK(13, 0)
#define PSE_FQ_CFG 0x008c
+#define PSE_FC_CFG 0x0098
+#define PSE_PORT6_SHARE_DIS BIT(22)
#define PSE_FQ_LIMIT_MASK GENMASK(14, 0)
#define REG_FE_PSE_BUF_SET 0x0090
--
2.43.0
^ permalink raw reply related [flat|nested] 5+ messages in thread* Re: [PATCH net v2] net: airoha: keep PPE offload when NPU refuses flow stats
2026-10-09 5:03 ` [PATCH net v2] " SAYANTAN NANDY
@ 2026-10-09 7:44 ` Lorenzo Bianconi
0 siblings, 0 replies; 5+ messages in thread
From: Lorenzo Bianconi @ 2026-10-09 7:44 UTC (permalink / raw)
To: SAYANTAN NANDY
Cc: netdev, andrew+netdev, linux-arm-kernel, linux-mediatek,
bread.hsu, sayantan.nandy
[-- Attachment #1: Type: text/plain, Size: 6633 bytes --]
> From: Chad Monroe <chad@monroe.io>
>
> With flow stats enabled, PPE offload setup requests flow statistics
> from the NPU. If the running NPU firmware does not support flow
> counters, the request fails and the current setup path aborts PPE
> offload.
>
> Treat flow statistics as an optional capability so that a failure to
> set up the counters does not prevent normal PPE offload. Record
> whether flow statistics are available and continue PPE initialization
> when the NPU refuses the flow-statistics request.
>
> Also treat a zero NPU statistics address returned by the firmware as a
> refusal. The host-side DMA buffer (foe_stats_dma) is allocated by
> dmam_alloc_coherent() in airoha_ppe_init() from system memory. The NPU
> statistics address (npu_stats_addr) is a separate allocation from the
> NPU firmware's internal SRAM pool. When that pool is exhausted, the
> firmware replies with success and npu_stats_addr = 0. A zero address
> does not provide a usable counter region and must not be passed to
> devm_ioremap().
>
> When flow stats are available, clear PSE_PORT6_SHARE_DIS so that PSE
> port 6 (CDM3 path to the NPU) participates in shared-buffer flow
> control, which the counter traffic path needs.
>
> When flow statistics are unavailable, PPE continues to operate without
> NPU flow counters while retaining normal offload functionality.
>
> This combines the original SmartRG/Airoha fixes for:
> - keeping PPE offload active when the NPU refuses flow statistics
> - treating a zero NPU statistics address as a flow-statistics refusal
>
> Based on the original SmartRG/Airoha work by Chad Monroe:
> 5ce96ab ("SDG-9458: keep PPE offload when NPU refuses flow stats")
> 0ad8528 ("SDG-9458: airoha: treat a zero NPU stats address as a refusal")
> Fixes: b81e0f2b58be ("net: airoha: Add FLOW_CLS_STATS callback support")
> Tested-on: AN7581 with MT7992
> Signed-off-by: Chad Monroe <chad@monroe.io>
> Signed-off-by: SAYANTAN NANDY <sayantann11@gmail.com>
> ---
>
> Changes since v1:
> - Rename flow_stats to flow_stats_cap (Lorenzo).
> - Explain that npu_stats_addr is an NPU firmware SRAM allocation,
> distinct from the host-side foe_stats_dma buffer (Lorenzo).
> - Explain why PSE_PORT6_SHARE_DIS is cleared for counter traffic
> (Lorenzo).
> - Use airoha_fe_clear() and shorten the warning message (Lorenzo).
> - Add hardware testing information requested by netdev-bot.
>
> drivers/net/ethernet/airoha/airoha_eth.h | 1 +
> drivers/net/ethernet/airoha/airoha_npu.c | 8 ++++++++
> drivers/net/ethernet/airoha/airoha_ppe.c | 17 +++++++++++------
> drivers/net/ethernet/airoha/airoha_regs.h | 2 ++
> 4 files changed, 22 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/net/ethernet/airoha/airoha_eth.h b/drivers/net/ethernet/airoha/airoha_eth.h
> index 8277c1c87bb3..da4a3ba69e3c 100644
> --- a/drivers/net/ethernet/airoha/airoha_eth.h
> +++ b/drivers/net/ethernet/airoha/airoha_eth.h
> @@ -617,6 +617,7 @@ struct airoha_ppe {
>
> void *foe;
> dma_addr_t foe_dma;
> + bool flow_stats_cap;
>
> struct rhashtable l2_flows;
>
> diff --git a/drivers/net/ethernet/airoha/airoha_npu.c b/drivers/net/ethernet/airoha/airoha_npu.c
> index 4d3195eb00f7..b32a01dbe06b 100644
> --- a/drivers/net/ethernet/airoha/airoha_npu.c
> +++ b/drivers/net/ethernet/airoha/airoha_npu.c
> @@ -450,6 +450,14 @@ static int airoha_npu_ppe_stats_setup(struct airoha_npu *npu,
> if (err)
> goto out;
>
> + /* The firmware reports success with a zero address when its SRAM
> + * pool has no room left for the counters.
> + */
> + if (!ppe_data->stats_info.npu_stats_addr) {
> + err = -ENOSPC;
> + goto out;
> + }
> +
> npu->stats = devm_ioremap(npu->dev,
> ppe_data->stats_info.npu_stats_addr,
> size);
> diff --git a/drivers/net/ethernet/airoha/airoha_ppe.c b/drivers/net/ethernet/airoha/airoha_ppe.c
> index 92611802801e..0957f331478a 100644
> --- a/drivers/net/ethernet/airoha/airoha_ppe.c
> +++ b/drivers/net/ethernet/airoha/airoha_ppe.c
> @@ -37,10 +37,7 @@ static const struct rhashtable_params airoha_l2_flow_table_params = {
>
> static int airoha_ppe_get_num_stats_entries(struct airoha_ppe *ppe)
> {
> - if (!IS_ENABLED(CONFIG_NET_AIROHA_FLOW_STATS))
> - return -EOPNOTSUPP;
> -
> - if (airoha_is_7583(ppe->eth))
> + if (!ppe->flow_stats_cap)
> return -EOPNOTSUPP;
Looking again at the code flow_stats_cap is only used here. Why do we need it
in the first place? I guess you it is enough to just not return an error in
airoha_ppe_offload_setup() and log the error instead (as you did).
>
> return PPE_STATS_NUM_ENTRIES;
> @@ -144,6 +141,9 @@ static void airoha_ppe_hw_init(struct airoha_ppe *ppe)
> sram_ppe_num_data_entries =
> PPE_RAM_NUM_ENTRIES_SHIFT(sram_ppe_num_data_entries);
>
> + if (ppe->flow_stats_cap)
> + airoha_fe_clear(eth, PSE_FC_CFG, PSE_PORT6_SHARE_DIS);
can you please explain what this configuration is doing? This register is not
documented.
> +
> for (i = 0; i < eth->soc->num_ppe; i++) {
> airoha_fe_wr(eth, REG_PPE_TB_BASE(i),
> ppe->foe_dma + sram_tb_size);
> @@ -1456,8 +1456,11 @@ static int airoha_ppe_offload_setup(struct airoha_eth *eth)
> if (ppe_num_stats_entries > 0) {
> err = npu->ops.ppe_init_stats(npu, ppe->foe_stats_dma,
> ppe_num_stats_entries);
> - if (err)
> - goto error_npu_put;
> + if (err) {
> + dev_warn(eth->dev, "NPU refused flow stats (%d)\n",
> + err);
> + ppe->flow_stats_cap = false;
please see above.
> + }
> }
>
> airoha_ppe_hw_init(ppe);
> @@ -1608,6 +1611,8 @@ int airoha_ppe_init(struct airoha_eth *eth)
> ppe->dev.priv = ppe;
> ppe->eth = eth;
> eth->ppe = ppe;
> + ppe->flow_stats_cap = IS_ENABLED(CONFIG_NET_AIROHA_FLOW_STATS) &&
> + !airoha_is_7583(eth);
please see above.
Regards,
Lorenzo
>
> ppe_num_entries = airoha_ppe_get_total_num_entries(ppe);
> foe_size = ppe_num_entries * sizeof(struct airoha_foe_entry);
> diff --git a/drivers/net/ethernet/airoha/airoha_regs.h b/drivers/net/ethernet/airoha/airoha_regs.h
> index 442b48c9b991..aee06c058586 100644
> --- a/drivers/net/ethernet/airoha/airoha_regs.h
> +++ b/drivers/net/ethernet/airoha/airoha_regs.h
> @@ -72,6 +72,8 @@
> #define PSE_CFG_OQ_RSV_MASK GENMASK(13, 0)
>
> #define PSE_FQ_CFG 0x008c
> +#define PSE_FC_CFG 0x0098
> +#define PSE_PORT6_SHARE_DIS BIT(22)
> #define PSE_FQ_LIMIT_MASK GENMASK(14, 0)
>
> #define REG_FE_PSE_BUF_SET 0x0090
> --
> 2.43.0
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2026-10-09 7:44 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-08 9:48 [PATCH net] net: airoha: keep PPE offload when NPU refuses flow stats SAYANTAN NANDY
2026-10-08 9:55 ` netdev-bot+sinfo
2026-10-08 10:44 ` Lorenzo Bianconi
2026-10-09 5:03 ` [PATCH net v2] " SAYANTAN NANDY
2026-10-09 7:44 ` Lorenzo Bianconi
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox