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