aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMoshe Shemesh2020-10-07 09:00:56 +0300
committerJakub Kicinski2020-10-09 12:06:53 -0700
commitbef878e865ea8a4e08d5b5d4ef56df681ff1d6b3 (patch)
tree092d39229ee727f25bcfc52621cd10cfde7db0ce
parent2d69356752ff862dbb0c7e6725874740799d7708 (diff)
net/mlx5: Add support for devlink reload limit no reset
Add support for devlink reload action fw_activate with reload limit no_reset which does firmware live patching, updating the firmware image without reset, no downtime and no configuration lose. The driver checks if the firmware is capable of handling the pending firmware changes as a live patch. If it is then it triggers firmware live patching flow. Signed-off-by: Moshe Shemesh <moshe@mellanox.com> Reviewed-by: Saeed Mahameed <saeedm@nvidia.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/devlink.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c
index cbfb84d1cac2..a28f95df2901 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c
@@ -111,6 +111,25 @@ out:
return err;
}
+static int mlx5_devlink_trigger_fw_live_patch(struct devlink *devlink,
+ struct netlink_ext_ack *extack)
+{
+ struct mlx5_core_dev *dev = devlink_priv(devlink);
+ u8 reset_level;
+ int err;
+
+ err = mlx5_fw_reset_query(dev, &reset_level, NULL);
+ if (err)
+ return err;
+ if (!(reset_level & MLX5_MFRL_REG_RESET_LEVEL0)) {
+ NL_SET_ERR_MSG_MOD(extack,
+ "FW upgrade to the stored FW can't be done by FW live patching");
+ return -EINVAL;
+ }
+
+ return mlx5_fw_reset_set_live_patch(dev);
+}
+
static int mlx5_devlink_reload_down(struct devlink *devlink, bool netns_change,
enum devlink_reload_action action,
enum devlink_reload_limit limit,
@@ -123,6 +142,8 @@ static int mlx5_devlink_reload_down(struct devlink *devlink, bool netns_change,
mlx5_unload_one(dev, false);
return 0;
case DEVLINK_RELOAD_ACTION_FW_ACTIVATE:
+ if (limit == DEVLINK_RELOAD_LIMIT_NO_RESET)
+ return mlx5_devlink_trigger_fw_live_patch(devlink, extack);
return mlx5_devlink_reload_fw_activate(devlink, extack);
default:
/* Unsupported action should not get to this function */
@@ -140,7 +161,10 @@ static int mlx5_devlink_reload_up(struct devlink *devlink, enum devlink_reload_a
*actions_performed = BIT(action);
switch (action) {
case DEVLINK_RELOAD_ACTION_DRIVER_REINIT:
+ return mlx5_load_one(dev, false);
case DEVLINK_RELOAD_ACTION_FW_ACTIVATE:
+ if (limit == DEVLINK_RELOAD_LIMIT_NO_RESET)
+ break;
/* On fw_activate action, also driver is reloaded and reinit performed */
*actions_performed |= BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT);
return mlx5_load_one(dev, false);
@@ -168,6 +192,7 @@ static const struct devlink_ops mlx5_devlink_ops = {
.info_get = mlx5_devlink_info_get,
.reload_actions = BIT(DEVLINK_RELOAD_ACTION_DRIVER_REINIT) |
BIT(DEVLINK_RELOAD_ACTION_FW_ACTIVATE),
+ .reload_limits = BIT(DEVLINK_RELOAD_LIMIT_NO_RESET),
.reload_down = mlx5_devlink_reload_down,
.reload_up = mlx5_devlink_reload_up,
};