Skip to content

Commit baac835

Browse files
Jianbo LiuSaeed Mahameed
authored andcommitted
net/mlx5e: Reduce eswitch mode_lock protection context
Currently eswitch mode_lock is so heavy, for example, it's locked during the whole process of the mode change, which may need to hold other locks. As the mode_lock is also used by IPSec to block mode and encap change now, it is easy to cause lock dependency. Since some of protections are also done by devlink lock, the eswitch mode_lock is not needed at those places, and thus the possibility of lockdep issue is reduced. Fixes: c8e350e ("net/mlx5e: Make TC and IPsec offloads mutually exclusive on a netdev") Signed-off-by: Jianbo Liu <[email protected]> Signed-off-by: Leon Romanovsky <[email protected]>
1 parent c2bf84f commit baac835

File tree

4 files changed

+52
-32
lines changed

4 files changed

+52
-32
lines changed

drivers/net/ethernet/mellanox/mlx5/core/en_accel/ipsec_fs.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2110,8 +2110,11 @@ static int mlx5e_ipsec_block_tc_offload(struct mlx5_core_dev *mdev)
21102110
struct mlx5_eswitch *esw = mdev->priv.eswitch;
21112111
int err = 0;
21122112

2113-
if (esw)
2114-
down_write(&esw->mode_lock);
2113+
if (esw) {
2114+
err = mlx5_esw_lock(esw);
2115+
if (err)
2116+
return err;
2117+
}
21152118

21162119
if (mdev->num_block_ipsec) {
21172120
err = -EBUSY;
@@ -2122,7 +2125,7 @@ static int mlx5e_ipsec_block_tc_offload(struct mlx5_core_dev *mdev)
21222125

21232126
unlock:
21242127
if (esw)
2125-
up_write(&esw->mode_lock);
2128+
mlx5_esw_unlock(esw);
21262129

21272130
return err;
21282131
}

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

Lines changed: 22 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1463,7 +1463,7 @@ int mlx5_eswitch_enable_locked(struct mlx5_eswitch *esw, int num_vfs)
14631463
{
14641464
int err;
14651465

1466-
lockdep_assert_held(&esw->mode_lock);
1466+
devl_assert_locked(priv_to_devlink(esw->dev));
14671467

14681468
if (!MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, ft_support)) {
14691469
esw_warn(esw->dev, "FDB is not supported, aborting ...\n");
@@ -1531,7 +1531,6 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs)
15311531
if (toggle_lag)
15321532
mlx5_lag_disable_change(esw->dev);
15331533

1534-
down_write(&esw->mode_lock);
15351534
if (!mlx5_esw_is_fdb_created(esw)) {
15361535
ret = mlx5_eswitch_enable_locked(esw, num_vfs);
15371536
} else {
@@ -1554,8 +1553,6 @@ int mlx5_eswitch_enable(struct mlx5_eswitch *esw, int num_vfs)
15541553
}
15551554
}
15561555

1557-
up_write(&esw->mode_lock);
1558-
15591556
if (toggle_lag)
15601557
mlx5_lag_enable_change(esw->dev);
15611558

@@ -1569,12 +1566,11 @@ void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf)
15691566
return;
15701567

15711568
devl_assert_locked(priv_to_devlink(esw->dev));
1572-
down_write(&esw->mode_lock);
15731569
/* If driver is unloaded, this function is called twice by remove_one()
15741570
* and mlx5_unload(). Prevent the second call.
15751571
*/
15761572
if (!esw->esw_funcs.num_vfs && !esw->esw_funcs.num_ec_vfs && !clear_vf)
1577-
goto unlock;
1573+
return;
15781574

15791575
esw_info(esw->dev, "Unload vfs: mode(%s), nvfs(%d), necvfs(%d), active vports(%d)\n",
15801576
esw->mode == MLX5_ESWITCH_LEGACY ? "LEGACY" : "OFFLOADS",
@@ -1603,9 +1599,6 @@ void mlx5_eswitch_disable_sriov(struct mlx5_eswitch *esw, bool clear_vf)
16031599
esw->esw_funcs.num_vfs = 0;
16041600
else
16051601
esw->esw_funcs.num_ec_vfs = 0;
1606-
1607-
unlock:
1608-
up_write(&esw->mode_lock);
16091602
}
16101603

