Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d19d0ac6 authored by Moshe Shemesh's avatar Moshe Shemesh Committed by Greg Kroah-Hartman
Browse files

net/mlx5: Fix command bad flow on command entry allocation failure




[ 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: e126ba97 ('mlx5: Add driver for Mellanox Connect-IB adapters')
Signed-off-by: default avatarMoshe Shemesh <moshe@mellanox.com>
Cc: kernel-team@fb.com
Signed-off-by: default avatarSaeed Mahameed <saeedm@mellanox.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent fca84d61
Loading
Loading
Loading
Loading
+17 −2
Original line number Diff line number Diff line
@@ -770,6 +770,10 @@ static void cb_timeout_handler(struct work_struct *work)
	mlx5_cmd_comp_handler(dev, 1UL << ent->idx, true);
}

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);
@@ -779,16 +783,27 @@ static void cmd_work_handler(struct work_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);