brintos

brintos / linux-shallow public Read only

0
0
Text · 5.9 KiB · 7302df2 Raw
227 lines · c
1// SPDX-License-Identifier: GPL-2.0+2 3#include "lan966x_main.h"4 5/* 0-8 : 9 port policers */6#define POL_IDX_PORT	07 8/* Policer order: Serial (QoS -> Port -> VCAP) */9#define POL_ORDER	0x1d310 11struct lan966x_tc_policer {12	/* kilobit per second */13	u32 rate;14	/* bytes */15	u32 burst;16};17 18static int lan966x_police_add(struct lan966x_port *port,19			      struct lan966x_tc_policer *pol,20			      u16 pol_idx)21{22	struct lan966x *lan966x = port->lan966x;23 24	/* Rate unit is 33 1/3 kpps */25	pol->rate = DIV_ROUND_UP(pol->rate * 3, 100);26	/* Avoid zero burst size */27	pol->burst = pol->burst ?: 1;28	/* Unit is 4kB */29	pol->burst = DIV_ROUND_UP(pol->burst, 4096);30 31	if (pol->rate > GENMASK(15, 0) ||32	    pol->burst > GENMASK(6, 0))33		return -EINVAL;34 35	lan_wr(ANA_POL_MODE_DROP_ON_YELLOW_ENA_SET(0) |36	       ANA_POL_MODE_MARK_ALL_FRMS_RED_ENA_SET(0) |37	       ANA_POL_MODE_IPG_SIZE_SET(20) |38	       ANA_POL_MODE_FRM_MODE_SET(1) |39	       ANA_POL_MODE_OVERSHOOT_ENA_SET(1),40	       lan966x, ANA_POL_MODE(pol_idx));41 42	lan_wr(ANA_POL_PIR_STATE_PIR_LVL_SET(0),43	       lan966x, ANA_POL_PIR_STATE(pol_idx));44 45	lan_wr(ANA_POL_PIR_CFG_PIR_RATE_SET(pol->rate) |46	       ANA_POL_PIR_CFG_PIR_BURST_SET(pol->burst),47	       lan966x, ANA_POL_PIR_CFG(pol_idx));48 49	return 0;50}51 52static void lan966x_police_del(struct lan966x_port *port, u16 pol_idx)53{54	struct lan966x *lan966x = port->lan966x;55 56	lan_wr(ANA_POL_MODE_DROP_ON_YELLOW_ENA_SET(0) |57	       ANA_POL_MODE_MARK_ALL_FRMS_RED_ENA_SET(0) |58	       ANA_POL_MODE_IPG_SIZE_SET(20) |59	       ANA_POL_MODE_FRM_MODE_SET(2) |60	       ANA_POL_MODE_OVERSHOOT_ENA_SET(1),61	       lan966x, ANA_POL_MODE(pol_idx));62 63	lan_wr(ANA_POL_PIR_STATE_PIR_LVL_SET(0),64	       lan966x, ANA_POL_PIR_STATE(pol_idx));65 66	lan_wr(ANA_POL_PIR_CFG_PIR_RATE_SET(GENMASK(14, 0)) |67	       ANA_POL_PIR_CFG_PIR_BURST_SET(0),68	       lan966x, ANA_POL_PIR_CFG(pol_idx));69}70 71static int lan966x_police_validate(struct lan966x_port *port,72				   const struct flow_action *action,73				   const struct flow_action_entry *act,74				   unsigned long police_id,75				   bool ingress,76				   struct netlink_ext_ack *extack)77{78	if (act->police.exceed.act_id != FLOW_ACTION_DROP) {79		NL_SET_ERR_MSG_MOD(extack,80				   "Offload not supported when exceed action is not drop");81		return -EOPNOTSUPP;82	}83 84	if (act->police.notexceed.act_id != FLOW_ACTION_PIPE &&85	    act->police.notexceed.act_id != FLOW_ACTION_ACCEPT) {86		NL_SET_ERR_MSG_MOD(extack,87				   "Offload not supported when conform action is not pipe or ok");88		return -EOPNOTSUPP;89	}90 91	if (act->police.notexceed.act_id == FLOW_ACTION_ACCEPT &&92	    !flow_action_is_last_entry(action, act)) {93		NL_SET_ERR_MSG_MOD(extack,94				   "Offload not supported when conform action is ok, but action is not last");95		return -EOPNOTSUPP;96	}97 98	if (act->police.peakrate_bytes_ps ||99	    act->police.avrate || act->police.overhead) {100		NL_SET_ERR_MSG_MOD(extack,101				   "Offload not supported when peakrate/avrate/overhead is configured");102		return -EOPNOTSUPP;103	}104 105	if (act->police.rate_pkt_ps) {106		NL_SET_ERR_MSG_MOD(extack,107				   "QoS offload not support packets per second");108		return -EOPNOTSUPP;109	}110 111	if (!ingress) {112		NL_SET_ERR_MSG_MOD(extack,113				   "Policer is not supported on egress");114		return -EOPNOTSUPP;115	}116 117	if (port->tc.ingress_shared_block) {118		NL_SET_ERR_MSG_MOD(extack,119				   "Policer is not supported on shared ingress blocks");120		return -EOPNOTSUPP;121	}122 123	if (port->tc.police_id && port->tc.police_id != police_id) {124		NL_SET_ERR_MSG_MOD(extack,125				   "Only one policer per port is supported");126		return -EEXIST;127	}128 129	return 0;130}131 132int lan966x_police_port_add(struct lan966x_port *port,133			    struct flow_action *action,134			    struct flow_action_entry *act,135			    unsigned long police_id,136			    bool ingress,137			    struct netlink_ext_ack *extack)138{139	struct lan966x *lan966x = port->lan966x;140	struct rtnl_link_stats64 new_stats;141	struct lan966x_tc_policer pol;142	struct flow_stats *old_stats;143	int err;144 145	err = lan966x_police_validate(port, action, act, police_id, ingress,146				      extack);147	if (err)148		return err;149 150	memset(&pol, 0, sizeof(pol));151 152	pol.rate = div_u64(act->police.rate_bytes_ps, 1000) * 8;153	pol.burst = act->police.burst;154 155	err = lan966x_police_add(port, &pol, POL_IDX_PORT + port->chip_port);156	if (err) {157		NL_SET_ERR_MSG_MOD(extack,158				   "Failed to add policer to port");159		return err;160	}161 162	lan_rmw(ANA_POL_CFG_PORT_POL_ENA_SET(1) |163		ANA_POL_CFG_POL_ORDER_SET(POL_ORDER),164		ANA_POL_CFG_PORT_POL_ENA |165		ANA_POL_CFG_POL_ORDER,166		lan966x, ANA_POL_CFG(port->chip_port));167 168	port->tc.police_id = police_id;169 170	/* Setup initial stats */171	old_stats = &port->tc.police_stat;172	lan966x_stats_get(port->dev, &new_stats);173	old_stats->bytes = new_stats.rx_bytes;174	old_stats->pkts = new_stats.rx_packets;175	old_stats->drops = new_stats.rx_dropped;176	old_stats->lastused = jiffies;177 178	return 0;179}180 181int lan966x_police_port_del(struct lan966x_port *port,182			    unsigned long police_id,183			    struct netlink_ext_ack *extack)184{185	struct lan966x *lan966x = port->lan966x;186 187	if (port->tc.police_id != police_id) {188		NL_SET_ERR_MSG_MOD(extack,189				   "Invalid policer id");190		return -EINVAL;191	}192 193	lan966x_police_del(port, POL_IDX_PORT + port->chip_port);194 195	lan_rmw(ANA_POL_CFG_PORT_POL_ENA_SET(0) |196		ANA_POL_CFG_POL_ORDER_SET(POL_ORDER),197		ANA_POL_CFG_PORT_POL_ENA |198		ANA_POL_CFG_POL_ORDER,199		lan966x, ANA_POL_CFG(port->chip_port));200 201	port->tc.police_id = 0;202 203	return 0;204}205 206void lan966x_police_port_stats(struct lan966x_port *port,207			       struct flow_stats *stats)208{209	struct rtnl_link_stats64 new_stats;210	struct flow_stats *old_stats;211 212	old_stats = &port->tc.police_stat;213	lan966x_stats_get(port->dev, &new_stats);214 215	flow_stats_update(stats,216			  new_stats.rx_bytes - old_stats->bytes,217			  new_stats.rx_packets - old_stats->pkts,218			  new_stats.rx_dropped - old_stats->drops,219			  old_stats->lastused,220			  FLOW_ACTION_HW_STATS_IMMEDIATE);221 222	old_stats->bytes = new_stats.rx_bytes;223	old_stats->pkts = new_stats.rx_packets;224	old_stats->drops = new_stats.rx_dropped;225	old_stats->lastused = jiffies;226}227