Commit c3bcf8cb authored by Jack Morgenstein's avatar Jack Morgenstein Committed by Greg Kroah-Hartman

net/mlx4_core: Fix locking in SRIOV mode when switching between events and polling

[ Upstream commit c07d2792 ]

In procedures mlx4_cmd_use_events() and mlx4_cmd_use_polling(), we need to
guarantee that there are no FW commands in progress on the comm channel
(for VFs) or wrapped FW commands (on the PF) when SRIOV is active.

We do this by also taking the slave_cmd_mutex when SRIOV is active.

This is especially important when switching from event to polling, since we
free the command-context array during the switch.  If there are FW commands
in progress (e.g., waiting for a completion event), the completion event
handler will access freed memory.

Since the decision to use comm_wait or comm_poll is taken before grabbing
the event_sem/poll_sem in mlx4_comm_cmd_wait/poll, we must take the
slave_cmd_mutex as well (to guarantee that the decision to use events or
polling and the call to the appropriate cmd function are atomic).

Fixes: a7e1f049 ("net/mlx4_core: Fix deadlock when switching between polling and event fw commands")
Signed-off-by: default avatarJack Morgenstein <jackm@dev.mellanox.co.il>
Signed-off-by: default avatarTariq Toukan <tariqt@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 1f34d8d2
...@@ -2645,6 +2645,8 @@ int mlx4_cmd_use_events(struct mlx4_dev *dev) ...@@ -2645,6 +2645,8 @@ int mlx4_cmd_use_events(struct mlx4_dev *dev)
if (!priv->cmd.context) if (!priv->cmd.context)
return -ENOMEM; return -ENOMEM;
if (mlx4_is_mfunc(dev))
mutex_lock(&priv->cmd.slave_cmd_mutex);
down_write(&priv->cmd.switch_sem); down_write(&priv->cmd.switch_sem);
for (i = 0; i < priv->cmd.max_cmds; ++i) { for (i = 0; i < priv->cmd.max_cmds; ++i) {
priv->cmd.context[i].token = i; priv->cmd.context[i].token = i;
...@@ -2670,6 +2672,8 @@ int mlx4_cmd_use_events(struct mlx4_dev *dev) ...@@ -2670,6 +2672,8 @@ int mlx4_cmd_use_events(struct mlx4_dev *dev)
down(&priv->cmd.poll_sem); down(&priv->cmd.poll_sem);
priv->cmd.use_events = 1; priv->cmd.use_events = 1;
up_write(&priv->cmd.switch_sem); up_write(&priv->cmd.switch_sem);
if (mlx4_is_mfunc(dev))
mutex_unlock(&priv->cmd.slave_cmd_mutex);
return err; return err;
} }
...@@ -2682,6 +2686,8 @@ void mlx4_cmd_use_polling(struct mlx4_dev *dev) ...@@ -2682,6 +2686,8 @@ void mlx4_cmd_use_polling(struct mlx4_dev *dev)
struct mlx4_priv *priv = mlx4_priv(dev); struct mlx4_priv *priv = mlx4_priv(dev);
int i; int i;
if (mlx4_is_mfunc(dev))
mutex_lock(&priv->cmd.slave_cmd_mutex);
down_write(&priv->cmd.switch_sem); down_write(&priv->cmd.switch_sem);
priv->cmd.use_events = 0; priv->cmd.use_events = 0;
...@@ -2693,6 +2699,8 @@ void mlx4_cmd_use_polling(struct mlx4_dev *dev) ...@@ -2693,6 +2699,8 @@ void mlx4_cmd_use_polling(struct mlx4_dev *dev)
up(&priv->cmd.poll_sem); up(&priv->cmd.poll_sem);
up_write(&priv->cmd.switch_sem); up_write(&priv->cmd.switch_sem);
if (mlx4_is_mfunc(dev))
mutex_unlock(&priv->cmd.slave_cmd_mutex);
} }
struct mlx4_cmd_mailbox *mlx4_alloc_cmd_mailbox(struct mlx4_dev *dev) struct mlx4_cmd_mailbox *mlx4_alloc_cmd_mailbox(struct mlx4_dev *dev)
......
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