1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /* Copyright (c) 2020 Mellanox Technologies. All rights reserved */
5 #include <linux/log2.h>
6 #include <linux/mutex.h>
7 #include <linux/netlink.h>
8 #include <net/devlink.h>
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;
24 struct mlxsw_sp_policer {
25 struct mlxsw_sp_policer_params params;
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,
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);
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;
50 struct mlxsw_sp_policer_core_ops {
51 int (*init)(struct mlxsw_sp_policer_core *policer_core);
54 static u64 mlxsw_sp_policer_rate_bytes_ps_kbps(u64 rate_bytes_ps)
56 return div_u64(rate_bytes_ps, 1000) * BITS_PER_BYTE;
59 static u8 mlxsw_sp_policer_burst_bytes_hw_units(u64 burst_bytes)
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.
64 u64 bs512 = div_u64(burst_bytes, 64);
69 return fls64(bs512) - 1;
72 static u64 mlxsw_sp_policer_single_rate_occ_get(void *priv)
74 struct mlxsw_sp_policer_family *family = priv;
76 return atomic_read(&family->policers_count);
80 mlxsw_sp_policer_single_rate_family_init(struct mlxsw_sp_policer_family *family)
82 struct mlxsw_core *core = family->mlxsw_sp->core;
83 struct devlink *devlink;
85 /* CPU policers are allocated from the first N policers in the global
86 * range, so skip them.
88 if (!MLXSW_CORE_RES_VALID(core, MAX_GLOBAL_POLICERS) ||
89 !MLXSW_CORE_RES_VALID(core, MAX_CPU_POLICERS))
92 family->start_index = MLXSW_CORE_RES_GET(core, MAX_CPU_POLICERS);
93 family->end_index = MLXSW_CORE_RES_GET(core, MAX_GLOBAL_POLICERS);
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,
106 mlxsw_sp_policer_single_rate_family_fini(struct mlxsw_sp_policer_family *family)
108 struct devlink *devlink = priv_to_devlink(family->mlxsw_sp->core);
110 devl_resource_occ_get_unregister(devlink,
111 MLXSW_SP_RESOURCE_SINGLE_RATE_POLICERS);
112 WARN_ON(atomic_read(&family->policers_count) != 0);
116 mlxsw_sp_policer_single_rate_index_alloc(struct mlxsw_sp_policer_family *family,
117 struct mlxsw_sp_policer *policer)
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);
129 atomic_inc(&family->policers_count);
135 static struct mlxsw_sp_policer *
136 mlxsw_sp_policer_single_rate_index_free(struct mlxsw_sp_policer_family *family,
139 struct mlxsw_sp_policer *policer;
141 atomic_dec(&family->policers_count);
143 mutex_lock(&family->lock);
144 policer = idr_remove(&family->policer_idr, policer_index);
145 mutex_unlock(&family->lock);
153 mlxsw_sp_policer_single_rate_init(struct mlxsw_sp_policer_family *family,
154 const struct mlxsw_sp_policer *policer)
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];
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);
165 return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(qpcr), qpcr_pl);
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)
173 struct mlxsw_sp_policer_core *policer_core = family->mlxsw_sp->policer_core;
174 u64 rate_bps = params->rate * BITS_PER_BYTE;
177 if (!params->bytes) {
178 NL_SET_ERR_MSG_MOD(extack, "Only bandwidth policing is currently supported by single rate policers");
182 if (!is_power_of_2(params->burst)) {
183 NL_SET_ERR_MSG_MOD(extack, "Policer burst size is not power of two");
187 bs = mlxsw_sp_policer_burst_bytes_hw_units(params->burst);
189 if (bs < policer_core->lowest_bs_bits) {
190 NL_SET_ERR_MSG_MOD(extack, "Policer burst size lower than limit");
194 if (bs > policer_core->highest_bs_bits) {
195 NL_SET_ERR_MSG_MOD(extack, "Policer burst size higher than limit");
199 if (rate_bps < MLXSW_REG_QPCR_LOWEST_CIR_BITS) {
200 NL_SET_ERR_MSG_MOD(extack, "Policer rate lower than limit");
204 if (rate_bps > MLXSW_REG_QPCR_HIGHEST_CIR_BITS) {
205 NL_SET_ERR_MSG_MOD(extack, "Policer rate higher than limit");
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,
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,
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,
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)
236 struct mlxsw_sp_policer_family *family;
237 struct mlxsw_sp_policer *policer;
240 family = mlxsw_sp->policer_core->family_arr[type];
242 err = family->ops->policer_params_check(family, params, extack);
246 policer = kmalloc(sizeof(*policer), GFP_KERNEL);
249 policer->params = *params;
251 err = family->ops->policer_index_alloc(family, policer);
253 NL_SET_ERR_MSG_MOD(extack, "Failed to allocate policer index");
254 goto err_policer_index_alloc;
257 err = family->ops->policer_init(family, policer);
259 NL_SET_ERR_MSG_MOD(extack, "Failed to initialize policer");
260 goto err_policer_init;
263 *p_policer_index = policer->index;
268 family->ops->policer_index_free(family, policer->index);
269 err_policer_index_alloc:
274 void mlxsw_sp_policer_del(struct mlxsw_sp *mlxsw_sp,
275 enum mlxsw_sp_policer_type type, u16 policer_index)
277 struct mlxsw_sp_policer_family *family;
278 struct mlxsw_sp_policer *policer;
280 family = mlxsw_sp->policer_core->family_arr[type];
281 policer = family->ops->policer_index_free(family, policer_index);
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)
289 struct mlxsw_sp_policer_family *family;
290 char qpcr_pl[MLXSW_REG_QPCR_LEN];
293 family = mlxsw_sp->policer_core->family_arr[type];
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);
302 *p_drops = mlxsw_reg_qpcr_violate_count_get(qpcr_pl);
308 mlxsw_sp_policer_family_register(struct mlxsw_sp *mlxsw_sp,
309 const struct mlxsw_sp_policer_family *tmpl)
311 struct mlxsw_sp_policer_family *family;
314 family = kmemdup(tmpl, sizeof(*family), GFP_KERNEL);
318 family->mlxsw_sp = mlxsw_sp;
319 idr_init(&family->policer_idr);
320 mutex_init(&family->lock);
322 err = family->ops->init(family);
324 goto err_family_init;
326 if (WARN_ON(family->start_index >= family->end_index)) {
328 goto err_index_check;
331 mlxsw_sp->policer_core->family_arr[tmpl->type] = family;
336 family->ops->fini(family);
338 mutex_destroy(&family->lock);
339 idr_destroy(&family->policer_idr);
345 mlxsw_sp_policer_family_unregister(struct mlxsw_sp *mlxsw_sp,
346 struct mlxsw_sp_policer_family *family)
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);
355 int mlxsw_sp_policers_init(struct mlxsw_sp *mlxsw_sp)
357 struct mlxsw_sp_policer_core *policer_core;
360 policer_core = kzalloc(sizeof(*policer_core), GFP_KERNEL);
363 mlxsw_sp->policer_core = policer_core;
364 policer_core->ops = mlxsw_sp->policer_core_ops;
366 err = policer_core->ops->init(policer_core);
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]);
373 goto err_family_register;
379 for (i--; i >= 0; i--) {
380 struct mlxsw_sp_policer_family *family;
382 family = mlxsw_sp->policer_core->family_arr[i];
383 mlxsw_sp_policer_family_unregister(mlxsw_sp, family);
386 kfree(mlxsw_sp->policer_core);
390 void mlxsw_sp_policers_fini(struct mlxsw_sp *mlxsw_sp)
394 for (i = MLXSW_SP_POLICER_TYPE_MAX; i >= 0; i--) {
395 struct mlxsw_sp_policer_family *family;
397 family = mlxsw_sp->policer_core->family_arr[i];
398 mlxsw_sp_policer_family_unregister(mlxsw_sp, family);
401 kfree(mlxsw_sp->policer_core);
404 int mlxsw_sp_policer_resources_register(struct mlxsw_core *mlxsw_core)
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;
411 if (!MLXSW_CORE_RES_VALID(mlxsw_core, MAX_GLOBAL_POLICERS) ||
412 !MLXSW_CORE_RES_VALID(mlxsw_core, MAX_CPU_POLICERS))
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;
419 devlink_resource_size_params_init(&size_params, global_policers,
421 DEVLINK_RESOURCE_UNIT_ENTRY);
422 err = devl_resource_register(devlink, "global_policers",
424 MLXSW_SP_RESOURCE_GLOBAL_POLICERS,
425 DEVLINK_RESOURCE_ID_PARENT_TOP,
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,
445 mlxsw_sp1_policer_core_init(struct mlxsw_sp_policer_core *policer_core)
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;
453 const struct mlxsw_sp_policer_core_ops mlxsw_sp1_policer_core_ops = {
454 .init = mlxsw_sp1_policer_core_init,
458 mlxsw_sp2_policer_core_init(struct mlxsw_sp_policer_core *policer_core)
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;
466 const struct mlxsw_sp_policer_core_ops mlxsw_sp2_policer_core_ops = {
467 .init = mlxsw_sp2_policer_core_init,