]> www.infradead.org Git - users/hch/misc.git/commitdiff
net/mlx5e: Keep netdev when leave switchdev for devlink set legacy only
authorJianbo Liu <jianbol@nvidia.com>
Fri, 20 Dec 2024 08:15:05 +0000 (10:15 +0200)
committerJakub Kicinski <kuba@kernel.org>
Mon, 23 Dec 2024 18:54:02 +0000 (10:54 -0800)
In the cited commit, when changing from switchdev to legacy mode,
uplink representor's netdev is kept, and its profile is replaced with
nic profile, so netdev is detached from old profile, then attach to
new profile.

During profile change, the hardware resources allocated by the old
profile will be cleaned up. However, the cleanup is relying on the
related kernel modules. And they may need to flush themselves first,
which is triggered by netdev events, for example, NETDEV_UNREGISTER.
However, netdev is kept, or netdev_register is called after the
cleanup, which may cause troubles because the resources are still
referred by kernel modules.

The same process applies to all the caes when uplink is leaving
switchdev mode, including devlink eswitch mode set legacy, driver
unload and devlink reload. For the first one, it can be blocked and
returns failure to users, whenever possible. But it's hard for the
others. Besides, the attachment to nic profile is unnecessary as the
netdev will be unregistered anyway for such cases.

So in this patch, the original behavior is kept only for devlink
eswitch set mode legacy. For the others, moves netdev unregistration
before the profile change.

Fixes: 7a9fb35e8c3a ("net/mlx5e: Do not reload ethernet ports when changing eswitch mode")
Signed-off-by: Jianbo Liu <jianbol@nvidia.com>
Signed-off-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20241220081505.1286093-5-tariqt@nvidia.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c
include/linux/mlx5/driver.h

index dd16d73000c3120a7be70d95e2d0457e00d2c39f..0ec17c276bdd2d3ec1fba6a498e96f1f28f595ed 100644 (file)
@@ -6542,8 +6542,23 @@ static void _mlx5e_remove(struct auxiliary_device *adev)
 
        mlx5_core_uplink_netdev_set(mdev, NULL);
        mlx5e_dcbnl_delete_app(priv);
-       unregister_netdev(priv->netdev);
-       _mlx5e_suspend(adev, false);
+       /* When unload driver, the netdev is in registered state
+        * if it's from legacy mode. If from switchdev mode, it
+        * is already unregistered before changing to NIC profile.
+        */
+       if (priv->netdev->reg_state == NETREG_REGISTERED) {
+               unregister_netdev(priv->netdev);
+               _mlx5e_suspend(adev, false);
+       } else {
+               struct mlx5_core_dev *pos;
+               int i;
+
+               if (test_bit(MLX5E_STATE_DESTROYING, &priv->state))
+                       mlx5_sd_for_each_dev(i, mdev, pos)
+                               mlx5e_destroy_mdev_resources(pos);
+               else
+                       _mlx5e_suspend(adev, true);
+       }
        /* Avoid cleanup if profile rollback failed. */
        if (priv->profile)
                priv->profile->cleanup(priv);
index 554f9cb5b53fd98625b6709e2a849b58ec0ed284..fdff9fd8a89ec14b7171a0792cf6e74832005ef2 100644 (file)
@@ -1509,6 +1509,21 @@ mlx5e_vport_uplink_rep_unload(struct mlx5e_rep_priv *rpriv)
 
        priv = netdev_priv(netdev);
 
+       /* This bit is set when using devlink to change eswitch mode from
+        * switchdev to legacy. As need to keep uplink netdev ifindex, we
+        * detach uplink representor profile and attach NIC profile only.
+        * The netdev will be unregistered later when unload NIC auxiliary
+        * driver for this case.
+        * We explicitly block devlink eswitch mode change if any IPSec rules
+        * offloaded, but can't block other cases, such as driver unload
+        * and devlink reload. We have to unregister netdev before profile
+        * change for those cases. This is to avoid resource leak because
+        * the offloaded rules don't have the chance to be unoffloaded before
+        * cleanup which is triggered by detach uplink representor profile.
+        */
+       if (!(priv->mdev->priv.flags & MLX5_PRIV_FLAGS_SWITCH_LEGACY))
+               unregister_netdev(netdev);
+
        mlx5e_netdev_attach_nic_profile(priv);
 }
 
index 40359f32072487238c8b77fbd49c876d468e8394..06076dd9ec6449ef21dcf078cab6f479da970904 100644 (file)
@@ -3777,6 +3777,8 @@ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
        esw->eswitch_operation_in_progress = true;
        up_write(&esw->mode_lock);
 
+       if (mode == DEVLINK_ESWITCH_MODE_LEGACY)
+               esw->dev->priv.flags |= MLX5_PRIV_FLAGS_SWITCH_LEGACY;
        mlx5_eswitch_disable_locked(esw);
        if (mode == DEVLINK_ESWITCH_MODE_SWITCHDEV) {
                if (mlx5_devlink_trap_get_num_active(esw->dev)) {
index fc7e6153b73d9e64869054d08801706bb1a5c84f..8f5991168ccdf021ff7f70776107a53d2219e4d2 100644 (file)
@@ -524,6 +524,7 @@ enum {
         * creation/deletion on drivers rescan. Unset during device attach.
         */
        MLX5_PRIV_FLAGS_DETACH = 1 << 2,
+       MLX5_PRIV_FLAGS_SWITCH_LEGACY = 1 << 3,
 };
 
 struct mlx5_adev {