16111604
/* Free resources for corresponding eswitch mode. It is called by devlink
@@ -1647,10 +1640,8 @@ void mlx5_eswitch_disable(struct mlx5_eswitch *esw)
16471640

16481641
devl_assert_locked(priv_to_devlink(esw->dev));
16491642
mlx5_lag_disable_change(esw->dev);
1650-
down_write(&esw->mode_lock);
16511643
mlx5_eswitch_disable_locked(esw);
16521644
esw->mode = MLX5_ESWITCH_LEGACY;
1653-
up_write(&esw->mode_lock);
16541645
mlx5_lag_enable_change(esw->dev);
16551646
}
16561647

@@ -2254,8 +2245,13 @@ bool mlx5_esw_hold(struct mlx5_core_dev *mdev)
22542245
if (!mlx5_esw_allowed(esw))
22552246
return true;
22562247

2257-
if (down_read_trylock(&esw->mode_lock) != 0)
2248+
if (down_read_trylock(&esw->mode_lock) != 0) {
2249+
if (esw->eswitch_operation_in_progress) {
2250+
up_read(&esw->mode_lock);
2251+
return false;
2252+
}
22582253
return true;
2254+
}
22592255

22602256
return false;
22612257
}
@@ -2312,14 +2308,27 @@ int mlx5_esw_try_lock(struct mlx5_eswitch *esw)
23122308
if (down_write_trylock(&esw->mode_lock) == 0)
23132309
return -EINVAL;
23142310

2315-
if (atomic64_read(&esw->user_count) > 0) {
2311+
if (esw->eswitch_operation_in_progress ||
2312+
atomic64_read(&esw->user_count) > 0) {
23162313
up_write(&esw->mode_lock);
23172314
return -EBUSY;
23182315
}
23192316

23202317
return esw->mode;
23212318
}
23222319

2320+
int mlx5_esw_lock(struct mlx5_eswitch *esw)
2321+
{
2322+
down_write(&esw->mode_lock);
2323+
2324+
if (esw->eswitch_operation_in_progress) {
2325+
up_write(&esw->mode_lock);
2326+
return -EBUSY;
2327+
}
2328+
2329+
return 0;
2330+
}
2331+
23232332
/**
23242333
* mlx5_esw_unlock() - Release write lock on esw mode lock
23252334
* @esw: eswitch device.

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -383,6 +383,7 @@ struct mlx5_eswitch {
383383
struct xarray paired;
384384
struct mlx5_devcom_comp_dev *devcom;
385385
u16 enabled_ipsec_vf_count;
386+
bool eswitch_operation_in_progress;
386387
};
387388

388389
void esw_offloads_disable(struct mlx5_eswitch *esw);
@@ -827,6 +828,7 @@ void mlx5_esw_release(struct mlx5_core_dev *dev);
827828
void mlx5_esw_get(struct mlx5_core_dev *dev);
828829
void mlx5_esw_put(struct mlx5_core_dev *dev);
829830
int mlx5_esw_try_lock(struct mlx5_eswitch *esw);
831+
int mlx5_esw_lock(struct mlx5_eswitch *esw);
830832
void mlx5_esw_unlock(struct mlx5_eswitch *esw);
831833

832834
void esw_vport_change_handle_locked(struct mlx5_vport *vport);

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

Lines changed: 22 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3733,13 +3733,16 @@ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
37333733
goto unlock;
37343734
}
37353735

3736+
esw->eswitch_operation_in_progress = true;
3737+
up_write(&esw->mode_lock);
3738+
37363739
mlx5_eswitch_disable_locked(esw);
37373740
if (mode == DEVLINK_ESWITCH_MODE_SWITCHDEV) {
37383741
if (mlx5_devlink_trap_get_num_active(esw->dev)) {
37393742
NL_SET_ERR_MSG_MOD(extack,
37403743
"Can't change mode while devlink traps are active");
37413744
err = -EOPNOTSUPP;
3742-
goto unlock;
3745+
goto skip;
37433746
}
37443747
err = esw_offloads_start(esw, extack);
37453748
} else if (mode == DEVLINK_ESWITCH_MODE_LEGACY) {
@@ -3749,6 +3752,9 @@ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
37493752
err = -EINVAL;
37503753
}
37513754

3755+
skip:
3756+
down_write(&esw->mode_lock);
3757+
esw->eswitch_operation_in_progress = false;
37523758
unlock:
37533759
mlx5_esw_unlock(esw);
37543760
enable_lag:
@@ -3759,16 +3765,12 @@ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode,
37593765
int mlx5_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode)
37603766
{
37613767
struct mlx5_eswitch *esw;
3762-
int err;
37633768

37643769
esw = mlx5_devlink_eswitch_get(devlink);
37653770
if (IS_ERR(esw))
37663771
return PTR_ERR(esw);
37673772

3768-
down_read(&esw->mode_lock);
3769-
err = esw_mode_to_devlink(esw->mode, mode);
3770-
up_read(&esw->mode_lock);
3771-
return err;
3773+
return esw_mode_to_devlink(esw->mode, mode);
37723774
}
37733775

37743776
static int mlx5_esw_vports_inline_set(struct mlx5_eswitch *esw, u8 mlx5_mode,
@@ -3862,11 +3864,15 @@ int mlx5_devlink_eswitch_inline_mode_set(struct devlink *devlink, u8 mode,
38623864
if (err)
38633865
goto out;
38643866

3867+
esw->eswitch_operation_in_progress = true;
3868+
up_write(&esw->mode_lock);
3869+
38653870
err = mlx5_esw_vports_inline_set(esw, mlx5_mode, extack);
3866-
if (err)
3867-
goto out;
3871+
if (!err)
3872+
esw->offloads.inline_mode = mlx5_mode;
38683873

3869-
esw->offloads.inline_mode = mlx5_mode;
3874+
down_write(&esw->mode_lock);
3875+
esw->eswitch_operation_in_progress = false;
38703876
up_write(&esw->mode_lock);
38713877
return 0;
38723878

@@ -3878,16 +3884,12 @@ int mlx5_devlink_eswitch_inline_mode_set(struct devlink *devlink, u8 mode,
38783884
int mlx5_devlink_eswitch_inline_mode_get(struct devlink *devlink, u8 *mode)
38793885
{
38803886
struct mlx5_eswitch *esw;
3881-
int err;
38823887

38833888
esw = mlx5_devlink_eswitch_get(devlink);
38843889
if (IS_ERR(esw))
38853890
return PTR_ERR(esw);
38863891

3887-
down_read(&esw->mode_lock);
3888-
err = esw_inline_mode_to_devlink(esw->offloads.inline_mode, mode);
3889-
up_read(&esw->mode_lock);
3890-
return err;
3892+
return esw_inline_mode_to_devlink(esw->offloads.inline_mode, mode);
38913893
}
38923894

38933895
bool mlx5_eswitch_block_encap(struct mlx5_core_dev *dev)
@@ -3969,6 +3971,9 @@ int mlx5_devlink_eswitch_encap_mode_set(struct devlink *devlink,
39693971
goto unlock;
39703972
}
39713973

3974+
esw->eswitch_operation_in_progress = true;
3975+
up_write(&esw->mode_lock);
3976+
39723977
esw_destroy_offloads_fdb_tables(esw);
39733978

39743979
esw->offloads.encap = encap;
@@ -3982,6 +3987,9 @@ int mlx5_devlink_eswitch_encap_mode_set(struct devlink *devlink,
39823987
(void)esw_create_offloads_fdb_tables(esw);
39833988
}
39843989

3990+
down_write(&esw->mode_lock);
3991+
esw->eswitch_operation_in_progress = false;
3992+
39853993
unlock:
39863994
up_write(&esw->mode_lock);
39873995
return err;
@@ -3996,9 +4004,7 @@ int mlx5_devlink_eswitch_encap_mode_get(struct devlink *devlink,
39964004
if (IS_ERR(esw))
39974005
return PTR_ERR(esw);
39984006

3999-
down_read(&esw->mode_lock);
40004007
*encap = esw->offloads.encap;
4001-
up_read(&esw->mode_lock);
40024008
return 0;
40034009
}
40044010

0 commit comments

Comments
 (0)