Skip to content

Commit c236986

Browse files
shayshyismb49
authored andcommitted
net/mlx5: Handle pairing of E-switch via uplink un/load APIs
BugLink: https://bugs.launchpad.net/bugs/2028979 commit 2be5bd4 upstream. In case user switch a device from switchdev mode to legacy mode, mlx5 first unpair the E-switch and afterwards unload the uplink vport. From the other hand, in case user remove or reload a device, mlx5 first unload the uplink vport and afterwards unpair the E-switch. The latter is causing a bug[1], hence, handle pairing of E-switch as part of uplink un/load APIs. [1] In case VF_LAG is used, every tc fdb flow is duplicated to the peer esw. However, the original esw keeps a pointer to this duplicated flow, not the peer esw. e.g.: if user create tc fdb flow over esw0, the flow is duplicated over esw1, in FW/HW, but in SW, esw0 keeps a pointer to the duplicated flow. During module unload while a peer tc fdb flow is still offloaded, in case the first device to be removed is the peer device (esw1 in the example above), the peer net-dev is destroyed, and so the mlx5e_priv is memset to 0. Afterwards, the peer device is trying to unpair himself from the original device (esw0 in the example above). Unpair API invoke the original device to clear peer flow from its eswitch (esw0), but the peer flow, which is stored over the original eswitch (esw0), is trying to use the peer mlx5e_priv, which is memset to 0 and result in bellow kernel-oops. [ 157.964081 ] BUG: unable to handle page fault for address: 000000000002ce60 [ 157.964662 ] #PF: supervisor read access in kernel mode [ 157.965123 ] #PF: error_code(0x0000) - not-present page [ 157.965582 ] PGD 0 P4D 0 [ 157.965866 ] Oops: 0000 [#1] SMP [ 157.967670 ] RIP: 0010:mlx5e_tc_del_fdb_flow+0x48/0x460 [mlx5_core] [ 157.976164 ] Call Trace: [ 157.976437 ] <TASK> [ 157.976690 ] __mlx5e_tc_del_fdb_peer_flow+0xe6/0x100 [mlx5_core] [ 157.977230 ] mlx5e_tc_clean_fdb_peer_flows+0x67/0x90 [mlx5_core] [ 157.977767 ] mlx5_esw_offloads_unpair+0x2d/0x1e0 [mlx5_core] [ 157.984653 ] mlx5_esw_offloads_devcom_event+0xbf/0x130 [mlx5_core] [ 157.985212 ] mlx5_devcom_send_event+0xa3/0xb0 [mlx5_core] [ 157.985714 ] esw_offloads_disable+0x5a/0x110 [mlx5_core] [ 157.986209 ] mlx5_eswitch_disable_locked+0x152/0x170 [mlx5_core] [ 157.986757 ] mlx5_eswitch_disable+0x51/0x80 [mlx5_core] [ 157.987248 ] mlx5_unload+0x2a/0xb0 [mlx5_core] [ 157.987678 ] mlx5_uninit_one+0x5f/0xd0 [mlx5_core] [ 157.988127 ] remove_one+0x64/0xe0 [mlx5_core] [ 157.988549 ] pci_device_remove+0x31/0xa0 [ 157.988933 ] device_release_driver_internal+0x18f/0x1f0 [ 157.989402 ] driver_detach+0x3f/0x80 [ 157.989754 ] bus_remove_driver+0x70/0xf0 [ 157.990129 ] pci_unregister_driver+0x34/0x90 [ 157.990537 ] mlx5_cleanup+0xc/0x1c [mlx5_core] [ 157.990972 ] __x64_sys_delete_module+0x15a/0x250 [ 157.991398 ] ? exit_to_user_mode_prepare+0xea/0x110 [ 157.991840 ] do_syscall_64+0x3d/0x90 [ 157.992198 ] entry_SYSCALL_64_after_hwframe+0x46/0xb0 Fixes: 04de7dd ("net/mlx5e: Infrastructure for duplicated offloading of TC flows") Fixes: 1418ddd ("net/mlx5e: Duplicate offloaded TC eswitch rules under uplink LAG") Signed-off-by: Shay Drory <shayd@nvidia.com> Reviewed-by: Roi Dayan <roid@nvidia.com> Signed-off-by: Saeed Mahameed <saeedm@nvidia.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Signed-off-by: Kamal Mostafa <kamal@canonical.com> Signed-off-by: Stefan Bader <stefan.bader@canonical.com>
1 parent 5b8847a commit c236986

