linux-omap.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next v4 0/9] net: ethernet: ti: am65-cpsw: add network flow classification support
@ 2025-05-14 12:04 Roger Quadros
  2025-05-14 12:04 ` [PATCH net-next v4 1/9] net: ethernet: ti: cpsw_ale: Update Policer fields for more ALE size/ports Roger Quadros
                   ` (8 more replies)
  0 siblings, 9 replies; 17+ messages in thread
From: Roger Quadros @ 2025-05-14 12:04 UTC (permalink / raw)
  To: Siddharth Vadapalli, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Russell King, danishanwar
  Cc: srk, linux-omap, netdev, linux-kernel, Roger Quadros

Adds support for -N/--config-nfc ethtool command for
configuring RX classfiers.

Currently only raw Ethernet (flow-type ether) matching is added
based on source/destination addresses and VLAN Priority (PCP).

The ALE policer engine is used to perform the matching and routing to
a specific RX channel.

Test cases:

Increase number of RX channels to 8
ip link set end1 down
ip link set end0 down
ethtool -L end0 rx 8

1) Ether source address test
	ethtool -N end0 flow-type ether src xx:yy:zz:aa:bb:cc action 5

  Traffic from that address should route to channel 5

2) Ether destination address test
	ethtool -N eth0 flow-type ether dst yy:zz:aa:bb:cc:dd action 4

  Traffic to that address should route to channel 4

3) Drop test
	ethtool -N end0 flow-type ether src xx:yy:zz:aa:bb:cc action -1

  Traffic from that address should be dropped

4) VLAN PCP test

on Remote create VLAN with ID 5 and all traffic mapping to required priority to test. e.g. 7
	sudo ip link add link eno1 name eno1.5 type vlan id 5 egress-qos-map 0:7 1:7 2:7 3:7 4:7 5:7 6:7 7:7
	sudo ifconfig eno1.5 192.168.10.1

on DUT create VLAN with id 5
	ip link add link end0 name end0.5 type vlan id 5
	ifconfig end0.5 192.168.10.5

VLAN pcp 7 vid 5 route to RX channel 6
	ethtool -N end0 flow-type ether vlan 0xe005 action 6

  Traffic from that VLAN with PCP 7 should route to channel 6

Signed-off-by: Roger Quadros <rogerq@kernel.org>
---
Changes in v4:
- Added missing mutex_unlock in error case in am65_cpsw_rxnfc_add_rule()
- Stop using devm_ variant for kalloc/kfree for rxnfc rules as we explictly
  manage freeing.
- Dropped unnecessary print message in am65_cpsw_set_rxnfc()
- Link to v3: https://lore.kernel.org/r/20250513-am65-cpsw-rx-class-v3-0-492d9a2586b6@kernel.org

Changes in v3:
- Fixed bug in cpsw_ale_policer_save/restore(). '* 4' is not needed for
  a u32 pointer.
- Fixed reverse Christmas tree order
- Moved mutex acquiring out of am65_cpsw_policer_find_match() and
  at beginning of am65_cpsw_rxnfc_add_rule()
- Link to v2: https://lore.kernel.org/r/20250505-am65-cpsw-rx-class-v2-0-5359ea025144@kernel.org

Changes in v2:
- Error out if VLAN_ID > 0 as VLAN ID based flow routing still doesn't
   seem to work. Drop commented out code.
- Limit lines to 80 characters whereever possible.
- Change struct am65_cpsw_rxnfc_rule.location from int to unsigned int.
- Add information about order of rules evaluation and multiple matches
   in commit log.
- Link to v1: https://lore.kernel.org/r/20250319-am65-cpsw-rx-class-v1-0-2bfded07490e@kernel.org

---
Roger Quadros (9):
      net: ethernet: ti: cpsw_ale: Update Policer fields for more ALE size/ports
      net: ethernet: ti: cpsw_ale: return ALE index in cpsw_ale_add_vlan()
      net: ethernet: ti: cpsw_ale: return ALE index in cpsw_ale_vlan_add_modify()
      net: ethernet: ti: cpsw_ale: return ALE index in cpsw_ale_add_ucast()
      net: ethernet: ti: cpsw_ale: add cpsw_ale_policer_reset_entry()
      net: ethernet: ti: cpsw_ale: add cpsw_ale_policer_set/clr_entry()
      net: ethernet: ti: cpsw_ale: add policer save restore for PM sleep
      net: ethernet: ti: am65-cpsw: add network flow classification support
      net: ethernet: ti: am65-cpsw: remove cpsw_ale_classifier_setup_default()

 drivers/net/ethernet/ti/am65-cpsw-ethtool.c   | 357 ++++++++++++++++++++++++++
 drivers/net/ethernet/ti/am65-cpsw-nuss.c      |  32 ++-
 drivers/net/ethernet/ti/am65-cpsw-nuss.h      |  16 ++
 drivers/net/ethernet/ti/am65-cpsw-switchdev.c |   6 +-
 drivers/net/ethernet/ti/cpsw.c                |   4 +-
 drivers/net/ethernet/ti/cpsw_ale.c            | 214 +++++++++------
 drivers/net/ethernet/ti/cpsw_ale.h            |  37 ++-
 drivers/net/ethernet/ti/cpsw_new.c            |   4 +-
 drivers/net/ethernet/ti/cpsw_switchdev.c      |   6 +-
 9 files changed, 583 insertions(+), 93 deletions(-)
---
base-commit: 9f607dc39b6658ba8ea647bd99725e68c66071b7
change-id: 20250305-am65-cpsw-rx-class-666006fab9dd

Best regards,
-- 
Roger Quadros <rogerq@kernel.org>


^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH net-next v4 1/9] net: ethernet: ti: cpsw_ale: Update Policer fields for more ALE size/ports
  2025-05-14 12:04 [PATCH net-next v4 0/9] net: ethernet: ti: am65-cpsw: add network flow classification support Roger Quadros
@ 2025-05-14 12:04 ` Roger Quadros
  2025-05-14 12:04 ` [PATCH net-next v4 2/9] net: ethernet: ti: cpsw_ale: return ALE index in cpsw_ale_add_vlan() Roger Quadros
                   ` (7 subsequent siblings)
  8 siblings, 0 replies; 17+ messages in thread
From: Roger Quadros @ 2025-05-14 12:04 UTC (permalink / raw)
  To: Siddharth Vadapalli, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Russell King, danishanwar
  Cc: srk, linux-omap, netdev, linux-kernel, Roger Quadros

Different SoCs have different sized ALE table and number of ports.
Expand the Policer fields to support 16 ports and 1024 ALE entries.

Signed-off-by: Roger Quadros <rogerq@kernel.org>
---
 drivers/net/ethernet/ti/cpsw_ale.c | 18 +++++++++---------
 1 file changed, 9 insertions(+), 9 deletions(-)

diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
index 7f77694ecfba..7bb63aad7724 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.c
+++ b/drivers/net/ethernet/ti/cpsw_ale.c
@@ -1341,33 +1341,33 @@ static const struct reg_field ale_fields_cpsw_nu[] = {
 	/* CPSW_ALE_POLICER_PORT_OUI_REG */
 	[POL_PORT_MEN]	= REG_FIELD(ALE_POLICER_PORT_OUI, 31, 31),
 	[POL_TRUNK_ID]	= REG_FIELD(ALE_POLICER_PORT_OUI, 30, 30),
-	[POL_PORT_NUM]	= REG_FIELD(ALE_POLICER_PORT_OUI, 25, 25),
+	[POL_PORT_NUM]	= REG_FIELD(ALE_POLICER_PORT_OUI, 25, 28),
 	[POL_PRI_MEN]	= REG_FIELD(ALE_POLICER_PORT_OUI, 19, 19),
 	[POL_PRI_VAL]	= REG_FIELD(ALE_POLICER_PORT_OUI, 16, 18),
 	[POL_OUI_MEN]	= REG_FIELD(ALE_POLICER_PORT_OUI, 15, 15),
-	[POL_OUI_INDEX]	= REG_FIELD(ALE_POLICER_PORT_OUI, 0, 5),
+	[POL_OUI_INDEX]	= REG_FIELD(ALE_POLICER_PORT_OUI, 0, 9),
 
 	/* CPSW_ALE_POLICER_DA_SA_REG */
 	[POL_DST_MEN]	= REG_FIELD(ALE_POLICER_DA_SA, 31, 31),
-	[POL_DST_INDEX]	= REG_FIELD(ALE_POLICER_DA_SA, 16, 21),
+	[POL_DST_INDEX]	= REG_FIELD(ALE_POLICER_DA_SA, 16, 25),
 	[POL_SRC_MEN]	= REG_FIELD(ALE_POLICER_DA_SA, 15, 15),
-	[POL_SRC_INDEX]	= REG_FIELD(ALE_POLICER_DA_SA, 0, 5),
+	[POL_SRC_INDEX]	= REG_FIELD(ALE_POLICER_DA_SA, 0, 9),
 
 	/* CPSW_ALE_POLICER_VLAN_REG */
 	[POL_OVLAN_MEN]		= REG_FIELD(ALE_POLICER_VLAN, 31, 31),
-	[POL_OVLAN_INDEX]	= REG_FIELD(ALE_POLICER_VLAN, 16, 21),
+	[POL_OVLAN_INDEX]	= REG_FIELD(ALE_POLICER_VLAN, 16, 25),
 	[POL_IVLAN_MEN]		= REG_FIELD(ALE_POLICER_VLAN, 15, 15),
-	[POL_IVLAN_INDEX]	= REG_FIELD(ALE_POLICER_VLAN, 0, 5),
+	[POL_IVLAN_INDEX]	= REG_FIELD(ALE_POLICER_VLAN, 0, 9),
 
 	/* CPSW_ALE_POLICER_ETHERTYPE_IPSA_REG */
 	[POL_ETHERTYPE_MEN]	= REG_FIELD(ALE_POLICER_ETHERTYPE_IPSA, 31, 31),
-	[POL_ETHERTYPE_INDEX]	= REG_FIELD(ALE_POLICER_ETHERTYPE_IPSA, 16, 21),
+	[POL_ETHERTYPE_INDEX]	= REG_FIELD(ALE_POLICER_ETHERTYPE_IPSA, 16, 25),
 	[POL_IPSRC_MEN]		= REG_FIELD(ALE_POLICER_ETHERTYPE_IPSA, 15, 15),
-	[POL_IPSRC_INDEX]	= REG_FIELD(ALE_POLICER_ETHERTYPE_IPSA, 0, 5),
+	[POL_IPSRC_INDEX]	= REG_FIELD(ALE_POLICER_ETHERTYPE_IPSA, 0, 9),
 
 	/* CPSW_ALE_POLICER_IPDA_REG */
 	[POL_IPDST_MEN]		= REG_FIELD(ALE_POLICER_IPDA, 31, 31),
-	[POL_IPDST_INDEX]	= REG_FIELD(ALE_POLICER_IPDA, 16, 21),
+	[POL_IPDST_INDEX]	= REG_FIELD(ALE_POLICER_IPDA, 16, 25),
 
 	/* CPSW_ALE_POLICER_TBL_CTL_REG */
 	/**

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH net-next v4 2/9] net: ethernet: ti: cpsw_ale: return ALE index in cpsw_ale_add_vlan()
  2025-05-14 12:04 [PATCH net-next v4 0/9] net: ethernet: ti: am65-cpsw: add network flow classification support Roger Quadros
  2025-05-14 12:04 ` [PATCH net-next v4 1/9] net: ethernet: ti: cpsw_ale: Update Policer fields for more ALE size/ports Roger Quadros
