Merge tag 'for-linus-2023030901' of git://git.kernel.org/pub/scm/linux/kernel/git...
[platform/kernel/linux-rpi.git] / drivers / net / ethernet / microchip / lan966x / lan966x_police.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    0
7
8 /* Policer order: Serial (QoS -> Port -> VCAP) */
9 #define POL_ORDER       0x1d3
10
11 struct lan966x_tc_policer {
12         /* kilobit per second */
13         u32 rate;
14         /* bytes */
15         u32 burst;
16 };
17
18 static 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
52 static int lan966x_police_del(struct lan966x_port *port,
53                               u16 pol_idx)
54 {
55         struct lan966x *lan966x = port->lan966x;
56
57         lan_wr(ANA_POL_MODE_DROP_ON_YELLOW_ENA_SET(0) |
58                ANA_POL_MODE_MARK_ALL_FRMS_RED_ENA_SET(0) |
59                ANA_POL_MODE_IPG_SIZE_SET(20) |
60                ANA_POL_MODE_FRM_MODE_SET(2) |
61                ANA_POL_MODE_OVERSHOOT_ENA_SET(1),
62                lan966x, ANA_POL_MODE(pol_idx));
63
64         lan_wr(ANA_POL_PIR_STATE_PIR_LVL_SET(0),
65                lan966x, ANA_POL_PIR_STATE(pol_idx));
66
67         lan_wr(ANA_POL_PIR_CFG_PIR_RATE_SET(GENMASK(14, 0)) |
68                ANA_POL_PIR_CFG_PIR_BURST_SET(0),
69                lan966x, ANA_POL_PIR_CFG(pol_idx));
70
71         return 0;
72 }
73
74 static int lan966x_police_validate(struct lan966x_port *port,
75                                    const struct flow_action *action,
76                                    const struct flow_action_entry *act,
77                                    unsigned long police_id,
78                                    bool ingress,
79                                    struct netlink_ext_ack *extack)
80 {
81         if (act->police.exceed.act_id != FLOW_ACTION_DROP) {
82                 NL_SET_ERR_MSG_MOD(extack,
83                                    "Offload not supported when exceed action is not drop");
84                 return -EOPNOTSUPP;
85         }
86
87         if (act->police.notexceed.act_id != FLOW_ACTION_PIPE &&
88             act->police.notexceed.act_id != FLOW_ACTION_ACCEPT) {
89                 NL_SET_ERR_MSG_MOD(extack,
90                                    "Offload not supported when conform action is not pipe or ok");
91                 return -EOPNOTSUPP;
92         }
93
94         if (act->police.notexceed.act_id == FLOW_ACTION_ACCEPT &&
95             !flow_action_is_last_entry(action, act)) {
96                 NL_SET_ERR_MSG_MOD(extack,
97                                    "Offload not supported when conform action is ok, but action is not last");
98                 return -EOPNOTSUPP;
99         }
100
101         if (act->police.peakrate_bytes_ps ||
102             act->police.avrate || act->police.overhead) {
103                 NL_SET_ERR_MSG_MOD(extack,
104                                    "Offload not supported when peakrate/avrate/overhead is configured");
105                 return -EOPNOTSUPP;
106         }
107
108         if (act->police.rate_pkt_ps) {
109                 NL_SET_ERR_MSG_MOD(extack,
110                                    "QoS offload not support packets per second");
111                 return -EOPNOTSUPP;
112         }
113
114         if (!ingress) {
115                 NL_SET_ERR_MSG_MOD(extack,
116                                    "Policer is not supported on egress");
117                 return -EOPNOTSUPP;
118         }
119
120         if (port->tc.ingress_shared_block) {
121                 NL_SET_ERR_MSG_MOD(extack,
122                                    "Policer is not supported on shared ingress blocks");
123                 return -EOPNOTSUPP;
124         }
125
126         if (port->tc.police_id && port->tc.police_id != police_id) {
127                 NL_SET_ERR_MSG_MOD(extack,
128                                    "Only one policer per port is supported");
129                 return -EEXIST;
130         }
131
132         return 0;
133 }
134
135 int lan966x_police_port_add(struct lan966x_port *port,
136                             struct flow_action *action,
137                             struct flow_action_entry *act,
138                             unsigned long police_id,
139                             bool ingress,
140                             struct netlink_ext_ack *extack)
141 {
142         struct lan966x *lan966x = port->lan966x;
143         struct rtnl_link_stats64 new_stats;
144         struct lan966x_tc_policer pol;
145         struct flow_stats *old_stats;
146         int err;
147
148         err = lan966x_police_validate(port, action, act, police_id, ingress,
149                                       extack);
150         if (err)
151                 return err;
152
153         memset(&pol, 0, sizeof(pol));
154
155         pol.rate = div_u64(act->police.rate_bytes_ps, 1000) * 8;
156         pol.burst = act->police.burst;
157
158         err = lan966x_police_add(port, &pol, POL_IDX_PORT + port->chip_port);
159         if (err) {
160                 NL_SET_ERR_MSG_MOD(extack,
161                                    "Failed to add policer to port");
162                 return err;
163         }
164
165         lan_rmw(ANA_POL_CFG_PORT_POL_ENA_SET(1) |
166                 ANA_POL_CFG_POL_ORDER_SET(POL_ORDER),
167                 ANA_POL_CFG_PORT_POL_ENA |
168                 ANA_POL_CFG_POL_ORDER,
169                 lan966x, ANA_POL_CFG(port->chip_port));
170
171         port->tc.police_id = police_id;
172
173         /* Setup initial stats */
174         old_stats = &port->tc.police_stat;
175         lan966x_stats_get(port->dev, &new_stats);
176         old_stats->bytes = new_stats.rx_bytes;
177         old_stats->pkts = new_stats.rx_packets;
178         old_stats->drops = new_stats.rx_dropped;
179         old_stats->lastused = jiffies;
180
181         return 0;
182 }
183
184 int lan966x_police_port_del(struct lan966x_port *port,
185                             unsigned long police_id,
186                             struct netlink_ext_ack *extack)
187 {
188         struct lan966x *lan966x = port->lan966x;
189         int err;
190
191         if (port->tc.police_id != police_id) {
192                 NL_SET_ERR_MSG_MOD(extack,
193                                    "Invalid policer id");
194                 return -EINVAL;
195         }
196
197         err = lan966x_police_del(port, port->tc.police_id);
198         if (err) {
199                 NL_SET_ERR_MSG_MOD(extack,
200                                    "Failed to add policer to port");
201                 return err;
202         }
203
204         lan_rmw(ANA_POL_CFG_PORT_POL_ENA_SET(0) |
205                 ANA_POL_CFG_POL_ORDER_SET(POL_ORDER),
206                 ANA_POL_CFG_PORT_POL_ENA |
207                 ANA_POL_CFG_POL_ORDER,
208                 lan966x, ANA_POL_CFG(port->chip_port));
209
210         port->tc.police_id = 0;
211
212         return 0;
213 }
214
215 void lan966x_police_port_stats(struct lan966x_port *port,
216                                struct flow_stats *stats)
217 {
218         struct rtnl_link_stats64 new_stats;
219         struct flow_stats *old_stats;
220
221         old_stats = &port->tc.police_stat;
222         lan966x_stats_get(port->dev, &new_stats);
223
224         flow_stats_update(stats,
225                           new_stats.rx_bytes - old_stats->bytes,
226                           new_stats.rx_packets - old_stats->pkts,
227                           new_stats.rx_dropped - old_stats->drops,
228                           old_stats->lastused,
229                           FLOW_ACTION_HW_STATS_IMMEDIATE);
230
231         old_stats->bytes = new_stats.rx_bytes;
232         old_stats->pkts = new_stats.rx_packets;
233         old_stats->drops = new_stats.rx_dropped;
234         old_stats->lastused = jiffies;
235 }