Merge branch 'for-v5.13-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/ebieder...
[linux-2.6-microblaze.git] / drivers / net / ethernet / mellanox / mlxsw / spectrum_policer.c
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /* Copyright (c) 2020 Mellanox Technologies. All rights reserved */
3
4 #include <linux/idr.h>
5 #include <linux/log2.h>
6 #include <linux/mutex.h>
7 #include <linux/netlink.h>
8 #include <net/devlink.h>
9
10 #include "spectrum.h"
11
12 struct mlxsw_sp_policer_family {
13         enum mlxsw_sp_policer_type type;
14         enum mlxsw_reg_qpcr_g qpcr_type;
15         struct mlxsw_sp *mlxsw_sp;
16         u16 start_index; /* Inclusive */
17         u16 end_index; /* Exclusive */
18         struct idr policer_idr;
19         struct mutex lock; /* Protects policer_idr */
20         atomic_t policers_count;
21         const struct mlxsw_sp_policer_family_ops *ops;
22 };
23
24 struct mlxsw_sp_policer {
25         struct mlxsw_sp_policer_params params;
26         u16 index;
27 };
28
29 struct mlxsw_sp_policer_family_ops {
30         int (*init)(struct mlxsw_sp_policer_family *family);
31         void (*fini)(struct mlxsw_sp_policer_family *family);
32         int (*policer_index_alloc)(struct mlxsw_sp_policer_family *family,
33                                    struct mlxsw_sp_policer *policer);
34         struct mlxsw_sp_policer * (*policer_index_free)(struct mlxsw_sp_policer_family *family,
35                                                         u16 policer_index);
36         int (*policer_init)(struct mlxsw_sp_policer_family *family,
37                             const struct mlxsw_sp_policer *policer);
38         int (*policer_params_check)(const struct mlxsw_sp_policer_family *family,
39                                     const struct mlxsw_sp_policer_params *params,
40                                     struct netlink_ext_ack *extack);
41 };
42
43 struct mlxsw_sp_policer_core {
44         struct mlxsw_sp_policer_family *family_arr[MLXSW_SP_POLICER_TYPE_MAX + 1];
45         const struct mlxsw_sp_policer_core_ops *ops;
46         u8 lowest_bs_bits;
47         u8 highest_bs_bits;
48 };
49
50 struct mlxsw_sp_policer_core_ops {
51         int (*init)(struct mlxsw_sp_policer_core *policer_core);
52 };
53
54 static u64 mlxsw_sp_policer_rate_bytes_ps_kbps(u64 rate_bytes_ps)
55 {
56         return div_u64(rate_bytes_ps, 1000) * BITS_PER_BYTE;
57 }
58
59 static u8 mlxsw_sp_policer_burst_bytes_hw_units(u64 burst_bytes)
60 {
61         /* Provided burst size is in bytes. The ASIC burst size value is
62          * (2 ^ bs) * 512 bits. Convert the provided size to 512-bit units.
63          */
64         u64 bs512 = div_u64(burst_bytes, 64);
65
66         if (!bs512)
67                 return 0;
68
69         return fls64(bs512) - 1;
70 }
71
72 static u64 mlxsw_sp_policer_single_rate_occ_get(void *priv)
73 {
74         struct mlxsw_sp_policer_family *family = priv;
75
76         return atomic_read(&family->policers_count);
77 }
78
79 static int
80 mlxsw_sp_policer_single_rate_family_init(struct mlxsw_sp_policer_family *family)
81 {
82         struct mlxsw_core *core = family->mlxsw_sp->core;
83         struct devlink *devlink;
84
85         /* CPU policers are allocated from the first N policers in the global
86          * range, so skip them.
87          */
88         if (!MLXSW_CORE_RES_VALID(core, MAX_GLOBAL_POLICERS) ||
89             !MLXSW_CORE_RES_VALID(core, MAX_CPU_POLICERS))
90                 return -EIO;
91
92         family->start_index = MLXSW_CORE_RES_GET(core, MAX_CPU_POLICERS);
93         family->end_index = MLXSW_CORE_RES_GET(core, MAX_GLOBAL_POLICERS);
94
95         atomic_set(&family->policers_count, 0);
96         devlink = priv_to_devlink(core);
97         devlink_resource_occ_get_register(devlink,
98                                           MLXSW_SP_RESOURCE_SINGLE_RATE_POLICERS,
99                                           mlxsw_sp_policer_single_rate_occ_get,
100                                           family);
101
102         return 0;
103 }
104
105 static void
106 mlxsw_sp_policer_single_rate_family_fini(struct mlxsw_sp_policer_family *family)
107 {
108         struct devlink *devlink = priv_to_devlink(family->mlxsw_sp->core);
109
110         devlink_resource_occ_get_unregister(devlink,
111                                             MLXSW_SP_RESOURCE_SINGLE_RATE_POLICERS);
112         WARN_ON(atomic_read(&family->policers_count) != 0);
113 }
114
115 static int
116 mlxsw_sp_policer_single_rate_index_alloc(struct mlxsw_sp_policer_family *family,
117                                          struct mlxsw_sp_policer *policer)
118 {
119         int id;
120
121         mutex_lock(&family->lock);
122         id = idr_alloc(&family->policer_idr, policer, family->start_index,
123                        family->end_index, GFP_KERNEL);
124         mutex_unlock(&family->lock);
125
126         if (id < 0)
127                 return id;
128
129         atomic_inc(&family->policers_count);
130         policer->index = id;
131
132         return 0;
133 }
134
135 static struct mlxsw_sp_policer *
136 mlxsw_sp_policer_single_rate_index_free(struct mlxsw_sp_policer_family *family,
137                                         u16 policer_index)
138 {
139         struct mlxsw_sp_policer *policer;
140
141         atomic_dec(&family->policers_count);
142
143         mutex_lock(&family->lock);
144         policer = idr_remove(&family->policer_idr, policer_index);
145         mutex_unlock(&family->lock);
146
147         WARN_ON(!policer);
148
149         return policer;
150 }
151
152 static int
153 mlxsw_sp_policer_single_rate_init(struct mlxsw_sp_policer_family *family,
154                                   const struct mlxsw_sp_policer *policer)
155 {
156         u64 rate_kbps = mlxsw_sp_policer_rate_bytes_ps_kbps(policer->params.rate);
157         u8 bs = mlxsw_sp_policer_burst_bytes_hw_units(policer->params.burst);
158         struct mlxsw_sp *mlxsw_sp = family->mlxsw_sp;
159         char qpcr_pl[MLXSW_REG_QPCR_LEN];
160
161         mlxsw_reg_qpcr_pack(qpcr_pl, policer->index, MLXSW_REG_QPCR_IR_UNITS_K,
162                             true, rate_kbps, bs);
163         mlxsw_reg_qpcr_clear_counter_set(qpcr_pl, true);
164
165         return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qpcr), qpcr_pl);
166 }
167
168 static int
169 mlxsw_sp_policer_single_rate_params_check(const struct mlxsw_sp_policer_family *family,
170                                           const struct mlxsw_sp_policer_params *params,
171                                           struct netlink_ext_ack *extack)
172 {
173         struct mlxsw_sp_policer_core *policer_core = family->mlxsw_sp->policer_core;
174         u64 rate_bps = params->rate * BITS_PER_BYTE;
175         u8 bs;
176
177         if (!params->bytes) {
178                 NL_SET_ERR_MSG_MOD(extack, "Only bandwidth policing is currently supported by single rate policers");
179                 return -EINVAL;
180         }
181
182         if (!is_power_of_2(params->burst)) {
183                 NL_SET_ERR_MSG_MOD(extack, "Policer burst size is not power of two");
184                 return -EINVAL;
185         }
186
187         bs = mlxsw_sp_policer_burst_bytes_hw_units(params->burst);
188
189         if (bs < policer_core->lowest_bs_bits) {
190                 NL_SET_ERR_MSG_MOD(extack, "Policer burst size lower than limit");
191                 return -EINVAL;
192         }
193
194         if (bs > policer_core->highest_bs_bits) {
195                 NL_SET_ERR_MSG_MOD(extack, "Policer burst size higher than limit");
196                 return -EINVAL;
197         }
198
199         if (rate_bps < MLXSW_REG_QPCR_LOWEST_CIR_BITS) {
200                 NL_SET_ERR_MSG_MOD(extack, "Policer rate lower than limit");
201                 return -EINVAL;
202         }
203
204         if (rate_bps > MLXSW_REG_QPCR_HIGHEST_CIR_BITS) {
205                 NL_SET_ERR_MSG_MOD(extack, "Policer rate higher than limit");
206                 return -EINVAL;
207         }
208
209         return 0;
210 }
211
212 static const struct mlxsw_sp_policer_family_ops mlxsw_sp_policer_single_rate_ops = {
213         .init                   = mlxsw_sp_policer_single_rate_family_init,
214         .fini                   = mlxsw_sp_policer_single_rate_family_fini,
215         .policer_index_alloc    = mlxsw_sp_policer_single_rate_index_alloc,
216         .policer_index_free     = mlxsw_sp_policer_single_rate_index_free,
217         .policer_init           = mlxsw_sp_policer_single_rate_init,
218         .policer_params_check   = mlxsw_sp_policer_single_rate_params_check,
219 };
220
221 static const struct mlxsw_sp_policer_family mlxsw_sp_policer_single_rate_family = {
222         .type           = MLXSW_SP_POLICER_TYPE_SINGLE_RATE,
223         .qpcr_type      = MLXSW_REG_QPCR_G_GLOBAL,
224         .ops            = &mlxsw_sp_policer_single_rate_ops,
225 };
226
227 static const struct mlxsw_sp_policer_family *mlxsw_sp_policer_family_arr[] = {
228         [MLXSW_SP_POLICER_TYPE_SINGLE_RATE]     = &mlxsw_sp_policer_single_rate_family,
229 };
230
231 int mlxsw_sp_policer_add(struct mlxsw_sp *mlxsw_sp,
232                          enum mlxsw_sp_policer_type type,
233                          const struct mlxsw_sp_policer_params *params,
234                          struct netlink_ext_ack *extack, u16 *p_policer_index)
235 {
236         struct mlxsw_sp_policer_family *family;
237         struct mlxsw_sp_policer *policer;
238         int err;
239
240         family = mlxsw_sp->policer_core->family_arr[type];
241
242         err = family->ops->policer_params_check(family, params, extack);
243         if (err)
244                 return err;
245
246         policer = kmalloc(sizeof(*policer), GFP_KERNEL);
247         if (!policer)
248                 return -ENOMEM;
249         policer->params = *params;
250
251         err = family->ops->policer_index_alloc(family, policer);
252         if (err) {
253                 NL_SET_ERR_MSG_MOD(extack, "Failed to allocate policer index");
254                 goto err_policer_index_alloc;
255         }
256
257         err = family->ops->policer_init(family, policer);
258         if (err) {
259                 NL_SET_ERR_MSG_MOD(extack, "Failed to initialize policer");
260                 goto err_policer_init;
261         }
262
263         *p_policer_index = policer->index;
264
265         return 0;
266
267 err_policer_init:
268         family->ops->policer_index_free(family, policer->index);
269 err_policer_index_alloc:
270         kfree(policer);
271         return err;
272 }
273
274 void mlxsw_sp_policer_del(struct mlxsw_sp *mlxsw_sp,
275                           enum mlxsw_sp_policer_type type, u16 policer_index)
276 {
277         struct mlxsw_sp_policer_family *family;
278         struct mlxsw_sp_policer *policer;
279
280         family = mlxsw_sp->policer_core->family_arr[type];
281         policer = family->ops->policer_index_free(family, policer_index);
282         kfree(policer);
283 }
284
285 int mlxsw_sp_policer_drops_counter_get(struct mlxsw_sp *mlxsw_sp,
286                                        enum mlxsw_sp_policer_type type,
287                                        u16 policer_index, u64 *p_drops)
288 {
289         struct mlxsw_sp_policer_family *family;
290         char qpcr_pl[MLXSW_REG_QPCR_LEN];
291         int err;
292
293         family = mlxsw_sp->policer_core->family_arr[type];
294
295         MLXSW_REG_ZERO(qpcr, qpcr_pl);
296         mlxsw_reg_qpcr_pid_set(qpcr_pl, policer_index);
297         mlxsw_reg_qpcr_g_set(qpcr_pl, family->qpcr_type);
298         err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(qpcr), qpcr_pl);
299         if (err)
300                 return err;
301
302         *p_drops = mlxsw_reg_qpcr_violate_count_get(qpcr_pl);
303
304         return 0;
305 }
306
307 static int
308 mlxsw_sp_policer_family_register(struct mlxsw_sp *mlxsw_sp,
309                                  const struct mlxsw_sp_policer_family *tmpl)
310 {
311         struct mlxsw_sp_policer_family *family;
312         int err;
313
314         family = kmemdup(tmpl, sizeof(*family), GFP_KERNEL);
315         if (!family)
316                 return -ENOMEM;
317
318         family->mlxsw_sp = mlxsw_sp;
319         idr_init(&family->policer_idr);
320         mutex_init(&family->lock);
321
322         err = family->ops->init(family);
323         if (err)
324                 goto err_family_init;
325
326         if (WARN_ON(family->start_index >= family->end_index)) {
327                 err = -EINVAL;
328                 goto err_index_check;
329         }
330
331         mlxsw_sp->policer_core->family_arr[tmpl->type] = family;
332
333         return 0;
334
335 err_index_check:
336         family->ops->fini(family);
337 err_family_init:
338         mutex_destroy(&family->lock);
339         idr_destroy(&family->policer_idr);
340         kfree(family);
341         return err;
342 }
343
344 static void
345 mlxsw_sp_policer_family_unregister(struct mlxsw_sp *mlxsw_sp,
346                                    struct mlxsw_sp_policer_family *family)
347 {
348         family->ops->fini(family);
349         mutex_destroy(&family->lock);
350         WARN_ON(!idr_is_empty(&family->policer_idr));
351         idr_destroy(&family->policer_idr);
352         kfree(family);
353 }
354
355 int mlxsw_sp_policers_init(struct mlxsw_sp *mlxsw_sp)
356 {
357         struct mlxsw_sp_policer_core *policer_core;
358         int i, err;
359
360         policer_core = kzalloc(sizeof(*policer_core), GFP_KERNEL);
361         if (!policer_core)
362                 return -ENOMEM;
363         mlxsw_sp->policer_core = policer_core;
364         policer_core->ops = mlxsw_sp->policer_core_ops;
365
366         err = policer_core->ops->init(policer_core);
367         if (err)
368                 goto err_init;
369
370         for (i = 0; i < MLXSW_SP_POLICER_TYPE_MAX + 1; i++) {
371                 err = mlxsw_sp_policer_family_register(mlxsw_sp, mlxsw_sp_policer_family_arr[i]);
372                 if (err)
373                         goto err_family_register;
374         }
375
376         return 0;
377
378 err_family_register:
379         for (i--; i >= 0; i--) {
380                 struct mlxsw_sp_policer_family *family;
381
382                 family = mlxsw_sp->policer_core->family_arr[i];
383                 mlxsw_sp_policer_family_unregister(mlxsw_sp, family);
384         }
385 err_init:
386         kfree(mlxsw_sp->policer_core);
387         return err;
388 }
389
390 void mlxsw_sp_policers_fini(struct mlxsw_sp *mlxsw_sp)
391 {
392         int i;
393
394         for (i = MLXSW_SP_POLICER_TYPE_MAX; i >= 0; i--) {
395                 struct mlxsw_sp_policer_family *family;
396
397                 family = mlxsw_sp->policer_core->family_arr[i];
398                 mlxsw_sp_policer_family_unregister(mlxsw_sp, family);
399         }
400
401         kfree(mlxsw_sp->policer_core);
402 }
403
404 int mlxsw_sp_policer_resources_register(struct mlxsw_core *mlxsw_core)
405 {
406         u64 global_policers, cpu_policers, single_rate_policers;
407         struct devlink *devlink = priv_to_devlink(mlxsw_core);
408         struct devlink_resource_size_params size_params;
409         int err;
410
411         if (!MLXSW_CORE_RES_VALID(mlxsw_core, MAX_GLOBAL_POLICERS) ||
412             !MLXSW_CORE_RES_VALID(mlxsw_core, MAX_CPU_POLICERS))
413                 return -EIO;
414
415         global_policers = MLXSW_CORE_RES_GET(mlxsw_core, MAX_GLOBAL_POLICERS);
416         cpu_policers = MLXSW_CORE_RES_GET(mlxsw_core, MAX_CPU_POLICERS);
417         single_rate_policers = global_policers - cpu_policers;
418
419         devlink_resource_size_params_init(&size_params, global_policers,
420                                           global_policers, 1,
421                                           DEVLINK_RESOURCE_UNIT_ENTRY);
422         err = devlink_resource_register(devlink, "global_policers",
423                                         global_policers,
424                                         MLXSW_SP_RESOURCE_GLOBAL_POLICERS,
425                                         DEVLINK_RESOURCE_ID_PARENT_TOP,
426                                         &size_params);
427         if (err)
428                 return err;
429
430         devlink_resource_size_params_init(&size_params, single_rate_policers,
431                                           single_rate_policers, 1,
432                                           DEVLINK_RESOURCE_UNIT_ENTRY);
433         err = devlink_resource_register(devlink, "single_rate_policers",
434                                         single_rate_policers,
435                                         MLXSW_SP_RESOURCE_SINGLE_RATE_POLICERS,
436                                         MLXSW_SP_RESOURCE_GLOBAL_POLICERS,
437                                         &size_params);
438         if (err)
439                 return err;
440
441         return 0;
442 }
443
444 static int
445 mlxsw_sp1_policer_core_init(struct mlxsw_sp_policer_core *policer_core)
446 {
447         policer_core->lowest_bs_bits = MLXSW_REG_QPCR_LOWEST_CBS_BITS_SP1;
448         policer_core->highest_bs_bits = MLXSW_REG_QPCR_HIGHEST_CBS_BITS_SP1;
449
450         return 0;
451 }
452
453 const struct mlxsw_sp_policer_core_ops mlxsw_sp1_policer_core_ops = {
454         .init = mlxsw_sp1_policer_core_init,
455 };
456
457 static int
458 mlxsw_sp2_policer_core_init(struct mlxsw_sp_policer_core *policer_core)
459 {
460         policer_core->lowest_bs_bits = MLXSW_REG_QPCR_LOWEST_CBS_BITS_SP2;
461         policer_core->highest_bs_bits = MLXSW_REG_QPCR_HIGHEST_CBS_BITS_SP2;
462
463         return 0;
464 }
465
466 const struct mlxsw_sp_policer_core_ops mlxsw_sp2_policer_core_ops = {
467         .init = mlxsw_sp2_policer_core_init,
468 };