]> git.proxmox.com Git - mirror_ubuntu-jammy-kernel.git/commitdiff
net/mlx5e: reset XPS on error flow if netdev isn't registered yet
authorSaeed Mahameed <saeedm@nvidia.com>
Thu, 25 Feb 2021 19:20:00 +0000 (11:20 -0800)
committerSaeed Mahameed <saeedm@nvidia.com>
Wed, 19 May 2021 06:01:38 +0000 (23:01 -0700)
mlx5e_attach_netdev can be called prior to registering the netdevice:
Example stack:

ipoib_new_child_link ->
ipoib_intf_init->
rdma_init_netdev->
mlx5_rdma_setup_rn->

mlx5e_attach_netdev->
mlx5e_num_channels_changed ->
mlx5e_set_default_xps_cpumasks ->
netif_set_xps_queue ->
__netif_set_xps_queue -> kmalloc

If any later stage fails at any point after mlx5e_num_channels_changed()
returns, XPS allocated maps will never be freed as they
are only freed during netdev unregistration, which will never happen for
yet to be registered netdevs.

Fixes: 3909a12e7913 ("net/mlx5e: Fix configuration of XPS cpumasks and netdev queues in corner cases")
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
Signed-off-by: Aya Levin <ayal@nvidia.com>
Reviewed-by: Tariq Toukan <tariqt@nvidia.com>
drivers/net/ethernet/mellanox/mlx5/core/en_main.c

index bca832cdc4cbe22bd3a26d9ac847311f32bb9738..89937b05507068ac815d367e92280db135a446f6 100644 (file)
@@ -5229,6 +5229,11 @@ static void mlx5e_update_features(struct net_device *netdev)
        rtnl_unlock();
 }
 
+static void mlx5e_reset_channels(struct net_device *netdev)
+{
+       netdev_reset_tc(netdev);
+}
+
 int mlx5e_attach_netdev(struct mlx5e_priv *priv)
 {
        const bool take_rtnl = priv->netdev->reg_state == NETREG_REGISTERED;
@@ -5283,6 +5288,7 @@ err_cleanup_tx:
        profile->cleanup_tx(priv);
 
 out:
+       mlx5e_reset_channels(priv->netdev);
        set_bit(MLX5E_STATE_DESTROYING, &priv->state);
        cancel_work_sync(&priv->update_stats_work);
        return err;
@@ -5300,6 +5306,7 @@ void mlx5e_detach_netdev(struct mlx5e_priv *priv)
 
        profile->cleanup_rx(priv);
        profile->cleanup_tx(priv);
+       mlx5e_reset_channels(priv->netdev);
        cancel_work_sync(&priv->update_stats_work);
 }