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 --- 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 8dc3a500c1c91..19217d443cc74 100644 --- a/drivers/net/ethernet/microchip/sparx5/sparx5_main.h +++ b/drivers/net/ethernet/microchip/sparx5/sparx5_main.h @@ -207,6 +207,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; @@ -230,6 +245,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 30da5db57ef35..fd5a75aa09603 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