@ 2025-05-14 12:04 ` Roger Quadros
  2025-05-14 12:04 ` [PATCH net-next v4 3/9] net: ethernet: ti: cpsw_ale: return ALE index in cpsw_ale_vlan_add_modify() Roger Quadros
                   ` (6 subsequent siblings)
  8 siblings, 0 replies; 17+ messages in thread
From: Roger Quadros @ 2025-05-14 12:04 UTC (permalink / raw)
  To: Siddharth Vadapalli, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Russell King, danishanwar
  Cc: srk, linux-omap, netdev, linux-kernel, Roger Quadros

Policer helpers will be interested to know what ALE index was used
for the added VLAN entry. So return the ALE index instead of zero
on success.

Modify existing users to check for less than zero as error case.

Signed-off-by: Roger Quadros <rogerq@kernel.org>
---
 drivers/net/ethernet/ti/cpsw.c     | 2 +-
 drivers/net/ethernet/ti/cpsw_ale.c | 6 +++---
 drivers/net/ethernet/ti/cpsw_new.c | 2 +-
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index a984b7d84e5e..2d23cba557f3 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -1026,7 +1026,7 @@ static inline int cpsw_add_vlan_ale_entry(struct cpsw_priv *priv,
 
 	ret = cpsw_ale_add_vlan(cpsw->ale, vid, port_mask, 0, port_mask,
 				unreg_mcast_mask);
-	if (ret != 0)
+	if (ret < 0)
 		return ret;
 
 	ret = cpsw_ale_add_ucast(cpsw->ale, priv->mac_addr,
diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
index 7bb63aad7724..0bdc95552410 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.c
+++ b/drivers/net/ethernet/ti/cpsw_ale.c
@@ -680,7 +680,7 @@ int cpsw_ale_add_vlan(struct cpsw_ale *ale, u16 vid, int port_mask, int untag,
 		return -ENOMEM;
 
 	cpsw_ale_write(ale, idx, ale_entry);
-	return 0;
+	return idx;
 }
 
 static void cpsw_ale_vlan_del_modify_int(struct cpsw_ale *ale,  u32 *ale_entry,
@@ -803,14 +803,14 @@ int cpsw_ale_vlan_add_modify(struct cpsw_ale *ale, u16 vid, int port_mask,
 
 	ret = cpsw_ale_add_vlan(ale, vid, vlan_members, untag_members,
 				reg_mcast_members, unreg_mcast_members);
-	if (ret) {
+	if (ret < 0) {
 		dev_err(ale->params.dev, "Unable to add vlan\n");
 		return ret;
 	}
 	dev_dbg(ale->params.dev, "port mask 0x%x untag 0x%x\n", vlan_members,
 		untag_mask);
 
-	return ret;
+	return 0;
 }
 
 void cpsw_ale_set_unreg_mcast(struct cpsw_ale *ale, int unreg_mcast_mask,
diff --git a/drivers/net/ethernet/ti/cpsw_new.c b/drivers/net/ethernet/ti/cpsw_new.c
index 5b5b52e4e7a7..1516171352cd 100644
--- a/drivers/net/ethernet/ti/cpsw_new.c
+++ b/drivers/net/ethernet/ti/cpsw_new.c
@@ -417,7 +417,7 @@ static int cpsw_add_vlan_ale_entry(struct cpsw_priv *priv,
 
 	ret = cpsw_ale_add_vlan(cpsw->ale, vid, port_mask, 0, port_mask,
 				unreg_mcast_mask);
-	if (ret != 0)
+	if (ret < 0)
 		return ret;
 
 	ret = cpsw_ale_add_ucast(cpsw->ale, priv->mac_addr,

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH net-next v4 3/9] net: ethernet: ti: cpsw_ale: return ALE index in cpsw_ale_vlan_add_modify()
  2025-05-14 12:04 [PATCH net-next v4 0/9] net: ethernet: ti: am65-cpsw: add network flow classification support Roger Quadros
  2025-05-14 12:04 ` [PATCH net-next v4 1/9] net: ethernet: ti: cpsw_ale: Update Policer fields for more ALE size/ports Roger Quadros
  2025-05-14 12:04 ` [PATCH net-next v4 2/9] net: ethernet: ti: cpsw_ale: return ALE index in cpsw_ale_add_vlan() Roger Quadros
@ 2025-05-14 12:04 ` Roger Quadros
  2025-05-14 12:04 ` [PATCH net-next v4 4/9] net: ethernet: ti: cpsw_ale: return ALE index in cpsw_ale_add_ucast() Roger Quadros
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 17+ messages in thread
From: Roger Quadros @ 2025-05-14 12:04 UTC (permalink / raw)
  To: Siddharth Vadapalli, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Russell King, danishanwar
  Cc: srk, linux-omap, netdev, linux-kernel, Roger Quadros

Policer helpers will need to know what ALE index was used for
the added VLAN entry. So return the ALE index instead of zero
on success.

Modify existing users to check for less than zero as error case.

Signed-off-by: Roger Quadros <rogerq@kernel.org>
---
 drivers/net/ethernet/ti/am65-cpsw-nuss.c      |  2 ++
 drivers/net/ethernet/ti/am65-cpsw-switchdev.c |  6 +++---
 drivers/net/ethernet/ti/cpsw_ale.c            | 10 +++++-----
 drivers/net/ethernet/ti/cpsw_switchdev.c      |  6 +++---
 4 files changed, 13 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index 988ce9119306..41dc963493de 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -321,6 +321,8 @@ static int am65_cpsw_nuss_ndo_slave_add_vid(struct net_device *ndev,
 	dev_info(common->dev, "Adding vlan %d to vlan filter\n", vid);
 	ret = cpsw_ale_vlan_add_modify(common->ale, vid, port_mask,
 				       unreg_mcast, port_mask, 0);
+	if (ret > 0)
+		ret = 0;
 
 	pm_runtime_put(common->dev);
 	return ret;
diff --git a/drivers/net/ethernet/ti/am65-cpsw-switchdev.c b/drivers/net/ethernet/ti/am65-cpsw-switchdev.c
index d4c56da98a6a..b284202bf480 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-switchdev.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-switchdev.c
@@ -175,7 +175,7 @@ static int am65_cpsw_port_vlan_add(struct am65_cpsw_port *port, bool untag, bool
 
 	ret = cpsw_ale_vlan_add_modify(cpsw->ale, vid, port_mask, untag_mask,
 				       reg_mcast_mask, unreg_mcast_mask);
-	if (ret) {
+	if (ret < 0) {
 		netdev_err(port->ndev, "Unable to add vlan\n");
 		return ret;
 	}
@@ -184,14 +184,14 @@ static int am65_cpsw_port_vlan_add(struct am65_cpsw_port *port, bool untag, bool
 		cpsw_ale_add_ucast(cpsw->ale, port->slave.mac_addr,
 				   HOST_PORT_NUM, ALE_VLAN | ALE_SECURE, vid);
 	if (!pvid)
-		return ret;
+		return 0;
 
 	am65_cpsw_set_pvid(port, vid, 0, 0);
 
 	netdev_dbg(port->ndev, "VID add: %s: vid:%u ports:%X\n",
 		   port->ndev->name, vid, port_mask);
 
-	return ret;
+	return 0;
 }
 
 static int am65_cpsw_port_vlan_del(struct am65_cpsw_port *port, u16 vid,
diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
index 0bdc95552410..952444b0c436 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.c
+++ b/drivers/net/ethernet/ti/cpsw_ale.c
@@ -780,7 +780,7 @@ int cpsw_ale_vlan_add_modify(struct cpsw_ale *ale, u16 vid, int port_mask,
 	u32 ale_entry[ALE_ENTRY_WORDS] = {0, 0, 0};
 	int reg_mcast_members, unreg_mcast_members;
 	int vlan_members, untag_members;
-	int idx, ret = 0;
+	int idx;
 
 	idx = cpsw_ale_match_vlan(ale, vid);
 	if (idx >= 0)
@@ -801,16 +801,16 @@ int cpsw_ale_vlan_add_modify(struct cpsw_ale *ale, u16 vid, int port_mask,
 	reg_mcast_members = (reg_mcast_members & ~port_mask) | reg_mask;
 	unreg_mcast_members = (unreg_mcast_members & ~port_mask) | unreg_mask;
 
-	ret = cpsw_ale_add_vlan(ale, vid, vlan_members, untag_members,
+	idx = cpsw_ale_add_vlan(ale, vid, vlan_members, untag_members,
 				reg_mcast_members, unreg_mcast_members);
-	if (ret < 0) {
+	if (idx < 0) {
 		dev_err(ale->params.dev, "Unable to add vlan\n");
-		return ret;
+		return idx;
 	}
 	dev_dbg(ale->params.dev, "port mask 0x%x untag 0x%x\n", vlan_members,
 		untag_mask);
 
-	return 0;
+	return idx;
 }
 
 void cpsw_ale_set_unreg_mcast(struct cpsw_ale *ale, int unreg_mcast_mask,
diff --git a/drivers/net/ethernet/ti/cpsw_switchdev.c b/drivers/net/ethernet/ti/cpsw_switchdev.c
index ce85f7610273..c767a47b2039 100644
--- a/drivers/net/ethernet/ti/cpsw_switchdev.c
+++ b/drivers/net/ethernet/ti/cpsw_switchdev.c
@@ -191,7 +191,7 @@ static int cpsw_port_vlan_add(struct cpsw_priv *priv, bool untag, bool pvid,
 
 	ret = cpsw_ale_vlan_add_modify(cpsw->ale, vid, port_mask, untag_mask,
 				       reg_mcast_mask, unreg_mcast_mask);
-	if (ret) {
+	if (ret < 0) {
 		dev_err(priv->dev, "Unable to add vlan\n");
 		return ret;
 	}
@@ -200,13 +200,13 @@ static int cpsw_port_vlan_add(struct cpsw_priv *priv, bool untag, bool pvid,
 		cpsw_ale_add_ucast(cpsw->ale, priv->mac_addr,
 				   HOST_PORT_NUM, ALE_VLAN, vid);
 	if (!pvid)
-		return ret;
+		return 0;
 
 	cpsw_set_pvid(priv, vid, 0, 0);
 
 	dev_dbg(priv->dev, "VID add: %s: vid:%u ports:%X\n",
 		priv->ndev->name, vid, port_mask);
-	return ret;
+	return 0;
 }
 
 static int cpsw_port_vlan_del(struct cpsw_priv *priv, u16 vid,

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH net-next v4 4/9] net: ethernet: ti: cpsw_ale: return ALE index in cpsw_ale_add_ucast()
  2025-05-14 12:04 [PATCH net-next v4 0/9] net: ethernet: ti: am65-cpsw: add network flow classification support Roger Quadros
                   ` (2 preceding siblings ...)
  2025-05-14 12:04 ` [PATCH net-next v4 3/9] net: ethernet: ti: cpsw_ale: return ALE index in cpsw_ale_vlan_add_modify() Roger Quadros
@ 2025-05-14 12:04 ` Roger Quadros
  2025-05-14 12:04 ` [PATCH net-next v4 5/9] net: ethernet: ti: cpsw_ale: add cpsw_ale_policer_reset_entry() Roger Quadros
                   ` (4 subsequent siblings)
  8 siblings, 0 replies; 17+ messages in thread
