Author: hselasky
Date: Wed Dec 12 12:29:22 2018
New Revision: 341945
URL: https://svnweb.freebsd.org/changeset/base/341945

Log:
  MFC r341566:
  mlx5: Fixes to allow command polling mode to exist alongside event mode.
  
  A command is either polling or event driven and the mode cannot change
  during execution of a command. Make sure the event handler only handle
  commands which are not polled. This is done by checking the command mode
  in the command handler before completing commands.
  
  Sponsored by:   Mellanox Technologies

Modified:
  stable/12/sys/dev/mlx5/driver.h
  stable/12/sys/dev/mlx5/mlx5_core/mlx5_cmd.c
  stable/12/sys/dev/mlx5/mlx5_core/mlx5_eq.c
  stable/12/sys/dev/mlx5/mlx5_core/mlx5_health.c
Directory Properties:
  stable/12/   (props changed)

Modified: stable/12/sys/dev/mlx5/driver.h
==============================================================================
--- stable/12/sys/dev/mlx5/driver.h     Wed Dec 12 12:28:24 2018        
(r341944)
+++ stable/12/sys/dev/mlx5/driver.h     Wed Dec 12 12:29:22 2018        
(r341945)
@@ -327,6 +327,11 @@ struct mlx5_traffic_counter {
        u64         octets;
 };
 
+enum mlx5_cmd_mode {
+       MLX5_CMD_MODE_POLLING,
+       MLX5_CMD_MODE_EVENTS
+};
+
 struct mlx5_cmd_stats {
        u64             sum;
        u64             n;
@@ -370,8 +375,9 @@ struct mlx5_cmd {
        struct workqueue_struct *wq;
        struct semaphore sem;
        struct semaphore pages_sem;
-       int     mode;
-       struct mlx5_cmd_work_ent *ent_arr[MLX5_MAX_COMMANDS];
+       enum mlx5_cmd_mode mode;
+       struct mlx5_cmd_work_ent * volatile ent_arr[MLX5_MAX_COMMANDS];
+       volatile enum mlx5_cmd_mode ent_mode[MLX5_MAX_COMMANDS];
        struct mlx5_cmd_debug dbg;
        struct cmd_msg_cache cache;
        int checksum_disabled;
@@ -984,7 +990,7 @@ void mlx5_cq_completion(struct mlx5_core_dev *dev, u32
 void mlx5_rsc_event(struct mlx5_core_dev *dev, u32 rsn, int event_type);
 void mlx5_srq_event(struct mlx5_core_dev *dev, u32 srqn, int event_type);
 struct mlx5_core_srq *mlx5_core_get_srq(struct mlx5_core_dev *dev, u32 srqn);
-void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vector);
+void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vector, enum 
mlx5_cmd_mode mode);
 void mlx5_cq_event(struct mlx5_core_dev *dev, u32 cqn, int event_type);
 int mlx5_create_map_eq(struct mlx5_core_dev *dev, struct mlx5_eq *eq, u8 
vecidx,
                       int nent, u64 mask, const char *name, struct mlx5_uar 
*uar);

Modified: stable/12/sys/dev/mlx5/mlx5_core/mlx5_cmd.c
==============================================================================
--- stable/12/sys/dev/mlx5/mlx5_core/mlx5_cmd.c Wed Dec 12 12:28:24 2018        
(r341944)
+++ stable/12/sys/dev/mlx5/mlx5_core/mlx5_cmd.c Wed Dec 12 12:29:22 2018        
(r341945)
@@ -50,11 +50,6 @@ enum {
 };
 
 enum {
-       CMD_MODE_POLLING,
-       CMD_MODE_EVENTS
-};
-
-enum {
        NUM_LONG_LISTS    = 2,
        NUM_MED_LISTS     = 64,
        LONG_LIST_SIZE    = (2ULL * 1024 * 1024 * 1024 / PAGE_SIZE) * 8 + 16 +
@@ -160,6 +155,8 @@ static int alloc_ent(struct mlx5_cmd_work_ent *ent)
                ent->busy = 1;
                ent->idx = ret;
                clear_bit(ent->idx, &cmd->bitmask);
+               cmd->ent_mode[ent->idx] =
+                   ent->polling ? MLX5_CMD_MODE_POLLING : MLX5_CMD_MODE_EVENTS;
                cmd->ent_arr[ent->idx] = ent;
        }
        spin_unlock_irqrestore(&cmd->alloc_lock, flags);
@@ -172,6 +169,8 @@ static void free_ent(struct mlx5_cmd *cmd, int idx)
        unsigned long flags;
 
        spin_lock_irqsave(&cmd->alloc_lock, flags);
+       cmd->ent_arr[idx] = NULL;       /* safety clear */
+       cmd->ent_mode[idx] = MLX5_CMD_MODE_POLLING;     /* reset mode */
        set_bit(idx, &cmd->bitmask);
        spin_unlock_irqrestore(&cmd->alloc_lock, flags);
 }
