diff options
author | Jakub Kicinski <kuba@kernel.org> | 2022-03-18 22:23:44 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2022-03-21 17:11:38 +0300 |
commit | 14e426bf1a4d77ac87d0fa2a964092a23f863e44 (patch) | |
tree | d4f9bb5b5757380586328e8b6433a8b7fff3da71 /drivers/net/ethernet/mellanox | |
parent | aff3a925094633a5b77058b9a715efbb12fc2698 (diff) | |
download | linux-14e426bf1a4d77ac87d0fa2a964092a23f863e44.tar.xz |
devlink: hold the instance lock during eswitch_mode callbacks
Make the devlink core hold the instance lock during eswitch_mode
callbacks. Cheat in case of mlx5 (see the cover letter).
Reviewed-by: Leon Romanovsky <leonro@nvidia.com>
Reviewed-by: Jiri Pirko <jiri@nvidia.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/mellanox')
-rw-r--r-- | drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c | 54 |
1 files changed, 42 insertions, 12 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 35cf4cb3098e..3f63df127091 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -3337,6 +3337,27 @@ static int eswitch_devlink_esw_mode_check(const struct mlx5_eswitch *esw) !mlx5_core_is_ecpf_esw_manager(esw->dev)) ? -EOPNOTSUPP : 0; } +/* FIXME: devl_unlock() followed by devl_lock() inside driver callback + * is never correct and prone to races. It's a transitional workaround, + * never repeat this pattern. + * + * This code MUST be fixed before removing devlink_mutex as it is safe + * to do only because of that mutex. + */ +static void mlx5_eswtich_mode_callback_enter(struct devlink *devlink, + struct mlx5_eswitch *esw) +{ + devl_unlock(devlink); + down_write(&esw->mode_lock); +} + +static void mlx5_eswtich_mode_callback_exit(struct devlink *devlink, + struct mlx5_eswitch *esw) +{ + up_write(&esw->mode_lock); + devl_lock(devlink); +} + int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode, struct netlink_ext_ack *extack) { @@ -3351,6 +3372,15 @@ int mlx5_devlink_eswitch_mode_set(struct devlink *devlink, u16 mode, if (esw_mode_from_devlink(mode, &mlx5_mode)) return -EINVAL; + /* FIXME: devl_unlock() followed by devl_lock() inside driver callback + * is never correct and prone to races. It's a transitional workaround, + * never repeat this pattern. + * + * This code MUST be fixed before removing devlink_mutex as it is safe + * to do only because of that mutex. + */ + devl_unlock(devlink); + mlx5_lag_disable_change(esw->dev); err = mlx5_esw_try_lock(esw); if (err < 0) { @@ -3381,6 +3411,7 @@ unlock: mlx5_esw_unlock(esw); enable_lag: mlx5_lag_enable_change(esw->dev); + devl_lock(devlink); return err; } @@ -3393,14 +3424,14 @@ int mlx5_devlink_eswitch_mode_get(struct devlink *devlink, u16 *mode) if (IS_ERR(esw)) return PTR_ERR(esw); - down_write(&esw->mode_lock); + mlx5_eswtich_mode_callback_enter(devlink, esw); err = eswitch_devlink_esw_mode_check(esw); if (err) goto unlock; err = esw_mode_to_devlink(esw->mode, mode); unlock: - up_write(&esw->mode_lock); + mlx5_eswtich_mode_callback_exit(devlink, esw); return err; } @@ -3447,7 +3478,7 @@ int mlx5_devlink_eswitch_inline_mode_set(struct devlink *devlink, u8 mode, if (IS_ERR(esw)) return PTR_ERR(esw); - down_write(&esw->mode_lock); + mlx5_eswtich_mode_callback_enter(devlink, esw); err = eswitch_devlink_esw_mode_check(esw); if (err) goto out; @@ -3484,11 +3515,11 @@ int mlx5_devlink_eswitch_inline_mode_set(struct devlink *devlink, u8 mode, goto out; esw->offloads.inline_mode = mlx5_mode; - up_write(&esw->mode_lock); + mlx5_eswtich_mode_callback_exit(devlink, esw); return 0; out: - up_write(&esw->mode_lock); + mlx5_eswtich_mode_callback_exit(devlink, esw); return err; } @@ -3501,14 +3532,14 @@ int mlx5_devlink_eswitch_inline_mode_get(struct devlink *devlink, u8 *mode) if (IS_ERR(esw)) return PTR_ERR(esw); - down_write(&esw->mode_lock); + mlx5_eswtich_mode_callback_enter(devlink, esw); err = eswitch_devlink_esw_mode_check(esw); if (err) goto unlock; err = esw_inline_mode_to_devlink(esw->offloads.inline_mode, mode); unlock: - up_write(&esw->mode_lock); + mlx5_eswtich_mode_callback_exit(devlink, esw); return err; } @@ -3524,7 +3555,7 @@ int mlx5_devlink_eswitch_encap_mode_set(struct devlink *devlink, if (IS_ERR(esw)) return PTR_ERR(esw); - down_write(&esw->mode_lock); + mlx5_eswtich_mode_callback_enter(devlink, esw); err = eswitch_devlink_esw_mode_check(esw); if (err) goto unlock; @@ -3570,7 +3601,7 @@ int mlx5_devlink_eswitch_encap_mode_set(struct devlink *devlink, } unlock: - up_write(&esw->mode_lock); + mlx5_eswtich_mode_callback_exit(devlink, esw); return err; } @@ -3584,15 +3615,14 @@ int mlx5_devlink_eswitch_encap_mode_get(struct devlink *devlink, if (IS_ERR(esw)) return PTR_ERR(esw); - - down_write(&esw->mode_lock); + mlx5_eswtich_mode_callback_enter(devlink, esw); err = eswitch_devlink_esw_mode_check(esw); if (err) goto unlock; *encap = esw->offloads.encap; unlock: - up_write(&esw->mode_lock); + mlx5_eswtich_mode_callback_exit(devlink, esw); return err; } |