Skip to content

Commit b697ef4

Browse files
cjubrankuba-moo
authored andcommitted
net/mlx5: Destroy vport QoS element when no configuration remains
If a VF has been configured and the user later clears all QoS settings, the vport element remains in the firmware QoS tree. This leads to inconsistent behavior compared to VFs that were never configured, since the FW assumes that unconfigured VFs are outside the QoS hierarchy. As a result, the bandwidth share across VFs may differ, even though none of them appear to have any configuration. Align the driver behavior with the FW expectation by destroying the vport QoS element when all configurations are removed. Fixes: c9497c9 ("net/mlx5: Add support for setting VF min rate") Fixes: cf7e737 ("net/mlx5: Manage TC arbiter nodes and implement full support for tc-bw") Signed-off-by: Carolina Jubran <[email protected]> Reviewed-by: Cosmin Ratiu <[email protected]> Signed-off-by: Mark Bloch <[email protected]> Reviewed-by: Przemek Kitszel <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jakub Kicinski <[email protected]>
1 parent e8f9735 commit b697ef4

File tree

1 file changed

+49
-8
lines changed
  • drivers/net/ethernet/mellanox/mlx5/core/esw

1 file changed

+49
-8
lines changed

drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1127,6 +1127,19 @@ static int mlx5_esw_qos_vport_enable(struct mlx5_vport *vport, enum sched_node_t
11271127
return err;
11281128
}
11291129

1130+
static void mlx5_esw_qos_vport_disable_locked(struct mlx5_vport *vport)
1131+
{
1132+
struct mlx5_eswitch *esw = vport->dev->priv.eswitch;
1133+
1134+
esw_assert_qos_lock_held(esw);
1135+
if (!vport->qos.sched_node)
1136+
return;
1137+
1138+
esw_qos_vport_disable(vport, NULL);
1139+
mlx5_esw_qos_vport_qos_free(vport);
1140+
esw_qos_put(esw);
1141+
}
1142+
11301143
void mlx5_esw_qos_vport_disable(struct mlx5_vport *vport)
11311144
{
11321145
struct mlx5_eswitch *esw = vport->dev->priv.eswitch;
@@ -1140,9 +1153,7 @@ void mlx5_esw_qos_vport_disable(struct mlx5_vport *vport)
11401153
parent = vport->qos.sched_node->parent;
11411154
WARN(parent, "Disabling QoS on port before detaching it from node");
11421155

1143-
esw_qos_vport_disable(vport, NULL);
1144-
mlx5_esw_qos_vport_qos_free(vport);
1145-
esw_qos_put(esw);
1156+
mlx5_esw_qos_vport_disable_locked(vport);
11461157
unlock:
11471158
esw_qos_unlock(esw);
11481159
}
@@ -1642,6 +1653,21 @@ static bool esw_qos_tc_bw_disabled(u32 *tc_bw)
16421653
return true;
16431654
}
16441655

1656+
static void esw_vport_qos_prune_empty(struct mlx5_vport *vport)
1657+
{
1658+
struct mlx5_esw_sched_node *vport_node = vport->qos.sched_node;
1659+
1660+
esw_assert_qos_lock_held(vport->dev->priv.eswitch);
1661+
if (!vport_node)
1662+
return;
1663+
1664+
if (vport_node->parent || vport_node->max_rate ||
1665+
vport_node->min_rate || !esw_qos_tc_bw_disabled(vport_node->tc_bw))
1666+
return;
1667+
1668+
mlx5_esw_qos_vport_disable_locked(vport);
1669+
}
1670+
16451671
int mlx5_esw_qos_init(struct mlx5_eswitch *esw)
16461672
{
16471673
if (esw->qos.domain)
@@ -1675,6 +1701,10 @@ int mlx5_esw_devlink_rate_leaf_tx_share_set(struct devlink_rate *rate_leaf, void
16751701

16761702
esw_qos_lock(esw);
16771703
err = mlx5_esw_qos_set_vport_min_rate(vport, tx_share, extack);
1704+
if (err)
1705+
goto out;
1706+
esw_vport_qos_prune_empty(vport);
1707+
out:
16781708
esw_qos_unlock(esw);
16791709
return err;
16801710
}
@@ -1696,6 +1726,10 @@ int mlx5_esw_devlink_rate_leaf_tx_max_set(struct devlink_rate *rate_leaf, void *
16961726

16971727
esw_qos_lock(esw);
16981728
err = mlx5_esw_qos_set_vport_max_rate(vport, tx_max, extack);
1729+
if (err)
1730+
goto out;
1731+
esw_vport_qos_prune_empty(vport);
1732+
out:
16991733
esw_qos_unlock(esw);
17001734
return err;
17011735
}
@@ -1733,6 +1767,7 @@ int mlx5_esw_devlink_rate_leaf_tc_bw_set(struct devlink_rate *rate_leaf,
17331767
if (vport_node->type == SCHED_NODE_TYPE_TC_ARBITER_TSAR)
17341768
err = esw_qos_vport_update(vport, SCHED_NODE_TYPE_VPORT,
17351769
vport_node->parent, extack);
1770+
esw_vport_qos_prune_empty(vport);
17361771
goto unlock;
17371772
}
17381773

@@ -1893,14 +1928,20 @@ int mlx5_esw_devlink_rate_leaf_parent_set(struct devlink_rate *devlink_rate,
18931928
void *priv, void *parent_priv,
18941929
struct netlink_ext_ack *extack)
18951930
{
1896-
struct mlx5_esw_sched_node *node;
1931+
struct mlx5_esw_sched_node *node = parent ? parent_priv : NULL;
18971932
struct mlx5_vport *vport = priv;
1933+
int err;
18981934

1899-
if (!parent)
1900-
return mlx5_esw_qos_vport_update_parent(vport, NULL, extack);
1935+
err = mlx5_esw_qos_vport_update_parent(vport, node, extack);
1936+
if (!err) {
1937+
struct mlx5_eswitch *esw = vport->dev->priv.eswitch;
1938+
1939+
esw_qos_lock(esw);
1940+
esw_vport_qos_prune_empty(vport);
1941+
esw_qos_unlock(esw);
1942+
}
19011943

1902-
node = parent_priv;
1903-
return mlx5_esw_qos_vport_update_parent(vport, node, extack);
1944+
return err;
19041945
}
19051946

19061947
static bool esw_qos_is_node_empty(struct mlx5_esw_sched_node *node)

0 commit comments

Comments
 (0)