mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-13 17:39:23 -04:00
net/mlx5: cmdif, Return value improvements
Make sure that the two basic command interface functions cmd_exec and cmd_invoke will return well defined return values: return < 0 : Command execution couldn't be submitted by driver return > 0 : Command execution couldn't be performed by firmware return = 0 : Command was executed by FW, Caller must check FW outbox status. These statuses are valid for the blocking call of cmd_exec() e.g. when callback == NULL, in a downstream patch, will refactor the code to provide the same return value semantics to the callback. Signed-off-by: Saeed Mahameed <saeedm@mellanox.com> Reviewed-by: Moshe Shemesh <moshe@nvidia.com> Signed-off-by: Saeed Mahameed <saeedm@nvidia.com>
This commit is contained in:
committed by
Saeed Mahameed
parent
6cb87869ad
commit
f086470122
@@ -190,10 +190,10 @@ static int verify_block_sig(struct mlx5_cmd_prot_block *block)
|
|||||||
int xor_len = sizeof(*block) - sizeof(block->data) - 1;
|
int xor_len = sizeof(*block) - sizeof(block->data) - 1;
|
||||||
|
|
||||||
if (xor8_buf(block, rsvd0_off, xor_len) != 0xff)
|
if (xor8_buf(block, rsvd0_off, xor_len) != 0xff)
|
||||||
return -EINVAL;
|
return -EHWPOISON;
|
||||||
|
|
||||||
if (xor8_buf(block, 0, sizeof(*block)) != 0xff)
|
if (xor8_buf(block, 0, sizeof(*block)) != 0xff)
|
||||||
return -EINVAL;
|
return -EHWPOISON;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -259,12 +259,12 @@ static int verify_signature(struct mlx5_cmd_work_ent *ent)
|
|||||||
|
|
||||||
sig = xor8_buf(ent->lay, 0, sizeof(*ent->lay));
|
sig = xor8_buf(ent->lay, 0, sizeof(*ent->lay));
|
||||||
if (sig != 0xff)
|
if (sig != 0xff)
|
||||||
return -EINVAL;
|
return -EHWPOISON;
|
||||||
|
|
||||||
for (i = 0; i < n && next; i++) {
|
for (i = 0; i < n && next; i++) {
|
||||||
err = verify_block_sig(next->buf);
|
err = verify_block_sig(next->buf);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return -EHWPOISON;
|
||||||
|
|
||||||
next = next->next;
|
next = next->next;
|
||||||
}
|
}
|
||||||
@@ -479,7 +479,7 @@ static int mlx5_internal_err_ret_value(struct mlx5_core_dev *dev, u16 op,
|
|||||||
case MLX5_CMD_OP_ALLOC_SF:
|
case MLX5_CMD_OP_ALLOC_SF:
|
||||||
*status = MLX5_DRIVER_STATUS_ABORTED;
|
*status = MLX5_DRIVER_STATUS_ABORTED;
|
||||||
*synd = MLX5_DRIVER_SYND;
|
*synd = MLX5_DRIVER_SYND;
|
||||||
return -EIO;
|
return -ENOLINK;
|
||||||
default:
|
default:
|
||||||
mlx5_core_err(dev, "Unknown FW command (%d)\n", op);
|
mlx5_core_err(dev, "Unknown FW command (%d)\n", op);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
@@ -1101,16 +1101,27 @@ static int wait_func(struct mlx5_core_dev *dev, struct mlx5_cmd_work_ent *ent)
|
|||||||
/* Notes:
|
/* Notes:
|
||||||
* 1. Callback functions may not sleep
|
* 1. Callback functions may not sleep
|
||||||
* 2. page queue commands do not support asynchrous completion
|
* 2. page queue commands do not support asynchrous completion
|
||||||
|
*
|
||||||
|
* return value in case (!callback):
|
||||||
|
* ret < 0 : Command execution couldn't be submitted by driver
|
||||||
|
* ret > 0 : Command execution couldn't be performed by firmware
|
||||||
|
* ret == 0: Command was executed by FW, Caller must check FW outbox status.
|
||||||
|
*
|
||||||
|
* return value in case (callback):
|
||||||
|
* ret < 0 : Command execution couldn't be submitted by driver
|
||||||
|
* ret == 0: Command will be submitted to FW for execution
|
||||||
|
* and the callback will be called for further status updates
|
||||||
*/
|
*/
|
||||||
static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in,
|
static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in,
|
||||||
struct mlx5_cmd_msg *out, void *uout, int uout_size,
|
struct mlx5_cmd_msg *out, void *uout, int uout_size,
|
||||||
mlx5_cmd_cbk_t callback,
|
mlx5_cmd_cbk_t callback,
|
||||||
void *context, int page_queue, u8 *status,
|
void *context, int page_queue,
|
||||||
u8 token, bool force_polling)
|
u8 token, bool force_polling)
|
||||||
{
|
{
|
||||||
struct mlx5_cmd *cmd = &dev->cmd;
|
struct mlx5_cmd *cmd = &dev->cmd;
|
||||||
struct mlx5_cmd_work_ent *ent;
|
struct mlx5_cmd_work_ent *ent;
|
||||||
struct mlx5_cmd_stats *stats;
|
struct mlx5_cmd_stats *stats;
|
||||||
|
u8 status = 0;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
s64 ds;
|
s64 ds;
|
||||||
u16 op;
|
u16 op;
|
||||||
@@ -1141,12 +1152,12 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in,
|
|||||||
cmd_work_handler(&ent->work);
|
cmd_work_handler(&ent->work);
|
||||||
} else if (!queue_work(cmd->wq, &ent->work)) {
|
} else if (!queue_work(cmd->wq, &ent->work)) {
|
||||||
mlx5_core_warn(dev, "failed to queue work\n");
|
mlx5_core_warn(dev, "failed to queue work\n");
|
||||||
err = -ENOMEM;
|
err = -EALREADY;
|
||||||
goto out_free;
|
goto out_free;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (callback)
|
if (callback)
|
||||||
goto out; /* mlx5_cmd_comp_handler() will put(ent) */
|
return 0; /* mlx5_cmd_comp_handler() will put(ent) */
|
||||||
|
|
||||||
err = wait_func(dev, ent);
|
err = wait_func(dev, ent);
|
||||||
if (err == -ETIMEDOUT || err == -ECANCELED)
|
if (err == -ETIMEDOUT || err == -ECANCELED)
|
||||||
@@ -1164,12 +1175,11 @@ static int mlx5_cmd_invoke(struct mlx5_core_dev *dev, struct mlx5_cmd_msg *in,
|
|||||||
mlx5_core_dbg_mask(dev, 1 << MLX5_CMD_TIME,
|
mlx5_core_dbg_mask(dev, 1 << MLX5_CMD_TIME,
|
||||||
"fw exec time for %s is %lld nsec\n",
|
"fw exec time for %s is %lld nsec\n",
|
||||||
mlx5_command_str(op), ds);
|
mlx5_command_str(op), ds);
|
||||||
*status = ent->status;
|
|
||||||
|
|
||||||
out_free:
|
out_free:
|
||||||
|
status = ent->status;
|
||||||
cmd_ent_put(ent);
|
cmd_ent_put(ent);
|
||||||
out:
|
return err ? : status;
|
||||||
return err;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t dbg_write(struct file *filp, const char __user *buf,
|
static ssize_t dbg_write(struct file *filp, const char __user *buf,
|
||||||
@@ -1719,7 +1729,7 @@ void mlx5_cmd_flush(struct mlx5_core_dev *dev)
|
|||||||
up(&cmd->sem);
|
up(&cmd->sem);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int status_to_err(u8 status)
|
static int deliv_status_to_err(u8 status)
|
||||||
{
|
{
|
||||||
switch (status) {
|
switch (status) {
|
||||||
case MLX5_CMD_DELIVERY_STAT_OK:
|
case MLX5_CMD_DELIVERY_STAT_OK:
|
||||||
@@ -1787,22 +1797,25 @@ static int is_manage_pages(void *in)
|
|||||||
return MLX5_GET(mbox_in, in, opcode) == MLX5_CMD_OP_MANAGE_PAGES;
|
return MLX5_GET(mbox_in, in, opcode) == MLX5_CMD_OP_MANAGE_PAGES;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Notes:
|
||||||
|
* 1. Callback functions may not sleep
|
||||||
|
* 2. Page queue commands do not support asynchrous completion
|
||||||
|
*/
|
||||||
static int cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out,
|
static int cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out,
|
||||||
int out_size, mlx5_cmd_cbk_t callback, void *context,
|
int out_size, mlx5_cmd_cbk_t callback, void *context,
|
||||||
bool force_polling)
|
bool force_polling)
|
||||||
{
|
{
|
||||||
struct mlx5_cmd_msg *inb;
|
u16 opcode = MLX5_GET(mbox_in, in, opcode);
|
||||||
struct mlx5_cmd_msg *outb;
|
struct mlx5_cmd_msg *inb, *outb;
|
||||||
int pages_queue;
|
int pages_queue;
|
||||||
gfp_t gfp;
|
gfp_t gfp;
|
||||||
int err;
|
|
||||||
u8 status = 0;
|
|
||||||
u32 drv_synd;
|
|
||||||
u16 opcode;
|
|
||||||
u8 token;
|
u8 token;
|
||||||
|
int err;
|
||||||
|
|
||||||
opcode = MLX5_GET(mbox_in, in, opcode);
|
|
||||||
if (mlx5_cmd_is_down(dev) || !opcode_allowed(&dev->cmd, opcode)) {
|
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);
|
err = mlx5_internal_err_ret_value(dev, opcode, &drv_synd, &status);
|
||||||
MLX5_SET(mbox_out, out, status, status);
|
MLX5_SET(mbox_out, out, status, status);
|
||||||
MLX5_SET(mbox_out, out, syndrome, drv_synd);
|
MLX5_SET(mbox_out, out, syndrome, drv_synd);
|
||||||
@@ -1833,26 +1846,22 @@ static int cmd_exec(struct mlx5_core_dev *dev, void *in, int in_size, void *out,
|
|||||||
}
|
}
|
||||||
|
|
||||||
err = mlx5_cmd_invoke(dev, inb, outb, out, out_size, callback, context,
|
err = mlx5_cmd_invoke(dev, inb, outb, out, out_size, callback, context,
|
||||||
pages_queue, &status, token, force_polling);
|
pages_queue, token, force_polling);
|
||||||
|
if (callback)
|
||||||
|
return err;
|
||||||
|
|
||||||
|
if (err > 0) /* Failed in FW, command didn't execute */
|
||||||
|
err = deliv_status_to_err(err);
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
goto out_out;
|
goto out_out;
|
||||||
|
|
||||||
mlx5_core_dbg(dev, "err %d, status %d\n", err, status);
|
/* command completed by FW */
|
||||||
if (status) {
|
err = mlx5_copy_from_msg(out, outb, out_size);
|
||||||
err = status_to_err(status);
|
|
||||||
goto out_out;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!callback)
|
|
||||||
err = mlx5_copy_from_msg(out, outb, out_size);
|
|
||||||
|
|
||||||
out_out:
|
out_out:
|
||||||
if (!callback)
|
mlx5_free_cmd_msg(dev, outb);
|
||||||
mlx5_free_cmd_msg(dev, outb);
|
|
||||||
|
|
||||||
out_in:
|
out_in:
|
||||||
if (!callback)
|
free_msg(dev, inb);
|
||||||
free_msg(dev, inb);
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user