@@ -786,7 +785,7 @@ static void cb_timeout_handler(struct work_struct *wor
         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)),
                        msg_to_opcode(ent->in));
-        mlx5_cmd_comp_handler(dev, 1UL << ent->idx);
+        mlx5_cmd_comp_handler(dev, 1UL << ent->idx, MLX5_CMD_MODE_EVENTS);
 }
 
 static void complete_command(struct mlx5_cmd_work_ent *ent)
@@ -897,11 +896,12 @@ static void cmd_work_handler(struct work_struct *work)
        mlx5_fwp_flush(cmd->cmd_page);
        iowrite32be(1 << ent->idx, &dev->iseg->cmd_dbell);
        mmiowb();
-       /* if not in polling don't use ent after this point*/
-       if (cmd->mode == CMD_MODE_POLLING || poll_cmd) {
+
+       /* if not in polling don't use ent after this point */
+       if (poll_cmd) {
                poll_timeout(ent);
                /* make sure we read the descriptor after ownership is SW */
-               mlx5_cmd_comp_handler(dev, 1U << ent->idx);
+               mlx5_cmd_comp_handler(dev, 1U << ent->idx, 
MLX5_CMD_MODE_POLLING);
        }
 }
 
@@ -938,15 +938,13 @@ static const char *deliv_status_to_str(u8 status)
 static int wait_func(struct mlx5_core_dev *dev, struct mlx5_cmd_work_ent *ent)
 {
        int timeout = msecs_to_jiffies(MLX5_CMD_TIMEOUT_MSEC);
-       struct mlx5_cmd *cmd = &dev->cmd;
        int err;
 
-       if (cmd->mode == CMD_MODE_POLLING || ent->polling) {
+       if (ent->polling) {
                wait_for_completion(&ent->done);
-               err = ent->ret;
        } else if (!wait_for_completion_timeout(&ent->done, timeout)) {
                 ent->ret = -ETIMEDOUT;
-                mlx5_cmd_comp_handler(dev, 1UL << ent->idx);
+                mlx5_cmd_comp_handler(dev, 1UL << ent->idx, 
MLX5_CMD_MODE_EVENTS);
         }
 
         err = ent->ret;
@@ -988,7 +986,7 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, 
        if (IS_ERR(ent))
                return PTR_ERR(ent);
 
-       ent->polling = force_polling;
+       ent->polling = force_polling || (cmd->mode == MLX5_CMD_MODE_POLLING);
 
        if (!callback)
                init_completion(&ent->done);
@@ -1158,12 +1156,12 @@ static void mlx5_cmd_change_mod(struct mlx5_core_dev *
 
 void mlx5_cmd_use_events(struct mlx5_core_dev *dev)
 {
-        mlx5_cmd_change_mod(dev, CMD_MODE_EVENTS);
+        mlx5_cmd_change_mod(dev, MLX5_CMD_MODE_EVENTS);
 }
 
 void mlx5_cmd_use_polling(struct mlx5_core_dev *dev)
 {
-        mlx5_cmd_change_mod(dev, CMD_MODE_POLLING);
+        mlx5_cmd_change_mod(dev, MLX5_CMD_MODE_POLLING);
 }
 
 static void free_msg(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *msg)
@@ -1179,7 +1177,8 @@ static void free_msg(struct mlx5_core_dev *dev, struct
        }
 }
 
-void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vector_flags)
+void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vector_flags,
+    enum mlx5_cmd_mode cmd_mode)
 {
        struct mlx5_cmd *cmd = &dev->cmd;
        struct mlx5_cmd_work_ent *ent;
@@ -1193,7 +1192,13 @@ void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, 
        while (vector != 0) {
                i = ffs(vector) - 1;
                vector &= ~(1U << i);
+               /* check command mode */
+               if (cmd->ent_mode[i] != cmd_mode)
+                       continue;
                ent = cmd->ent_arr[i];
+               /* check if command was already handled */
+               if (ent == NULL)
+                       continue;
                 if (ent->callback)
                         cancel_delayed_work(&ent->cb_timeout_work);
                ent->ts2 = ktime_get_ns();
@@ -1545,7 +1550,7 @@ int mlx5_cmd_init(struct mlx5_core_dev *dev)
 
        mlx5_core_dbg(dev, "descriptor at dma 0x%llx\n", (unsigned long 
long)(cmd->dma));
 
-       cmd->mode = CMD_MODE_POLLING;
+       cmd->mode = MLX5_CMD_MODE_POLLING;
 
        err = create_msg_cache(dev);
        if (err) {

Modified: stable/12/sys/dev/mlx5/mlx5_core/mlx5_eq.c
==============================================================================
--- stable/12/sys/dev/mlx5/mlx5_core/mlx5_eq.c  Wed Dec 12 12:28:24 2018        
(r341944)
+++ stable/12/sys/dev/mlx5/mlx5_core/mlx5_eq.c  Wed Dec 12 12:29:22 2018        
(r341945)
@@ -254,8 +254,10 @@ static int mlx5_eq_int(struct mlx5_core_dev *dev, stru
                        break;
 
                case MLX5_EVENT_TYPE_CMD:
-                       if (dev->state != MLX5_DEVICE_STATE_INTERNAL_ERROR)
-                               mlx5_cmd_comp_handler(dev, 
be32_to_cpu(eqe->data.cmd.vector));
+                       if (dev->state != MLX5_DEVICE_STATE_INTERNAL_ERROR) {
+                               mlx5_cmd_comp_handler(dev, 
be32_to_cpu(eqe->data.cmd.vector),
+                                   MLX5_CMD_MODE_EVENTS);
+                       }
                        break;
 
                case MLX5_EVENT_TYPE_PORT_CHANGE:

Modified: stable/12/sys/dev/mlx5/mlx5_core/mlx5_health.c
==============================================================================
--- stable/12/sys/dev/mlx5/mlx5_core/mlx5_health.c      Wed Dec 12 12:28:24 
2018        (r341944)
+++ stable/12/sys/dev/mlx5/mlx5_core/mlx5_health.c      Wed Dec 12 12:29:22 
2018        (r341945)
@@ -141,7 +141,7 @@ static void mlx5_trigger_cmd_completions(struct mlx5_c
        spin_unlock_irqrestore(&dev->cmd.alloc_lock, flags);
 
        mlx5_core_dbg(dev, "vector 0x%jx\n", (uintmax_t)vector);
-       mlx5_cmd_comp_handler(dev, vector);
+       mlx5_cmd_comp_handler(dev, vector, MLX5_CMD_MODE_EVENTS);
        return;
 
 no_trig:
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to