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
12struct 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
24struct mlxsw_sp_policer {
25	struct mlxsw_sp_policer_params params;
26	u16 index;
27};
28
29struct 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
43struct 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
50struct mlxsw_sp_policer_core_ops {
51	int (*init)(struct mlxsw_sp_policer_core *policer_core);
52};
53
54static 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
59static 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
72static 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
79static int
80mlxsw_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	devl_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
105static void
106mlxsw_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	devl_resource_occ_get_unregister(devlink,
111					 MLXSW_SP_RESOURCE_SINGLE_RATE_POLICERS);
112	WARN_ON(atomic_read(&family->policers_count) != 0);
113}
114
115static int
116mlxsw_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
135static struct mlxsw_sp_policer *
136mlxsw_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
152static int
153mlxsw_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
168static int
169mlxsw_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
212static 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
221static 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
227static 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
231int 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
267err_policer_init:
268	family->ops->policer_index_free(family, policer->index);
269err_policer_index_alloc:
270	kfree(policer);
271	return err;
272}
273
274void 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
285int 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
307static int
308mlxsw_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
335err_index_check:
336	family->ops->fini(family);
337err_family_init:
338	mutex_destroy(&family->lock);
339	idr_destroy(&family->policer_idr);
340	kfree(family);
341	return err;
342}
343
344static void
345mlxsw_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
355int 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
378err_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	}
385err_init:
386	kfree(mlxsw_sp->policer_core);
387	return err;
388}
389
390void 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
404int 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 = devl_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 = devl_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
444static int
445mlxsw_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
453const struct mlxsw_sp_policer_core_ops mlxsw_sp1_policer_core_ops = {
454	.init = mlxsw_sp1_policer_core_init,
455};
456
457static int
458mlxsw_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
466const struct mlxsw_sp_policer_core_ops mlxsw_sp2_policer_core_ops = {
467	.init = mlxsw_sp2_policer_core_init,
468};
469