mirror of
https://github.com/torvalds/linux.git
synced 2024-11-30 16:11:38 +00:00
net/mlx5: Fix potential deadlock in command mode change
Call command completion handler in case of timeout when working in
interrupts mode.
Avoid flushing the commands workqueue after acquiring the semaphores to
prevent a potential deadlock.
Fixes: e126ba97db
('mlx5: Add driver for Mellanox Connect-IB adapters')
Signed-off-by: Mohamad Haj Yahia <mohamad@mellanox.com>
Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
d57847dc41
commit
9cba4ebcf3
@ -710,13 +710,13 @@ static int wait_func(struct mlx5_core_dev *dev, struct mlx5_cmd_work_ent *ent)
|
||||
|
||||
if (cmd->mode == CMD_MODE_POLLING) {
|
||||
wait_for_completion(&ent->done);
|
||||
err = ent->ret;
|
||||
} else {
|
||||
if (!wait_for_completion_timeout(&ent->done, timeout))
|
||||
err = -ETIMEDOUT;
|
||||
else
|
||||
err = 0;
|
||||
} else if (!wait_for_completion_timeout(&ent->done, timeout)) {
|
||||
ent->ret = -ETIMEDOUT;
|
||||
mlx5_cmd_comp_handler(dev, 1UL << ent->idx);
|
||||
}
|
||||
|
||||
err = ent->ret;
|
||||
|
||||
if (err == -ETIMEDOUT) {
|
||||
mlx5_core_warn(dev, "%s(0x%x) timeout. Will cause a leak of a command resource\n",
|
||||
mlx5_command_str(msg_to_opcode(ent->in)),
|
||||
@ -774,28 +774,26 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in,
|
||||
goto out_free;
|
||||
}
|
||||
|
||||
if (!callback) {
|
||||
err = wait_func(dev, ent);
|
||||
if (err == -ETIMEDOUT)
|
||||
goto out;
|
||||
if (callback)
|
||||
goto out;
|
||||
|
||||
ds = ent->ts2 - ent->ts1;
|
||||
op = be16_to_cpu(((struct mlx5_inbox_hdr *)in->first.data)->opcode);
|
||||
if (op < ARRAY_SIZE(cmd->stats)) {
|
||||
stats = &cmd->stats[op];
|
||||
spin_lock_irq(&stats->lock);
|
||||
stats->sum += ds;
|
||||
++stats->n;
|
||||
spin_unlock_irq(&stats->lock);
|
||||
}
|
||||
mlx5_core_dbg_mask(dev, 1 << MLX5_CMD_TIME,
|
||||
"fw exec time for %s is %lld nsec\n",
|
||||
mlx5_command_str(op), ds);
|
||||
*status = ent->status;
|
||||
free_cmd(ent);
|
||||
err = wait_func(dev, ent);
|
||||
if (err == -ETIMEDOUT)
|
||||
goto out_free;
|
||||
|
||||
ds = ent->ts2 - ent->ts1;
|
||||
op = be16_to_cpu(((struct mlx5_inbox_hdr *)in->first.data)->opcode);
|
||||
if (op < ARRAY_SIZE(cmd->stats)) {
|
||||
stats = &cmd->stats[op];
|
||||
spin_lock_irq(&stats->lock);
|
||||
stats->sum += ds;
|
||||
++stats->n;
|
||||
spin_unlock_irq(&stats->lock);
|
||||
}
|
||||
|
||||
return err;
|
||||
mlx5_core_dbg_mask(dev, 1 << MLX5_CMD_TIME,
|
||||
"fw exec time for %s is %lld nsec\n",
|
||||
mlx5_command_str(op), ds);
|
||||
*status = ent->status;
|
||||
|
||||
out_free:
|
||||
free_cmd(ent);
|
||||
@ -1185,41 +1183,30 @@ err_dbg:
|
||||
return err;
|
||||
}
|
||||
|
||||
void mlx5_cmd_use_events(struct mlx5_core_dev *dev)
|
||||
static void mlx5_cmd_change_mod(struct mlx5_core_dev *dev, int mode)
|
||||
{
|
||||
struct mlx5_cmd *cmd = &dev->cmd;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < cmd->max_reg_cmds; i++)
|
||||
down(&cmd->sem);
|
||||
|
||||
down(&cmd->pages_sem);
|
||||
|
||||
flush_workqueue(cmd->wq);
|
||||
|
||||
cmd->mode = CMD_MODE_EVENTS;
|
||||
cmd->mode = mode;
|
||||
|
||||
up(&cmd->pages_sem);
|
||||
for (i = 0; i < cmd->max_reg_cmds; i++)
|
||||
up(&cmd->sem);
|
||||
}
|
||||
|
||||
void mlx5_cmd_use_events(struct mlx5_core_dev *dev)
|
||||
{
|
||||
mlx5_cmd_change_mod(dev, CMD_MODE_EVENTS);
|
||||
}
|
||||
|
||||
void mlx5_cmd_use_polling(struct mlx5_core_dev *dev)
|
||||
{
|
||||
struct mlx5_cmd *cmd = &dev->cmd;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < cmd->max_reg_cmds; i++)
|
||||
down(&cmd->sem);
|
||||
|
||||
down(&cmd->pages_sem);
|
||||
|
||||
flush_workqueue(cmd->wq);
|
||||
cmd->mode = CMD_MODE_POLLING;
|
||||
|
||||
up(&cmd->pages_sem);
|
||||
for (i = 0; i < cmd->max_reg_cmds; i++)
|
||||
up(&cmd->sem);
|
||||
mlx5_cmd_change_mod(dev, CMD_MODE_POLLING);
|
||||
}
|
||||
|
||||
static void free_msg(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *msg)
|
||||
|
Loading…
Reference in New Issue
Block a user