[PATCH net-next 3/5] net: sparx5: Track shared tc blocks and per-port policer state

From: Daniel Machon

Date: Fri Oct 09 2026 - 08:52:41 EST


A police action on a shared tc block applies one aggregate rate to all
ports bound to the block, which a per-port policer cannot implement.
The port policer offload therefore needs to know whether the ingress
block of a port is shared.

Add struct sparx5_port_tc to each port, holding a flag that records
whether the ingress block is shared, and the state of the four policers
of the port.

Signed-off-by: Daniel Machon <daniel.machon@xxxxxxxxxxxxx>
---
drivers/net/ethernet/microchip/sparx5/sparx5_main.h | 16 ++++++++++++++++
drivers/net/ethernet/microchip/sparx5/sparx5_tc.c | 14 ++++++++++++--
2 files changed, 28 insertions(+), 2 deletions(-)

diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h
index 0f7d8440f614..021ac7a52034 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h
@@ -206,6 +206,21 @@ struct sparx5_port_config {
u32 sd_sgpio;
};

+#define SPX5_POLICERS_PER_PORT 4 /* Number of ingress port policers */
+
+struct sparx5_port_policer {
+ struct flow_stats prev;
+ struct flow_stats stats;
+ /* Port policers hold the client reference (cookie) */
+ unsigned long policer;
+};
+
+struct sparx5_port_tc {
+ /* Ingress uses a shared filter block */
+ bool ingress_block_shared;
+ struct sparx5_port_policer port_policer[SPX5_POLICERS_PER_PORT];
+};
+
struct sparx5_port {
struct net_device *ndev;
struct sparx5 *sparx5;
@@ -229,6 +244,7 @@ struct sparx5_port {
enum sparx5_vlan_port_type vlan_type;
u32 custom_etype;
bool vlan_aware;
+ struct sparx5_port_tc tc;
struct hrtimer inj_timer;
/* ptp */
u8 ptp_cmd;
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_tc.c b/drivers/net/ethernet/microchip/sparx5/sparx5_tc.c
index 28b2514c8330..9ac99627eafc 100644
--- a/drivers/net/ethernet/microchip/sparx5/sparx5_tc.c
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_tc.c
@@ -47,7 +47,9 @@ static int sparx5_tc_block_cb_egress(enum tc_setup_type type,
static int sparx5_tc_setup_block(struct net_device *ndev,
struct flow_block_offload *fbo)
{
+ struct sparx5_port *port = netdev_priv(ndev);
flow_setup_cb_t *cb;
+ int err;

if (fbo->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
cb = sparx5_tc_block_cb_ingress;
@@ -56,8 +58,16 @@ static int sparx5_tc_setup_block(struct net_device *ndev,
else
return -EOPNOTSUPP;

- return flow_block_cb_setup_simple(fbo, &sparx5_block_cb_list,
- cb, ndev, ndev, false);
+ err = flow_block_cb_setup_simple(fbo, &sparx5_block_cb_list,
+ cb, ndev, ndev, false);
+ if (err)
+ return err;
+
+ if (fbo->binder_type == FLOW_BLOCK_BINDER_TYPE_CLSACT_INGRESS)
+ port->tc.ingress_block_shared =
+ fbo->command == FLOW_BLOCK_BIND && fbo->block_shared;
+
+ return 0;
}

static void sparx5_tc_get_layer_and_idx(struct sparx5 *sparx5, u32 parent,

--
2.34.1