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 tsar_ix, u32 max_rate, u32 bw_share)
29 if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, esw_scheduling))
32 MLX5_SET(scheduling_context, sched_ctx, max_average_bw, max_rate);
33 MLX5_SET(scheduling_context, sched_ctx, bw_share, bw_share);
34 bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW;
35 bitmask |= MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_BW_SHARE;
37 return mlx5_modify_scheduling_element_cmd(dev,
38 SCHEDULING_HIERARCHY_E_SWITCH,
44 static int esw_qos_group_config(struct mlx5_eswitch *esw, struct mlx5_esw_rate_group *group,
45 u32 max_rate, u32 bw_share, struct netlink_ext_ack *extack)
47 u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {};
48 struct mlx5_core_dev *dev = esw->dev;
51 err = esw_qos_tsar_config(dev, sched_ctx,
55 NL_SET_ERR_MSG_MOD(extack, "E-Switch modify group TSAR element failed");
57 trace_mlx5_esw_group_qos_config(dev, group, group->tsar_ix, bw_share, max_rate);
62 static int esw_qos_vport_config(struct mlx5_eswitch *esw,
63 struct mlx5_vport *vport,
64 u32 max_rate, u32 bw_share,
65 struct netlink_ext_ack *extack)
67 u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {};
68 struct mlx5_core_dev *dev = esw->dev;
71 if (!vport->qos.enabled)
74 err = esw_qos_tsar_config(dev, sched_ctx, vport->qos.esw_tsar_ix,
78 "E-Switch modify TSAR vport element failed (vport=%d,err=%d)\n",
80 NL_SET_ERR_MSG_MOD(extack, "E-Switch modify TSAR vport element failed");
84 trace_mlx5_esw_vport_qos_config(vport, bw_share, max_rate);
89 static u32 esw_qos_calculate_min_rate_divider(struct mlx5_eswitch *esw,
90 struct mlx5_esw_rate_group *group,
93 u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
94 struct mlx5_vport *evport;
95 u32 max_guarantee = 0;
99 struct mlx5_esw_rate_group *group;
101 list_for_each_entry(group, &esw->qos.groups, list) {
102 if (group->min_rate < max_guarantee)
104 max_guarantee = group->min_rate;
107 mlx5_esw_for_each_vport(esw, i, evport) {
108 if (!evport->enabled || !evport->qos.enabled ||
109 evport->qos.group != group || evport->qos.min_rate < max_guarantee)
111 max_guarantee = evport->qos.min_rate;
116 return max_t(u32, max_guarantee / fw_max_bw_share, 1);
118 /* If vports min rate divider is 0 but their group has bw_share configured, then
119 * need to set bw_share for vports to minimal value.
121 if (!group_level && !max_guarantee && group && group->bw_share)
126 static u32 esw_qos_calc_bw_share(u32 min_rate, u32 divider, u32 fw_max)
129 return MLX5_RATE_TO_BW_SHARE(min_rate, divider, fw_max);
134 static int esw_qos_normalize_vports_min_rate(struct mlx5_eswitch *esw,
135 struct mlx5_esw_rate_group *group,
136 struct netlink_ext_ack *extack)
138 u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
139 u32 divider = esw_qos_calculate_min_rate_divider(esw, group, false);
140 struct mlx5_vport *evport;
145 mlx5_esw_for_each_vport(esw, i, evport) {
146 if (!evport->enabled || !evport->qos.enabled || evport->qos.group != group)
148 bw_share = esw_qos_calc_bw_share(evport->qos.min_rate, divider, fw_max_bw_share);
150 if (bw_share == evport->qos.bw_share)
153 err = esw_qos_vport_config(esw, evport, evport->qos.max_rate, bw_share, extack);
157 evport->qos.bw_share = bw_share;
163 static int esw_qos_normalize_groups_min_rate(struct mlx5_eswitch *esw, u32 divider,
164 struct netlink_ext_ack *extack)
166 u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
167 struct mlx5_esw_rate_group *group;
171 list_for_each_entry(group, &esw->qos.groups, list) {
172 bw_share = esw_qos_calc_bw_share(group->min_rate, divider, fw_max_bw_share);
174 if (bw_share == group->bw_share)
177 err = esw_qos_group_config(esw, group, group->max_rate, bw_share, extack);
181 group->bw_share = bw_share;
183 /* All the group's vports need to be set with default bw_share
184 * to enable them with QOS
186 err = esw_qos_normalize_vports_min_rate(esw, group, extack);
195 static int esw_qos_set_vport_min_rate(struct mlx5_eswitch *esw, struct mlx5_vport *evport,
196 u32 min_rate, struct netlink_ext_ack *extack)
198 u32 fw_max_bw_share, previous_min_rate;
199 bool min_rate_supported;
202 lockdep_assert_held(&esw->state_lock);
203 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
204 min_rate_supported = MLX5_CAP_QOS(esw->dev, esw_bw_share) &&
205 fw_max_bw_share >= MLX5_MIN_BW_SHARE;
206 if (min_rate && !min_rate_supported)
208 if (min_rate == evport->qos.min_rate)
211 previous_min_rate = evport->qos.min_rate;
212 evport->qos.min_rate = min_rate;
213 err = esw_qos_normalize_vports_min_rate(esw, evport->qos.group, extack);
215 evport->qos.min_rate = previous_min_rate;
220 static int esw_qos_set_vport_max_rate(struct mlx5_eswitch *esw, struct mlx5_vport *evport,
221 u32 max_rate, struct netlink_ext_ack *extack)
223 u32 act_max_rate = max_rate;
224 bool max_rate_supported;
227 lockdep_assert_held(&esw->state_lock);
228 max_rate_supported = MLX5_CAP_QOS(esw->dev, esw_rate_limit);
230 if (max_rate && !max_rate_supported)
232 if (max_rate == evport->qos.max_rate)
235 /* If parent group has rate limit need to set to group
236 * value when new max rate is 0.
238 if (evport->qos.group && !max_rate)
239 act_max_rate = evport->qos.group->max_rate;
241 err = esw_qos_vport_config(esw, evport, act_max_rate, evport->qos.bw_share, extack);
244 evport->qos.max_rate = max_rate;
249 static int esw_qos_set_group_min_rate(struct mlx5_eswitch *esw, struct mlx5_esw_rate_group *group,
250 u32 min_rate, struct netlink_ext_ack *extack)
252 u32 fw_max_bw_share = MLX5_CAP_QOS(esw->dev, max_tsar_bw_share);
253 struct mlx5_core_dev *dev = esw->dev;
254 u32 previous_min_rate, divider;
257 if (!(MLX5_CAP_QOS(dev, esw_bw_share) && fw_max_bw_share >= MLX5_MIN_BW_SHARE))
260 if (min_rate == group->min_rate)
263 previous_min_rate = group->min_rate;
264 group->min_rate = min_rate;
265 divider = esw_qos_calculate_min_rate_divider(esw, group, true);
266 err = esw_qos_normalize_groups_min_rate(esw, divider, extack);
268 group->min_rate = previous_min_rate;
269 NL_SET_ERR_MSG_MOD(extack, "E-Switch group min rate setting failed");
271 /* Attempt restoring previous configuration */
272 divider = esw_qos_calculate_min_rate_divider(esw, group, true);
273 if (esw_qos_normalize_groups_min_rate(esw, divider, extack))
274 NL_SET_ERR_MSG_MOD(extack, "E-Switch BW share restore failed");
280 static int esw_qos_set_group_max_rate(struct mlx5_eswitch *esw,
281 struct mlx5_esw_rate_group *group,
282 u32 max_rate, struct netlink_ext_ack *extack)
284 struct mlx5_vport *vport;
288 if (group->max_rate == max_rate)
291 err = esw_qos_group_config(esw, group, max_rate, group->bw_share, extack);
295 group->max_rate = max_rate;
297 /* Any unlimited vports in the group should be set
298 * with the value of the group.
300 mlx5_esw_for_each_vport(esw, i, vport) {
301 if (!vport->enabled || !vport->qos.enabled ||
302 vport->qos.group != group || vport->qos.max_rate)
305 err = esw_qos_vport_config(esw, vport, max_rate, vport->qos.bw_share, extack);
307 NL_SET_ERR_MSG_MOD(extack,
308 "E-Switch vport implicit rate limit setting failed");
314 static int esw_qos_vport_create_sched_element(struct mlx5_eswitch *esw,
315 struct mlx5_vport *vport,
316 u32 max_rate, u32 bw_share)
318 u32 sched_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {};
319 struct mlx5_esw_rate_group *group = vport->qos.group;
320 struct mlx5_core_dev *dev = esw->dev;
325 parent_tsar_ix = group ? group->tsar_ix : esw->qos.root_tsar_ix;
326 MLX5_SET(scheduling_context, sched_ctx, element_type,
327 SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT);
328 vport_elem = MLX5_ADDR_OF(scheduling_context, sched_ctx, element_attributes);
329 MLX5_SET(vport_element, vport_elem, vport_number, vport->vport);
330 MLX5_SET(scheduling_context, sched_ctx, parent_element_id, parent_tsar_ix);
331 MLX5_SET(scheduling_context, sched_ctx, max_average_bw, max_rate);
332 MLX5_SET(scheduling_context, sched_ctx, bw_share, bw_share);
334 err = mlx5_create_scheduling_element_cmd(dev,
335 SCHEDULING_HIERARCHY_E_SWITCH,
337 &vport->qos.esw_tsar_ix);
339 esw_warn(esw->dev, "E-Switch create TSAR vport element failed (vport=%d,err=%d)\n",
347 static int esw_qos_update_group_scheduling_element(struct mlx5_eswitch *esw,
348 struct mlx5_vport *vport,
349 struct mlx5_esw_rate_group *curr_group,
350 struct mlx5_esw_rate_group *new_group,
351 struct netlink_ext_ack *extack)
356 err = mlx5_destroy_scheduling_element_cmd(esw->dev,
357 SCHEDULING_HIERARCHY_E_SWITCH,
358 vport->qos.esw_tsar_ix);
360 NL_SET_ERR_MSG_MOD(extack, "E-Switch destroy TSAR vport element failed");
364 vport->qos.group = new_group;
365 max_rate = vport->qos.max_rate ? vport->qos.max_rate : new_group->max_rate;
367 /* If vport is unlimited, we set the group's value.
368 * Therefore, if the group is limited it will apply to
369 * the vport as well and if not, vport will remain unlimited.
371 err = esw_qos_vport_create_sched_element(esw, vport, max_rate, vport->qos.bw_share);
373 NL_SET_ERR_MSG_MOD(extack, "E-Switch vport group set failed.");
380 vport->qos.group = curr_group;
381 max_rate = vport->qos.max_rate ? vport->qos.max_rate : curr_group->max_rate;
382 if (esw_qos_vport_create_sched_element(esw, vport, max_rate, vport->qos.bw_share))
383 esw_warn(esw->dev, "E-Switch vport group restore failed (vport=%d)\n",
389 static int esw_qos_vport_update_group(struct mlx5_eswitch *esw,
390 struct mlx5_vport *vport,
391 struct mlx5_esw_rate_group *group,
392 struct netlink_ext_ack *extack)
394 struct mlx5_esw_rate_group *new_group, *curr_group;
400 curr_group = vport->qos.group;
401 new_group = group ?: esw->qos.group0;
402 if (curr_group == new_group)
405 err = esw_qos_update_group_scheduling_element(esw, vport, curr_group, new_group, extack);
409 /* Recalculate bw share weights of old and new groups */
410 if (vport->qos.bw_share || new_group->bw_share) {
411 esw_qos_normalize_vports_min_rate(esw, curr_group, extack);
412 esw_qos_normalize_vports_min_rate(esw, new_group, extack);
418 static struct mlx5_esw_rate_group *
419 __esw_qos_create_rate_group(struct mlx5_eswitch *esw, struct netlink_ext_ack *extack)
421 u32 tsar_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {};
422 struct mlx5_esw_rate_group *group;
426 group = kzalloc(sizeof(*group), GFP_KERNEL);
428 return ERR_PTR(-ENOMEM);
430 MLX5_SET(scheduling_context, tsar_ctx, parent_element_id,
431 esw->qos.root_tsar_ix);
432 err = mlx5_create_scheduling_element_cmd(esw->dev,
433 SCHEDULING_HIERARCHY_E_SWITCH,
437 NL_SET_ERR_MSG_MOD(extack, "E-Switch create TSAR for group failed");
441 list_add_tail(&group->list, &esw->qos.groups);
443 divider = esw_qos_calculate_min_rate_divider(esw, group, true);
445 err = esw_qos_normalize_groups_min_rate(esw, divider, extack);
447 NL_SET_ERR_MSG_MOD(extack, "E-Switch groups normalization failed");
451 trace_mlx5_esw_group_qos_create(esw->dev, group, group->tsar_ix);
456 list_del(&group->list);
457 if (mlx5_destroy_scheduling_element_cmd(esw->dev,
458 SCHEDULING_HIERARCHY_E_SWITCH,
460 NL_SET_ERR_MSG_MOD(extack, "E-Switch destroy TSAR for group failed");
466 static int esw_qos_get(struct mlx5_eswitch *esw, struct netlink_ext_ack *extack);
467 static void esw_qos_put(struct mlx5_eswitch *esw);
469 static struct mlx5_esw_rate_group *
470 esw_qos_create_rate_group(struct mlx5_eswitch *esw, struct netlink_ext_ack *extack)
472 struct mlx5_esw_rate_group *group;
475 if (!MLX5_CAP_QOS(esw->dev, log_esw_max_sched_depth))
476 return ERR_PTR(-EOPNOTSUPP);
478 err = esw_qos_get(esw, extack);
482 group = __esw_qos_create_rate_group(esw, extack);
489 static int __esw_qos_destroy_rate_group(struct mlx5_eswitch *esw,
490 struct mlx5_esw_rate_group *group,
491 struct netlink_ext_ack *extack)
496 list_del(&group->list);
498 divider = esw_qos_calculate_min_rate_divider(esw, NULL, true);
499 err = esw_qos_normalize_groups_min_rate(esw, divider, extack);
501 NL_SET_ERR_MSG_MOD(extack, "E-Switch groups' normalization failed");
503 err = mlx5_destroy_scheduling_element_cmd(esw->dev,
504 SCHEDULING_HIERARCHY_E_SWITCH,
507 NL_SET_ERR_MSG_MOD(extack, "E-Switch destroy TSAR_ID failed");
509 trace_mlx5_esw_group_qos_destroy(esw->dev, group, group->tsar_ix);
516 static int esw_qos_destroy_rate_group(struct mlx5_eswitch *esw,
517 struct mlx5_esw_rate_group *group,
518 struct netlink_ext_ack *extack)
522 err = __esw_qos_destroy_rate_group(esw, group, extack);
528 static bool esw_qos_element_type_supported(struct mlx5_core_dev *dev, int type)
531 case SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR:
532 return MLX5_CAP_QOS(dev, esw_element_type) &
533 ELEMENT_TYPE_CAP_MASK_TASR;
534 case SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT:
535 return MLX5_CAP_QOS(dev, esw_element_type) &
536 ELEMENT_TYPE_CAP_MASK_VPORT;
537 case SCHEDULING_CONTEXT_ELEMENT_TYPE_VPORT_TC:
538 return MLX5_CAP_QOS(dev, esw_element_type) &
539 ELEMENT_TYPE_CAP_MASK_VPORT_TC;
540 case SCHEDULING_CONTEXT_ELEMENT_TYPE_PARA_VPORT_TC:
541 return MLX5_CAP_QOS(dev, esw_element_type) &
542 ELEMENT_TYPE_CAP_MASK_PARA_VPORT_TC;
547 static int esw_qos_create(struct mlx5_eswitch *esw, struct netlink_ext_ack *extack)
549 u32 tsar_ctx[MLX5_ST_SZ_DW(scheduling_context)] = {};
550 struct mlx5_core_dev *dev = esw->dev;
554 if (!MLX5_CAP_GEN(dev, qos) || !MLX5_CAP_QOS(dev, esw_scheduling))
557 if (!esw_qos_element_type_supported(dev, SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR))
560 MLX5_SET(scheduling_context, tsar_ctx, element_type,
561 SCHEDULING_CONTEXT_ELEMENT_TYPE_TSAR);
563 attr = MLX5_ADDR_OF(scheduling_context, tsar_ctx, element_attributes);
564 *attr = cpu_to_be32(TSAR_ELEMENT_TSAR_TYPE_DWRR << 16);
566 err = mlx5_create_scheduling_element_cmd(dev,
567 SCHEDULING_HIERARCHY_E_SWITCH,
569 &esw->qos.root_tsar_ix);
571 esw_warn(dev, "E-Switch create root TSAR failed (%d)\n", err);
575 INIT_LIST_HEAD(&esw->qos.groups);
576 if (MLX5_CAP_QOS(dev, log_esw_max_sched_depth)) {
577 esw->qos.group0 = __esw_qos_create_rate_group(esw, extack);
578 if (IS_ERR(esw->qos.group0)) {
579 esw_warn(dev, "E-Switch create rate group 0 failed (%ld)\n",
580 PTR_ERR(esw->qos.group0));
581 err = PTR_ERR(esw->qos.group0);
585 refcount_set(&esw->qos.refcnt, 1);
590 if (mlx5_destroy_scheduling_element_cmd(esw->dev, SCHEDULING_HIERARCHY_E_SWITCH,
591 esw->qos.root_tsar_ix))
592 esw_warn(esw->dev, "E-Switch destroy root TSAR failed.\n");
597 static void esw_qos_destroy(struct mlx5_eswitch *esw)
602 __esw_qos_destroy_rate_group(esw, esw->qos.group0, NULL);
604 err = mlx5_destroy_scheduling_element_cmd(esw->dev,
605 SCHEDULING_HIERARCHY_E_SWITCH,
606 esw->qos.root_tsar_ix);
608 esw_warn(esw->dev, "E-Switch destroy root TSAR failed (%d)\n", err);
611 static int esw_qos_get(struct mlx5_eswitch *esw, struct netlink_ext_ack *extack)
615 lockdep_assert_held(&esw->state_lock);
617 if (!refcount_inc_not_zero(&esw->qos.refcnt)) {
618 /* esw_qos_create() set refcount to 1 only on success.
619 * No need to decrement on failure.
621 err = esw_qos_create(esw, extack);
627 static void esw_qos_put(struct mlx5_eswitch *esw)
629 lockdep_assert_held(&esw->state_lock);
630 if (refcount_dec_and_test(&esw->qos.refcnt))
631 esw_qos_destroy(esw);
634 static int esw_qos_vport_enable(struct mlx5_eswitch *esw, struct mlx5_vport *vport,
635 u32 max_rate, u32 bw_share, struct netlink_ext_ack *extack)
639 lockdep_assert_held(&esw->state_lock);
640 if (vport->qos.enabled)
643 err = esw_qos_get(esw, extack);
647 vport->qos.group = esw->qos.group0;
649 err = esw_qos_vport_create_sched_element(esw, vport, max_rate, bw_share);
653 vport->qos.enabled = true;
654 trace_mlx5_esw_vport_qos_create(vport, bw_share, max_rate);
664 void mlx5_esw_qos_vport_disable(struct mlx5_eswitch *esw, struct mlx5_vport *vport)
668 lockdep_assert_held(&esw->state_lock);
669 if (!vport->qos.enabled)
671 WARN(vport->qos.group && vport->qos.group != esw->qos.group0,
672 "Disabling QoS on port before detaching it from group");
674 err = mlx5_destroy_scheduling_element_cmd(esw->dev,
675 SCHEDULING_HIERARCHY_E_SWITCH,
676 vport->qos.esw_tsar_ix);
678 esw_warn(esw->dev, "E-Switch destroy TSAR vport element failed (vport=%d,err=%d)\n",
681 memset(&vport->qos, 0, sizeof(vport->qos));
682 trace_mlx5_esw_vport_qos_destroy(vport);
687 int mlx5_esw_qos_set_vport_rate(struct mlx5_eswitch *esw, struct mlx5_vport *vport,
688 u32 max_rate, u32 min_rate)
692 lockdep_assert_held(&esw->state_lock);
693 err = esw_qos_vport_enable(esw, vport, 0, 0, NULL);
697 err = esw_qos_set_vport_min_rate(esw, vport, min_rate, NULL);
699 err = esw_qos_set_vport_max_rate(esw, vport, max_rate, NULL);
704 int mlx5_esw_qos_modify_vport_rate(struct mlx5_eswitch *esw, u16 vport_num, u32 rate_mbps)
706 u32 ctx[MLX5_ST_SZ_DW(scheduling_context)] = {};
707 struct mlx5_vport *vport;
711 vport = mlx5_eswitch_get_vport(esw, vport_num);
713 return PTR_ERR(vport);
715 mutex_lock(&esw->state_lock);
716 if (!vport->qos.enabled) {
717 /* Eswitch QoS wasn't enabled yet. Enable it and vport QoS. */
718 err = esw_qos_vport_enable(esw, vport, rate_mbps, vport->qos.bw_share, NULL);
720 MLX5_SET(scheduling_context, ctx, max_average_bw, rate_mbps);
722 bitmask = MODIFY_SCHEDULING_ELEMENT_IN_MODIFY_BITMASK_MAX_AVERAGE_BW;
723 err = mlx5_modify_scheduling_element_cmd(esw->dev,
724 SCHEDULING_HIERARCHY_E_SWITCH,
726 vport->qos.esw_tsar_ix,
729 mutex_unlock(&esw->state_lock);
734 #define MLX5_LINKSPEED_UNIT 125000 /* 1Mbps in Bps */
736 /* Converts bytes per second value passed in a pointer into megabits per
737 * second, rewriting last. If converted rate exceed link speed or is not a
738 * fraction of Mbps - returns error.
740 static int esw_qos_devlink_rate_to_mbps(struct mlx5_core_dev *mdev, const char *name,
741 u64 *rate, struct netlink_ext_ack *extack)
743 u32 link_speed_max, reminder;
747 err = mlx5e_port_max_linkspeed(mdev, &link_speed_max);
749 NL_SET_ERR_MSG_MOD(extack, "Failed to get link maximum speed");
753 value = div_u64_rem(*rate, MLX5_LINKSPEED_UNIT, &reminder);
755 pr_err("%s rate value %lluBps not in link speed units of 1Mbps.\n",
757 NL_SET_ERR_MSG_MOD(extack, "TX rate value not in link speed units of 1Mbps");
761 if (value > link_speed_max) {
762 pr_err("%s rate value %lluMbps exceed link maximum speed %u.\n",
763 name, value, link_speed_max);
764 NL_SET_ERR_MSG_MOD(extack, "TX rate value exceed link maximum speed");
772 /* Eswitch devlink rate API */
774 int mlx5_esw_devlink_rate_leaf_tx_share_set(struct devlink_rate *rate_leaf, void *priv,
775 u64 tx_share, struct netlink_ext_ack *extack)
777 struct mlx5_vport *vport = priv;
778 struct mlx5_eswitch *esw;
781 esw = vport->dev->priv.eswitch;
782 if (!mlx5_esw_allowed(esw))
785 err = esw_qos_devlink_rate_to_mbps(vport->dev, "tx_share", &tx_share, extack);
789 mutex_lock(&esw->state_lock);
790 err = esw_qos_vport_enable(esw, vport, 0, 0, extack);
794 err = esw_qos_set_vport_min_rate(esw, vport, tx_share, extack);
796 mutex_unlock(&esw->state_lock);
800 int mlx5_esw_devlink_rate_leaf_tx_max_set(struct devlink_rate *rate_leaf, void *priv,
801 u64 tx_max, struct netlink_ext_ack *extack)
803 struct mlx5_vport *vport = priv;
804 struct mlx5_eswitch *esw;
807 esw = vport->dev->priv.eswitch;
808 if (!mlx5_esw_allowed(esw))
811 err = esw_qos_devlink_rate_to_mbps(vport->dev, "tx_max", &tx_max, extack);
815 mutex_lock(&esw->state_lock);
816 err = esw_qos_vport_enable(esw, vport, 0, 0, extack);
820 err = esw_qos_set_vport_max_rate(esw, vport, tx_max, extack);
822 mutex_unlock(&esw->state_lock);
826 int mlx5_esw_devlink_rate_node_tx_share_set(struct devlink_rate *rate_node, void *priv,
827 u64 tx_share, struct netlink_ext_ack *extack)
829 struct mlx5_core_dev *dev = devlink_priv(rate_node->devlink);
830 struct mlx5_eswitch *esw = dev->priv.eswitch;
831 struct mlx5_esw_rate_group *group = priv;
834 err = esw_qos_devlink_rate_to_mbps(dev, "tx_share", &tx_share, extack);
838 mutex_lock(&esw->state_lock);
839 err = esw_qos_set_group_min_rate(esw, group, tx_share, extack);
840 mutex_unlock(&esw->state_lock);
844 int mlx5_esw_devlink_rate_node_tx_max_set(struct devlink_rate *rate_node, void *priv,
845 u64 tx_max, struct netlink_ext_ack *extack)
847 struct mlx5_core_dev *dev = devlink_priv(rate_node->devlink);
848 struct mlx5_eswitch *esw = dev->priv.eswitch;
849 struct mlx5_esw_rate_group *group = priv;
852 err = esw_qos_devlink_rate_to_mbps(dev, "tx_max", &tx_max, extack);
856 mutex_lock(&esw->state_lock);
857 err = esw_qos_set_group_max_rate(esw, group, tx_max, extack);
858 mutex_unlock(&esw->state_lock);
862 int mlx5_esw_devlink_rate_node_new(struct devlink_rate *rate_node, void **priv,
863 struct netlink_ext_ack *extack)
865 struct mlx5_esw_rate_group *group;
866 struct mlx5_eswitch *esw;
869 esw = mlx5_devlink_eswitch_get(rate_node->devlink);
873 mutex_lock(&esw->state_lock);
874 if (esw->mode != MLX5_ESWITCH_OFFLOADS) {
875 NL_SET_ERR_MSG_MOD(extack,
876 "Rate node creation supported only in switchdev mode");
881 group = esw_qos_create_rate_group(esw, extack);
883 err = PTR_ERR(group);
889 mutex_unlock(&esw->state_lock);
893 int mlx5_esw_devlink_rate_node_del(struct devlink_rate *rate_node, void *priv,
894 struct netlink_ext_ack *extack)
896 struct mlx5_esw_rate_group *group = priv;
897 struct mlx5_eswitch *esw;
900 esw = mlx5_devlink_eswitch_get(rate_node->devlink);
904 mutex_lock(&esw->state_lock);
905 err = esw_qos_destroy_rate_group(esw, group, extack);
906 mutex_unlock(&esw->state_lock);
910 int mlx5_esw_qos_vport_update_group(struct mlx5_eswitch *esw,
911 struct mlx5_vport *vport,
912 struct mlx5_esw_rate_group *group,
913 struct netlink_ext_ack *extack)
917 mutex_lock(&esw->state_lock);
918 if (!vport->qos.enabled && !group)
921 err = esw_qos_vport_enable(esw, vport, 0, 0, extack);
923 err = esw_qos_vport_update_group(esw, vport, group, extack);
925 mutex_unlock(&esw->state_lock);
929 int mlx5_esw_devlink_rate_parent_set(struct devlink_rate *devlink_rate,
930 struct devlink_rate *parent,
931 void *priv, void *parent_priv,
932 struct netlink_ext_ack *extack)
934 struct mlx5_esw_rate_group *group;
935 struct mlx5_vport *vport = priv;
938 return mlx5_esw_qos_vport_update_group(vport->dev->priv.eswitch,
939 vport, NULL, extack);
942 return mlx5_esw_qos_vport_update_group(vport->dev->priv.eswitch, vport, group, extack);