From: Alexei Lazar In mlx5e_init_nic_rx(), a failure subsequent to mlx5e_create_flow_steering() initiates an error cleanup flow, where mlx5e_destroy_flow_steering() calls mlx5e_del_vlan_rules() that contains WARN_ON_ONCE(fs->state_destroy). This warning fires because state_destroy is set before flow steering is fully initialized. To fix this, initialize NIC flow steering with state_destroy cleared, and set state_destroy only after profile->init_rx() succeeds. This keeps the flag cleared while mlx5e_create_flow_steering() is building its tables, so its internal error paths can destroy partially created flow steering without triggering the warning. The flag is set in mlx5e_attach_netdev(), rather than in mlx5e_init_nic_rx(), so non-NIC profiles such as representors also get state_destroy set after a detach/attach cycle. Previously, the 'out' label in mlx5e_attach_netdev() cleared state_destroy on every attach failure. Now that the flag is only set after init_rx() succeeds, the sole failure path that can observe it set is profile->enable() failing. Handle it at err_cleanup_rx: clear state_destroy so that cleanup_rx() can tear down flow steering without triggering the warning, and cancel set_rx_mode_work, which enable() is responsible for queueing, so the worker cannot run against flow steering that is being destroyed. Fixes: 8c7353b6f716 ("net/mlx5e: Fix VLAN cleanup flow") Signed-off-by: Alexei Lazar Signed-off-by: Gal Pressman Reviewed-by: Shahar Shitrit Signed-off-by: Tariq Toukan --- .../net/ethernet/mellanox/mlx5/core/en_main.c | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 38ce7d0a9001..13409f6585ba 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -6039,9 +6039,7 @@ static int mlx5e_nic_init(struct mlx5_core_dev *mdev, priv->dfs_root = debugfs_create_dir("nic", mlx5_debugfs_get_dev_root(mdev)); - fs = mlx5e_fs_init(priv->profile, mdev, - !test_bit(MLX5E_STATE_DESTROYING, &priv->state), - priv->dfs_root); + fs = mlx5e_fs_init(priv->profile, mdev, false, priv->dfs_root); if (!fs) { err = -ENOMEM; mlx5_core_err(mdev, "FS initialization failed, %d\n", err); @@ -6556,9 +6554,6 @@ int mlx5e_attach_netdev(struct mlx5e_priv *priv) int err; clear_bit(MLX5E_STATE_DESTROYING, &priv->state); - if (priv->fs) - mlx5e_fs_set_state_destroy(priv->fs, - !test_bit(MLX5E_STATE_DESTROYING, &priv->state)); /* Validate the max_wqe_size_sq capability. */ if (WARN_ON_ONCE(mlx5e_get_max_sq_wqebbs(priv->mdev) < MLX5E_MAX_TX_WQEBBS)) { @@ -6619,6 +6614,9 @@ int mlx5e_attach_netdev(struct mlx5e_priv *priv) if (err) goto err_cleanup_tx; + if (priv->fs) + mlx5e_fs_set_state_destroy(priv->fs, true); + if (profile->enable) { err = profile->enable(priv); if (err) @@ -6630,6 +6628,10 @@ int mlx5e_attach_netdev(struct mlx5e_priv *priv) return 0; err_cleanup_rx: + if (priv->fs) { + mlx5e_fs_set_state_destroy(priv->fs, false); + cancel_work_sync(&priv->set_rx_mode_work); + } profile->cleanup_rx(priv); err_cleanup_tx: profile->cleanup_tx(priv); @@ -6637,9 +6639,6 @@ int mlx5e_attach_netdev(struct mlx5e_priv *priv) out: mlx5e_reset_channels(priv->netdev); set_bit(MLX5E_STATE_DESTROYING, &priv->state); - if (priv->fs) - mlx5e_fs_set_state_destroy(priv->fs, - !test_bit(MLX5E_STATE_DESTROYING, &priv->state)); cancel_work_sync(&priv->update_stats_work); return err; } @@ -6650,8 +6649,7 @@ void mlx5e_detach_netdev(struct mlx5e_priv *priv) set_bit(MLX5E_STATE_DESTROYING, &priv->state); if (priv->fs) - mlx5e_fs_set_state_destroy(priv->fs, - !test_bit(MLX5E_STATE_DESTROYING, &priv->state)); + mlx5e_fs_set_state_destroy(priv->fs, false); if (profile->disable) profile->disable(priv); base-commit: f4377bf85887f57b59abb5479f7660a81ffe4449 -- 2.44.0