1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved. */
7 #define CREATE_TRACE_POINTS
8 #include "diag/qos_tracepoint.h"
10 /* Minimum supported BW share value by the HW is 1 Mbit/sec */
11 #define MLX5_MIN_BW_SHARE 1
13 #define MLX5_RATE_TO_BW_SHARE(rate, divider, limit) \
14 min_t(u32, max_t(u32, DIV_ROUND_UP(rate, divider), MLX5_MIN_BW_SHARE), limit)
16 struct mlx5_esw_rate_group
{
21 struct list_head list
;
24 static int esw_qos_tsar_config(struct mlx5_core_dev
*dev
, u32
*sched_ctx
,
25 u32 parent_ix
, u32 tsar_ix
,
26 u32 max_rate
, u32 bw_share
)
30 if (!MLX5_CAP_GEN(dev
, qos
) || !MLX5_CAP_QOS(dev
, esw_scheduling
))
33 MLX5_SET(scheduling_context
, sched_ctx
, parent_element_id
, parent_ix
);
34 MLX5_SET(scheduling_context
, sched_ctx
, max_average_bw
, max_rate
);
35 MLX5_SET(scheduling_context
, sched_ctx
, bw_share
, bw_share
);
36 bitmask
|= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW
;
37 bitmask
|= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_BW_SHARE
;
39 return mlx5_modify_scheduling_element_cmd(dev
,
40 SCHEDULING_HIERARCHY_E_SWITCH
,
46 static int esw_qos_group_config(struct mlx5_eswitch
*esw
, struct mlx5_esw_rate_group
*group
,
47 u32 max_rate
, u32 bw_share
, struct netlink_ext_ack
*extack
)
49 u32 sched_ctx
[MLX5_ST_SZ_DW(scheduling_context
)] = {};
50 struct mlx5_core_dev
*dev
= esw
->dev
;
53 err
= esw_qos_tsar_config(dev
, sched_ctx
,
54 esw
->qos
.root_tsar_ix
, group
->tsar_ix
,
57 NL_SET_ERR_MSG_MOD(extack
, "E-Switch modify group TSAR element failed");
59 trace_mlx5_esw_group_qos_config(dev
, group
, group
->tsar_ix
, bw_share
, max_rate
);
64 static int esw_qos_vport_config(struct mlx5_eswitch
*esw
,
65 struct mlx5_vport
*vport
,
66 u32 max_rate
, u32 bw_share
,
67 struct netlink_ext_ack
*extack
)
69 u32 sched_ctx
[MLX5_ST_SZ_DW(scheduling_context
)] = {};
70 struct mlx5_esw_rate_group
*group
= vport
->qos
.group
;
71 struct mlx5_core_dev
*dev
= esw
->dev
;
76 if (!vport
->qos
.enabled
)
79 parent_tsar_ix
= group
? group
->tsar_ix
: esw
->qos
.root_tsar_ix
;
80 MLX5_SET(scheduling_context
, sched_ctx
, element_type
,
81 SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT
);
82 vport_elem
= MLX5_ADDR_OF(scheduling_context
, sched_ctx
,
84 MLX5_SET(vport_element
, vport_elem
, vport_number
, vport
->vport
);
86 err
= esw_qos_tsar_config(dev
, sched_ctx
, parent_tsar_ix
, vport
->qos
.esw_tsar_ix
,
90 "E-Switch modify TSAR vport element failed (vport=%d,err=%d)\n",
92 NL_SET_ERR_MSG_MOD(extack
, "E-Switch modify TSAR vport element failed");
96 trace_mlx5_esw_vport_qos_config(vport
, bw_share
, max_rate
);
101 static u32
esw_qos_calculate_min_rate_divider(struct mlx5_eswitch
*esw
,
102 struct mlx5_esw_rate_group
*group
,
105 u32 fw_max_bw_share
= MLX5_CAP_QOS(esw
->dev
, max_tsar_bw_share
);
106 struct mlx5_vport
*evport
;
107 u32 max_guarantee
= 0;
111 struct mlx5_esw_rate_group
*group
;
113 list_for_each_entry(group
, &esw
->qos
.groups
, list
) {
114 if (group
->min_rate
< max_guarantee
)
116 max_guarantee
= group
->min_rate
;
119 mlx5_esw_for_each_vport(esw
, i
, evport
) {
120 if (!evport
->enabled
|| !evport
->qos
.enabled
||
121 evport
->qos
.group
!= group
|| evport
->qos
.min_rate
< max_guarantee
)
123 max_guarantee
= evport
->qos
.min_rate
;
128 return max_t(u32
, max_guarantee
/ fw_max_bw_share
, 1);
130 /* If vports min rate divider is 0 but their group has bw_share configured, then
131 * need to set bw_share for vports to minimal value.
133 if (!group_level
&& !max_guarantee
&& group
->bw_share
)
138 static u32
esw_qos_calc_bw_share(u32 min_rate
, u32 divider
, u32 fw_max
)
141 return MLX5_RATE_TO_BW_SHARE(min_rate
, divider
, fw_max
);
146 static int esw_qos_normalize_vports_min_rate(struct mlx5_eswitch
*esw
,
147 struct mlx5_esw_rate_group
*group
,
148 struct netlink_ext_ack
*extack
)
150 u32 fw_max_bw_share
= MLX5_CAP_QOS(esw
->dev
, max_tsar_bw_share
);
151 u32 divider
= esw_qos_calculate_min_rate_divider(esw
, group
, false);
152 struct mlx5_vport
*evport
;
157 mlx5_esw_for_each_vport(esw
, i
, evport
) {
158 if (!evport
->enabled
|| !evport
->qos
.enabled
|| evport
->qos
.group
!= group
)
160 bw_share
= esw_qos_calc_bw_share(evport
->qos
.min_rate
, divider
, fw_max_bw_share
);
162 if (bw_share
== evport
->qos
.bw_share
)
165 err
= esw_qos_vport_config(esw
, evport
, evport
->qos
.max_rate
, bw_share
, extack
);
169 evport
->qos
.bw_share
= bw_share
;
175 static int esw_qos_normalize_groups_min_rate(struct mlx5_eswitch
*esw
, u32 divider
,
176 struct netlink_ext_ack
*extack
)
178 u32 fw_max_bw_share
= MLX5_CAP_QOS(esw
->dev
, max_tsar_bw_share
);
179 struct mlx5_esw_rate_group
*group
;
183 list_for_each_entry(group
, &esw
->qos
.groups
, list
) {
184 bw_share
= esw_qos_calc_bw_share(group
->min_rate
, divider
, fw_max_bw_share
);
186 if (bw_share
== group
->bw_share
)
189 err
= esw_qos_group_config(esw
, group
, group
->max_rate
, bw_share
, extack
);
193 group
->bw_share
= bw_share
;
195 /* All the group's vports need to be set with default bw_share
196 * to enable them with QOS
198 err
= esw_qos_normalize_vports_min_rate(esw
, group
, extack
);
207 int mlx5_esw_qos_set_vport_min_rate(struct mlx5_eswitch
*esw
,
208 struct mlx5_vport
*evport
,
210 struct netlink_ext_ack
*extack
)
212 u32 fw_max_bw_share
, previous_min_rate
;
213 bool min_rate_supported
;
216 lockdep_assert_held(&esw
->state_lock
);
217 fw_max_bw_share
= MLX5_CAP_QOS(esw
->dev
, max_tsar_bw_share
);
218 min_rate_supported
= MLX5_CAP_QOS(esw
->dev
, esw_bw_share
) &&
219 fw_max_bw_share
>= MLX5_MIN_BW_SHARE
;
220 if (min_rate
&& !min_rate_supported
)
222 if (min_rate
== evport
->qos
.min_rate
)
225 previous_min_rate
= evport
->qos
.min_rate
;
226 evport
->qos
.min_rate
= min_rate
;
227 err
= esw_qos_normalize_vports_min_rate(esw
, evport
->qos
.group
, extack
);
229 evport
->qos
.min_rate
= previous_min_rate
;
234 int mlx5_esw_qos_set_vport_max_rate(struct mlx5_eswitch
*esw
,
235 struct mlx5_vport
*evport
,
237 struct netlink_ext_ack
*extack
)
239 u32 act_max_rate
= max_rate
;
240 bool max_rate_supported
;
243 lockdep_assert_held(&esw
->state_lock
);
244 max_rate_supported
= MLX5_CAP_QOS(esw
->dev
, esw_rate_limit
);
246 if (max_rate
&& !max_rate_supported
)
248 if (max_rate
== evport
->qos
.max_rate
)
251 /* If parent group has rate limit need to set to group
252 * value when new max rate is 0.
254 if (evport
->qos
.group
&& !max_rate
)
255 act_max_rate
= evport
->qos
.group
->max_rate
;
257 err
= esw_qos_vport_config(esw
, evport
, act_max_rate
, evport
->qos
.bw_share
, extack
);
260 evport
->qos
.max_rate
= max_rate
;
265 static int esw_qos_set_group_min_rate(struct mlx5_eswitch
*esw
, struct mlx5_esw_rate_group
*group
,
266 u32 min_rate
, struct netlink_ext_ack
*extack
)
268 u32 fw_max_bw_share
= MLX5_CAP_QOS(esw
->dev
, max_tsar_bw_share
);
269 struct mlx5_core_dev
*dev
= esw
->dev
;
270 u32 previous_min_rate
, divider
;
273 if (!(MLX5_CAP_QOS(dev
, esw_bw_share
) && fw_max_bw_share
>= MLX5_MIN_BW_SHARE
))
276 if (min_rate
== group
->min_rate
)
279 previous_min_rate
= group
->min_rate
;
280 group
->min_rate
= min_rate
;
281 divider
= esw_qos_calculate_min_rate_divider(esw
, group
, true);
282 err
= esw_qos_normalize_groups_min_rate(esw
, divider
, extack
);
284 group
->min_rate
= previous_min_rate
;
285 NL_SET_ERR_MSG_MOD(extack
, "E-Switch group min rate setting failed");
287 /* Attempt restoring previous configuration */
288 divider
= esw_qos_calculate_min_rate_divider(esw
, group
, true);
289 if (esw_qos_normalize_groups_min_rate(esw
, divider
, extack
))
290 NL_SET_ERR_MSG_MOD(extack
, "E-Switch BW share restore failed");
296 static int esw_qos_set_group_max_rate(struct mlx5_eswitch
*esw
,
297 struct mlx5_esw_rate_group
*group
,
298 u32 max_rate
, struct netlink_ext_ack
*extack
)
300 struct mlx5_vport
*vport
;
304 if (group
->max_rate
== max_rate
)
307 err
= esw_qos_group_config(esw
, group
, max_rate
, group
->bw_share
, extack
);
311 group
->max_rate
= max_rate
;
313 /* Any unlimited vports in the group should be set
314 * with the value of the group.
316 mlx5_esw_for_each_vport(esw
, i
, vport
) {
317 if (!vport
->enabled
|| !vport
->qos
.enabled
||
318 vport
->qos
.group
!= group
|| vport
->qos
.max_rate
)
321 err
= esw_qos_vport_config(esw
, vport
, max_rate
, vport
->qos
.bw_share
, extack
);
323 NL_SET_ERR_MSG_MOD(extack
,
324 "E-Switch vport implicit rate limit setting failed");
330 static int esw_qos_vport_create_sched_element(struct mlx5_eswitch
*esw
,
331 struct mlx5_vport
*vport
,
332 u32 max_rate
, u32 bw_share
)
334 u32 sched_ctx
[MLX5_ST_SZ_DW(scheduling_context
)] = {};
335 struct mlx5_esw_rate_group
*group
= vport
->qos
.group
;
336 struct mlx5_core_dev
*dev
= esw
->dev
;
341 parent_tsar_ix
= group
? group
->tsar_ix
: esw
->qos
.root_tsar_ix
;
342 MLX5_SET(scheduling_context
, sched_ctx
, element_type
,
343 SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT
);
344 vport_elem
= MLX5_ADDR_OF(scheduling_context
, sched_ctx
, element_attributes
);
345 MLX5_SET(vport_element
, vport_elem
, vport_number
, vport
->vport
);
346 MLX5_SET(scheduling_context
, sched_ctx
, parent_element_id
, parent_tsar_ix
);
347 MLX5_SET(scheduling_context
, sched_ctx
, max_average_bw
, max_rate
);
348 MLX5_SET(scheduling_context
, sched_ctx
, bw_share
, bw_share
);
350 err
= mlx5_create_scheduling_element_cmd(dev
,
351 SCHEDULING_HIERARCHY_E_SWITCH
,
353 &vport
->qos
.esw_tsar_ix
);
355 esw_warn(esw
->dev
, "E-Switch create TSAR vport element failed (vport=%d,err=%d)\n",
363 static int esw_qos_update_group_scheduling_element(struct mlx5_eswitch
*esw
,
364 struct mlx5_vport
*vport
,
365 struct mlx5_esw_rate_group
*curr_group
,
366 struct mlx5_esw_rate_group
*new_group
,
367 struct netlink_ext_ack
*extack
)
372 err
= mlx5_destroy_scheduling_element_cmd(esw
->dev
,
373 SCHEDULING_HIERARCHY_E_SWITCH
,
374 vport
->qos
.esw_tsar_ix
);
376 NL_SET_ERR_MSG_MOD(extack
, "E-Switch destroy TSAR vport element failed");
380 vport
->qos
.group
= new_group
;
381 max_rate
= vport
->qos
.max_rate
? vport
->qos
.max_rate
: new_group
->max_rate
;
383 /* If vport is unlimited, we set the group's value.
384 * Therefore, if the group is limited it will apply to
385 * the vport as well and if not, vport will remain unlimited.
387 err
= esw_qos_vport_create_sched_element(esw
, vport
, max_rate
, vport
->qos
.bw_share
);
389 NL_SET_ERR_MSG_MOD(extack
, "E-Switch vport group set failed.");
396 vport
->qos
.group
= curr_group
;
397 max_rate
= vport
->qos
.max_rate
? vport
->qos
.max_rate
: curr_group
->max_rate
;
398 if (esw_qos_vport_create_sched_element(esw
, vport
, max_rate
, vport
->qos
.bw_share
))
399 esw_warn(esw
->dev
, "E-Switch vport group restore failed (vport=%d)\n",
405 static int esw_qos_vport_update_group(struct mlx5_eswitch
*esw
,
406 struct mlx5_vport
*vport
,
407 struct mlx5_esw_rate_group
*group
,
408 struct netlink_ext_ack
*extack
)
410 struct mlx5_esw_rate_group
*new_group
, *curr_group
;
416 curr_group
= vport
->qos
.group
;
417 new_group
= group
?: esw
->qos
.group0
;
418 if (curr_group
== new_group
)
421 err
= esw_qos_update_group_scheduling_element(esw
, vport
, curr_group
, new_group
, extack
);
425 /* Recalculate bw share weights of old and new groups */
426 if (vport
->qos
.bw_share
|| new_group
->bw_share
) {
427 esw_qos_normalize_vports_min_rate(esw
, curr_group
, extack
);
428 esw_qos_normalize_vports_min_rate(esw
, new_group
, extack
);
434 static struct mlx5_esw_rate_group
*
435 esw_qos_create_rate_group(struct mlx5_eswitch
*esw
, struct netlink_ext_ack
*extack
)
437 u32 tsar_ctx
[MLX5_ST_SZ_DW(scheduling_context
)] = {};
438 struct mlx5_esw_rate_group
*group
;
442 if (!MLX5_CAP_QOS(esw
->dev
, log_esw_max_sched_depth
))
443 return ERR_PTR(-EOPNOTSUPP
);
445 group
= kzalloc(sizeof(*group
), GFP_KERNEL
);
447 return ERR_PTR(-ENOMEM
);
449 MLX5_SET(scheduling_context
, tsar_ctx
, parent_element_id
,
450 esw
->qos
.root_tsar_ix
);
451 err
= mlx5_create_scheduling_element_cmd(esw
->dev
,
452 SCHEDULING_HIERARCHY_E_SWITCH
,
456 NL_SET_ERR_MSG_MOD(extack
, "E-Switch create TSAR for group failed");
460 list_add_tail(&group
->list
, &esw
->qos
.groups
);
462 divider
= esw_qos_calculate_min_rate_divider(esw
, group
, true);
464 err
= esw_qos_normalize_groups_min_rate(esw
, divider
, extack
);
466 NL_SET_ERR_MSG_MOD(extack
, "E-Switch groups normalization failed");
470 trace_mlx5_esw_group_qos_create(esw
->dev
, group
, group
->tsar_ix
);
475 list_del(&group
->list
);
476 if (mlx5_destroy_scheduling_element_cmd(esw
->dev
,
477 SCHEDULING_HIERARCHY_E_SWITCH
,
479 NL_SET_ERR_MSG_MOD(extack
, "E-Switch destroy TSAR for group failed");
485 static int esw_qos_destroy_rate_group(struct mlx5_eswitch
*esw
,
486 struct mlx5_esw_rate_group
*group
,
487 struct netlink_ext_ack
*extack
)
492 list_del(&group
->list
);
494 divider
= esw_qos_calculate_min_rate_divider(esw
, NULL
, true);
495 err
= esw_qos_normalize_groups_min_rate(esw
, divider
, extack
);
497 NL_SET_ERR_MSG_MOD(extack
, "E-Switch groups' normalization failed");
499 err
= mlx5_destroy_scheduling_element_cmd(esw
->dev
,
500 SCHEDULING_HIERARCHY_E_SWITCH
,
503 NL_SET_ERR_MSG_MOD(extack
, "E-Switch destroy TSAR_ID failed");
505 trace_mlx5_esw_group_qos_destroy(esw
->dev
, group
, group
->tsar_ix
);
510 static bool esw_qos_element_type_supported(struct mlx5_core_dev
*dev
, int type
)
513 case SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR
:
514 return MLX5_CAP_QOS(dev
, esw_element_type
) &
515 ELEMENT_TYPE_CAP_MASK_TASR
;
516 case SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT
:
517 return MLX5_CAP_QOS(dev
, esw_element_type
) &
518 ELEMENT_TYPE_CAP_MASK_VPORT
;
519 case SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT_TC
:
520 return MLX5_CAP_QOS(dev
, esw_element_type
) &
521 ELEMENT_TYPE_CAP_MASK_VPORT_TC
;
522 case SCHEDULING_CONTEXT_ELEMENT_TYPE_PARA_VPORT_TC
:
523 return MLX5_CAP_QOS(dev
, esw_element_type
) &
524 ELEMENT_TYPE_CAP_MASK_PARA_VPORT_TC
;
529 void mlx5_esw_qos_create(struct mlx5_eswitch
*esw
)
531 u32 tsar_ctx
[MLX5_ST_SZ_DW(scheduling_context
)] = {};
532 struct mlx5_core_dev
*dev
= esw
->dev
;
536 if (!MLX5_CAP_GEN(dev
, qos
) || !MLX5_CAP_QOS(dev
, esw_scheduling
))
539 if (!esw_qos_element_type_supported(dev
, SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR
))
542 mutex_lock(&esw
->state_lock
);
543 if (esw
->qos
.enabled
)
546 MLX5_SET(scheduling_context
, tsar_ctx
, element_type
,
547 SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR
);
549 attr
= MLX5_ADDR_OF(scheduling_context
, tsar_ctx
, element_attributes
);
550 *attr
= cpu_to_be32(TSAR_ELEMENT_TSAR_TYPE_DWRR
<< 16);
552 err
= mlx5_create_scheduling_element_cmd(dev
,
553 SCHEDULING_HIERARCHY_E_SWITCH
,
555 &esw
->qos
.root_tsar_ix
);
557 esw_warn(dev
, "E-Switch create root TSAR failed (%d)\n", err
);
561 INIT_LIST_HEAD(&esw
->qos
.groups
);
562 if (MLX5_CAP_QOS(dev
, log_esw_max_sched_depth
)) {
563 esw
->qos
.group0
= esw_qos_create_rate_group(esw
, NULL
);
564 if (IS_ERR(esw
->qos
.group0
)) {
565 esw_warn(dev
, "E-Switch create rate group 0 failed (%ld)\n",
566 PTR_ERR(esw
->qos
.group0
));
570 esw
->qos
.enabled
= true;
572 mutex_unlock(&esw
->state_lock
);
576 err
= mlx5_destroy_scheduling_element_cmd(esw
->dev
,
577 SCHEDULING_HIERARCHY_E_SWITCH
,
578 esw
->qos
.root_tsar_ix
);
580 esw_warn(esw
->dev
, "E-Switch destroy root TSAR failed (%d)\n", err
);
581 mutex_unlock(&esw
->state_lock
);
584 void mlx5_esw_qos_destroy(struct mlx5_eswitch
*esw
)
586 struct devlink
*devlink
= priv_to_devlink(esw
->dev
);
589 devlink_rate_nodes_destroy(devlink
);
590 mutex_lock(&esw
->state_lock
);
591 if (!esw
->qos
.enabled
)
595 esw_qos_destroy_rate_group(esw
, esw
->qos
.group0
, NULL
);
597 err
= mlx5_destroy_scheduling_element_cmd(esw
->dev
,
598 SCHEDULING_HIERARCHY_E_SWITCH
,
599 esw
->qos
.root_tsar_ix
);
601 esw_warn(esw
->dev
, "E-Switch destroy root TSAR failed (%d)\n", err
);
603 esw
->qos
.enabled
= false;
605 mutex_unlock(&esw
->state_lock
);
608 int mlx5_esw_qos_vport_enable(struct mlx5_eswitch
*esw
, struct mlx5_vport
*vport
,
609 u32 max_rate
, u32 bw_share
)
613 lockdep_assert_held(&esw
->state_lock
);
614 if (!esw
->qos
.enabled
)
617 if (vport
->qos
.enabled
)
620 vport
->qos
.group
= esw
->qos
.group0
;
622 err
= esw_qos_vport_create_sched_element(esw
, vport
, max_rate
, bw_share
);
624 vport
->qos
.enabled
= true;
625 trace_mlx5_esw_vport_qos_create(vport
, bw_share
, max_rate
);
631 void mlx5_esw_qos_vport_disable(struct mlx5_eswitch
*esw
, struct mlx5_vport
*vport
)
635 lockdep_assert_held(&esw
->state_lock
);
636 if (!esw
->qos
.enabled
|| !vport
->qos
.enabled
)
638 WARN(vport
->qos
.group
&& vport
->qos
.group
!= esw
->qos
.group0
,
639 "Disabling QoS on port before detaching it from group");
641 err
= mlx5_destroy_scheduling_element_cmd(esw
->dev
,
642 SCHEDULING_HIERARCHY_E_SWITCH
,
643 vport
->qos
.esw_tsar_ix
);
645 esw_warn(esw
->dev
, "E-Switch destroy TSAR vport element failed (vport=%d,err=%d)\n",
648 vport
->qos
.enabled
= false;
649 trace_mlx5_esw_vport_qos_destroy(vport
);
652 int mlx5_esw_qos_modify_vport_rate(struct mlx5_eswitch
*esw
, u16 vport_num
, u32 rate_mbps
)
654 u32 ctx
[MLX5_ST_SZ_DW(scheduling_context
)] = {};
655 struct mlx5_vport
*vport
;
658 vport
= mlx5_eswitch_get_vport(esw
, vport_num
);
660 return PTR_ERR(vport
);
662 if (!vport
->qos
.enabled
)
665 MLX5_SET(scheduling_context
, ctx
, max_average_bw
, rate_mbps
);
666 bitmask
= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW
;
668 return mlx5_modify_scheduling_element_cmd(esw
->dev
,
669 SCHEDULING_HIERARCHY_E_SWITCH
,
671 vport
->qos
.esw_tsar_ix
,
675 #define MLX5_LINKSPEED_UNIT 125000 /* 1Mbps in Bps */
677 /* Converts bytes per second value passed in a pointer into megabits per
678 * second, rewriting last. If converted rate exceed link speed or is not a
679 * fraction of Mbps - returns error.
681 static int esw_qos_devlink_rate_to_mbps(struct mlx5_core_dev
*mdev
, const char *name
,
682 u64
*rate
, struct netlink_ext_ack
*extack
)
684 u32 link_speed_max
, reminder
;
688 err
= mlx5e_port_max_linkspeed(mdev
, &link_speed_max
);
690 NL_SET_ERR_MSG_MOD(extack
, "Failed to get link maximum speed");
694 value
= div_u64_rem(*rate
, MLX5_LINKSPEED_UNIT
, &reminder
);
696 pr_err("%s rate value %lluBps not in link speed units of 1Mbps.\n",
698 NL_SET_ERR_MSG_MOD(extack
, "TX rate value not in link speed units of 1Mbps");
702 if (value
> link_speed_max
) {
703 pr_err("%s rate value %lluMbps exceed link maximum speed %u.\n",
704 name
, value
, link_speed_max
);
705 NL_SET_ERR_MSG_MOD(extack
, "TX rate value exceed link maximum speed");
713 /* Eswitch devlink rate API */
715 int mlx5_esw_devlink_rate_leaf_tx_share_set(struct devlink_rate
*rate_leaf
, void *priv
,
716 u64 tx_share
, struct netlink_ext_ack
*extack
)
718 struct mlx5_vport
*vport
= priv
;
719 struct mlx5_eswitch
*esw
;
722 esw
= vport
->dev
->priv
.eswitch
;
723 if (!mlx5_esw_allowed(esw
))
726 err
= esw_qos_devlink_rate_to_mbps(vport
->dev
, "tx_share", &tx_share
, extack
);
730 mutex_lock(&esw
->state_lock
);
731 err
= mlx5_esw_qos_set_vport_min_rate(esw
, vport
, tx_share
, extack
);
732 mutex_unlock(&esw
->state_lock
);
736 int mlx5_esw_devlink_rate_leaf_tx_max_set(struct devlink_rate
*rate_leaf
, void *priv
,
737 u64 tx_max
, struct netlink_ext_ack
*extack
)
739 struct mlx5_vport
*vport
= priv
;
740 struct mlx5_eswitch
*esw
;
743 esw
= vport
->dev
->priv
.eswitch
;
744 if (!mlx5_esw_allowed(esw
))
747 err
= esw_qos_devlink_rate_to_mbps(vport
->dev
, "tx_max", &tx_max
, extack
);
751 mutex_lock(&esw
->state_lock
);
752 err
= mlx5_esw_qos_set_vport_max_rate(esw
, vport
, tx_max
, extack
);
753 mutex_unlock(&esw
->state_lock
);
757 int mlx5_esw_devlink_rate_node_tx_share_set(struct devlink_rate
*rate_node
, void *priv
,
758 u64 tx_share
, struct netlink_ext_ack
*extack
)
760 struct mlx5_core_dev
*dev
= devlink_priv(rate_node
->devlink
);
761 struct mlx5_eswitch
*esw
= dev
->priv
.eswitch
;
762 struct mlx5_esw_rate_group
*group
= priv
;
765 err
= esw_qos_devlink_rate_to_mbps(dev
, "tx_share", &tx_share
, extack
);
769 mutex_lock(&esw
->state_lock
);
770 err
= esw_qos_set_group_min_rate(esw
, group
, tx_share
, extack
);
771 mutex_unlock(&esw
->state_lock
);
775 int mlx5_esw_devlink_rate_node_tx_max_set(struct devlink_rate
*rate_node
, void *priv
,
776 u64 tx_max
, struct netlink_ext_ack
*extack
)
778 struct mlx5_core_dev
*dev
= devlink_priv(rate_node
->devlink
);
779 struct mlx5_eswitch
*esw
= dev
->priv
.eswitch
;
780 struct mlx5_esw_rate_group
*group
= priv
;
783 err
= esw_qos_devlink_rate_to_mbps(dev
, "tx_max", &tx_max
, extack
);
787 mutex_lock(&esw
->state_lock
);
788 err
= esw_qos_set_group_max_rate(esw
, group
, tx_max
, extack
);
789 mutex_unlock(&esw
->state_lock
);
793 int mlx5_esw_devlink_rate_node_new(struct devlink_rate
*rate_node
, void **priv
,
794 struct netlink_ext_ack
*extack
)
796 struct mlx5_esw_rate_group
*group
;
797 struct mlx5_eswitch
*esw
;
800 esw
= mlx5_devlink_eswitch_get(rate_node
->devlink
);
804 mutex_lock(&esw
->state_lock
);
805 if (esw
->mode
!= MLX5_ESWITCH_OFFLOADS
) {
806 NL_SET_ERR_MSG_MOD(extack
,
807 "Rate node creation supported only in switchdev mode");
812 group
= esw_qos_create_rate_group(esw
, extack
);
814 err
= PTR_ERR(group
);
820 mutex_unlock(&esw
->state_lock
);
824 int mlx5_esw_devlink_rate_node_del(struct devlink_rate
*rate_node
, void *priv
,
825 struct netlink_ext_ack
*extack
)
827 struct mlx5_esw_rate_group
*group
= priv
;
828 struct mlx5_eswitch
*esw
;
831 esw
= mlx5_devlink_eswitch_get(rate_node
->devlink
);
835 mutex_lock(&esw
->state_lock
);
836 err
= esw_qos_destroy_rate_group(esw
, group
, extack
);
837 mutex_unlock(&esw
->state_lock
);
841 int mlx5_esw_qos_vport_update_group(struct mlx5_eswitch
*esw
,
842 struct mlx5_vport
*vport
,
843 struct mlx5_esw_rate_group
*group
,
844 struct netlink_ext_ack
*extack
)
848 mutex_lock(&esw
->state_lock
);
849 err
= esw_qos_vport_update_group(esw
, vport
, group
, extack
);
850 mutex_unlock(&esw
->state_lock
);
854 int mlx5_esw_devlink_rate_parent_set(struct devlink_rate
*devlink_rate
,
855 struct devlink_rate
*parent
,
856 void *priv
, void *parent_priv
,
857 struct netlink_ext_ack
*extack
)
859 struct mlx5_esw_rate_group
*group
;
860 struct mlx5_vport
*vport
= priv
;
863 return mlx5_esw_qos_vport_update_group(vport
->dev
->priv
.eswitch
,
864 vport
, NULL
, extack
);
867 return mlx5_esw_qos_vport_update_group(vport
->dev
->priv
.eswitch
, vport
, group
, extack
);