From: Roger Quadros @ 2025-05-14 12:04 UTC (permalink / raw)
  To: Siddharth Vadapalli, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Russell King, danishanwar
  Cc: srk, linux-omap, netdev, linux-kernel, Roger Quadros

Policer helpers will need to know what ALE index was used for
the added unicast entry. So return the ALE index instead of zero
on success.

Modify existing users to check for less than zero as error case.

Signed-off-by: Roger Quadros <rogerq@kernel.org>
---
 drivers/net/ethernet/ti/cpsw.c     | 2 +-
 drivers/net/ethernet/ti/cpsw_ale.c | 2 +-
 drivers/net/ethernet/ti/cpsw_new.c | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index 2d23cba557f3..d1abd2fb63c9 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -1031,7 +1031,7 @@ static inline int cpsw_add_vlan_ale_entry(struct cpsw_priv *priv,
 
 	ret = cpsw_ale_add_ucast(cpsw->ale, priv->mac_addr,
 				 HOST_PORT_NUM, ALE_VLAN, vid);
-	if (ret != 0)
+	if (ret < 0)
 		goto clean_vid;
 
 	ret = cpsw_ale_add_mcast(cpsw->ale, priv->ndev->broadcast,
diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
index 952444b0c436..74dc431f1c1b 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.c
+++ b/drivers/net/ethernet/ti/cpsw_ale.c
@@ -534,7 +534,7 @@ int cpsw_ale_add_ucast(struct cpsw_ale *ale, const u8 *addr, int port,
 		return -ENOMEM;
 
 	cpsw_ale_write(ale, idx, ale_entry);
-	return 0;
+	return idx;
 }
 
 int cpsw_ale_del_ucast(struct cpsw_ale *ale, const u8 *addr, int port,
diff --git a/drivers/net/ethernet/ti/cpsw_new.c b/drivers/net/ethernet/ti/cpsw_new.c
index 1516171352cd..944fa3db94a2 100644
--- a/drivers/net/ethernet/ti/cpsw_new.c
+++ b/drivers/net/ethernet/ti/cpsw_new.c
@@ -422,7 +422,7 @@ static int cpsw_add_vlan_ale_entry(struct cpsw_priv *priv,
 
 	ret = cpsw_ale_add_ucast(cpsw->ale, priv->mac_addr,
 				 HOST_PORT_NUM, ALE_VLAN, vid);
-	if (ret != 0)
+	if (ret < 0)
 		goto clean_vid;
 
 	ret = cpsw_ale_add_mcast(cpsw->ale, priv->ndev->broadcast,

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH net-next v4 5/9] net: ethernet: ti: cpsw_ale: add cpsw_ale_policer_reset_entry()
  2025-05-14 12:04 [PATCH net-next v4 0/9] net: ethernet: ti: am65-cpsw: add network flow classification support Roger Quadros
                   ` (3 preceding siblings ...)
  2025-05-14 12:04 ` [PATCH net-next v4 4/9] net: ethernet: ti: cpsw_ale: return ALE index in cpsw_ale_add_ucast() Roger Quadros
@ 2025-05-14 12:04 ` Roger Quadros
  2025-05-14 12:04 ` [PATCH net-next v4 6/9] net: ethernet: ti: cpsw_ale: add cpsw_ale_policer_set/clr_entry() Roger Quadros
                   ` (3 subsequent siblings)
  8 siblings, 0 replies; 17+ messages in thread
From: Roger Quadros @ 2025-05-14 12:04 UTC (permalink / raw)
  To: Siddharth Vadapalli, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Russell King, danishanwar
  Cc: srk, linux-omap, netdev, linux-kernel, Roger Quadros

Add new helper cpsw_ale_policer_reset_entry() to reset a single
policer entry. Clear all fields instead of just clearing the enable bits.

Export cpsw_ale_policer_reset() as it will be required by cpsw
drivers using policer.

Signed-off-by: Roger Quadros <rogerq@kernel.org>
---
 drivers/net/ethernet/ti/cpsw_ale.c | 35 +++++++++++++++--------------------
 drivers/net/ethernet/ti/cpsw_ale.h |  4 ++++
 2 files changed, 19 insertions(+), 20 deletions(-)

diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
index 74dc431f1c1b..49ea1c00be3d 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.c
+++ b/drivers/net/ethernet/ti/cpsw_ale.c
@@ -1674,30 +1674,25 @@ static void cpsw_ale_policer_thread_idx_enable(struct cpsw_ale *ale, u32 idx,
 	regmap_field_write(ale->fields[ALE_THREAD_ENABLE], enable ? 1 : 0);
 }
 
+static void cpsw_ale_policer_reset_entry(struct cpsw_ale *ale, u32 idx)
+{
+	int i;
+
+	cpsw_ale_policer_read_idx(ale, idx);
+	for (i = 0; i < CPSW_ALE_POLICER_ENTRY_WORDS; i++)
+		writel_relaxed(0, ale->params.ale_regs +
+			       ALE_POLICER_PORT_OUI + 4 * i);
+	cpsw_ale_policer_thread_idx_enable(ale, idx, 0, 0);
+	cpsw_ale_policer_write_idx(ale, idx);
+}
+
 /* Disable all policer entries and thread mappings */
-static void cpsw_ale_policer_reset(struct cpsw_ale *ale)
+void cpsw_ale_policer_reset(struct cpsw_ale *ale)
 {
 	int i;
 
-	for (i = 0; i < ale->params.num_policers ; i++) {
-		cpsw_ale_policer_read_idx(ale, i);
-		regmap_field_write(ale->fields[POL_PORT_MEN], 0);
-		regmap_field_write(ale->fields[POL_PRI_MEN], 0);
-		regmap_field_write(ale->fields[POL_OUI_MEN], 0);
-		regmap_field_write(ale->fields[POL_DST_MEN], 0);
-		regmap_field_write(ale->fields[POL_SRC_MEN], 0);
-		regmap_field_write(ale->fields[POL_OVLAN_MEN], 0);
-		regmap_field_write(ale->fields[POL_IVLAN_MEN], 0);
-		regmap_field_write(ale->fields[POL_ETHERTYPE_MEN], 0);
-		regmap_field_write(ale->fields[POL_IPSRC_MEN], 0);
-		regmap_field_write(ale->fields[POL_IPDST_MEN], 0);
-		regmap_field_write(ale->fields[POL_EN], 0);
-		regmap_field_write(ale->fields[POL_RED_DROP_EN], 0);
-		regmap_field_write(ale->fields[POL_YELLOW_DROP_EN], 0);
-		regmap_field_write(ale->fields[POL_PRIORITY_THREAD_EN], 0);
-
-		cpsw_ale_policer_thread_idx_enable(ale, i, 0, 0);
-	}
+	for (i = 0; i < ale->params.num_policers ; i++)
+		cpsw_ale_policer_reset_entry(ale, i);
 }
 
 /* Default classifier is to map 8 user priorities to N receive channels */
diff --git a/drivers/net/ethernet/ti/cpsw_ale.h b/drivers/net/ethernet/ti/cpsw_ale.h
index 87b7d1b3a34a..ce59fec75774 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.h
+++ b/drivers/net/ethernet/ti/cpsw_ale.h
@@ -156,6 +156,9 @@ enum cpsw_ale_port_state {
 #define ALE_ENTRY_BITS		68
 #define ALE_ENTRY_WORDS	DIV_ROUND_UP(ALE_ENTRY_BITS, 32)
 
+/* Policer */
+#define CPSW_ALE_POLICER_ENTRY_WORDS	8
+
 struct cpsw_ale *cpsw_ale_create(struct cpsw_ale_params *params);
 
 void cpsw_ale_start(struct cpsw_ale *ale);
@@ -195,5 +198,6 @@ int cpsw_ale_vlan_del_modify(struct cpsw_ale *ale, u16 vid, int port_mask);
 void cpsw_ale_set_unreg_mcast(struct cpsw_ale *ale, int unreg_mcast_mask,
 			      bool add);
 void cpsw_ale_classifier_setup_default(struct cpsw_ale *ale, int num_rx_ch);
+void cpsw_ale_policer_reset(struct cpsw_ale *ale);
 
 #endif

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH net-next v4 6/9] net: ethernet: ti: cpsw_ale: add cpsw_ale_policer_set/clr_entry()
  2025-05-14 12:04 [PATCH net-next v4 0/9] net: ethernet: ti: am65-cpsw: add network flow classification support Roger Quadros
                   ` (4 preceding siblings ...)
  2025-05-14 12:04 ` [PATCH net-next v4 5/9] net: ethernet: ti: cpsw_ale: add cpsw_ale_policer_reset_entry() Roger Quadros
@ 2025-05-14 12:04 ` Roger Quadros
  2025-05-14 12:04 ` [PATCH net-next v4 7/9] net: ethernet: ti: cpsw_ale: add policer save restore for PM sleep Roger Quadros
                   ` (2 subsequent siblings)
  8 siblings, 0 replies; 17+ messages in thread
From: Roger Quadros @ 2025-05-14 12:04 UTC (permalink / raw)
  To: Siddharth Vadapalli, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Russell King, danishanwar
  Cc: srk, linux-omap, netdev, linux-kernel, Roger Quadros

Add cpsw_ale_policer_set/clr_entry() helpers.
So far Raw Ethernet matching based on Source/Destination address
and VLAN Priority (PCP) is supported.

Signed-off-by: Roger Quadros <rogerq@kernel.org>
---
 drivers/net/ethernet/ti/cpsw_ale.c | 77 ++++++++++++++++++++++++++++++++++++++
 drivers/net/ethernet/ti/cpsw_ale.h | 28 ++++++++++++++
 2 files changed, 105 insertions(+)

diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
index 49ea1c00be3d..ce216606d915 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.c
+++ b/drivers/net/ethernet/ti/cpsw_ale.c
@@ -1746,3 +1746,80 @@ void cpsw_ale_classifier_setup_default(struct cpsw_ale *ale, int num_rx_ch)
 						   1);
 	}
 }
+
+#define HOST_PORT_NUM 0
+
+/* Clear Policer and associated ALE table entries */
+void cpsw_ale_policer_clr_entry(struct cpsw_ale *ale, u32 policer_idx,
+				struct cpsw_ale_policer_cfg *cfg)
+{
+	cpsw_ale_policer_reset_entry(ale, policer_idx);
+
+	/* We do not delete ALE entries that were added in set_entry
+	 * as they might still be in use by the port e.g. VLAN id
+	 * or port MAC address
+	 */
+
+	/* clear BLOCKED in case we set it */
+	if ((cfg->match_flags & CPSW_ALE_POLICER_MATCH_MACSRC) && cfg->drop)
+		cpsw_ale_add_ucast(ale, cfg->src_addr, HOST_PORT_NUM, 0, 0);
+
+	if ((cfg->match_flags & CPSW_ALE_POLICER_MATCH_MACDST) && cfg->drop)
+		cpsw_ale_add_ucast(ale, cfg->dst_addr, HOST_PORT_NUM, 0, 0);
+}
+
+int cpsw_ale_policer_set_entry(struct cpsw_ale *ale, u32 policer_idx,
+			       struct cpsw_ale_policer_cfg *cfg)
+{
+	int ale_idx;
+	u16 ale_flags = cfg->drop ? ALE_BLOCKED : 0;
+
+	/* A single policer can support multiple match types simultaneously
+	 * There can be only one ALE entry per address
+	 */
+	cpsw_ale_policer_reset_entry(ale, policer_idx);
+	cpsw_ale_policer_read_idx(ale, policer_idx);
+
+	if (cfg->match_flags & CPSW_ALE_POLICER_MATCH_MACSRC) {
+		ale_idx = cpsw_ale_add_ucast(ale, cfg->src_addr, HOST_PORT_NUM,
+					     ale_flags, 0);
+		if (ale_idx < 0)
+			return -ENOENT;
+
+		/* update policer entry */
+		regmap_field_write(ale->fields[POL_SRC_INDEX], ale_idx);
+		regmap_field_write(ale->fields[POL_SRC_MEN], 1);
+	}
+
+	if (cfg->match_flags & CPSW_ALE_POLICER_MATCH_MACDST) {
+		ale_idx = cpsw_ale_add_ucast(ale, cfg->dst_addr, HOST_PORT_NUM,
+					     ale_flags, 0);
+		if (ale_idx < 0)
+			return -ENOENT;
+
+		/* update policer entry */
+		regmap_field_write(ale->fields[POL_DST_INDEX], ale_idx);
+		regmap_field_write(ale->fields[POL_DST_MEN], 1);
+	}
+
+	if (cfg->match_flags & CPSW_ALE_POLICER_MATCH_OVLAN) {
+		/* VLAN ID based flow routing not yet working,
+		 * only PCP matching for now
+		 */
+		if (cfg->vid > 0)
+			return -EINVAL;
+
+		regmap_field_write(ale->fields[POL_PRI_VAL], cfg->vlan_prio);
+		regmap_field_write(ale->fields[POL_PRI_MEN], 1);
+	}
+
+	cpsw_ale_policer_write_idx(ale, policer_idx);
+
+	/* Map to thread id provided by the config */
+	if (!cfg->drop) {
+		cpsw_ale_policer_thread_idx_enable(ale, policer_idx,
+						   cfg->thread_id, true);
+	}
+
+	return 0;
+}
diff --git a/drivers/net/ethernet/ti/cpsw_ale.h b/drivers/net/ethernet/ti/cpsw_ale.h
index ce59fec75774..11d333bf5a52 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.h
+++ b/drivers/net/ethernet/ti/cpsw_ale.h
@@ -159,6 +159,30 @@ enum cpsw_ale_port_state {
 /* Policer */
 #define CPSW_ALE_POLICER_ENTRY_WORDS	8
 
+/* Policer match flags */
+#define CPSW_ALE_POLICER_MATCH_PORT	BIT(0)
+#define CPSW_ALE_POLICER_MATCH_PRI	BIT(1)
+#define CPSW_ALE_POLICER_MATCH_OUI	BIT(2)
+#define CPSW_ALE_POLICER_MATCH_MACDST	BIT(3)
+#define CPSW_ALE_POLICER_MATCH_MACSRC	BIT(4)
+#define CPSW_ALE_POLICER_MATCH_OVLAN	BIT(5)
+#define CPSW_ALE_POLICER_MATCH_IVLAN	BIT(6)
+#define CPSW_ALE_POLICER_MATCH_ETHTYPE	BIT(7)
+#define CPSW_ALE_POLICER_MATCH_IPSRC	BIT(8)
+#define CPSW_ALE_POLICER_MATCH_IPDST	BIT(9)
+
+struct cpsw_ale_policer_cfg {
+	u32 match_flags;
+	u16 ether_type;
+	u16 vid;
+	u8 vlan_prio;
+	u8 src_addr[ETH_ALEN];
+	u8 dst_addr[ETH_ALEN];
+	bool drop;
+	u64 thread_id;
+	int port_id;
+};
+
 struct cpsw_ale *cpsw_ale_create(struct cpsw_ale_params *params);
 
 void cpsw_ale_start(struct cpsw_ale *ale);
@@ -199,5 +223,9 @@ void cpsw_ale_set_unreg_mcast(struct cpsw_ale *ale, int unreg_mcast_mask,
 			      bool add);
 void cpsw_ale_classifier_setup_default(struct cpsw_ale *ale, int num_rx_ch);
 void cpsw_ale_policer_reset(struct cpsw_ale *ale);
+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);
 
 #endif

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH net-next v4 7/9] net: ethernet: ti: cpsw_ale: add policer save restore for PM sleep
  2025-05-14 12:04 [PATCH net-next v4 0/9] net: ethernet: ti: am65-cpsw: add network flow classification support Roger Quadros
                   ` (5 preceding siblings ...)
  2025-05-14 12:04 ` [PATCH net-next v4 6/9] net: ethernet: ti: cpsw_ale: add cpsw_ale_policer_set/clr_entry() Roger Quadros
