Commit 734dc065 authored by Daniel Jurgens's avatar Daniel Jurgens Committed by Jason Gunthorpe

net/mlx5: Fix race for multiple RoCE enable

There are two potential problems with the existing implementation.

1. Enable and disable can race after the atomic operations.
2. If a command fails the refcount is left in an inconsistent state.

Introduce a lock and perform error checking.

Fixes: a6f7d2af ("net/mlx5: Add support for multiple RoCE enable")
Signed-off-by: default avatarDaniel Jurgens <danielj@mellanox.com>
Reviewed-by: default avatarParav Pandit <parav@mellanox.com>
Signed-off-by: default avatarLeon Romanovsky <leon@kernel.org>
Signed-off-by: default avatarJason Gunthorpe <jgg@mellanox.com>
parent 776a3906
...@@ -36,6 +36,9 @@ ...@@ -36,6 +36,9 @@
#include <linux/mlx5/vport.h> #include <linux/mlx5/vport.h>
#include "mlx5_core.h" #include "mlx5_core.h"
/* Mutex to hold while enabling or disabling RoCE */
static DEFINE_MUTEX(mlx5_roce_en_lock);
static int _mlx5_query_vport_state(struct mlx5_core_dev *mdev, u8 opmod, static int _mlx5_query_vport_state(struct mlx5_core_dev *mdev, u8 opmod,
u16 vport, u32 *out, int outlen) u16 vport, u32 *out, int outlen)
{ {
...@@ -988,17 +991,35 @@ static int mlx5_nic_vport_update_roce_state(struct mlx5_core_dev *mdev, ...@@ -988,17 +991,35 @@ static int mlx5_nic_vport_update_roce_state(struct mlx5_core_dev *mdev,
int mlx5_nic_vport_enable_roce(struct mlx5_core_dev *mdev) int mlx5_nic_vport_enable_roce(struct mlx5_core_dev *mdev)
{ {
if (atomic_inc_return(&mdev->roce.roce_en) != 1) int err = 0;
return 0;
return mlx5_nic_vport_update_roce_state(mdev, MLX5_VPORT_ROCE_ENABLED); mutex_lock(&mlx5_roce_en_lock);
if (!mdev->roce.roce_en)
err = mlx5_nic_vport_update_roce_state(mdev, MLX5_VPORT_ROCE_ENABLED);
if (!err)
mdev->roce.roce_en++;
mutex_unlock(&mlx5_roce_en_lock);
return err;
} }
EXPORT_SYMBOL_GPL(mlx5_nic_vport_enable_roce); EXPORT_SYMBOL_GPL(mlx5_nic_vport_enable_roce);
int mlx5_nic_vport_disable_roce(struct mlx5_core_dev *mdev) int mlx5_nic_vport_disable_roce(struct mlx5_core_dev *mdev)
{ {
if (atomic_dec_return(&mdev->roce.roce_en) != 0) int err = 0;
return 0;
return mlx5_nic_vport_update_roce_state(mdev, MLX5_VPORT_ROCE_DISABLED); mutex_lock(&mlx5_roce_en_lock);
if (mdev->roce.roce_en) {
mdev->roce.roce_en--;
if (mdev->roce.roce_en == 0)
err = mlx5_nic_vport_update_roce_state(mdev, MLX5_VPORT_ROCE_DISABLED);
if (err)
mdev->roce.roce_en++;
}
mutex_unlock(&mlx5_roce_en_lock);
return err;
} }
EXPORT_SYMBOL_GPL(mlx5_nic_vport_disable_roce); EXPORT_SYMBOL_GPL(mlx5_nic_vport_disable_roce);
......
...@@ -835,7 +835,7 @@ struct mlx5_core_dev { ...@@ -835,7 +835,7 @@ struct mlx5_core_dev {
struct mlx5e_resources mlx5e_res; struct mlx5e_resources mlx5e_res;
struct { struct {
struct mlx5_rsvd_gids reserved_gids; struct mlx5_rsvd_gids reserved_gids;
atomic_t roce_en; u32 roce_en;
} roce; } roce;
#ifdef CONFIG_MLX5_FPGA #ifdef CONFIG_MLX5_FPGA
struct mlx5_fpga_device *fpga; struct mlx5_fpga_device *fpga;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment