OSDN Git Service

net/mlx5: Fix command bad flow on command entry allocation failure
authorMoshe Shemesh <moshe@mellanox.com>
Sun, 25 Jun 2017 15:45:32 +0000 (18:45 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 11 Aug 2017 16:08:55 +0000 (09:08 -0700)
[ 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

index cc19906..6c66d29 100644 (file)
@@ -630,6 +630,10 @@ static void dump_command(struct mlx5_core_dev *dev,
                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 *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);