@ 2025-05-14 12:04 ` Roger Quadros
  2025-05-14 12:04 ` [PATCH net-next v4 8/9] net: ethernet: ti: am65-cpsw: add network flow classification support Roger Quadros
  2025-05-14 12:04 ` [PATCH net-next v4 9/9] net: ethernet: ti: am65-cpsw: remove cpsw_ale_classifier_setup_default() Roger Quadros
  8 siblings, 0 replies; 17+ messages in thread
From: Roger Quadros @ 2025-05-14 12:04 UTC (permalink / raw)
  To: Siddharth Vadapalli, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Russell King, danishanwar
  Cc: srk, linux-omap, netdev, linux-kernel, Roger Quadros

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@kernel.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 41dc963493de..07df61f343d3 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -3503,7 +3503,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;
 
@@ -3606,10 +3606,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;
@@ -3695,6 +3711,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];
@@ -3772,6 +3789,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 917c37e4e89b..61daa5db12e6 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 ce216606d915..0cd27a6fe575 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 11d333bf5a52..dbc095397389 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


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH net-next v4 8/9] net: ethernet: ti: am65-cpsw: add network flow classification support
  2025-05-14 12:04 [PATCH net-next v4 0/9] net: ethernet: ti: am65-cpsw: add network flow classification support Roger Quadros
                   ` (6 preceding siblings ...)
  2025-05-14 12:04 ` [PATCH net-next v4 7/9] net: ethernet: ti: cpsw_ale: add policer save restore for PM sleep Roger Quadros
@ 2025-05-14 12:04 ` Roger Quadros
  2025-05-17  1:29   ` Jakub Kicinski
  2025-05-14 12:04 ` [PATCH net-next v4 9/9] net: ethernet: ti: am65-cpsw: remove cpsw_ale_classifier_setup_default() Roger Quadros
  8 siblings, 1 reply; 17+ messages in thread