3 files changed

Lines changed: 9 additions & 6 deletions

File tree

drivers/net/ethernet/mellanox/mlx5/core/en_tc.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5357,6 +5357,8 @@ int mlx5e_tc_esw_init(struct mlx5_rep_uplink_priv *uplink_priv)
53575357
goto err_register_fib_notifier;
53585358
}
53595359

5360+
mlx5_esw_offloads_devcom_init(esw);
5361+
53605362
return 0;
53615363

53625364
err_register_fib_notifier:
@@ -5383,7 +5385,7 @@ void mlx5e_tc_esw_cleanup(struct mlx5_rep_uplink_priv *uplink_priv)
53835385
priv = netdev_priv(rpriv->netdev);
53845386
esw = priv->mdev->priv.eswitch;
53855387

5386-
mlx5e_tc_clean_fdb_peer_flows(esw);
5388+
mlx5_esw_offloads_devcom_cleanup(esw);
53875389

53885390
mlx5e_tc_tun_cleanup(uplink_priv->encap);
53895391

drivers/net/ethernet/mellanox/mlx5/core/eswitch.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,8 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs);
370370
void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf);
371371
void mlx5_eswitch_disable_locked(struct mlx5_eswitch *esw);
372372
void mlx5_eswitch_disable(struct mlx5_eswitch *esw);
373+
void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw);
374+
void mlx5_esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw);
373375
int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw,
374376
u16 vport, const u8 *mac);
375377
int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw,
@@ -771,6 +773,8 @@ static inline void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw) {}
771773
static inline int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs) { return 0; }
772774
static inline void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf) {}
773775
static inline void mlx5_eswitch_disable(struct mlx5_eswitch *esw) {}
776+
static inline void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw) {}
777+
static inline void mlx5_esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw) {}
774778
static inline bool mlx5_eswitch_is_funcs_handler(struct mlx5_core_dev *dev) { return false; }
775779
static inline
776780
int mlx5_eswitch_set_vport_state(struct mlx5_eswitch *esw, u16 vport, int link_state) { return 0; }

drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2894,7 +2894,7 @@ static int mlx5_esw_offloads_devcom_event(int event,
28942894
return err;
28952895
}
28962896

2897-
static void esw_offloads_devcom_init(struct mlx5_eswitch *esw)
2897+
void mlx5_esw_offloads_devcom_init(struct mlx5_eswitch *esw)
28982898
{
28992899
struct mlx5_devcom *devcom = esw->dev->priv.devcom;
29002900

@@ -2917,7 +2917,7 @@ static void esw_offloads_devcom_init(struct mlx5_eswitch *esw)
29172917
ESW_OFFLOADS_DEVCOM_PAIR, esw);
29182918
}
29192919

2920-
static void esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw)
2920+
void mlx5_esw_offloads_devcom_cleanup(struct mlx5_eswitch *esw)
29212921
{
29222922
struct mlx5_devcom *devcom = esw->dev->priv.devcom;
29232923

@@ -3387,8 +3387,6 @@ int esw_offloads_enable(struct mlx5_eswitch *esw)
33873387
if (err)
33883388
goto err_vports;
33893389

3390-
esw_offloads_devcom_init(esw);
3391-
33923390
return 0;
33933391

33943392
err_vports:
@@ -3429,7 +3427,6 @@ static int esw_offloads_stop(struct mlx5_eswitch *esw,
34293427

34303428
void esw_offloads_disable(struct mlx5_eswitch *esw)
34313429
{
3432-
esw_offloads_devcom_cleanup(esw);
34333430
mlx5_eswitch_disable_pf_vf_vports(esw);
34343431
esw_offloads_unload_rep(esw, MLX5_VPORT_UPLINK);
34353432
esw_set_passing_vport_metadata(esw, false);

0 commit comments

Comments
 (0)