Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 26 Mar 2018 20:06:37 +0000 (UTC)
From:      Hans Petter Selasky <hselasky@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org
Subject:   svn commit: r331572 - stable/11/sys/dev/mlx5/mlx5_core
Message-ID:  <201803262006.w2QK6bvt006380@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: hselasky
Date: Mon Mar 26 20:06:37 2018
New Revision: 331572
URL: https://svnweb.freebsd.org/changeset/base/331572

Log:
  MFC r330599:
  Fix potential deadlock in command mode change in mlx5core.
  
  Call command completion handler in case of timeout when working in
  interrupts mode. Avoid flushing the commands workqueue after acquiring
  the semaphores to prevent a potential deadlock.
  
  linux commit 9cba4ebcf374c3772f6eb61f2d065294b2451b49
  
  Sponsored by:	Mellanox Technologies

Modified:
  stable/11/sys/dev/mlx5/mlx5_core/mlx5_cmd.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/dev/mlx5/mlx5_core/mlx5_cmd.c
==============================================================================
--- stable/11/sys/dev/mlx5/mlx5_core/mlx5_cmd.c	Mon Mar 26 20:05:22 2018	(r331571)
+++ stable/11/sys/dev/mlx5/mlx5_core/mlx5_cmd.c	Mon Mar 26 20:06:37 2018	(r331572)
@@ -735,11 +735,6 @@ static void cmd_work_handler(struct work_struct *work)
 	struct semaphore *sem;
 
 	sem = ent->page_queue ? &cmd->pages_sem : &cmd->sem;
-	if (cmd->moving_to_polling) {
-		mlx5_core_warn(dev, "not expecting command execution, ignoring...\n");
-		return;
-	}
-
 	down(sem);
 
 	if (alloc_ent(ent) < 0) {
@@ -826,13 +821,13 @@ static int wait_func(struct mlx5_core_dev *dev, struct
 	if (cmd->mode == CMD_MODE_POLLING) {
 		wait_for_completion(&ent->done);
 		err = ent->ret;
-	} else {
-		if (!wait_for_completion_timeout(&ent->done, timeout))
-			err = -ETIMEDOUT;
-		else
-			err = 0;
-	}
+	} else if (!wait_for_completion_timeout(&ent->done, timeout)) {
+                ent->ret = -ETIMEDOUT;
+                mlx5_cmd_comp_handler(dev, 1UL << ent->idx);
+        }
 
+        err = ent->ret;
+
 	if (err == -ETIMEDOUT) {
 		mlx5_core_warn(dev, "%s(0x%x) timeout. Will cause a leak of a command resource\n",
 			       mlx5_command_str(msg_to_opcode(ent->in)),
@@ -881,27 +876,28 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, 
 		goto out_free;
 	}
 
-	if (!callback) {
-		err = wait_func(dev, ent);
-		if (err == -ETIMEDOUT)
-			goto out;
+	if (callback)
+                goto out;
 
-		ds = ent->ts2 - ent->ts1;
-		op = be16_to_cpu(((struct mlx5_inbox_hdr *)in->first.data)->opcode);
-		if (op < ARRAY_SIZE(cmd->stats)) {
-			stats = &cmd->stats[op];
-			spin_lock_irq(&stats->lock);
-			stats->sum += ds;
-			++stats->n;
-			spin_unlock_irq(&stats->lock);
-		}
-		mlx5_core_dbg_mask(dev, 1 << MLX5_CMD_TIME,
-				   "fw exec time for %s is %lld nsec\n",
-				   mlx5_command_str(op), (long long)ds);
-		*status = ent->status;
-		free_cmd(ent);
-	}
+        err = wait_func(dev, ent);
+        if (err == -ETIMEDOUT)
+                goto out;
 
+        ds = ent->ts2 - ent->ts1;
+        op = be16_to_cpu(((struct mlx5_inbox_hdr *)in->first.data)->opcode);
+        if (op < ARRAY_SIZE(cmd->stats)) {
+                stats = &cmd->stats[op];
+                spin_lock_irq(&stats->lock);
+                stats->sum += ds;
+                ++stats->n;
+                spin_unlock_irq(&stats->lock);
+        }
+        mlx5_core_dbg_mask(dev, 1 << MLX5_CMD_TIME,
+                           "fw exec time for %s is %lld nsec\n",
+                           mlx5_command_str(op), (long long)ds);
+        *status = ent->status;
+        free_cmd(ent);
+
 	return err;
 
 out_free:
@@ -1017,7 +1013,7 @@ static void clean_debug_files(struct mlx5_core_dev *de
 }
 
 
-void mlx5_cmd_use_events(struct mlx5_core_dev *dev)
+static void mlx5_cmd_change_mod(struct mlx5_core_dev *dev, int mode)
 {
 	struct mlx5_cmd *cmd = &dev->cmd;
 	int i;
@@ -1026,26 +1022,21 @@ void mlx5_cmd_use_events(struct mlx5_core_dev *dev)
 		down(&cmd->sem);
 
 	down(&cmd->pages_sem);
+	cmd->mode = mode;
 
-	flush_workqueue(cmd->wq);
-
-	cmd->mode = CMD_MODE_EVENTS;
-
 	up(&cmd->pages_sem);
 	for (i = 0; i < cmd->max_reg_cmds; i++)
 		up(&cmd->sem);
 }
 
-void mlx5_cmd_use_polling(struct mlx5_core_dev *dev)
+void mlx5_cmd_use_events(struct mlx5_core_dev *dev)
 {
-	struct mlx5_cmd *cmd = &dev->cmd;
+        mlx5_cmd_change_mod(dev, CMD_MODE_EVENTS);
+}
 
-	synchronize_irq(dev->priv.eq_table.pages_eq.irqn);
-	flush_workqueue(dev->priv.pg_wq);
-	cmd->moving_to_polling = 1;
-	flush_workqueue(cmd->wq);
-	cmd->mode = CMD_MODE_POLLING;
-	cmd->moving_to_polling = 0;
+void mlx5_cmd_use_polling(struct mlx5_core_dev *dev)
+{
+        mlx5_cmd_change_mod(dev, CMD_MODE_POLLING);
 }
 
 static void free_msg(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *msg)



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201803262006.w2QK6bvt006380>