Commit 732a0dee authored by David S. Miller's avatar David S. Miller

Merge branch 'mlxfw-Improve-error-reporting-and-FW-reactivate-support'

Saeed Mahameed says:

====================
mlxfw: Improve error reporting and FW reactivate support

This patchset improves mlxfw error reporting to netlink and to
kernel log.

V2:
 - Use proper err codes, EBUSY/EIO instead of EALREADY/EREMOTEIO
 - Fix typo.

From Eran and me.

1) patch #1, Make mlxfw/mlxsw fw flash devlink status notify generic,
   and enable it for mlx5.

2) patches #2..#5 are improving mlxfw flash error messages by
reporting detailed mlxfw FSM error messages to netlink and kernel log.

3) patches #6,7 From Eran: Add FW reactivate flow to  mlxfw and mlx5
====================
Reviewed-by: default avatarJakub Kicinski <kuba@kernel.org>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents b105e8e2 b7331aa2
...@@ -613,6 +613,44 @@ static void mlx5_fsm_release(struct mlxfw_dev *mlxfw_dev, u32 fwhandle) ...@@ -613,6 +613,44 @@ static void mlx5_fsm_release(struct mlxfw_dev *mlxfw_dev, u32 fwhandle)
fwhandle, 0); fwhandle, 0);
} }
#define MLX5_FSM_REACTIVATE_TOUT 5000 /* msecs */
static int mlx5_fsm_reactivate(struct mlxfw_dev *mlxfw_dev, u8 *status)
{
unsigned long exp_time = jiffies + msecs_to_jiffies(MLX5_FSM_REACTIVATE_TOUT);
struct mlx5_mlxfw_dev *mlx5_mlxfw_dev =
container_of(mlxfw_dev, struct mlx5_mlxfw_dev, mlxfw_dev);
struct mlx5_core_dev *dev = mlx5_mlxfw_dev->mlx5_core_dev;
u32 out[MLX5_ST_SZ_DW(mirc_reg)];
u32 in[MLX5_ST_SZ_DW(mirc_reg)];
int err;
if (!MLX5_CAP_MCAM_REG2(dev, mirc))
return -EOPNOTSUPP;
memset(in, 0, sizeof(in));
err = mlx5_core_access_reg(dev, in, sizeof(in), out,
sizeof(out), MLX5_REG_MIRC, 0, 1);
if (err)
return err;
do {
memset(out, 0, sizeof(out));
err = mlx5_core_access_reg(dev, in, sizeof(in), out,
sizeof(out), MLX5_REG_MIRC, 0, 0);
if (err)
return err;
*status = MLX5_GET(mirc_reg, out, status_code);
if (*status != MLXFW_FSM_REACTIVATE_STATUS_BUSY)
return 0;
msleep(20);
} while (time_before(jiffies, exp_time));
return 0;
}
static const struct mlxfw_dev_ops mlx5_mlxfw_dev_ops = { static const struct mlxfw_dev_ops mlx5_mlxfw_dev_ops = {
.component_query = mlx5_component_query, .component_query = mlx5_component_query,
.fsm_lock = mlx5_fsm_lock, .fsm_lock = mlx5_fsm_lock,
...@@ -620,6 +658,7 @@ static const struct mlxfw_dev_ops mlx5_mlxfw_dev_ops = { ...@@ -620,6 +658,7 @@ static const struct mlxfw_dev_ops mlx5_mlxfw_dev_ops = {
.fsm_block_download = mlx5_fsm_block_download, .fsm_block_download = mlx5_fsm_block_download,
.fsm_component_verify = mlx5_fsm_component_verify, .fsm_component_verify = mlx5_fsm_component_verify,
.fsm_activate = mlx5_fsm_activate, .fsm_activate = mlx5_fsm_activate,
.fsm_reactivate = mlx5_fsm_reactivate,
.fsm_query_state = mlx5_fsm_query_state, .fsm_query_state = mlx5_fsm_query_state,
.fsm_cancel = mlx5_fsm_cancel, .fsm_cancel = mlx5_fsm_cancel,
.fsm_release = mlx5_fsm_release .fsm_release = mlx5_fsm_release
...@@ -634,6 +673,7 @@ int mlx5_firmware_flash(struct mlx5_core_dev *dev, ...@@ -634,6 +673,7 @@ int mlx5_firmware_flash(struct mlx5_core_dev *dev,
.ops = &mlx5_mlxfw_dev_ops, .ops = &mlx5_mlxfw_dev_ops,
.psid = dev->board_id, .psid = dev->board_id,
.psid_size = strlen(dev->board_id), .psid_size = strlen(dev->board_id),
.devlink = priv_to_devlink(dev),
}, },
.mlx5_core_dev = dev .mlx5_core_dev = dev
}; };
......
...@@ -12,3 +12,4 @@ config MLXFW ...@@ -12,3 +12,4 @@ config MLXFW
To compile this driver as a module, choose M here: the To compile this driver as a module, choose M here: the
module will be called mlxfw. module will be called mlxfw.
select XZ_DEC select XZ_DEC
select NET_DEVLINK
...@@ -6,6 +6,30 @@ ...@@ -6,6 +6,30 @@
#include <linux/firmware.h> #include <linux/firmware.h>
#include <linux/netlink.h> #include <linux/netlink.h>
#include <linux/device.h>
#include <net/devlink.h>
struct mlxfw_dev {
const struct mlxfw_dev_ops *ops;
const char *psid;
u16 psid_size;
struct devlink *devlink;
};
static inline
struct device *mlxfw_dev_dev(struct mlxfw_dev *mlxfw_dev)
{
return mlxfw_dev->devlink->dev;
}
#define MLXFW_PRFX "mlxfw: "
#define mlxfw_info(mlxfw_dev, fmt, ...) \
dev_info(mlxfw_dev_dev(mlxfw_dev), MLXFW_PRFX fmt, ## __VA_ARGS__)
#define mlxfw_err(mlxfw_dev, fmt, ...) \
dev_err(mlxfw_dev_dev(mlxfw_dev), MLXFW_PRFX fmt, ## __VA_ARGS__)
#define mlxfw_dbg(mlxfw_dev, fmt, ...) \
dev_dbg(mlxfw_dev_dev(mlxfw_dev), MLXFW_PRFX fmt, ## __VA_ARGS__)
enum mlxfw_fsm_state { enum mlxfw_fsm_state {
MLXFW_FSM_STATE_IDLE, MLXFW_FSM_STATE_IDLE,
...@@ -31,7 +55,19 @@ enum mlxfw_fsm_state_err { ...@@ -31,7 +55,19 @@ enum mlxfw_fsm_state_err {
MLXFW_FSM_STATE_ERR_MAX, MLXFW_FSM_STATE_ERR_MAX,
}; };
struct mlxfw_dev; enum mlxfw_fsm_reactivate_status {
MLXFW_FSM_REACTIVATE_STATUS_OK,
MLXFW_FSM_REACTIVATE_STATUS_BUSY,
MLXFW_FSM_REACTIVATE_STATUS_PROHIBITED_FW_VER_ERR,
MLXFW_FSM_REACTIVATE_STATUS_FIRST_PAGE_COPY_FAILED,
MLXFW_FSM_REACTIVATE_STATUS_FIRST_PAGE_ERASE_FAILED,
MLXFW_FSM_REACTIVATE_STATUS_FIRST_PAGE_RESTORE_FAILED,
MLXFW_FSM_REACTIVATE_STATUS_CANDIDATE_FW_DEACTIVATION_FAILED,
MLXFW_FSM_REACTIVATE_STATUS_FW_ALREADY_ACTIVATED,
MLXFW_FSM_REACTIVATE_STATUS_ERR_DEVICE_RESET_REQUIRED,
MLXFW_FSM_REACTIVATE_STATUS_ERR_FW_PROGRAMMING_NEEDED,
MLXFW_FSM_REACTIVATE_STATUS_MAX,
};
struct mlxfw_dev_ops { struct mlxfw_dev_ops {
int (*component_query)(struct mlxfw_dev *mlxfw_dev, u16 component_index, int (*component_query)(struct mlxfw_dev *mlxfw_dev, u16 component_index,
...@@ -51,6 +87,8 @@ struct mlxfw_dev_ops { ...@@ -51,6 +87,8 @@ struct mlxfw_dev_ops {
int (*fsm_activate)(struct mlxfw_dev *mlxfw_dev, u32 fwhandle); int (*fsm_activate)(struct mlxfw_dev *mlxfw_dev, u32 fwhandle);
int (*fsm_reactivate)(struct mlxfw_dev *mlxfw_dev, u8 *status);
int (*fsm_query_state)(struct mlxfw_dev *mlxfw_dev, u32 fwhandle, int (*fsm_query_state)(struct mlxfw_dev *mlxfw_dev, u32 fwhandle,
enum mlxfw_fsm_state *fsm_state, enum mlxfw_fsm_state *fsm_state,
enum mlxfw_fsm_state_err *fsm_state_err); enum mlxfw_fsm_state_err *fsm_state_err);
...@@ -58,16 +96,6 @@ struct mlxfw_dev_ops { ...@@ -58,16 +96,6 @@ struct mlxfw_dev_ops {
void (*fsm_cancel)(struct mlxfw_dev *mlxfw_dev, u32 fwhandle); void (*fsm_cancel)(struct mlxfw_dev *mlxfw_dev, u32 fwhandle);
void (*fsm_release)(struct mlxfw_dev *mlxfw_dev, u32 fwhandle); void (*fsm_release)(struct mlxfw_dev *mlxfw_dev, u32 fwhandle);
void (*status_notify)(struct mlxfw_dev *mlxfw_dev,
const char *msg, const char *comp_name,
u32 done_bytes, u32 total_bytes);
};
struct mlxfw_dev {
const struct mlxfw_dev_ops *ops;
const char *psid;
u16 psid_size;
}; };
#if IS_REACHABLE(CONFIG_MLXFW) #if IS_REACHABLE(CONFIG_MLXFW)
......
...@@ -16,38 +16,70 @@ ...@@ -16,38 +16,70 @@
(MLXFW_FSM_STATE_WAIT_TIMEOUT_MS / MLXFW_FSM_STATE_WAIT_CYCLE_MS) (MLXFW_FSM_STATE_WAIT_TIMEOUT_MS / MLXFW_FSM_STATE_WAIT_CYCLE_MS)
#define MLXFW_FSM_MAX_COMPONENT_SIZE (10 * (1 << 20)) #define MLXFW_FSM_MAX_COMPONENT_SIZE (10 * (1 << 20))
static const char * const mlxfw_fsm_state_err_str[] = { static const int mlxfw_fsm_state_errno[] = {
[MLXFW_FSM_STATE_ERR_ERROR] = [MLXFW_FSM_STATE_ERR_ERROR] = -EIO,
"general error", [MLXFW_FSM_STATE_ERR_REJECTED_DIGEST_ERR] = -EBADMSG,
[MLXFW_FSM_STATE_ERR_REJECTED_DIGEST_ERR] = [MLXFW_FSM_STATE_ERR_REJECTED_NOT_APPLICABLE] = -ENOENT,
"component hash mismatch", [MLXFW_FSM_STATE_ERR_REJECTED_UNKNOWN_KEY] = -ENOKEY,
[MLXFW_FSM_STATE_ERR_REJECTED_NOT_APPLICABLE] = [MLXFW_FSM_STATE_ERR_REJECTED_AUTH_FAILED] = -EACCES,
"component not applicable", [MLXFW_FSM_STATE_ERR_REJECTED_UNSIGNED] = -EKEYREVOKED,
[MLXFW_FSM_STATE_ERR_REJECTED_UNKNOWN_KEY] = [MLXFW_FSM_STATE_ERR_REJECTED_KEY_NOT_APPLICABLE] = -EKEYREJECTED,
"unknown key", [MLXFW_FSM_STATE_ERR_REJECTED_BAD_FORMAT] = -ENOEXEC,
[MLXFW_FSM_STATE_ERR_REJECTED_AUTH_FAILED] = [MLXFW_FSM_STATE_ERR_BLOCKED_PENDING_RESET] = -EBUSY,
"authentication failed", [MLXFW_FSM_STATE_ERR_MAX] = -EINVAL
[MLXFW_FSM_STATE_ERR_REJECTED_UNSIGNED] =
"component was not signed",
[MLXFW_FSM_STATE_ERR_REJECTED_KEY_NOT_APPLICABLE] =
"key not applicable",
[MLXFW_FSM_STATE_ERR_REJECTED_BAD_FORMAT] =
"bad format",
[MLXFW_FSM_STATE_ERR_BLOCKED_PENDING_RESET] =
"pending reset",
[MLXFW_FSM_STATE_ERR_MAX] =
"unknown error"
}; };
static void mlxfw_status_notify(struct mlxfw_dev *mlxfw_dev, #define MLXFW_ERR_PRFX "Firmware flash failed: "
const char *msg, const char *comp_name, #define MLXFW_ERR_MSG(fwdev, extack, msg, err) do { \
u32 done_bytes, u32 total_bytes) mlxfw_err(fwdev, "%s, err (%d)\n", MLXFW_ERR_PRFX msg, err); \
NL_SET_ERR_MSG_MOD(extack, MLXFW_ERR_PRFX msg); \
} while (0)
static int mlxfw_fsm_state_err(struct mlxfw_dev *mlxfw_dev,
struct netlink_ext_ack *extack,
enum mlxfw_fsm_state_err err)
{ {
if (!mlxfw_dev->ops->status_notify) enum mlxfw_fsm_state_err fsm_state_err;
return;
mlxfw_dev->ops->status_notify(mlxfw_dev, msg, comp_name, fsm_state_err = min_t(enum mlxfw_fsm_state_err, err,
done_bytes, total_bytes); MLXFW_FSM_STATE_ERR_MAX);
}
switch (fsm_state_err) {
case MLXFW_FSM_STATE_ERR_ERROR:
MLXFW_ERR_MSG(mlxfw_dev, extack, "general error", err);
break;
case MLXFW_FSM_STATE_ERR_REJECTED_DIGEST_ERR:
MLXFW_ERR_MSG(mlxfw_dev, extack, "component hash mismatch", err);
break;
case MLXFW_FSM_STATE_ERR_REJECTED_NOT_APPLICABLE:
MLXFW_ERR_MSG(mlxfw_dev, extack, "component not applicable", err);
break;
case MLXFW_FSM_STATE_ERR_REJECTED_UNKNOWN_KEY:
MLXFW_ERR_MSG(mlxfw_dev, extack, "unknown key", err);
break;
case MLXFW_FSM_STATE_ERR_REJECTED_AUTH_FAILED:
MLXFW_ERR_MSG(mlxfw_dev, extack, "authentication failed", err);
break;
case MLXFW_FSM_STATE_ERR_REJECTED_UNSIGNED:
MLXFW_ERR_MSG(mlxfw_dev, extack, "component was not signed", err);
break;
case MLXFW_FSM_STATE_ERR_REJECTED_KEY_NOT_APPLICABLE:
MLXFW_ERR_MSG(mlxfw_dev, extack, "key not applicable", err);
break;
case MLXFW_FSM_STATE_ERR_REJECTED_BAD_FORMAT:
MLXFW_ERR_MSG(mlxfw_dev, extack, "bad format", err);
break;
case MLXFW_FSM_STATE_ERR_BLOCKED_PENDING_RESET:
MLXFW_ERR_MSG(mlxfw_dev, extack, "pending reset", err);
break;
case MLXFW_FSM_STATE_ERR_OK: /* fall through */
case MLXFW_FSM_STATE_ERR_MAX:
MLXFW_ERR_MSG(mlxfw_dev, extack, "unknown error", err);
break;
};
return mlxfw_fsm_state_errno[fsm_state_err];
};
static int mlxfw_fsm_state_wait(struct mlxfw_dev *mlxfw_dev, u32 fwhandle, static int mlxfw_fsm_state_wait(struct mlxfw_dev *mlxfw_dev, u32 fwhandle,
enum mlxfw_fsm_state fsm_state, enum mlxfw_fsm_state fsm_state,
...@@ -62,21 +94,18 @@ static int mlxfw_fsm_state_wait(struct mlxfw_dev *mlxfw_dev, u32 fwhandle, ...@@ -62,21 +94,18 @@ static int mlxfw_fsm_state_wait(struct mlxfw_dev *mlxfw_dev, u32 fwhandle,
retry: retry:
err = mlxfw_dev->ops->fsm_query_state(mlxfw_dev, fwhandle, err = mlxfw_dev->ops->fsm_query_state(mlxfw_dev, fwhandle,
&curr_fsm_state, &fsm_state_err); &curr_fsm_state, &fsm_state_err);
if (err) if (err) {
MLXFW_ERR_MSG(mlxfw_dev, extack, "FSM state query failed", err);
return err; return err;
if (fsm_state_err != MLXFW_FSM_STATE_ERR_OK) {
fsm_state_err = min_t(enum mlxfw_fsm_state_err,
fsm_state_err, MLXFW_FSM_STATE_ERR_MAX);
pr_err("Firmware flash failed: %s\n",
mlxfw_fsm_state_err_str[fsm_state_err]);
NL_SET_ERR_MSG_MOD(extack, "Firmware flash failed");
return -EINVAL;
} }
if (fsm_state_err != MLXFW_FSM_STATE_ERR_OK)
return mlxfw_fsm_state_err(mlxfw_dev, extack, fsm_state_err);
if (curr_fsm_state != fsm_state) { if (curr_fsm_state != fsm_state) {
if (--times == 0) { if (--times == 0) {
pr_err("Timeout reached on FSM state change"); MLXFW_ERR_MSG(mlxfw_dev, extack,
NL_SET_ERR_MSG_MOD(extack, "Timeout reached on FSM state change"); "Timeout reached on FSM state change", -ETIMEDOUT);
return -ETIMEDOUT; return -ETIMEDOUT;
} }
msleep(MLXFW_FSM_STATE_WAIT_CYCLE_MS); msleep(MLXFW_FSM_STATE_WAIT_CYCLE_MS);
...@@ -85,6 +114,92 @@ static int mlxfw_fsm_state_wait(struct mlxfw_dev *mlxfw_dev, u32 fwhandle, ...@@ -85,6 +114,92 @@ static int mlxfw_fsm_state_wait(struct mlxfw_dev *mlxfw_dev, u32 fwhandle,
return 0; return 0;
} }
static int
mlxfw_fsm_reactivate_err(struct mlxfw_dev *mlxfw_dev,
struct netlink_ext_ack *extack, u8 err)
{
enum mlxfw_fsm_reactivate_status status;
#define MXFW_REACT_PRFX "Reactivate FSM: "
#define MLXFW_REACT_ERR(msg, err) \
MLXFW_ERR_MSG(mlxfw_dev, extack, MXFW_REACT_PRFX msg, err)
status = min_t(enum mlxfw_fsm_reactivate_status, err,
MLXFW_FSM_REACTIVATE_STATUS_MAX);
switch (status) {
case MLXFW_FSM_REACTIVATE_STATUS_BUSY:
MLXFW_REACT_ERR("busy", err);
break;
case MLXFW_FSM_REACTIVATE_STATUS_PROHIBITED_FW_VER_ERR:
MLXFW_REACT_ERR("prohibited fw ver", err);
break;
case MLXFW_FSM_REACTIVATE_STATUS_FIRST_PAGE_COPY_FAILED:
MLXFW_REACT_ERR("first page copy failed", err);
break;
case MLXFW_FSM_REACTIVATE_STATUS_FIRST_PAGE_ERASE_FAILED:
MLXFW_REACT_ERR("first page erase failed", err);
break;
case MLXFW_FSM_REACTIVATE_STATUS_FIRST_PAGE_RESTORE_FAILED:
MLXFW_REACT_ERR("first page restore failed", err);
break;
case MLXFW_FSM_REACTIVATE_STATUS_CANDIDATE_FW_DEACTIVATION_FAILED:
MLXFW_REACT_ERR("candidate fw deactivation failed", err);
break;
case MLXFW_FSM_REACTIVATE_STATUS_ERR_DEVICE_RESET_REQUIRED:
MLXFW_REACT_ERR("device reset required", err);
break;
case MLXFW_FSM_REACTIVATE_STATUS_ERR_FW_PROGRAMMING_NEEDED:
MLXFW_REACT_ERR("fw progamming needed", err);
break;
case MLXFW_FSM_REACTIVATE_STATUS_FW_ALREADY_ACTIVATED:
MLXFW_REACT_ERR("fw already activated", err);
break;
case MLXFW_FSM_REACTIVATE_STATUS_OK: /* fall through */
case MLXFW_FSM_REACTIVATE_STATUS_MAX:
MLXFW_REACT_ERR("unexpected error", err);
break;
};
return -EREMOTEIO;
};
static int mlxfw_fsm_reactivate(struct mlxfw_dev *mlxfw_dev,
struct netlink_ext_ack *extack,
bool *supported)
{
u8 status;
int err;
if (!mlxfw_dev->ops->fsm_reactivate)
return 0;
err = mlxfw_dev->ops->fsm_reactivate(mlxfw_dev, &status);
if (err == -EOPNOTSUPP) {
*supported = false;
return 0;
}
if (err) {
MLXFW_ERR_MSG(mlxfw_dev, extack,
"Could not reactivate firmware flash", err);
return err;
}
if (status == MLXFW_FSM_REACTIVATE_STATUS_OK ||
status == MLXFW_FSM_REACTIVATE_STATUS_FW_ALREADY_ACTIVATED)
return 0;
return mlxfw_fsm_reactivate_err(mlxfw_dev, extack, status);
}
static void mlxfw_status_notify(struct mlxfw_dev *mlxfw_dev,
const char *msg, const char *comp_name,
u32 done_bytes, u32 total_bytes)
{
devlink_flash_update_status_notify(mlxfw_dev->devlink, msg, comp_name,
done_bytes, total_bytes);
}
#define MLXFW_ALIGN_DOWN(x, align_bits) ((x) & ~((1 << (align_bits)) - 1)) #define MLXFW_ALIGN_DOWN(x, align_bits) ((x) & ~((1 << (align_bits)) - 1))
#define MLXFW_ALIGN_UP(x, align_bits) \ #define MLXFW_ALIGN_UP(x, align_bits) \
MLXFW_ALIGN_DOWN((x) + ((1 << (align_bits)) - 1), (align_bits)) MLXFW_ALIGN_DOWN((x) + ((1 << (align_bits)) - 1), (align_bits))
...@@ -92,6 +207,7 @@ static int mlxfw_fsm_state_wait(struct mlxfw_dev *mlxfw_dev, u32 fwhandle, ...@@ -92,6 +207,7 @@ static int mlxfw_fsm_state_wait(struct mlxfw_dev *mlxfw_dev, u32 fwhandle,
static int mlxfw_flash_component(struct mlxfw_dev *mlxfw_dev, static int mlxfw_flash_component(struct mlxfw_dev *mlxfw_dev,
u32 fwhandle, u32 fwhandle,
struct mlxfw_mfa2_component *comp, struct mlxfw_mfa2_component *comp,
bool reactivate_supp,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
u16 comp_max_write_size; u16 comp_max_write_size;
...@@ -108,34 +224,43 @@ static int mlxfw_flash_component(struct mlxfw_dev *mlxfw_dev, ...@@ -108,34 +224,43 @@ static int mlxfw_flash_component(struct mlxfw_dev *mlxfw_dev,
err = mlxfw_dev->ops->component_query(mlxfw_dev, comp->index, err = mlxfw_dev->ops->component_query(mlxfw_dev, comp->index,
&comp_max_size, &comp_align_bits, &comp_max_size, &comp_align_bits,
&comp_max_write_size); &comp_max_write_size);
if (err) if (err) {
MLXFW_ERR_MSG(mlxfw_dev, extack, "FSM component query failed", err);
return err; return err;
}
comp_max_size = min_t(u32, comp_max_size, MLXFW_FSM_MAX_COMPONENT_SIZE); comp_max_size = min_t(u32, comp_max_size, MLXFW_FSM_MAX_COMPONENT_SIZE);
if (comp->data_size > comp_max_size) { if (comp->data_size > comp_max_size) {
pr_err("Component %d is of size %d which is bigger than limit %d\n", MLXFW_ERR_MSG(mlxfw_dev, extack,
comp->index, comp->data_size, comp_max_size); "Component size is bigger than limit", -EINVAL);
NL_SET_ERR_MSG_MOD(extack, "Component is bigger than limit");
return -EINVAL; return -EINVAL;
} }
comp_max_write_size = MLXFW_ALIGN_DOWN(comp_max_write_size, comp_max_write_size = MLXFW_ALIGN_DOWN(comp_max_write_size,
comp_align_bits); comp_align_bits);
pr_debug("Component update\n"); mlxfw_dbg(mlxfw_dev, "Component update\n");
mlxfw_status_notify(mlxfw_dev, "Updating component", comp_name, 0, 0); mlxfw_status_notify(mlxfw_dev, "Updating component", comp_name, 0, 0);
err = mlxfw_dev->ops->fsm_component_update(mlxfw_dev, fwhandle, err = mlxfw_dev->ops->fsm_component_update(mlxfw_dev, fwhandle,
comp->index, comp->index,
comp->data_size); comp->data_size);
if (err) if (err) {
if (!reactivate_supp)
MLXFW_ERR_MSG(mlxfw_dev, extack,
"FSM component update failed, FW reactivate is not supported",
err);
else
MLXFW_ERR_MSG(mlxfw_dev, extack,
"FSM component update failed", err);
return err; return err;
}
err = mlxfw_fsm_state_wait(mlxfw_dev, fwhandle, err = mlxfw_fsm_state_wait(mlxfw_dev, fwhandle,
MLXFW_FSM_STATE_DOWNLOAD, extack); MLXFW_FSM_STATE_DOWNLOAD, extack);
if (err) if (err)
goto err_out; goto err_out;
pr_debug("Component download\n"); mlxfw_dbg(mlxfw_dev, "Component download\n");
mlxfw_status_notify(mlxfw_dev, "Downloading component", mlxfw_status_notify(mlxfw_dev, "Downloading component",
comp_name, 0, comp->data_size); comp_name, 0, comp->data_size);
for (offset = 0; for (offset = 0;
...@@ -147,19 +272,25 @@ static int mlxfw_flash_component(struct mlxfw_dev *mlxfw_dev, ...@@ -147,19 +272,25 @@ static int mlxfw_flash_component(struct mlxfw_dev *mlxfw_dev,
err = mlxfw_dev->ops->fsm_block_download(mlxfw_dev, fwhandle, err = mlxfw_dev->ops->fsm_block_download(mlxfw_dev, fwhandle,
block_ptr, block_size, block_ptr, block_size,
offset); offset);
if (err) if (err) {
MLXFW_ERR_MSG(mlxfw_dev, extack,
"Component download failed", err);
goto err_out; goto err_out;
}
mlxfw_status_notify(mlxfw_dev, "Downloading component", mlxfw_status_notify(mlxfw_dev, "Downloading component",
comp_name, offset + block_size, comp_name, offset + block_size,
comp->data_size); comp->data_size);
} }
pr_debug("Component verify\n"); mlxfw_dbg(mlxfw_dev, "Component verify\n");
mlxfw_status_notify(mlxfw_dev, "Verifying component", comp_name, 0, 0); mlxfw_status_notify(mlxfw_dev, "Verifying component", comp_name, 0, 0);
err = mlxfw_dev->ops->fsm_component_verify(mlxfw_dev, fwhandle, err = mlxfw_dev->ops->fsm_component_verify(mlxfw_dev, fwhandle,
comp->index); comp->index);
if (err) if (err) {
MLXFW_ERR_MSG(mlxfw_dev, extack,
"FSM component verify failed", err);
goto err_out; goto err_out;
}
err = mlxfw_fsm_state_wait(mlxfw_dev, fwhandle, err = mlxfw_fsm_state_wait(mlxfw_dev, fwhandle,
MLXFW_FSM_STATE_LOCKED, extack); MLXFW_FSM_STATE_LOCKED, extack);
...@@ -174,6 +305,7 @@ static int mlxfw_flash_component(struct mlxfw_dev *mlxfw_dev, ...@@ -174,6 +305,7 @@ static int mlxfw_flash_component(struct mlxfw_dev *mlxfw_dev,
static int mlxfw_flash_components(struct mlxfw_dev *mlxfw_dev, u32 fwhandle, static int mlxfw_flash_components(struct mlxfw_dev *mlxfw_dev, u32 fwhandle,
struct mlxfw_mfa2_file *mfa2_file, struct mlxfw_mfa2_file *mfa2_file,
bool reactivate_supp,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
u32 component_count; u32 component_count;
...@@ -184,8 +316,8 @@ static int mlxfw_flash_components(struct mlxfw_dev *mlxfw_dev, u32 fwhandle, ...@@ -184,8 +316,8 @@ static int mlxfw_flash_components(struct mlxfw_dev *mlxfw_dev, u32 fwhandle,
mlxfw_dev->psid_size, mlxfw_dev->psid_size,
&component_count); &component_count);
if (err) { if (err) {
pr_err("Could not find device PSID in MFA2 file\n"); MLXFW_ERR_MSG(mlxfw_dev, extack,
NL_SET_ERR_MSG_MOD(extack, "Could not find device PSID in MFA2 file"); "Could not find device PSID in MFA2 file", err);
return err; return err;
} }
...@@ -194,11 +326,17 @@ static int mlxfw_flash_components(struct mlxfw_dev *mlxfw_dev, u32 fwhandle, ...@@ -194,11 +326,17 @@ static int mlxfw_flash_components(struct mlxfw_dev *mlxfw_dev, u32 fwhandle,
comp = mlxfw_mfa2_file_component_get(mfa2_file, mlxfw_dev->psid, comp = mlxfw_mfa2_file_component_get(mfa2_file, mlxfw_dev->psid,
mlxfw_dev->psid_size, i); mlxfw_dev->psid_size, i);
if (IS_ERR(comp)) if (IS_ERR(comp)) {
return PTR_ERR(comp); err = PTR_ERR(comp);
MLXFW_ERR_MSG(mlxfw_dev, extack,
"Failed to get MFA2 component", err);
return err;
}
pr_info("Flashing component type %d\n", comp->index); mlxfw_info(mlxfw_dev, "Flashing component type %d\n",
err = mlxfw_flash_component(mlxfw_dev, fwhandle, comp, extack); comp->index);
err = mlxfw_flash_component(mlxfw_dev, fwhandle, comp,
reactivate_supp, extack);
mlxfw_mfa2_file_component_put(comp); mlxfw_mfa2_file_component_put(comp);
if (err) if (err)
return err; return err;
...@@ -211,26 +349,32 @@ int mlxfw_firmware_flash(struct mlxfw_dev *mlxfw_dev, ...@@ -211,26 +349,32 @@ int mlxfw_firmware_flash(struct mlxfw_dev *mlxfw_dev,
struct netlink_ext_ack *extack) struct netlink_ext_ack *extack)
{ {
struct mlxfw_mfa2_file *mfa2_file; struct mlxfw_mfa2_file *mfa2_file;
bool reactivate_supp = true;
u32 fwhandle; u32 fwhandle;
int err; int err;
if (!mlxfw_mfa2_check(firmware)) { if (!mlxfw_mfa2_check(firmware)) {
pr_err("Firmware file is not MFA2\n"); MLXFW_ERR_MSG(mlxfw_dev, extack,
NL_SET_ERR_MSG_MOD(extack, "Firmware file is not MFA2"); "Firmware file is not MFA2", -EINVAL);
return -EINVAL; return -EINVAL;
} }
mfa2_file = mlxfw_mfa2_file_init(firmware); mfa2_file = mlxfw_mfa2_file_init(firmware);
if (IS_ERR(mfa2_file)) if (IS_ERR(mfa2_file)) {
return PTR_ERR(mfa2_file); err = PTR_ERR(mfa2_file);
MLXFW_ERR_MSG(mlxfw_dev, extack,
"Failed to initialize MFA2 firmware file", err);
return err;
}
pr_info("Initialize firmware flash process\n"); mlxfw_info(mlxfw_dev, "Initialize firmware flash process\n");
devlink_flash_update_begin_notify(mlxfw_dev->devlink);
mlxfw_status_notify(mlxfw_dev, "Initializing firmware flash process", mlxfw_status_notify(mlxfw_dev, "Initializing firmware flash process",
NULL, 0, 0); NULL, 0, 0);
err = mlxfw_dev->ops->fsm_lock(mlxfw_dev, &fwhandle); err = mlxfw_dev->ops->fsm_lock(mlxfw_dev, &fwhandle);
if (err) { if (err) {
pr_err("Could not lock the firmware FSM\n"); MLXFW_ERR_MSG(mlxfw_dev, extack,
NL_SET_ERR_MSG_MOD(extack, "Could not lock the firmware FSM"); "Could not lock the firmware FSM", err);
goto err_fsm_lock; goto err_fsm_lock;
} }
...@@ -239,16 +383,26 @@ int mlxfw_firmware_flash(struct mlxfw_dev *mlxfw_dev, ...@@ -239,16 +383,26 @@ int mlxfw_firmware_flash(struct mlxfw_dev *mlxfw_dev,
if (err) if (err)
goto err_state_wait_idle_to_locked; goto err_state_wait_idle_to_locked;
err = mlxfw_flash_components(mlxfw_dev, fwhandle, mfa2_file, extack); err = mlxfw_fsm_reactivate(mlxfw_dev, extack, &reactivate_supp);
if (err)
goto err_fsm_reactivate;
err = mlxfw_fsm_state_wait(mlxfw_dev, fwhandle,
MLXFW_FSM_STATE_LOCKED, extack);
if (err)
goto err_state_wait_reactivate_to_locked;
err = mlxfw_flash_components(mlxfw_dev, fwhandle, mfa2_file,
reactivate_supp, extack);
if (err) if (err)
goto err_flash_components; goto err_flash_components;
pr_debug("Activate image\n"); mlxfw_dbg(mlxfw_dev, "Activate image\n");
mlxfw_status_notify(mlxfw_dev, "Activating image", NULL, 0, 0); mlxfw_status_notify(mlxfw_dev, "Activating image", NULL, 0, 0);
err = mlxfw_dev->ops->fsm_activate(mlxfw_dev, fwhandle); err = mlxfw_dev->ops->fsm_activate(mlxfw_dev, fwhandle);
if (err) { if (err) {
pr_err("Could not activate the downloaded image\n"); MLXFW_ERR_MSG(mlxfw_dev, extack,
NL_SET_ERR_MSG_MOD(extack, "Could not activate the downloaded image"); "Could not activate the downloaded image", err);
goto err_fsm_activate; goto err_fsm_activate;
} }
...@@ -257,21 +411,25 @@ int mlxfw_firmware_flash(struct mlxfw_dev *mlxfw_dev, ...@@ -257,21 +411,25 @@ int mlxfw_firmware_flash(struct mlxfw_dev *mlxfw_dev,
if (err) if (err)
goto err_state_wait_activate_to_locked; goto err_state_wait_activate_to_locked;
pr_debug("Handle release\n"); mlxfw_dbg(mlxfw_dev, "Handle release\n");
mlxfw_dev->ops->fsm_release(mlxfw_dev, fwhandle); mlxfw_dev->ops->fsm_release(mlxfw_dev, fwhandle);
pr_info("Firmware flash done.\n"); mlxfw_info(mlxfw_dev, "Firmware flash done\n");
mlxfw_status_notify(mlxfw_dev, "Firmware flash done", NULL, 0, 0); mlxfw_status_notify(mlxfw_dev, "Firmware flash done", NULL, 0, 0);
mlxfw_mfa2_file_fini(mfa2_file); mlxfw_mfa2_file_fini(mfa2_file);
devlink_flash_update_end_notify(mlxfw_dev->devlink);
return 0; return 0;
err_state_wait_activate_to_locked: err_state_wait_activate_to_locked:
err_fsm_activate: err_fsm_activate:
err_flash_components: err_flash_components:
err_state_wait_reactivate_to_locked:
err_fsm_reactivate:
err_state_wait_idle_to_locked: err_state_wait_idle_to_locked:
mlxfw_dev->ops->fsm_release(mlxfw_dev, fwhandle); mlxfw_dev->ops->fsm_release(mlxfw_dev, fwhandle);
err_fsm_lock: err_fsm_lock:
mlxfw_mfa2_file_fini(mfa2_file); mlxfw_mfa2_file_fini(mfa2_file);
devlink_flash_update_end_notify(mlxfw_dev->devlink);
return err; return err;
} }
EXPORT_SYMBOL(mlxfw_firmware_flash); EXPORT_SYMBOL(mlxfw_firmware_flash);
......
...@@ -347,19 +347,6 @@ static void mlxsw_sp_fsm_release(struct mlxfw_dev *mlxfw_dev, u32 fwhandle) ...@@ -347,19 +347,6 @@ static void mlxsw_sp_fsm_release(struct mlxfw_dev *mlxfw_dev, u32 fwhandle)
mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mcc), mcc_pl); mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mcc), mcc_pl);
} }
static void mlxsw_sp_status_notify(struct mlxfw_dev *mlxfw_dev,
const char *msg, const char *comp_name,
u32 done_bytes, u32 total_bytes)
{
struct mlxsw_sp_mlxfw_dev *mlxsw_sp_mlxfw_dev =
container_of(mlxfw_dev, struct mlxsw_sp_mlxfw_dev, mlxfw_dev);
struct mlxsw_sp *mlxsw_sp = mlxsw_sp_mlxfw_dev->mlxsw_sp;
devlink_flash_update_status_notify(priv_to_devlink(mlxsw_sp->core),
msg, comp_name,
done_bytes, total_bytes);
}
static const struct mlxfw_dev_ops mlxsw_sp_mlxfw_dev_ops = { static const struct mlxfw_dev_ops mlxsw_sp_mlxfw_dev_ops = {
.component_query = mlxsw_sp_component_query, .component_query = mlxsw_sp_component_query,
.fsm_lock = mlxsw_sp_fsm_lock, .fsm_lock = mlxsw_sp_fsm_lock,
...@@ -370,7 +357,6 @@ static const struct mlxfw_dev_ops mlxsw_sp_mlxfw_dev_ops = { ...@@ -370,7 +357,6 @@ static const struct mlxfw_dev_ops mlxsw_sp_mlxfw_dev_ops = {
.fsm_query_state = mlxsw_sp_fsm_query_state, .fsm_query_state = mlxsw_sp_fsm_query_state,
.fsm_cancel = mlxsw_sp_fsm_cancel, .fsm_cancel = mlxsw_sp_fsm_cancel,
.fsm_release = mlxsw_sp_fsm_release, .fsm_release = mlxsw_sp_fsm_release,
.status_notify = mlxsw_sp_status_notify,
}; };
static int mlxsw_sp_firmware_flash(struct mlxsw_sp *mlxsw_sp, static int mlxsw_sp_firmware_flash(struct mlxsw_sp *mlxsw_sp,
...@@ -382,16 +368,15 @@ static int mlxsw_sp_firmware_flash(struct mlxsw_sp *mlxsw_sp, ...@@ -382,16 +368,15 @@ static int mlxsw_sp_firmware_flash(struct mlxsw_sp *mlxsw_sp,
.ops = &mlxsw_sp_mlxfw_dev_ops, .ops = &mlxsw_sp_mlxfw_dev_ops,
.psid = mlxsw_sp->bus_info->psid, .psid = mlxsw_sp->bus_info->psid,
.psid_size = strlen(mlxsw_sp->bus_info->psid), .psid_size = strlen(mlxsw_sp->bus_info->psid),
.devlink = priv_to_devlink(mlxsw_sp->core),
}, },
.mlxsw_sp = mlxsw_sp .mlxsw_sp = mlxsw_sp
}; };
int err; int err;
mlxsw_core_fw_flash_start(mlxsw_sp->core); mlxsw_core_fw_flash_start(mlxsw_sp->core);
devlink_flash_update_begin_notify(priv_to_devlink(mlxsw_sp->core));
err = mlxfw_firmware_flash(&mlxsw_sp_mlxfw_dev.mlxfw_dev, err = mlxfw_firmware_flash(&mlxsw_sp_mlxfw_dev.mlxfw_dev,
firmware, extack); firmware, extack);
devlink_flash_update_end_notify(priv_to_devlink(mlxsw_sp->core));
mlxsw_core_fw_flash_end(mlxsw_sp->core); mlxsw_core_fw_flash_end(mlxsw_sp->core);
return err; return err;
......
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