From: Roger Quadros @ 2025-05-14 12:04 UTC (permalink / raw)
  To: Siddharth Vadapalli, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Russell King, danishanwar
  Cc: srk, linux-omap, netdev, linux-kernel, Roger Quadros

Adds support for -N/--config-nfc ethtool command for
configuring RX classfiers.

Currently only raw Ethernet (flow-type ether) matching is added
based on source/destination addresses and VLAN Priority (PCP).

The ALE policer engine is used to perform the matching and routing to
a specific RX channel.

The TRM doesn't mention anything about order of evaluation of the
classifier rules however it does mention in [1]
"if multiple classifier matches occur, the highest match
with thread enable bit set will be used."

[1] 3.1.4.6.1.12.3.1 Classifier to CPPI Transmit Flow ID Mapping
in AM62x TRM https://www.ti.com/lit/pdf/spruiv7

Signed-off-by: Roger Quadros <rogerq@kernel.org>
---
 drivers/net/ethernet/ti/am65-cpsw-ethtool.c | 357 ++++++++++++++++++++++++++++
 drivers/net/ethernet/ti/am65-cpsw-nuss.c    |   3 +
 drivers/net/ethernet/ti/am65-cpsw-nuss.h    |  15 ++
 3 files changed, 375 insertions(+)

diff --git a/drivers/net/ethernet/ti/am65-cpsw-ethtool.c b/drivers/net/ethernet/ti/am65-cpsw-ethtool.c
index 9032444435e9..41f4baf06507 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-ethtool.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-ethtool.c
@@ -970,6 +970,361 @@ static int am65_cpsw_set_coalesce(struct net_device *ndev, struct ethtool_coales
 	return am65_cpsw_set_per_queue_coalesce(ndev, 0, coal);
 }
 
