mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-31 02:21:39 -04:00
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:
committed by
Paolo Abeni
parent
f8128b13df
commit
89a0881183
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user