Commit 0a415276 authored by Saeed Mahameed's avatar Saeed Mahameed Committed by Saeed Mahameed

net/mlx5: cmdif, Refactor error handling and reporting of async commands

Same as the new mlx5_cmd_do API, report all information to callers and
let them handle the error values and outbox parsing.

The user callback status "work->user_callback(status)" is now similar to
the error rc code returned from the blocking mlx5_cmd_do() version,
and now is defined as follows:

 -EREMOTEIO : Command executed by FW, outbox.status != MLX5_CMD_STAT_OK.
              Caller must check FW outbox status.
 0 : Command execution successful,  outbox.status == MLX5_CMD_STAT_OK.
 < 0 : Command couldn't execute, FW or driver induced error.
Signed-off-by: default avatarSaeed Mahameed <saeedm@mellanox.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@nvidia.com>
parent 31803e59
...@@ -140,6 +140,19 @@ static int destroy_mkey(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr) ...@@ -140,6 +140,19 @@ static int destroy_mkey(struct mlx5_ib_dev *dev, struct mlx5_ib_mr *mr)
return mlx5_core_destroy_mkey(dev->mdev, mr->mmkey.key); return mlx5_core_destroy_mkey(dev->mdev, mr->mmkey.key);
} }
static void create_mkey_warn(struct mlx5_ib_dev *dev, int status, void *out)
{
if (status == -ENXIO) /* core driver is not available */
return;
mlx5_ib_warn(dev, "async reg mr failed. status %d\n", status);
if (status != -EREMOTEIO) /* driver specific failure */
return;
/* Failed in FW, print cmd out failure details */
mlx5_cmd_out_err(dev->mdev, MLX5_CMD_OP_CREATE_MKEY, 0, out);
}
static void create_mkey_callback(int status, struct mlx5_async_work *context) static void create_mkey_callback(int status, struct mlx5_async_work *context)
{ {
struct mlx5_ib_mr *mr = struct mlx5_ib_mr *mr =
...@@ -149,7 +162,7 @@ static void create_mkey_callback(int status, struct mlx5_async_work *context) ...@@ -149,7 +162,7 @@ static void create_mkey_callback(int status, struct mlx5_async_work *context)
unsigned long flags; unsigned long flags;
if (status) { if (status) {
mlx5_ib_warn(dev, "async reg mr failed. status %d\n", status); create_mkey_warn(dev, status, mr->out);
kfree(mr); kfree(mr);
spin_lock_irqsave(&ent->lock, flags); spin_lock_irqsave(&ent->lock, flags);
ent->pending--; ent->pending--;
......
...@@ -760,6 +760,18 @@ struct mlx5_ifc_mbox_in_bits { ...@@ -760,6 +760,18 @@ struct mlx5_ifc_mbox_in_bits {
u8 reserved_at_40[0x40]; u8 reserved_at_40[0x40];
}; };
void mlx5_cmd_out_err(struct mlx5_core_dev *dev, u16 opcode, u16 op_mod, void *out)
{
u32 syndrome = MLX5_GET(mbox_out, out, syndrome);
u8 status = MLX5_GET(mbox_out, out, status);
mlx5_core_err_rl(dev,
"%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_to_err(status));
}
EXPORT_SYMBOL(mlx5_cmd_out_err);
static void cmd_status_print(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; u16 opcode, op_mod;
...@@ -778,10 +790,7 @@ static void cmd_status_print(struct mlx5_core_dev *dev, void *in, void *out) ...@@ -778,10 +790,7 @@ static void cmd_status_print(struct mlx5_core_dev *dev, void *in, void *out)
err = cmd_status_to_err(status); err = cmd_status_to_err(status);
if (!uid && opcode != MLX5_CMD_OP_DESTROY_MKEY) if (!uid && opcode != MLX5_CMD_OP_DESTROY_MKEY)
mlx5_core_err_rl(dev, mlx5_cmd_out_err(dev, opcode, op_mod, out);
"%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, err);
else else
mlx5_core_dbg(dev, mlx5_core_dbg(dev,
"%s(0x%x) op_mod(0x%x) uid(%d) failed, status %s(0x%x), syndrome (0x%x), err(%d)\n", "%s(0x%x) op_mod(0x%x) uid(%d) failed, status %s(0x%x), syndrome (0x%x), err(%d)\n",
...@@ -1686,20 +1695,18 @@ static void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool force ...@@ -1686,20 +1695,18 @@ static void mlx5_cmd_comp_handler(struct mlx5_core_dev *dev, u64 vec, bool force
callback = ent->callback; callback = ent->callback;
context = ent->context; context = ent->context;
err = ent->ret; err = ent->ret ? : ent->status;
if (!err && !ent->status) { if (err > 0) /* Failed in FW, command didn't execute */
err = deliv_status_to_err(err);
if (!err)
err = mlx5_copy_from_msg(ent->uout, err = mlx5_copy_from_msg(ent->uout,
ent->out, ent->out,
ent->uout_size); ent->uout_size);
err = mlx5_cmd_check(dev, err, ent->in->first.data,
ent->uout);
}
mlx5_free_cmd_msg(dev, ent->out); mlx5_free_cmd_msg(dev, ent->out);
free_msg(dev, ent->in); free_msg(dev, ent->in);
err = err ? err : ent->status;
/* final consumer is done, release ent */ /* final consumer is done, release ent */
cmd_ent_put(ent); cmd_ent_put(ent);
callback(err, context); callback(err, context);
...@@ -1870,6 +1877,18 @@ static int cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out, ...@@ -1870,6 +1877,18 @@ static int cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out,
return err; return err;
} }
/* preserve -EREMOTEIO for outbox.status != OK, otherwise return err as is */
static int cmd_status_err(int err, void *out)
{
if (err) /* -EREMOTEIO is preserved */
return err == -EREMOTEIO ? -EIO : err;
if (MLX5_GET(mbox_out, out, status) != MLX5_CMD_STAT_OK)
return -EREMOTEIO;
return 0;
}
/** /**
* mlx5_cmd_do - Executes a fw command, wait for completion. * mlx5_cmd_do - Executes a fw command, wait for completion.
* Unlike mlx5_cmd_exec, this function will not translate or intercept * Unlike mlx5_cmd_exec, this function will not translate or intercept
...@@ -1892,13 +1911,7 @@ int mlx5_cmd_do(struct mlx5_core_dev *dev, void *in, int in_size, void *out, int ...@@ -1892,13 +1911,7 @@ int mlx5_cmd_do(struct mlx5_core_dev *dev, void *in, int in_size, void *out, int
{ {
int err = cmd_exec(dev, in, in_size, out, out_size, NULL, NULL, false); int err = cmd_exec(dev, in, in_size, out, out_size, NULL, NULL, false);
if (err) /* -EREMOTEIO is preserved */ return cmd_status_err(err, out);
return err == -EREMOTEIO ? -EIO : err;
if (MLX5_GET(mbox_out, out, status) != MLX5_CMD_STAT_OK)
return -EREMOTEIO;
return 0;
} }
EXPORT_SYMBOL(mlx5_cmd_do); EXPORT_SYMBOL(mlx5_cmd_do);
...@@ -1942,12 +1955,7 @@ int mlx5_cmd_exec_polling(struct mlx5_core_dev *dev, void *in, int in_size, ...@@ -1942,12 +1955,7 @@ int mlx5_cmd_exec_polling(struct mlx5_core_dev *dev, void *in, int in_size,
{ {
int 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);
if (err) /* -EREMOTEIO is preserved */ err = cmd_status_err(err, out);
return err == -EREMOTEIO ? -EIO : err;
if (MLX5_GET(mbox_out, out, status) != MLX5_CMD_STAT_OK)
err = -EREMOTEIO;
return mlx5_cmd_check(dev, err, in, out); return mlx5_cmd_check(dev, err, in, out);
} }
EXPORT_SYMBOL(mlx5_cmd_exec_polling); EXPORT_SYMBOL(mlx5_cmd_exec_polling);
...@@ -1980,8 +1988,10 @@ EXPORT_SYMBOL(mlx5_cmd_cleanup_async_ctx); ...@@ -1980,8 +1988,10 @@ EXPORT_SYMBOL(mlx5_cmd_cleanup_async_ctx);
static void mlx5_cmd_exec_cb_handler(int status, void *_work) static void mlx5_cmd_exec_cb_handler(int status, void *_work)
{ {
struct mlx5_async_work *work = _work; struct mlx5_async_work *work = _work;
struct mlx5_async_ctx *ctx = work->ctx; struct mlx5_async_ctx *ctx;
ctx = work->ctx;
status = cmd_status_err(status, work->out);
work->user_callback(status, work); work->user_callback(status, work);
if (atomic_dec_and_test(&ctx->num_inflight)) if (atomic_dec_and_test(&ctx->num_inflight))
wake_up(&ctx->wait); wake_up(&ctx->wait);
...@@ -1995,6 +2005,7 @@ int mlx5_cmd_exec_cb(struct mlx5_async_ctx *ctx, void *in, int in_size, ...@@ -1995,6 +2005,7 @@ int mlx5_cmd_exec_cb(struct mlx5_async_ctx *ctx, void *in, int in_size,
work->ctx = ctx; work->ctx = ctx;
work->user_callback = callback; work->user_callback = callback;
work->out = out;
if (WARN_ON(!atomic_inc_not_zero(&ctx->num_inflight))) if (WARN_ON(!atomic_inc_not_zero(&ctx->num_inflight)))
return -EIO; return -EIO;
ret = cmd_exec(ctx->dev, in, in_size, out, out_size, ret = cmd_exec(ctx->dev, in, in_size, out, out_size,
......
...@@ -955,6 +955,7 @@ typedef void (*mlx5_async_cbk_t)(int status, struct mlx5_async_work *context); ...@@ -955,6 +955,7 @@ typedef void (*mlx5_async_cbk_t)(int status, struct mlx5_async_work *context);
struct mlx5_async_work { struct mlx5_async_work {
struct mlx5_async_ctx *ctx; struct mlx5_async_ctx *ctx;
mlx5_async_cbk_t user_callback; mlx5_async_cbk_t user_callback;
void *out; /* pointer to the cmd output buffer */
}; };
void mlx5_cmd_init_async_ctx(struct mlx5_core_dev *dev, void mlx5_cmd_init_async_ctx(struct mlx5_core_dev *dev,
...@@ -963,7 +964,7 @@ void mlx5_cmd_cleanup_async_ctx(struct mlx5_async_ctx *ctx); ...@@ -963,7 +964,7 @@ void mlx5_cmd_cleanup_async_ctx(struct mlx5_async_ctx *ctx);
int mlx5_cmd_exec_cb(struct mlx5_async_ctx *ctx, void *in, int in_size, int mlx5_cmd_exec_cb(struct mlx5_async_ctx *ctx, void *in, int in_size,
void *out, int out_size, mlx5_async_cbk_t callback, void *out, int out_size, mlx5_async_cbk_t callback,
struct mlx5_async_work *work); struct mlx5_async_work *work);
void mlx5_cmd_out_err(struct mlx5_core_dev *dev, u16 opcode, u16 op_mod, void *out);
int mlx5_cmd_do(struct mlx5_core_dev *dev, void *in, int in_size, void *out, int out_size); int mlx5_cmd_do(struct mlx5_core_dev *dev, void *in, int in_size, void *out, int out_size);
int mlx5_cmd_check(struct mlx5_core_dev *dev, int err, void *in, void *out); int mlx5_cmd_check(struct mlx5_core_dev *dev, int err, void *in, void *out);
int mlx5_cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out, int mlx5_cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment