net/mlx5: cmdif, cmd_check refactoring
authorSaeed Mahameed <saeedm@mellanox.com>
Mon, 6 Apr 2020 00:50:25 +0000 (17:50 -0700)
committerSaeed Mahameed <saeedm@nvidia.com>
Wed, 23 Feb 2022 23:21:59 +0000 (15:21 -0800)
Do not mangle the command outbox in the internal low level cmd_exec and
cmd_invoke functions.

Instead return a proper unique error code and move the driver error
checking to be at a higher level in mlx5_cmd_exec().

Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
Reviewed-by: Moshe Shemesh <moshe@nvidia.com>
Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
drivers/net/ethernet/mellanox/mlx5/core/cmd.c
drivers/net/ethernet/mellanox/mlx5/core/main.c
include/linux/mlx5/driver.h

index 3c6a533ee0c959dd8a0211b1e63e88917cd18519..7ff01b901f53cfa2fb7c682fcf66553f1a49b390 100644 (file)
@@ -760,43 +760,61 @@ struct mlx5_ifc_mbox_in_bits {
        u8         reserved_at_40[0x40];
 };
 
-void mlx5_cmd_mbox_status(void *out, u8 *status, u32 *syndrome)
-{
-       *status = MLX5_GET(mbox_out, out, status);
-       *syndrome = MLX5_GET(mbox_out, out, syndrome);
-}
-
-static int mlx5_cmd_check(struct mlx5_core_dev *dev, void *in, void *out)
+static void cmd_status_print(struct mlx5_core_dev *dev, void *in, void *out)
 {
+       u16 opcode, op_mod;
        u32 syndrome;
        u8  status;
-       u16 opcode;
-       u16 op_mod;
        u16 uid;
+       int err;
 
-       mlx5_cmd_mbox_status(out, &status, &syndrome);
-       if (!status)
-               return 0;
+       syndrome = MLX5_GET(mbox_out, out, syndrome);
+       status = MLX5_GET(mbox_out, out, status);
 
        opcode = MLX5_GET(mbox_in, in, opcode);
        op_mod = MLX5_GET(mbox_in, in, op_mod);
        uid    = MLX5_GET(mbox_in, in, uid);
 
+       err = cmd_status_to_err(status);
+
        if (!uid && opcode != MLX5_CMD_OP_DESTROY_MKEY)
                mlx5_core_err_rl(dev,
-                       "%s(0x%x) op_mod(0x%x) failed, status %s(0x%x), syndrome (0x%x)\n",
+                       "%s(0x%x) op_mod(0x%x) failed, status %s(0x%x), syndrome (0x%x), err(%d)\n",
                        mlx5_command_str(opcode), opcode, op_mod,
-                       cmd_status_str(status), status, syndrome);
+                       cmd_status_str(status), status, syndrome, err);
        else
                mlx5_core_dbg(dev,
-                     "%s(0x%x) op_mod(0x%x) failed, status %s(0x%x), syndrome (0x%x)\n",
-                     mlx5_command_str(opcode),
-                     opcode, op_mod,
-                     cmd_status_str(status),
-                     status,
-                     syndrome);
+                       "%s(0x%x) op_mod(0x%x) uid(%d) failed, status %s(0x%x), syndrome (0x%x), err(%d)\n",
+                       mlx5_command_str(opcode), opcode, op_mod, uid,
+                       cmd_status_str(status), status, syndrome, err);
+}
+
+static int mlx5_cmd_check(struct mlx5_core_dev *dev, int err, void *in, void *out)
+{
+       /* aborted due to PCI error or via reset flow mlx5_cmd_trigger_completions() */
+       if (err == -ENXIO) {
+               u16 opcode = MLX5_GET(mbox_in, in, opcode);
+               u32 syndrome;
+               u8 status;
+
+               /* PCI Error, emulate command return status, for smooth reset */
+               err = mlx5_internal_err_ret_value(dev, opcode, &syndrome, &status);
+               MLX5_SET(mbox_out, out, status, status);
+               MLX5_SET(mbox_out, out, syndrome, syndrome);
+               if (!err)
+                       return 0;
+       }
+
+       /* driver or FW delivery error */
+       if (err)
+               return err;
 
-       return cmd_status_to_err(status);
+       /* check outbox status */
+       err = cmd_status_to_err(MLX5_GET(mbox_out, out, status));
+       if (err)
+               cmd_status_print(dev, in, out);
+
+       return err;
 }
 
 static void dump_command(struct mlx5_core_dev *dev,
@@ -980,13 +998,7 @@ static void cmd_work_handler(struct work_struct *work)
 
        /* Skip sending command to fw if internal error */
        if (mlx5_cmd_is_down(dev) || !opcode_allowed(&dev->cmd, ent->op)) {
-               u8 status = 0;
-               u32 drv_synd;
-
-               ent->ret = mlx5_internal_err_ret_value(dev, msg_to_opcode(ent->in), &drv_synd, &status);
-               MLX5_SET(mbox_out, ent->out, status, status);
-               MLX5_SET(mbox_out, ent->out, syndrome, drv_synd);
-
+               ent->ret = -ENXIO;
                mlx5_cmd_comp_handler(dev, 1ULL << ent->idx, true);
                return;
        }
@@ -1005,6 +1017,31 @@ static void cmd_work_handler(struct work_struct *work)
        }
 }
 
+static int deliv_status_to_err(u8 status)
+{
+       switch (status) {
+       case MLX5_CMD_DELIVERY_STAT_OK:
+       case MLX5_DRIVER_STATUS_ABORTED:
+               return 0;
+       case MLX5_CMD_DELIVERY_STAT_SIGNAT_ERR:
+       case MLX5_CMD_DELIVERY_STAT_TOK_ERR:
+               return -EBADR;
+       case MLX5_CMD_DELIVERY_STAT_BAD_BLK_NUM_ERR:
+       case MLX5_CMD_DELIVERY_STAT_OUT_PTR_ALIGN_ERR:
+       case MLX5_CMD_DELIVERY_STAT_IN_PTR_ALIGN_ERR:
+               return -EFAULT; /* Bad address */
+       case MLX5_CMD_DELIVERY_STAT_IN_LENGTH_ERR:
+       case MLX5_CMD_DELIVERY_STAT_OUT_LENGTH_ERR:
+       case MLX5_CMD_DELIVERY_STAT_CMD_DESCR_ERR:
+       case MLX5_CMD_DELIVERY_STAT_RES_FLD_NOT_CLR_ERR:
+               return -ENOMSG;
+       case MLX5_CMD_DELIVERY_STAT_FW_ERR:
+               return -EIO;
+       default:
+               return -EINVAL;
+       }
+}
+
 static const char *deliv_status_to_str(u8 status)
 {
        switch (status) {
@@ -1622,15 +1659,15 @@ static void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool force
                        ent->ts2 = ktime_get_ns();
                        memcpy(ent->out->first.data, ent->lay->out, sizeof(ent->lay->out));
                        dump_command(dev, ent, 0);
-                       if (!ent->ret) {
+
+                       if (vec & MLX5_TRIGGERED_CMD_COMP)
+                               ent->ret = -ENXIO;
+
+                       if (!ent->ret) { /* Command completed by FW */
                                if (!cmd->checksum_disabled)
                                        ent->ret = verify_signature(ent);
-                               else
-                                       ent->ret = 0;
-                               if (vec & MLX5_TRIGGERED_CMD_COMP)
-                                       ent->status = MLX5_DRIVER_STATUS_ABORTED;
-                               else
-                                       ent->status = ent->lay->status_own >> 1;
+
+                               ent->status = ent->lay->status_own >> 1;
 
                                mlx5_core_dbg(dev, "command completed. ret 0x%x, delivery status %s(0x%x)\n",
                                              ent->ret, deliv_status_to_str(ent->status), ent->status);
@@ -1649,14 +1686,13 @@ static void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool force
                                callback = ent->callback;
                                context = ent->context;
                                err = ent->ret;
-                               if (!err) {
+                               if (!err && !ent->status) {
                                        err = mlx5_copy_from_msg(ent->uout,
                                                                 ent->out,
                                                                 ent->uout_size);
 
-                                       err = err ? err : mlx5_cmd_check(dev,
-                                                                       ent->in->first.data,
-                                                                       ent->uout);
+                                       err = mlx5_cmd_check(dev, err, ent->in->first.data,
+                                                            ent->uout);
                                }
 
                                mlx5_free_cmd_msg(dev, ent->out);
@@ -1729,31 +1765,6 @@ void mlx5_cmd_flush(struct mlx5_core_dev *dev)
                up(&cmd->sem);
 }
 
-static int deliv_status_to_err(u8 status)
-{
-       switch (status) {
-       case MLX5_CMD_DELIVERY_STAT_OK:
-       case MLX5_DRIVER_STATUS_ABORTED:
-               return 0;
-       case MLX5_CMD_DELIVERY_STAT_SIGNAT_ERR:
-       case MLX5_CMD_DELIVERY_STAT_TOK_ERR:
-               return -EBADR;
-       case MLX5_CMD_DELIVERY_STAT_BAD_BLK_NUM_ERR:
-       case MLX5_CMD_DELIVERY_STAT_OUT_PTR_ALIGN_ERR:
-       case MLX5_CMD_DELIVERY_STAT_IN_PTR_ALIGN_ERR:
-               return -EFAULT; /* Bad address */
-       case MLX5_CMD_DELIVERY_STAT_IN_LENGTH_ERR:
-       case MLX5_CMD_DELIVERY_STAT_OUT_LENGTH_ERR:
-       case MLX5_CMD_DELIVERY_STAT_CMD_DESCR_ERR:
-       case MLX5_CMD_DELIVERY_STAT_RES_FLD_NOT_CLR_ERR:
-               return -ENOMSG;
-       case MLX5_CMD_DELIVERY_STAT_FW_ERR:
-               return -EIO;
-       default:
-               return -EINVAL;
-       }
-}
-
 static struct mlx5_cmd_msg *alloc_msg(struct mlx5_core_dev *dev, int in_size,
                                      gfp_t gfp)
 {
@@ -1812,15 +1823,8 @@ static int cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out,
        u8 token;
        int err;
 
-       if (mlx5_cmd_is_down(dev) || !opcode_allowed(&dev->cmd, opcode)) {
-               u32 drv_synd;
-               u8 status;
-
-               err = mlx5_internal_err_ret_value(dev, opcode, &drv_synd, &status);
-               MLX5_SET(mbox_out, out, status, status);
-               MLX5_SET(mbox_out, out, syndrome, drv_synd);
-               return err;
-       }
+       if (mlx5_cmd_is_down(dev) || !opcode_allowed(&dev->cmd, opcode))
+               return -ENXIO;
 
        pages_queue = is_manage_pages(in);
        gfp = callback ? GFP_ATOMIC : GFP_KERNEL;
@@ -1865,13 +1869,24 @@ out_in:
        return err;
 }
 
+/**
+ * mlx5_cmd_exec - Executes a fw command, wait for completion
+ *
+ * @dev: mlx5 core device
+ * @in: inbox mlx5_ifc command buffer
+ * @in_size: inbox buffer size
+ * @out: outbox mlx5_ifc buffer
+ * @out_size: outbox size
+ *
+ * @return: 0 if no error, FW command execution was successful,
+ *          and outbox status is ok.
+ */
 int mlx5_cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out,
                  int out_size)
 {
-       int err;
+       int err = cmd_exec(dev, in, in_size, out, out_size, NULL, NULL, false);
 
-       err = cmd_exec(dev, in, in_size, out, out_size, NULL, NULL, false);
-       return err ? : mlx5_cmd_check(dev, in, out);
+       return mlx5_cmd_check(dev, err, in, out);
 }
 EXPORT_SYMBOL(mlx5_cmd_exec);
 
@@ -1932,11 +1947,9 @@ EXPORT_SYMBOL(mlx5_cmd_exec_cb);
 int mlx5_cmd_exec_polling(struct mlx5_core_dev *dev, void *in, int in_size,
                          void *out, int out_size)
 {
-       int err;
-
-       err = cmd_exec(dev, in, in_size, out, out_size, NULL, NULL, true);
+       int err = cmd_exec(dev, in, in_size, out, out_size, NULL, NULL, true);
 
-       return err ? : mlx5_cmd_check(dev, in, out);
+       return mlx5_cmd_check(dev, err, in, out);
 }
 EXPORT_SYMBOL(mlx5_cmd_exec_polling);
 
index 2c774f367199d6846241abab218e11706aa76064..cea1a8ac196e6af410779d1b8aae049b8ede2c02 100644 (file)
@@ -736,10 +736,9 @@ static int mlx5_core_set_issi(struct mlx5_core_dev *dev)
        MLX5_SET(query_issi_in, query_in, opcode, MLX5_CMD_OP_QUERY_ISSI);
        err = mlx5_cmd_exec_inout(dev, query_issi, query_in, query_out);
        if (err) {
-               u32 syndrome;
-               u8 status;
+               u32 syndrome = MLX5_GET(query_issi_out, query_out, syndrome);
+               u8 status = MLX5_GET(query_issi_out, query_out, status);
 
-               mlx5_cmd_mbox_status(query_out, &status, &syndrome);
                if (!status || syndrome == MLX5_DRIVER_SYND) {
                        mlx5_core_err(dev, "Failed to query ISSI err(%d) status(%d) synd(%d)\n",
                                      err, status, syndrome);
index 1b398c9e17b98fbfbf236fb543393d92944c9497..8a8408708e6c6f9d1ab453d7afece4b678db3a7f 100644 (file)
@@ -981,7 +981,6 @@ int mlx5_cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out,
 
 int mlx5_cmd_exec_polling(struct mlx5_core_dev *dev, void *in, int in_size,
                          void *out, int out_size);
-void mlx5_cmd_mbox_status(void *out, u8 *status, u32 *syndrome);
 bool mlx5_cmd_is_down(struct mlx5_core_dev *dev);
 
 int mlx5_core_get_caps(struct mlx5_core_dev *dev, enum mlx5_cap_type cap_type);