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: a6f7d2aff6 ("net/mlx5: Add support for multiple RoCE enable")
Signed-off-by: Daniel Jurgens <danielj@mellanox.com>
Reviewed-by: Parav Pandit <parav@mellanox.com>
Signed-off-by: Leon Romanovsky <leon@kernel.org>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
This commit is contained in:
Daniel Jurgens 2018-01-04 17:25:31 +02:00 committed by Jason Gunthorpe
parent 776a3906b6
commit 734dc065fc
2 changed files with 28 additions and 7 deletions

View file

@ -36,6 +36,9 @@
#include <linux/mlx5/vport.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,
u16 vport, u32 *out, int outlen)
{
@ -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)
{
if (atomic_inc_return(&mdev->roce.roce_en) != 1)
return 0;
return mlx5_nic_vport_update_roce_state(mdev, MLX5_VPORT_ROCE_ENABLED);
int err = 0;
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);
int mlx5_nic_vport_disable_roce(struct mlx5_core_dev *mdev)
{
if (atomic_dec_return(&mdev->roce.roce_en) != 0)
return 0;
return mlx5_nic_vport_update_roce_state(mdev, MLX5_VPORT_ROCE_DISABLED);
int err = 0;
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);

View file

@ -835,7 +835,7 @@ struct mlx5_core_dev {
struct mlx5e_resources mlx5e_res;
struct {
struct mlx5_rsvd_gids reserved_gids;
atomic_t roce_en;
u32 roce_en;
} roce;
#ifdef CONFIG_MLX5_FPGA
struct mlx5_fpga_device *fpga;