| From foo@baz Tue Aug 8 16:51:58 PDT 2017 |
| From: Moshe Shemesh <moshe@mellanox.com> |
| Date: Sun, 25 Jun 2017 18:45:32 +0300 |
| Subject: net/mlx5: Fix command bad flow on command entry allocation failure |
| |
| From: Moshe Shemesh <moshe@mellanox.com> |
| |
| |
| [ Upstream commit 219c81f7d1d5a89656cb3b53d3b4e11e93608d80 ] |
| |
| When driver fail to allocate an entry to send command to FW, it must |
| notify the calling function and release the memory allocated for |
| this command. |
| |
| Fixes: e126ba97dba9e ('mlx5: Add driver for Mellanox Connect-IB adapters') |
| Signed-off-by: Moshe Shemesh <moshe@mellanox.com> |
| Cc: kernel-team@fb.com |
| Signed-off-by: Saeed Mahameed <saeedm@mellanox.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/net/ethernet/mellanox/mlx5/core/cmd.c | 19 +++++++++++++++++-- |
| 1 file changed, 17 insertions(+), 2 deletions(-) |
| |
| --- a/drivers/net/ethernet/mellanox/mlx5/core/cmd.c |
| +++ b/drivers/net/ethernet/mellanox/mlx5/core/cmd.c |
| @@ -630,6 +630,10 @@ static void dump_command(struct mlx5_cor |
| pr_debug("\n"); |
| } |
| |
| +static void free_msg(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *msg); |
| +static void mlx5_free_cmd_msg(struct mlx5_core_dev *dev, |
| + struct mlx5_cmd_msg *msg); |
| + |
| static void cmd_work_handler(struct work_struct *work) |
| { |
| struct mlx5_cmd_work_ent *ent = container_of(work, struct mlx5_cmd_work_ent, work); |
| @@ -638,16 +642,27 @@ static void cmd_work_handler(struct work |
| struct mlx5_cmd_layout *lay; |
| struct semaphore *sem; |
| unsigned long flags; |
| + int alloc_ret; |
| |
| sem = ent->page_queue ? &cmd->pages_sem : &cmd->sem; |
| down(sem); |
| if (!ent->page_queue) { |
| - ent->idx = alloc_ent(cmd); |
| - if (ent->idx < 0) { |
| + alloc_ret = alloc_ent(cmd); |
| + if (alloc_ret < 0) { |
| + if (ent->callback) { |
| + ent->callback(-EAGAIN, ent->context); |
| + mlx5_free_cmd_msg(dev, ent->out); |
| + free_msg(dev, ent->in); |
| + free_cmd(ent); |
| + } else { |
| + ent->ret = -EAGAIN; |
| + complete(&ent->done); |
| + } |
| mlx5_core_err(dev, "failed to allocate command entry\n"); |
| up(sem); |
| return; |
| } |
| + ent->idx = alloc_ret; |
| } else { |
| ent->idx = cmd->max_reg_cmds; |
| spin_lock_irqsave(&cmd->alloc_lock, flags); |