[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20251024-am65-cpsw-rx-class-v5-7-c7c2950a2d25@kernel.org>
Date: Fri, 24 Oct 2025 23:46:06 +0300
From: Roger Quadros <rogerq@...nel.org>
To: Siddharth Vadapalli <s-vadapalli@...com>,
Andrew Lunn <andrew+netdev@...n.ch>,
"David S. Miller" <davem@...emloft.net>, Eric Dumazet <edumazet@...gle.com>,
Jakub Kicinski <kuba@...nel.org>, Paolo Abeni <pabeni@...hat.com>,
Russell King <linux@...linux.org.uk>, danishanwar@...com
Cc: srk@...com, linux-omap@...r.kernel.org, netdev@...r.kernel.org,
linux-kernel@...r.kernel.org, Roger Quadros <rogerq@...nel.org>
Subject: [PATCH net-next v5 7/9] net: ethernet: ti: cpsw_ale: add policer
save restore for PM sleep
On some K3 platforms CPSW context is lost during PM sleep.
Add cpsw_ale_policer_save() and cpsw_ale_policer_restore() helpers.
In am65-cpsw driver, save the policer context during PM suspend and
restore it during PM resume.
Signed-off-by: Roger Quadros <rogerq@...nel.org>
---
drivers/net/ethernet/ti/am65-cpsw-nuss.c | 24 +++++++++++++++---
drivers/net/ethernet/ti/am65-cpsw-nuss.h | 1 +
drivers/net/ethernet/ti/cpsw_ale.c | 42 ++++++++++++++++++++++++++++++++
drivers/net/ethernet/ti/cpsw_ale.h | 4 +++
4 files changed, 68 insertions(+), 3 deletions(-)
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index 977f32962cd0bc63528718e47a4bfae813676f01..93ff139966ea0e26d3cd44a2f6eb7f9cbd2611d5 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -3523,7 +3523,7 @@ static int am65_cpsw_nuss_probe(struct platform_device *pdev)
struct device_node *node;
struct resource *res;
struct clk *clk;
- int ale_entries;
+ int tbl_entries;
__be64 id_temp;
int ret, i;
@@ -3626,10 +3626,26 @@ static int am65_cpsw_nuss_probe(struct platform_device *pdev)
goto err_of_clear;
}
- ale_entries = common->ale->params.ale_entries;
+ tbl_entries = common->ale->params.ale_entries;
common->ale_context = devm_kzalloc(dev,
- ale_entries * ALE_ENTRY_WORDS * sizeof(u32),
+ tbl_entries * ALE_ENTRY_WORDS * sizeof(u32),
GFP_KERNEL);
+ if (!common->ale_context) {
+ ret = -ENOMEM;
+ goto err_of_clear;
+ }
+
+ tbl_entries = common->ale->params.num_policers;
+ i = CPSW_ALE_POLICER_ENTRY_WORDS + 1; /* 8 CFG + 1 Thread_val */
+ i *= tbl_entries; /* for all policers */
+ i += 1; /* thread_def register */
+ common->policer_context = devm_kzalloc(dev, i * sizeof(u32),
+ GFP_KERNEL);
+ if (!common->policer_context) {
+ ret = -ENOMEM;
+ goto err_of_clear;
+ }
+
ret = am65_cpsw_init_cpts(common);
if (ret)
goto err_of_clear;
@@ -3715,6 +3731,7 @@ static int am65_cpsw_nuss_suspend(struct device *dev)
int i, ret;
cpsw_ale_dump(common->ale, common->ale_context);
+ cpsw_ale_policer_save(common->ale, common->policer_context);
host_p->vid_context = readl(host_p->port_base + AM65_CPSW_PORT_VLAN_REG_OFFSET);
for (i = 0; i < common->port_num; i++) {
port = &common->ports[i];
@@ -3792,6 +3809,7 @@ static int am65_cpsw_nuss_resume(struct device *dev)
writel(host_p->vid_context, host_p->port_base + AM65_CPSW_PORT_VLAN_REG_OFFSET);
cpsw_ale_restore(common->ale, common->ale_context);
+ cpsw_ale_policer_restore(common->ale, common->policer_context);
return 0;
}
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.h b/drivers/net/ethernet/ti/am65-cpsw-nuss.h
index 917c37e4e89bd933d3001f6c35a62db01cd8da4c..61daa5db12e631588eba71351ba3bc0139456bf5 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.h
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.h
@@ -190,6 +190,7 @@ struct am65_cpsw_common {
unsigned char switch_id[MAX_PHYS_ITEM_ID_LEN];
/* only for suspend/resume context restore */
u32 *ale_context;
+ u32 *policer_context;
};
struct am65_cpsw_ndev_priv {
diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
index 9641c3d688c768a227b557f7c1a31fe77c9a738b..9492d0cf06bbbe227899e9a235f2fe52da3acad6 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.c
+++ b/drivers/net/ethernet/ti/cpsw_ale.c
@@ -1823,3 +1823,45 @@ int cpsw_ale_policer_set_entry(struct cpsw_ale *ale, u32 policer_idx,
return 0;
}
+
+void cpsw_ale_policer_save(struct cpsw_ale *ale, u32 *data)
+{
+ int i, idx;
+
+ for (idx = 0; idx < ale->params.num_policers; idx++) {
+ cpsw_ale_policer_read_idx(ale, idx);
+
+ for (i = 0; i < CPSW_ALE_POLICER_ENTRY_WORDS; i++)
+ data[i] = readl_relaxed(ale->params.ale_regs +
+ ALE_POLICER_PORT_OUI + 4 * i);
+
+ regmap_field_write(ale->fields[ALE_THREAD_CLASS_INDEX], idx);
+ data[i++] = readl_relaxed(ale->params.ale_regs +
+ ALE_THREAD_VAL);
+ data += i;
+ }
+
+ data[0] = readl_relaxed(ale->params.ale_regs + ALE_THREAD_DEF);
+}
+
+void cpsw_ale_policer_restore(struct cpsw_ale *ale, u32 *data)
+{
+ int i, idx;
+
+ for (idx = 0; idx < ale->params.num_policers; idx++) {
+ cpsw_ale_policer_read_idx(ale, idx);
+
+ for (i = 0; i < CPSW_ALE_POLICER_ENTRY_WORDS; i++)
+ writel_relaxed(data[i], ale->params.ale_regs +
+ ALE_POLICER_PORT_OUI + 4 * i);
+
+ cpsw_ale_policer_write_idx(ale, idx);
+
+ regmap_field_write(ale->fields[ALE_THREAD_CLASS_INDEX], idx);
+ writel_relaxed(data[i++], ale->params.ale_regs +
+ ALE_THREAD_VAL);
+ data += i;
+ }
+
+ writel_relaxed(data[0], ale->params.ale_regs + ALE_THREAD_DEF);
+}
diff --git a/drivers/net/ethernet/ti/cpsw_ale.h b/drivers/net/ethernet/ti/cpsw_ale.h
index 11d333bf5a5280374573833050a4e3893d85dc28..dbc095397389d36df54a29d46e905f7eeb790e87 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.h
+++ b/drivers/net/ethernet/ti/cpsw_ale.h
@@ -171,6 +171,8 @@ enum cpsw_ale_port_state {
#define CPSW_ALE_POLICER_MATCH_IPSRC BIT(8)
#define CPSW_ALE_POLICER_MATCH_IPDST BIT(9)
+#define CPSW_ALE_POLICER_ENTRY_WORDS 8
+
struct cpsw_ale_policer_cfg {
u32 match_flags;
u16 ether_type;
@@ -227,5 +229,7 @@ int cpsw_ale_policer_set_entry(struct cpsw_ale *ale, u32 policer_idx,
struct cpsw_ale_policer_cfg *cfg);
void cpsw_ale_policer_clr_entry(struct cpsw_ale *ale, u32 policer_idx,
struct cpsw_ale_policer_cfg *cfg);
+void cpsw_ale_policer_save(struct cpsw_ale *ale, u32 *data);
+void cpsw_ale_policer_restore(struct cpsw_ale *ale, u32 *data);
#endif
--
2.34.1
Powered by blists - more mailing lists