net/mlx5: qos: Refactor vport QoS cleanup

Qos cleanup is a complex affair, because of the two modes of operation
(legacy and switchdev).

Leaf QoS is removed:
1. In legacy mode by esw_vport_cleanup() -> mlx5_esw_qos_vport_disable()
2. In switchdev mode by mlx5_esw_offloads_devlink_port_unregister() ->
mlx5_esw_qos_vport_update_parent(). A little later in the same flow, the
calls in 1 happen but they are noops.

Zooming out a bit, from both mlx5_eswitch_disable_locked() and
mlx5_eswitch_disable_sriov() the leaves are destroyed before the nodes,
which is the reverse of what should be.

For SFs there's no devl_rate_nodes_destroy() call to unparent the
affected leaf.

Sanitize all of this by:
1. Destroying nodes before leaves in both legacy and switchdev mode.
2. Only removing vport qos from esw_vport_cleanup(), reachable from both
   legacy and switchdev and also reachable by SF removal.
3. Unexpose mlx5_esw_qos_vport_update_parent(), which becomes internal
   to qos.
4. Remove the WARN in mlx5_esw_qos_vport_disable().

This also takes care of a theoretical corner case, when
mlx5_esw_qos_vport_update_parent() tried to reattach the vport to
the original parent on failure, which can fail as well, leaving the
vport in a broken state.

Signed-off-by: Cosmin Ratiu <cratiu@nvidia.com>
Reviewed-by: Carolina Jubran <cjubran@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260701073254.754518-10-tariqt@nvidia.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
This commit is contained in:
Cosmin Ratiu
2026-07-01 10:32:49 +03:00
committed by Paolo Abeni
parent f8128b13df
commit 89a0881183
4 changed files with 14 additions and 22 deletions

View File

@@ -268,7 +268,6 @@ void mlx5_esw_offloads_devlink_port_unregister(struct mlx5_vport *vport)
dl_port = vport->dl_port;
mlx5_esw_devlink_port_res_unregister(&dl_port->dl_port);
mlx5_esw_qos_vport_update_parent(vport, NULL, NULL);
devl_rate_leaf_destroy(&dl_port->dl_port);
devl_port_unregister(&dl_port->dl_port);

View File

@@ -1139,18 +1139,10 @@ static void mlx5_esw_qos_vport_disable_locked(struct mlx5_vport *vport)
void mlx5_esw_qos_vport_disable(struct mlx5_vport *vport)
{
struct mlx5_eswitch *esw = vport->dev->priv.eswitch;
struct mlx5_esw_sched_node *parent;
lockdep_assert_held(&esw->state_lock);
esw_qos_lock(esw);
if (!vport->qos.sched_node)
goto unlock;
parent = vport->qos.sched_node->parent;
WARN(parent, "Disabling QoS on port before detaching it from node");
mlx5_esw_qos_vport_disable_locked(vport);
unlock:
esw_qos_unlock(esw);
}
@@ -1866,8 +1858,10 @@ int mlx5_esw_devlink_rate_node_del(struct devlink_rate *rate_node, void *priv,
return 0;
}
int mlx5_esw_qos_vport_update_parent(struct mlx5_vport *vport, struct mlx5_esw_sched_node *parent,
struct netlink_ext_ack *extack)
static int
mlx5_esw_qos_vport_update_parent(struct mlx5_vport *vport,
struct mlx5_esw_sched_node *parent,
struct netlink_ext_ack *extack)
{
struct mlx5_eswitch *esw = vport->dev->priv.eswitch;
int err = 0;

View File

@@ -1990,6 +1990,13 @@ void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf)
esw->esw_funcs.num_vfs, esw->esw_funcs.num_ec_vfs, esw->enabled_vports);
mlx5_eswitch_invalidate_wq(esw);
if (esw->mode == MLX5_ESWITCH_OFFLOADS) {
struct devlink *devlink = priv_to_devlink(esw->dev);
devl_rate_nodes_destroy(devlink);
}
mlx5_esw_reps_block(esw);
if (!mlx5_core_is_ecpf(esw->dev)) {
@@ -2003,12 +2010,6 @@ void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf)
}
mlx5_esw_reps_unblock(esw);
if (esw->mode == MLX5_ESWITCH_OFFLOADS) {
struct devlink *devlink = priv_to_devlink(esw->dev);
devl_rate_nodes_destroy(devlink);
}
/* Destroy legacy fdb when disabling sriov in legacy mode. */
if (esw->mode == MLX5_ESWITCH_LEGACY)
mlx5_eswitch_disable_locked(esw);
@@ -2039,6 +2040,9 @@ void mlx5_eswitch_disable_locked(struct mlx5_eswitch *esw)
esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS",
esw->esw_funcs.num_vfs, esw->esw_funcs.num_ec_vfs, esw->enabled_vports);
if (esw->mode == MLX5_ESWITCH_OFFLOADS)
devl_rate_nodes_destroy(devlink);
if (esw->fdb_table.flags & MLX5_ESW_FDB_CREATED) {
esw->fdb_table.flags &= ~MLX5_ESW_FDB_CREATED;
if (esw->mode == MLX5_ESWITCH_OFFLOADS)
@@ -2047,9 +2051,6 @@ void mlx5_eswitch_disable_locked(struct mlx5_eswitch *esw)
esw_legacy_disable(esw);
mlx5_esw_acls_ns_cleanup(esw);
}
if (esw->mode == MLX5_ESWITCH_OFFLOADS)
devl_rate_nodes_destroy(devlink);
}
void mlx5_eswitch_disable(struct mlx5_eswitch *esw)

View File

@@ -482,8 +482,6 @@ int mlx5_eswitch_set_vport_trust(struct mlx5_eswitch *esw,
u16 vport_num, bool setting);
int mlx5_eswitch_set_vport_rate(struct mlx5_eswitch *esw, u16 vport,
u32 max_rate, u32 min_rate);
int mlx5_esw_qos_vport_update_parent(struct mlx5_vport *vport, struct mlx5_esw_sched_node *node,
struct netlink_ext_ack *extack);
int mlx5_eswitch_set_vepa(struct mlx5_eswitch *esw, u8 setting);
int mlx5_eswitch_get_vepa(struct mlx5_eswitch *esw, u8 *setting);
int mlx5_eswitch_get_vport_config(struct mlx5_eswitch *esw,