From: Cosmin Ratiu <[email protected]>

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 <[email protected]>
Reviewed-by: Carolina Jubran <[email protected]>
Signed-off-by: Tariq Toukan <[email protected]>
---
 .../mellanox/mlx5/core/esw/devlink_port.c     |  1 -
 .../net/ethernet/mellanox/mlx5/core/esw/qos.c | 14 ++++----------
 .../net/ethernet/mellanox/mlx5/core/eswitch.c | 19 ++++++++++---------
 .../net/ethernet/mellanox/mlx5/core/eswitch.h |  2 --
 4 files changed, 14 insertions(+), 22 deletions(-)

diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c 
b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c
index 6e50311faa27..8c27a33f9d7b 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/devlink_port.c
@@ -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);
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c 
b/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c
index d04fda4b3778..204f47c99142 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/qos.c
@@ -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;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c 
b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
index a0e2ca87b8d8..b67f15a8f766 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.c
@@ -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)
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h 
b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
index fea72b1dedab..140343f2b913 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
+++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch.h
@@ -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,
-- 
2.44.0


Reply via email to