From 82101a443a8696240cba3e59830470bab553bb1b Mon Sep 17 00:00:00 2001 From: Hans Petter Selasky Date: Tue, 2 Oct 2018 16:01:33 +0000 Subject: [PATCH] Selectivly backport fix for firmware command hang when switching from polling-based firmware commands to event based firmware commands. This is a direct commit. Linux commit: a7e1f04905e5b2b90251974dddde781301b6be37 Sponsored by: Mellanox Technologies --- sys/ofed/drivers/net/mlx4/cmd.c | 22 ++++++++++++++++------ sys/ofed/drivers/net/mlx4/mlx4.h | 2 ++ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/sys/ofed/drivers/net/mlx4/cmd.c b/sys/ofed/drivers/net/mlx4/cmd.c index f0805e8c8afa..88137a5a430b 100644 --- a/sys/ofed/drivers/net/mlx4/cmd.c +++ b/sys/ofed/drivers/net/mlx4/cmd.c @@ -794,14 +794,19 @@ int __mlx4_cmd(struct mlx4_dev *dev, u64 in_param, u64 *out_param, return -EIO; if (!mlx4_is_mfunc(dev) || (native && mlx4_is_master(dev))) { + int ret; + + down_read(&mlx4_priv(dev)->cmd.switch_sem); if (mlx4_priv(dev)->cmd.use_events) - return mlx4_cmd_wait(dev, in_param, out_param, - out_is_imm, in_modifier, - op_modifier, op, timeout); + ret = mlx4_cmd_wait(dev, in_param, out_param, + out_is_imm, in_modifier, + op_modifier, op, timeout); else - return mlx4_cmd_poll(dev, in_param, out_param, - out_is_imm, in_modifier, - op_modifier, op, timeout); + ret = mlx4_cmd_poll(dev, in_param, out_param, + out_is_imm, in_modifier, + op_modifier, op, timeout); + up_read(&mlx4_priv(dev)->cmd.switch_sem); + return ret; } return mlx4_slave_cmd(dev, in_param, out_param, out_is_imm, in_modifier, op_modifier, op, timeout); @@ -2253,6 +2258,7 @@ int mlx4_cmd_init(struct mlx4_dev *dev) { struct mlx4_priv *priv = mlx4_priv(dev); + init_rwsem(&priv->cmd.switch_sem); mutex_init(&priv->cmd.hcr_mutex); mutex_init(&priv->cmd.slave_cmd_mutex); sema_init(&priv->cmd.poll_sem, 1); @@ -2351,6 +2357,7 @@ int mlx4_cmd_use_events(struct mlx4_dev *dev) if (!priv->cmd.context) return -ENOMEM; + down_write(&priv->cmd.switch_sem); for (i = 0; i < priv->cmd.max_cmds; ++i) { priv->cmd.context[i].token = i; priv->cmd.context[i].next = i + 1; @@ -2370,6 +2377,7 @@ int mlx4_cmd_use_events(struct mlx4_dev *dev) down(&priv->cmd.poll_sem); priv->cmd.use_events = 1; + up_write(&priv->cmd.switch_sem); return err; } @@ -2382,6 +2390,7 @@ void mlx4_cmd_use_polling(struct mlx4_dev *dev) struct mlx4_priv *priv = mlx4_priv(dev); int i; + down_write(&priv->cmd.switch_sem); priv->cmd.use_events = 0; for (i = 0; i < priv->cmd.max_cmds; ++i) @@ -2390,6 +2399,7 @@ void mlx4_cmd_use_polling(struct mlx4_dev *dev) kfree(priv->cmd.context); up(&priv->cmd.poll_sem); + up_write(&priv->cmd.switch_sem); } struct mlx4_cmd_mailbox *mlx4_alloc_cmd_mailbox(struct mlx4_dev *dev) diff --git a/sys/ofed/drivers/net/mlx4/mlx4.h b/sys/ofed/drivers/net/mlx4/mlx4.h index bef2e004374e..8ebf64a4670d 100644 --- a/sys/ofed/drivers/net/mlx4/mlx4.h +++ b/sys/ofed/drivers/net/mlx4/mlx4.h @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -596,6 +597,7 @@ struct mlx4_cmd { struct mutex slave_cmd_mutex; struct semaphore poll_sem; struct semaphore event_sem; + struct rw_semaphore switch_sem; int max_cmds; spinlock_t context_lock; int free_head;