+#define AM65_CPSW_FLOW_TYPE(f) ((f) & ~(FLOW_EXT | FLOW_MAC_EXT))
+
+/* rxnfc_lock must be held */
+static struct am65_cpsw_rxnfc_rule *am65_cpsw_get_rule(struct am65_cpsw_port *port,
+						       int location)
+{
+	struct am65_cpsw_rxnfc_rule *rule;
+
+	list_for_each_entry(rule, &port->rxnfc_rules, list) {
+		if (rule->location == location)
+			return rule;
+	}
+
+	return NULL;
+}
+
+/* rxnfc_lock must be held */
+static void am65_cpsw_del_rule(struct am65_cpsw_port *port,
+			       struct am65_cpsw_rxnfc_rule *rule)
+{
+	cpsw_ale_policer_clr_entry(port->common->ale, rule->location,
+				   &rule->cfg);
+	list_del(&rule->list);
+	port->rxnfc_count--;
+	kfree(rule);
+}
+
+/* rxnfc_lock must be held */
+static int am65_cpsw_add_rule(struct am65_cpsw_port *port,
+			      struct am65_cpsw_rxnfc_rule *rule)
+{
+	struct am65_cpsw_rxnfc_rule *prev = NULL, *cur;
+	int ret;
+
+	ret = cpsw_ale_policer_set_entry(port->common->ale, rule->location,
+					 &rule->cfg);
+	if (ret)
+		return ret;
+
+	list_for_each_entry(cur, &port->rxnfc_rules, list) {
+		if (cur->location >= rule->location)
+			break;
+		prev = cur;
+	}
+
+	list_add(&rule->list, prev ? &prev->list : &port->rxnfc_rules);
+	port->rxnfc_count++;
+
+	return 0;
+}
+
+#define ETHER_TYPE_FULL_MASK cpu_to_be16(FIELD_MAX(U16_MAX))
+#define VLAN_TCI_FULL_MASK ETHER_TYPE_FULL_MASK
+
+static int am65_cpsw_rxnfc_get_rule(struct am65_cpsw_port *port,
+				    struct ethtool_rxnfc *rxnfc)
+{
+	struct ethtool_rx_flow_spec *fs = &rxnfc->fs;
+	struct am65_cpsw_rxnfc_rule *rule;
+	struct cpsw_ale_policer_cfg *cfg;
+
+	mutex_lock(&port->rxnfc_lock);
+	rule = am65_cpsw_get_rule(port, fs->location);
+	if (!rule) {
+		mutex_unlock(&port->rxnfc_lock);
+		return -ENOENT;
+	}
+
+	cfg = &rule->cfg;
+
+	/* build flowspec from policer_cfg */
+	fs->flow_type = ETHER_FLOW;
+	fs->ring_cookie = cfg->thread_id;
+
+	/* clear all masks. Seems to be inverted */
+	eth_broadcast_addr(fs->m_u.ether_spec.h_dest);
+	eth_broadcast_addr(fs->m_u.ether_spec.h_source);
+	fs->m_u.ether_spec.h_proto = ETHER_TYPE_FULL_MASK;
+	fs->m_ext.vlan_tci = htons(0xFFFF);
+	fs->m_ext.vlan_etype = ETHER_TYPE_FULL_MASK;
+	fs->m_ext.data[0] = cpu_to_be32(FIELD_MAX(U32_MAX));
+	fs->m_ext.data[1] = cpu_to_be32(FIELD_MAX(U32_MAX));
+
+	if (cfg->match_flags & CPSW_ALE_POLICER_MATCH_MACDST) {
+		ether_addr_copy(fs->h_u.ether_spec.h_dest,
+				cfg->dst_addr);
+		eth_zero_addr(fs->m_u.ether_spec.h_dest);
+	}
+
+	if (cfg->match_flags & CPSW_ALE_POLICER_MATCH_MACSRC) {
+		ether_addr_copy(fs->h_u.ether_spec.h_source,
+				cfg->src_addr);
+		eth_zero_addr(fs->m_u.ether_spec.h_source);
+	}
+
+	if (cfg->match_flags & CPSW_ALE_POLICER_MATCH_OVLAN) {
+		fs->flow_type |= FLOW_EXT;
+		fs->h_ext.vlan_tci = htons(FIELD_PREP(VLAN_VID_MASK, cfg->vid)
+					   | FIELD_PREP(VLAN_PRIO_MASK, cfg->vlan_prio));
+		fs->m_ext.vlan_tci = 0;
+	}
+
+	mutex_unlock(&port->rxnfc_lock);
+
+	return 0;
+}
+
+static int am65_cpsw_rxnfc_get_all(struct am65_cpsw_port *port,
+				   struct ethtool_rxnfc *rxnfc,
+				   u32 *rule_locs)
+{
+	struct am65_cpsw_rxnfc_rule *rule;
+	int count = 0;
+
+	rxnfc->data = port->rxnfc_max;
+	mutex_lock(&port->rxnfc_lock);
+
+	list_for_each_entry(rule, &port->rxnfc_rules, list) {
+		if (count == rxnfc->rule_cnt) {
+			mutex_unlock(&port->rxnfc_lock);
+			return -EMSGSIZE;
+		}
+
+		rule_locs[count] = rule->location;
+		count++;
+	}
+
+	mutex_unlock(&port->rxnfc_lock);
+	rxnfc->rule_cnt = count;
+
+	return 0;
+}
+
+static int am65_cpsw_get_rxnfc(struct net_device *ndev,
+			       struct ethtool_rxnfc *rxnfc,
+			       u32 *rule_locs)
+{
+	struct am65_cpsw_common *common = am65_ndev_to_common(ndev);
+	struct am65_cpsw_port *port = am65_ndev_to_port(ndev);
+
+	switch (rxnfc->cmd) {
+	case ETHTOOL_GRXRINGS:
+		rxnfc->data = common->rx_ch_num_flows;
+		return 0;
+	case ETHTOOL_GRXCLSRLCNT: /* Get RX classification rule count */
+		rxnfc->rule_cnt = port->rxnfc_count;
+		rxnfc->data = port->rxnfc_max;
+		return 0;
+	case ETHTOOL_GRXCLSRULE: /* Get RX classification rule */
+		return am65_cpsw_rxnfc_get_rule(port, rxnfc);
+	case ETHTOOL_GRXCLSRLALL: /* Get all RX classification rules */
+		return am65_cpsw_rxnfc_get_all(port, rxnfc, rule_locs);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
+/* validate the rxnfc rule and convert it to policer config */
+static int am65_cpsw_rxnfc_validate(struct am65_cpsw_port *port,
+				    struct ethtool_rxnfc *rxnfc,
+				    struct cpsw_ale_policer_cfg *cfg)
+{
+	struct ethtool_rx_flow_spec *fs = &rxnfc->fs;
+	struct ethhdr *eth_mask;
+	int flow_type;
+
+	flow_type = AM65_CPSW_FLOW_TYPE(fs->flow_type);
+	memset(cfg, 0, sizeof(*cfg));
+
+	if (flow_type & FLOW_RSS)
+		return -EINVAL;
+
+	if (fs->location == RX_CLS_LOC_ANY ||
+	    fs->location >= port->rxnfc_max)
+		return -EINVAL;
+
+	if (fs->ring_cookie == RX_CLS_FLOW_DISC)
+		cfg->drop = true;
+	else if (fs->ring_cookie > AM65_CPSW_MAX_QUEUES)
+		return -EINVAL;
+
+	cfg->port_id = port->port_id;
+	cfg->thread_id = fs->ring_cookie;
+
+	switch (flow_type) {
+	case ETHER_FLOW:
+		eth_mask = &fs->m_u.ether_spec;
+
+		/* etherType matching is supported by h/w but not yet here */
+		if (eth_mask->h_proto)
+			return -EINVAL;
+
+		/* Only support source matching addresses by full mask */
+		if (is_broadcast_ether_addr(eth_mask->h_source)) {
+			cfg->match_flags |= CPSW_ALE_POLICER_MATCH_MACSRC;
+			ether_addr_copy(cfg->src_addr,
+					fs->h_u.ether_spec.h_source);
+		}
+
+		/* Only support destination matching addresses by full mask */
+		if (is_broadcast_ether_addr(eth_mask->h_dest)) {
+			cfg->match_flags |= CPSW_ALE_POLICER_MATCH_MACDST;
+			ether_addr_copy(cfg->dst_addr,
+					fs->h_u.ether_spec.h_dest);
+		}
+
+		if ((fs->flow_type & FLOW_EXT) && fs->m_ext.vlan_tci) {
+			/* Don't yet support vlan ethertype */
+			if (fs->m_ext.vlan_etype)
+				return -EINVAL;
+
+			if (fs->m_ext.vlan_tci != VLAN_TCI_FULL_MASK)
+				return -EINVAL;
+
+			cfg->vid = FIELD_GET(VLAN_VID_MASK,
+					     ntohs(fs->h_ext.vlan_tci));
+			cfg->vlan_prio = FIELD_GET(VLAN_PRIO_MASK,
+						   ntohs(fs->h_ext.vlan_tci));
+			cfg->match_flags |= CPSW_ALE_POLICER_MATCH_OVLAN;
+		}
+
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/* rxnfc_lock must be held */
+static int am65_cpsw_policer_find_match(struct am65_cpsw_port *port,
+					struct cpsw_ale_policer_cfg *cfg)
+{
+	struct am65_cpsw_rxnfc_rule *rule;
+	int loc = -EINVAL;
+
+	list_for_each_entry(rule, &port->rxnfc_rules, list) {
+		if (!memcmp(&rule->cfg, cfg, sizeof(*cfg))) {
+			loc = rule->location;
+			break;
+		}
+	}
+
+	mutex_unlock(&port->rxnfc_lock);
+
+	return loc;
+}
+
+static int am65_cpsw_rxnfc_add_rule(struct am65_cpsw_port *port,
+				    struct ethtool_rxnfc *rxnfc)
+{
+	struct ethtool_rx_flow_spec *fs = &rxnfc->fs;
+	struct am65_cpsw_rxnfc_rule *rule;
+	struct cpsw_ale_policer_cfg cfg;
+	int loc, ret;
+
+	if (am65_cpsw_rxnfc_validate(port, rxnfc, &cfg))
+		return -EINVAL;
+
+	/* need to check if similar rule is already present at another location,
+	 * if yes error out
+	 */
+	mutex_lock(&port->rxnfc_lock);
+	loc = am65_cpsw_policer_find_match(port, &cfg);
+	if (loc >= 0 && loc != fs->location) {
+		netdev_info(port->ndev,
+			    "rule already exists in location %d. not adding\n",
+			    loc);
+		mutex_unlock(&port->rxnfc_lock);
+		return -EINVAL;
+	}
+
+	/* delete exisiting rule */
+	if (loc >= 0) {
+		rule = am65_cpsw_get_rule(port, loc);
+		if (rule)
+			am65_cpsw_del_rule(port, rule);
+	}
+
+	rule = kzalloc(sizeof(*rule), GFP_KERNEL);
+	if (!rule) {
+		mutex_unlock(&port->rxnfc_lock);
+		return -ENOMEM;
+	}
+
+	INIT_LIST_HEAD(&rule->list);
+	memcpy(&rule->cfg, &cfg, sizeof(cfg));
+	rule->location = fs->location;
+	ret = am65_cpsw_add_rule(port, rule);
+	if (ret)
+		kfree(rule);
+	mutex_unlock(&port->rxnfc_lock);
+
+	return ret;
+}
+
+static int am65_cpsw_rxnfc_del_rule(struct am65_cpsw_port *port,
+				    struct ethtool_rxnfc *rxnfc)
+{
+	struct ethtool_rx_flow_spec *fs = &rxnfc->fs;
+	struct am65_cpsw_rxnfc_rule *rule;
+
+	mutex_lock(&port->rxnfc_lock);
+	rule = am65_cpsw_get_rule(port, fs->location);
+	if (!rule) {
+		mutex_unlock(&port->rxnfc_lock);
+		return -ENOENT;
+	}
+
+	am65_cpsw_del_rule(port, rule);
+	/* rule freed in am65_cpsw_del_rule() */
+	mutex_unlock(&port->rxnfc_lock);
+
+	return 0;
+}
+
+void am65_cpsw_rxnfc_init(struct am65_cpsw_port *port)
+{
+	struct cpsw_ale *ale = port->common->ale;
+
+	mutex_init(&port->rxnfc_lock);
+	INIT_LIST_HEAD(&port->rxnfc_rules);
+	port->rxnfc_max = ale->params.num_policers;
+
+	/* disable all rules */
+	cpsw_ale_policer_reset(ale);
+}
+
+void am65_cpsw_rxnfc_cleanup(struct am65_cpsw_port *port)
+{
+	struct am65_cpsw_rxnfc_rule *rule, *tmp;
+
+	mutex_lock(&port->rxnfc_lock);
+
+	list_for_each_entry_safe(rule, tmp, &port->rxnfc_rules, list)
+		am65_cpsw_del_rule(port, rule);
+
+	mutex_unlock(&port->rxnfc_lock);
+}
+
+static int am65_cpsw_set_rxnfc(struct net_device *ndev,
+			       struct ethtool_rxnfc *rxnfc)
+{
+	struct am65_cpsw_port *port = am65_ndev_to_port(ndev);
+
+	switch (rxnfc->cmd) {
+	case ETHTOOL_SRXCLSRLINS:
+		return am65_cpsw_rxnfc_add_rule(port, rxnfc);
+	case ETHTOOL_SRXCLSRLDEL:
+		return am65_cpsw_rxnfc_del_rule(port, rxnfc);
+	default:
+		return -EOPNOTSUPP;
+	}
+}
+
 const struct ethtool_ops am65_cpsw_ethtool_ops_slave = {
 	.begin			= am65_cpsw_ethtool_op_begin,
 	.complete		= am65_cpsw_ethtool_op_complete,
@@ -1007,4 +1362,6 @@ const struct ethtool_ops am65_cpsw_ethtool_ops_slave = {
 	.get_mm			= am65_cpsw_get_mm,
 	.set_mm			= am65_cpsw_set_mm,
 	.get_mm_stats		= am65_cpsw_get_mm_stats,
+	.get_rxnfc		= am65_cpsw_get_rxnfc,
+	.set_rxnfc		= am65_cpsw_set_rxnfc,
 };
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index 07df61f343d3..cdb83ae54656 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -2758,6 +2758,7 @@ am65_cpsw_nuss_init_port_ndev(struct am65_cpsw_common *common, u32 port_idx)
 		return -ENOMEM;
 	}
 
+	am65_cpsw_rxnfc_init(port);
 	ndev_priv = netdev_priv(port->ndev);
 	ndev_priv->port = port;
 	ndev_priv->msg_enable = AM65_CPSW_DEBUG;
@@ -2870,6 +2871,7 @@ static void am65_cpsw_nuss_cleanup_ndev(struct am65_cpsw_common *common)
 			unregister_netdev(port->ndev);
 		free_netdev(port->ndev);
 		port->ndev = NULL;
+		am65_cpsw_rxnfc_cleanup(port);
 	}
 }
 
@@ -3172,6 +3174,7 @@ static int am65_cpsw_dl_switch_mode_set(struct devlink *dl, u32 id,
 	/* clean up ALE table */
 	cpsw_ale_control_set(cpsw->ale, HOST_PORT_NUM, ALE_CLEAR, 1);
 	cpsw_ale_control_get(cpsw->ale, HOST_PORT_NUM, ALE_AGEOUT);
+	cpsw_ale_policer_reset(cpsw->ale);
 
 	if (switch_en) {
 		dev_info(cpsw->dev, "Enable switch mode\n");
diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.h b/drivers/net/ethernet/ti/am65-cpsw-nuss.h
index 61daa5db12e6..8b83c9a0965d 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.h
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.h
@@ -16,6 +16,7 @@
 #include <net/devlink.h>
 #include <net/xdp.h>
 #include "am65-cpsw-qos.h"
+#include "cpsw_ale.h"
 
 struct am65_cpts;
 
@@ -40,6 +41,12 @@ struct am65_cpsw_slave_data {
 	struct phylink_config		phylink_config;
 };
 
+struct am65_cpsw_rxnfc_rule {
+	struct list_head list;
+	unsigned int location;
+	struct cpsw_ale_policer_cfg cfg;
+};
+
 struct am65_cpsw_port {
 	struct am65_cpsw_common		*common;
 	struct net_device		*ndev;
@@ -59,6 +66,11 @@ struct am65_cpsw_port {
 	struct xdp_rxq_info		xdp_rxq[AM65_CPSW_MAX_QUEUES];
 	/* Only for suspend resume context */
 	u32				vid_context;
+	/* Classifier flows */
+	struct mutex rxnfc_lock;
+	struct list_head rxnfc_rules;
+	int rxnfc_count;
+	int rxnfc_max;
 };
 
 enum am65_cpsw_tx_buf_type {
@@ -229,4 +241,7 @@ int am65_cpsw_nuss_update_tx_rx_chns(struct am65_cpsw_common *common,
 
 bool am65_cpsw_port_dev_check(const struct net_device *dev);
 
+void am65_cpsw_rxnfc_init(struct am65_cpsw_port *port);
+void am65_cpsw_rxnfc_cleanup(struct am65_cpsw_port *port);
+
 #endif /* AM65_CPSW_NUSS_H_ */

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* [PATCH net-next v4 9/9] net: ethernet: ti: am65-cpsw: remove cpsw_ale_classifier_setup_default()
  2025-05-14 12:04 [PATCH net-next v4 0/9] net: ethernet: ti: am65-cpsw: add network flow classification support Roger Quadros
                   ` (7 preceding siblings ...)
  2025-05-14 12:04 ` [PATCH net-next v4 8/9] net: ethernet: ti: am65-cpsw: add network flow classification support Roger Quadros
@ 2025-05-14 12:04 ` Roger Quadros
  2025-05-16  9:25   ` Simon Horman
  8 siblings, 1 reply; 17+ messages in thread
From: Roger Quadros @ 2025-05-14 12:04 UTC (permalink / raw)
  To: Siddharth Vadapalli, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Russell King, danishanwar
  Cc: srk, linux-omap, netdev, linux-kernel, Roger Quadros

The RX classifier can now be configured by user using ethtool -N.
So drop cpsw_ale_classifier_setup_default().

Signed-off-by: Roger Quadros <rogerq@kernel.org>
---
 drivers/net/ethernet/ti/am65-cpsw-nuss.c |  3 --
 drivers/net/ethernet/ti/cpsw_ale.c       | 52 --------------------------------
 drivers/net/ethernet/ti/cpsw_ale.h       |  1 -
 3 files changed, 56 deletions(-)

diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
index cdb83ae54656..0523c81a2a54 100644
--- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c
+++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c
@@ -2497,9 +2497,6 @@ static int am65_cpsw_nuss_init_rx_chns(struct am65_cpsw_common *common)
 		}
 	}
 
-	/* setup classifier to route priorities to flows */
-	cpsw_ale_classifier_setup_default(common->ale, common->rx_ch_num_flows);
-
 	return 0;
 
 err_request_irq:
diff --git a/drivers/net/ethernet/ti/cpsw_ale.c b/drivers/net/ethernet/ti/cpsw_ale.c
index 0cd27a6fe575..ba639d87706b 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.c
+++ b/drivers/net/ethernet/ti/cpsw_ale.c
@@ -1695,58 +1695,6 @@ void cpsw_ale_policer_reset(struct cpsw_ale *ale)
 		cpsw_ale_policer_reset_entry(ale, i);
 }
 
-/* Default classifier is to map 8 user priorities to N receive channels */
-void cpsw_ale_classifier_setup_default(struct cpsw_ale *ale, int num_rx_ch)
-{
-	int pri, idx;
-
-	/* Reference:
-	 * IEEE802.1Q-2014, Standard for Local and metropolitan area networks
-	 *    Table I-2 - Traffic type acronyms
-	 *    Table I-3 - Defining traffic types
-	 * Section I.4 Traffic types and priority values, states:
-	 * "0 is thus used both for default priority and for Best Effort, and
-	 *  Background is associated with a priority value of 1. This means
-	 * that the value 1 effectively communicates a lower priority than 0."
-	 *
-	 * In the table below, Priority Code Point (PCP) 0 is assigned
-	 * to a higher priority thread than PCP 1 wherever possible.
-	 * The table maps which thread the PCP traffic needs to be
-	 * sent to for a given number of threads (RX channels). Upper threads
-	 * have higher priority.
-	 * e.g. if number of threads is 8 then user priority 0 will map to
-	 * pri_thread_map[8-1][0] i.e. thread 1
-	 */
-
-	int pri_thread_map[8][8] = {   /* BK,BE,EE,CA,VI,VO,IC,NC */
-					{ 0, 0, 0, 0, 0, 0, 0, 0, },
-					{ 0, 0, 0, 0, 1, 1, 1, 1, },
-					{ 0, 0, 0, 0, 1, 1, 2, 2, },
-					{ 0, 0, 1, 1, 2, 2, 3, 3, },
-					{ 0, 0, 1, 1, 2, 2, 3, 4, },
-					{ 1, 0, 2, 2, 3, 3, 4, 5, },
-					{ 1, 0, 2, 3, 4, 4, 5, 6, },
-					{ 1, 0, 2, 3, 4, 5, 6, 7 } };
-
-	cpsw_ale_policer_reset(ale);
-
-	/* use first 8 classifiers to map 8 (DSCP/PCP) priorities to channels */
-	for (pri = 0; pri < 8; pri++) {
-		idx = pri;
-
-		/* Classifier 'idx' match on priority 'pri' */
-		cpsw_ale_policer_read_idx(ale, idx);
-		regmap_field_write(ale->fields[POL_PRI_VAL], pri);
-		regmap_field_write(ale->fields[POL_PRI_MEN], 1);
-		cpsw_ale_policer_write_idx(ale, idx);
-
-		/* Map Classifier 'idx' to thread provided by the map */
-		cpsw_ale_policer_thread_idx_enable(ale, idx,
-						   pri_thread_map[num_rx_ch - 1][pri],
-						   1);
-	}
-}
-
 #define HOST_PORT_NUM 0
 
 /* Clear Policer and associated ALE table entries */
diff --git a/drivers/net/ethernet/ti/cpsw_ale.h b/drivers/net/ethernet/ti/cpsw_ale.h
index dbc095397389..5c9614730998 100644
--- a/drivers/net/ethernet/ti/cpsw_ale.h
+++ b/drivers/net/ethernet/ti/cpsw_ale.h
@@ -223,7 +223,6 @@ int cpsw_ale_vlan_add_modify(struct cpsw_ale *ale, u16 vid, int port_mask,
 int cpsw_ale_vlan_del_modify(struct cpsw_ale *ale, u16 vid, int port_mask);
 void cpsw_ale_set_unreg_mcast(struct cpsw_ale *ale, int unreg_mcast_mask,
 			      bool add);
-void cpsw_ale_classifier_setup_default(struct cpsw_ale *ale, int num_rx_ch);
 void cpsw_ale_policer_reset(struct cpsw_ale *ale);
 int cpsw_ale_policer_set_entry(struct cpsw_ale *ale, u32 policer_idx,
 			       struct cpsw_ale_policer_cfg *cfg);

-- 
2.34.1


^ permalink raw reply related	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v4 9/9] net: ethernet: ti: am65-cpsw: remove cpsw_ale_classifier_setup_default()
  2025-05-14 12:04 ` [PATCH net-next v4 9/9] net: ethernet: ti: am65-cpsw: remove cpsw_ale_classifier_setup_default() Roger Quadros
@ 2025-05-16  9:25   ` Simon Horman
  2025-08-13 13:12     ` Roger Quadros
  0 siblings, 1 reply; 17+ messages in thread
From: Simon Horman @ 2025-05-16  9:25 UTC (permalink / raw)
  To: Roger Quadros
  Cc: Siddharth Vadapalli, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Russell King, danishanwar, srk,
	linux-omap, netdev, linux-kernel

On Wed, May 14, 2025 at 03:04:29PM +0300, Roger Quadros wrote:
> The RX classifier can now be configured by user using ethtool -N.
> So drop cpsw_ale_classifier_setup_default().
> 
> Signed-off-by: Roger Quadros <rogerq@kernel.org>

Hi Roger,

Could you shed some light on how this effects user's experience,
say after probing the driver but without issuing any ethtool commands?

...

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v4 8/9] net: ethernet: ti: am65-cpsw: add network flow classification support
  2025-05-14 12:04 ` [PATCH net-next v4 8/9] net: ethernet: ti: am65-cpsw: add network flow classification support Roger Quadros
@ 2025-05-17  1:29   ` Jakub Kicinski
  2025-08-13 13:49     ` Roger Quadros
  0 siblings, 1 reply; 17+ messages in thread
From: Jakub Kicinski @ 2025-05-17  1:29 UTC (permalink / raw)
  To: Roger Quadros
  Cc: Siddharth Vadapalli, Andrew Lunn, David S. Miller, Eric Dumazet,
	Paolo Abeni, Russell King, danishanwar, srk, linux-omap, netdev,
	linux-kernel

On Wed, 14 May 2025 15:04:28 +0300 Roger Quadros wrote:
> The TRM doesn't mention anything about order of evaluation of the
> classifier rules however it does mention in [1]
> "if multiple classifier matches occur, the highest match
> with thread enable bit set will be used."

So we're not sure how to maintain the user requested ordering?
Am I reading this correctly? If so then ..

> +	if (fs->location == RX_CLS_LOC_ANY ||

.. why are we rejecting LOC_ANY? 

I'd think that, in fact, LOC_ANY should be the only loc we can support.
Note that ethtool hides the location logic on the CLI, if user doesn't
request a location and driver reports RX_CLS_LOC_SPECIAL ethtool will
set the location to LOC_ANY.

> +	    fs->location >= port->rxnfc_max)
> +		return -EINVAL;

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v4 9/9] net: ethernet: ti: am65-cpsw: remove cpsw_ale_classifier_setup_default()
  2025-05-16  9:25   ` Simon Horman
@ 2025-08-13 13:12     ` Roger Quadros
  0 siblings, 0 replies; 17+ messages in thread
From: Roger Quadros @ 2025-08-13 13:12 UTC (permalink / raw)
  To: Simon Horman
  Cc: Siddharth Vadapalli, Andrew Lunn, David S. Miller, Eric Dumazet,
	Jakub Kicinski, Paolo Abeni, Russell King, danishanwar, srk,
	linux-omap, netdev, linux-kernel

Hi Simon,

On 16/05/2025 12:25, Simon Horman wrote:
> On Wed, May 14, 2025 at 03:04:29PM +0300, Roger Quadros wrote:
>> The RX classifier can now be configured by user using ethtool -N.
>> So drop cpsw_ale_classifier_setup_default().
>>
>> Signed-off-by: Roger Quadros <rogerq@kernel.org>
> 
> Hi Roger,
> 
> Could you shed some light on how this effects user's experience,
> say after probing the driver but without issuing any ethtool commands?
> 

Default behavior is that all traffic is routed to channel 0.
I will mention this in the commit log.

-- 
cheers,
-roger


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v4 8/9] net: ethernet: ti: am65-cpsw: add network flow classification support
  2025-05-17  1:29   ` Jakub Kicinski
@ 2025-08-13 13:49     ` Roger Quadros
  2025-08-13 14:48       ` Jakub Kicinski
  0 siblings, 1 reply; 17+ messages in thread
From: Roger Quadros @ 2025-08-13 13:49 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Siddharth Vadapalli, Andrew Lunn, David S. Miller, Eric Dumazet,
	Paolo Abeni, Russell King, danishanwar, srk, linux-omap, netdev,
	linux-kernel



On 17/05/2025 04:29, Jakub Kicinski wrote:
> On Wed, 14 May 2025 15:04:28 +0300 Roger Quadros wrote:
>> The TRM doesn't mention anything about order of evaluation of the
>> classifier rules however it does mention in [1]
>> "if multiple classifier matches occur, the highest match
>> with thread enable bit set will be used."
> 
> So we're not sure how to maintain the user requested ordering?

Currently we are using the user/ethtool provided location as is.

> Am I reading this correctly? If so then ..
> 
>> +	if (fs->location == RX_CLS_LOC_ANY ||
> 
> .. why are we rejecting LOC_ANY? 

Because driver doesn't have logic to decide the location and relies on ethtool to
decide it if user doesn't supply it.

> 
> I'd think that, in fact, LOC_ANY should be the only loc we can support.
> Note that ethtool hides the location logic on the CLI, if user doesn't
> request a location and driver reports RX_CLS_LOC_SPECIAL ethtool will
> set the location to LOC_ANY.
> 
>> +	    fs->location >= port->rxnfc_max)
>> +		return -EINVAL;

-- 
cheers,
-roger


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v4 8/9] net: ethernet: ti: am65-cpsw: add network flow classification support
  2025-08-13 13:49     ` Roger Quadros
@ 2025-08-13 14:48       ` Jakub Kicinski
  2025-08-14 13:44         ` Roger Quadros
  0 siblings, 1 reply; 17+ messages in thread
From: Jakub Kicinski @ 2025-08-13 14:48 UTC (permalink / raw)
  To: Roger Quadros
  Cc: Siddharth Vadapalli, Andrew Lunn, David S. Miller, Eric Dumazet,
	Paolo Abeni, Russell King, danishanwar, srk, linux-omap, netdev,
	linux-kernel

On Wed, 13 Aug 2025 16:49:27 +0300 Roger Quadros wrote:
> On 17/05/2025 04:29, Jakub Kicinski wrote:
> > On Wed, 14 May 2025 15:04:28 +0300 Roger Quadros wrote:  
> >> The TRM doesn't mention anything about order of evaluation of the
> >> classifier rules however it does mention in [1]
> >> "if multiple classifier matches occur, the highest match
> >> with thread enable bit set will be used."  
> > 
> > So we're not sure how to maintain the user requested ordering?  
> 
> Currently we are using the user/ethtool provided location as is.
> 
> > Am I reading this correctly? If so then ..
> >   
> >> +	if (fs->location == RX_CLS_LOC_ANY ||  
> > 
> > .. why are we rejecting LOC_ANY?   
> 
> Because driver doesn't have logic to decide the location and relies on ethtool to
> decide it if user doesn't supply it.

The location supplied by the user may have semantic significance.
IOW locations may be interpreted as priorities.
It's better to support LOC_ANY and add the 10 lines of code to
allocate the id in the driver..

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v4 8/9] net: ethernet: ti: am65-cpsw: add network flow classification support
  2025-08-13 14:48       ` Jakub Kicinski
@ 2025-08-14 13:44         ` Roger Quadros
  2025-08-14 15:08           ` Jakub Kicinski
  0 siblings, 1 reply; 17+ messages in thread
From: Roger Quadros @ 2025-08-14 13:44 UTC (permalink / raw)
  To: Jakub Kicinski
  Cc: Siddharth Vadapalli, Andrew Lunn, David S. Miller, Eric Dumazet,
	Paolo Abeni, Russell King, danishanwar, srk, linux-omap, netdev,
	linux-kernel



On 13/08/2025 17:48, Jakub Kicinski wrote:
> On Wed, 13 Aug 2025 16:49:27 +0300 Roger Quadros wrote:
>> On 17/05/2025 04:29, Jakub Kicinski wrote:
>>> On Wed, 14 May 2025 15:04:28 +0300 Roger Quadros wrote:  
>>>> The TRM doesn't mention anything about order of evaluation of the
>>>> classifier rules however it does mention in [1]
>>>> "if multiple classifier matches occur, the highest match
>>>> with thread enable bit set will be used."  
>>>
>>> So we're not sure how to maintain the user requested ordering?  
>>
>> Currently we are using the user/ethtool provided location as is.
>>
>>> Am I reading this correctly? If so then ..
>>>   
>>>> +	if (fs->location == RX_CLS_LOC_ANY ||  
>>>
>>> .. why are we rejecting LOC_ANY?   
>>
>> Because driver doesn't have logic to decide the location and relies on ethtool to
>> decide it if user doesn't supply it.
> 
> The location supplied by the user may have semantic significance.
> IOW locations may be interpreted as priorities.

OK. Is there any convention on location vs priority for user or it is driver dependent?
i.e. Does higher location mean higher priority?

> It's better to support LOC_ANY and add the 10 lines of code to
> allocate the id in the driver..

OK.

I did more tests and it seems that higher locations in the classifier override the lower locations.

With this new information, what is the best approach?

I can add support for LOC_ANY with logic to find first available free location.
If driver supports LOC_ANY, does driver also need to support explicit location supplied by user? In this case I think user convention and driver convention of location vs priority must match.

-- 
cheers,
-roger


^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH net-next v4 8/9] net: ethernet: ti: am65-cpsw: add network flow classification support
  2025-08-14 13:44         ` Roger Quadros
@ 2025-08-14 15:08           ` Jakub Kicinski
  0 siblings, 0 replies; 17+ messages in thread
From: Jakub Kicinski @ 2025-08-14 15:08 UTC (permalink / raw)
  To: Roger Quadros
  Cc: Siddharth Vadapalli, Andrew Lunn, David S. Miller, Eric Dumazet,
	Paolo Abeni, Russell King, danishanwar, srk, linux-omap, netdev,
	linux-kernel

On Thu, 14 Aug 2025 16:44:49 +0300 Roger Quadros wrote:
> >> Because driver doesn't have logic to decide the location and relies on ethtool to
> >> decide it if user doesn't supply it.  
> > 
> > The location supplied by the user may have semantic significance.
> > IOW locations may be interpreted as priorities.  
> 
> OK. Is there any convention on location vs priority for user or it is driver dependent?
> i.e. Does higher location mean higher priority?

/**
 * struct ethtool_rx_flow_spec - classification rule for RX flows
[...]
 * @location: Location of rule in the table.  Locations must be
 *	numbered such that a flow matching multiple rules will be
 *	classified according to the first (lowest numbered) rule.
 */

> > It's better to support LOC_ANY and add the 10 lines of code to
> > allocate the id in the driver..  
> 
> OK.
> 
> I did more tests and it seems that higher locations in the classifier override the lower locations.
> 
> With this new information, what is the best approach?
> 
> I can add support for LOC_ANY with logic to find first available free location.
> If driver supports LOC_ANY, does driver also need to support explicit
> location supplied by user? In this case I think user convention and
> driver convention of location vs priority must match.

If your device supports ordering then it's up to you.
LOC_ANY has slight performance advantage, because CLI doesn't have 
to dump all the rules to find an unused ID. But I'm mostly concerned
about the semantics, the performance thing may not matter, depending
on how many rules you can support in the first place.. up to you.

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2025-08-14 15:08 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-14 12:04 [PATCH net-next v4 0/9] net: ethernet: ti: am65-cpsw: add network flow classification support Roger Quadros
2025-05-14 12:04 ` [PATCH net-next v4 1/9] net: ethernet: ti: cpsw_ale: Update Policer fields for more ALE size/ports Roger Quadros
2025-05-14 12:04 ` [PATCH net-next v4 2/9] net: ethernet: ti: cpsw_ale: return ALE index in cpsw_ale_add_vlan() Roger Quadros
2025-05-14 12:04 ` [PATCH net-next v4 3/9] net: ethernet: ti: cpsw_ale: return ALE index in cpsw_ale_vlan_add_modify() Roger Quadros
2025-05-14 12:04 ` [PATCH net-next v4 4/9] net: ethernet: ti: cpsw_ale: return ALE index in cpsw_ale_add_ucast() Roger Quadros
2025-05-14 12:04 ` [PATCH net-next v4 5/9] net: ethernet: ti: cpsw_ale: add cpsw_ale_policer_reset_entry() Roger Quadros
2025-05-14 12:04 ` [PATCH net-next v4 6/9] net: ethernet: ti: cpsw_ale: add cpsw_ale_policer_set/clr_entry() Roger Quadros
2025-05-14 12:04 ` [PATCH net-next v4 7/9] net: ethernet: ti: cpsw_ale: add policer save restore for PM sleep Roger Quadros
2025-05-14 12:04 ` [PATCH net-next v4 8/9] net: ethernet: ti: am65-cpsw: add network flow classification support Roger Quadros
2025-05-17  1:29   ` Jakub Kicinski
2025-08-13 13:49     ` Roger Quadros
2025-08-13 14:48       ` Jakub Kicinski
2025-08-14 13:44         ` Roger Quadros
2025-08-14 15:08           ` Jakub Kicinski
2025-05-14 12:04 ` [PATCH net-next v4 9/9] net: ethernet: ti: am65-cpsw: remove cpsw_ale_classifier_setup_default() Roger Quadros
2025-05-16  9:25   ` Simon Horman
2025-08-13 13:12     ` Roger Quadros

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).