]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
net/mlx5e: Pass netdev to mlx5e_destroy_netdev instead of priv
authorSaeed Mahameed <saeedm@nvidia.com>
Thu, 8 Jan 2026 21:26:56 +0000 (13:26 -0800)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 23 Jan 2026 10:18:38 +0000 (11:18 +0100)
[ Upstream commit 4ef8512e1427111f7ba92b4a847d181ff0aeec42 ]

mlx5e_priv is an unstable structure that can be memset(0) if profile
attaching fails.

Pass netdev to mlx5e_destroy_netdev() to guarantee it will work on a
valid netdev.

On mlx5e_remove: Check validity of priv->profile, before attempting
to cleanup any resources that might be not there.

This fixes a kernel oops in mlx5e_remove when switchdev mode fails due
to change profile failure.

$ devlink dev eswitch set pci/0000:00:03.0 mode switchdev
Error: mlx5_core: Failed setting eswitch to offloads.
dmesg:
workqueue: Failed to create a rescuer kthread for wq "mlx5e": -EINTR
mlx5_core 0012:03:00.1: mlx5e_netdev_init_profile:6214:(pid 37199): mlx5e_priv_init failed, err=-12
mlx5_core 0012:03:00.1 gpu3rdma1: mlx5e_netdev_change_profile: new profile init failed, -12
workqueue: Failed to create a rescuer kthread for wq "mlx5e": -EINTR
mlx5_core 0012:03:00.1: mlx5e_netdev_init_profile:6214:(pid 37199): mlx5e_priv_init failed, err=-12
mlx5_core 0012:03:00.1 gpu3rdma1: mlx5e_netdev_change_profile: failed to rollback to orig profile, -12

$ devlink dev reload pci/0000:00:03.0 ==> oops

BUG: kernel NULL pointer dereference, address: 0000000000000370
PGD 0 P4D 0
Oops: Oops: 0000 [#1] SMP NOPTI
CPU: 15 UID: 0 PID: 520 Comm: devlink Not tainted 6.18.0-rc5+ #115 PREEMPT(voluntary)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-2.fc40 04/01/2014
RIP: 0010:mlx5e_dcbnl_dscp_app+0x23/0x100
RSP: 0018:ffffc9000083f8b8 EFLAGS: 00010286
RAX: ffff8881126fc380 RBX: ffff8881015ac400 RCX: ffffffff826ffc45
RDX: 0000000000000000 RSI: 0000000000000001 RDI: ffff8881035109c0
RBP: ffff8881035109c0 R08: ffff888101e3e838 R09: ffff888100264e10
R10: ffffc9000083f898 R11: ffffc9000083f8a0 R12: ffff888101b921a0
R13: ffff888101b921a0 R14: ffff8881015ac9a0 R15: ffff8881015ac400
FS:  00007f789a3c8740(0000) GS:ffff88856aa59000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000000000370 CR3: 000000010b6c0001 CR4: 0000000000370ef0
Call Trace:
 <TASK>
 mlx5e_remove+0x57/0x110
 device_release_driver_internal+0x19c/0x200
 bus_remove_device+0xc6/0x130
 device_del+0x160/0x3d0
 ? devl_param_driverinit_value_get+0x2d/0x90
 mlx5_detach_device+0x89/0xe0
 mlx5_unload_one_devl_locked+0x3a/0x70
 mlx5_devlink_reload_down+0xc8/0x220
 devlink_reload+0x7d/0x260
 devlink_nl_reload_doit+0x45b/0x5a0
 genl_family_rcv_msg_doit+0xe8/0x140

Fixes: c4d7eb57687f ("net/mxl5e: Add change profile method")
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
Reviewed-by: Shay Drori <shayd@nvidia.com>
Reviewed-by: Tariq Toukan <tariqt@nvidia.com>
Link: https://patch.msgid.link/20260108212657.25090-4-saeed@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c

index 084c68479f7348d73b1fd879f9c53991b63d5c13..8245a149cdf852f49b325f3d873262c4363489e9 100644 (file)
@@ -1220,7 +1220,7 @@ struct net_device *
 mlx5e_create_netdev(struct mlx5_core_dev *mdev, const struct mlx5e_profile *profile);
 int mlx5e_attach_netdev(struct mlx5e_priv *priv);
 void mlx5e_detach_netdev(struct mlx5e_priv *priv);
-void mlx5e_destroy_netdev(struct mlx5e_priv *priv);
+void mlx5e_destroy_netdev(struct net_device *netdev);
 int mlx5e_netdev_change_profile(struct net_device *netdev,
                                struct mlx5_core_dev *mdev,
                                const struct mlx5e_profile *new_profile,
index 4e2f985273a3939fea237cf623a9a3c01913c425..5085bc8965dffe3d2075ab9d69cb633c1b42b531 100644 (file)
@@ -6311,11 +6311,12 @@ void mlx5e_netdev_attach_nic_profile(struct net_device *netdev,
        mlx5e_netdev_change_profile(netdev, mdev, &mlx5e_nic_profile, NULL);
 }
 
-void mlx5e_destroy_netdev(struct mlx5e_priv *priv)
+void mlx5e_destroy_netdev(struct net_device *netdev)
 {
-       struct net_device *netdev = priv->netdev;
+       struct mlx5e_priv *priv = netdev_priv(netdev);
 
-       mlx5e_priv_cleanup(priv);
+       if (priv->profile)
+               mlx5e_priv_cleanup(priv);
        free_netdev(netdev);
 }
 
@@ -6472,7 +6473,7 @@ err_resume:
 err_profile_cleanup:
        profile->cleanup(priv);
 err_destroy_netdev:
-       mlx5e_destroy_netdev(priv);
+       mlx5e_destroy_netdev(netdev);
 err_devlink_port_unregister:
        mlx5e_devlink_port_unregister(mlx5e_dev);
 err_devlink_unregister:
@@ -6507,7 +6508,9 @@ static void _mlx5e_remove(struct auxiliary_device *adev)
        struct mlx5_core_dev *mdev = edev->mdev;
 
        mlx5_core_uplink_netdev_set(mdev, NULL);
-       mlx5e_dcbnl_delete_app(priv);
+
+       if (priv->profile)
+               mlx5e_dcbnl_delete_app(priv);
        /* 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.
@@ -6528,7 +6531,7 @@ static void _mlx5e_remove(struct auxiliary_device *adev)
        /* Avoid cleanup if profile rollback failed. */
        if (priv->profile)
                priv->profile->cleanup(priv);
-       mlx5e_destroy_netdev(priv);
+       mlx5e_destroy_netdev(netdev);
        mlx5e_devlink_port_unregister(mlx5e_dev);
        mlx5e_destroy_devlink(mlx5e_dev);
 }
index b461954b974c6a2e123f91958b0ecb32ba91dd69..763b264721af1892f5bc53c5fbc430a9dd8d36c2 100644 (file)
@@ -1602,7 +1602,7 @@ err_cleanup_profile:
        priv->profile->cleanup(priv);
 
 err_destroy_netdev:
-       mlx5e_destroy_netdev(netdev_priv(netdev));
+       mlx5e_destroy_netdev(netdev);
        return err;
 }
 
@@ -1657,7 +1657,7 @@ mlx5e_vport_rep_unload(struct mlx5_eswitch_rep *rep)
        mlx5e_rep_vnic_reporter_destroy(priv);
        mlx5e_detach_netdev(priv);
        priv->profile->cleanup(priv);
-       mlx5e_destroy_netdev(priv);
+       mlx5e_destroy_netdev(netdev);
 free_ppriv:
        kvfree(ppriv); /* mlx5e_rep_priv */
 }