aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/ethernet/mellanox/mlx4/main.c
diff options
context:
space:
mode:
authorRoland Dreier <roland@purestorage.com>2012-09-25 21:24:07 -0700
committerRoland Dreier <roland@purestorage.com>2012-09-30 20:33:46 -0700
commitf3d4c89ee4a8c993cc334a67f84a3fb724a1dd35 (patch)
tree5b003102f64cf1df23a43f738627e2f7cf1e21cc /drivers/net/ethernet/mellanox/mlx4/main.c
parent84b1f1538fadd066cc9877c2276f3fefd8a79bc4 (diff)
mlx4_core: Fix crash on uninitialized priv->cmd.slave_sem
On an SR-IOV master device, __mlx4_init_one() calls mlx4_init_hca() before mlx4_multi_func_init(). However, for unlucky configurations, mlx4_init_hca() might call mlx4_SENSE_PORT() (via mlx4_dev_cap()), and that calls mlx4_cmd_imm() with MLX4_CMD_WRAPPED set. However, on a multifunction device with MLX4_CMD_WRAPPED, __mlx4_cmd() calls into mlx4_slave_cmd(), and that immediately tries to do down(&priv->cmd.slave_sem); but priv->cmd.slave_sem isn't initialized until mlx4_multi_func_init() (which we haven't called yet). The next thing it tries to do is access priv->mfunc.vhcr, but that hasn't been allocated yet. Fix this by moving the initialization of slave_sem and vhcr up into mlx4_cmd_init(). Also, since slave_sem is really just being used as a mutex, convert it into a slave_cmd_mutex. Signed-off-by: Roland Dreier <roland@purestorage.com>
Diffstat (limited to 'drivers/net/ethernet/mellanox/mlx4/main.c')
-rw-r--r--drivers/net/ethernet/mellanox/mlx4/main.c11
1 files changed, 6 insertions, 5 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index 296288c7cb3..1e9f816a94d 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -1159,10 +1159,10 @@ static void mlx4_slave_exit(struct mlx4_dev *dev)
{
struct mlx4_priv *priv = mlx4_priv(dev);
- down(&priv->cmd.slave_sem);
+ mutex_lock(&priv->cmd.slave_cmd_mutex);
if (mlx4_comm_cmd(dev, MLX4_COMM_CMD_RESET, 0, MLX4_COMM_TIME))
mlx4_warn(dev, "Failed to close slave function.\n");
- up(&priv->cmd.slave_sem);
+ mutex_unlock(&priv->cmd.slave_cmd_mutex);
}
static int map_bf_area(struct mlx4_dev *dev)
@@ -1214,7 +1214,7 @@ static int mlx4_init_slave(struct mlx4_dev *dev)
u32 slave_read;
u32 cmd_channel_ver;
- down(&priv->cmd.slave_sem);
+ mutex_lock(&priv->cmd.slave_cmd_mutex);
priv->cmd.max_cmds = 1;
mlx4_warn(dev, "Sending reset\n");
ret_from_reset = mlx4_comm_cmd(dev, MLX4_COMM_CMD_RESET, 0,
@@ -1263,12 +1263,13 @@ static int mlx4_init_slave(struct mlx4_dev *dev)
goto err;
if (mlx4_comm_cmd(dev, MLX4_COMM_CMD_VHCR_EN, dma, MLX4_COMM_TIME))
goto err;
- up(&priv->cmd.slave_sem);
+
+ mutex_unlock(&priv->cmd.slave_cmd_mutex);
return 0;
err:
mlx4_comm_cmd(dev, MLX4_COMM_CMD_RESET, 0, 0);
- up(&priv->cmd.slave_sem);
+ mutex_unlock(&priv->cmd.slave_cmd_mutex);
return -EIO;
}