Commit 2d693567 authored by Moshe Shemesh's avatar Moshe Shemesh Committed by Jakub Kicinski

net/mlx5: Add support for fw live patch event

Firmware live patch event notifies the driver that the firmware was just
updated using live patch. In such case the driver should not reload or
re-initiate entities, part to updating the firmware version and
re-initiate the firmware tracer which can be updated by live patch with
new strings database to help debugging an issue.
Signed-off-by: default avatarMoshe Shemesh <moshe@mellanox.com>
Reviewed-by: default avatarSaeed Mahameed <saeedm@nvidia.com>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent b4f7cbb3
...@@ -1066,6 +1066,58 @@ void mlx5_fw_tracer_destroy(struct mlx5_fw_tracer *tracer) ...@@ -1066,6 +1066,58 @@ void mlx5_fw_tracer_destroy(struct mlx5_fw_tracer *tracer)
kvfree(tracer); kvfree(tracer);
} }
static int mlx5_fw_tracer_recreate_strings_db(struct mlx5_fw_tracer *tracer)
{
struct mlx5_core_dev *dev;
int err;
cancel_work_sync(&tracer->read_fw_strings_work);
mlx5_fw_tracer_clean_ready_list(tracer);
mlx5_fw_tracer_clean_print_hash(tracer);
mlx5_fw_tracer_clean_saved_traces_array(tracer);
mlx5_fw_tracer_free_strings_db(tracer);
dev = tracer->dev;
err = mlx5_query_mtrc_caps(tracer);
if (err) {
mlx5_core_dbg(dev, "FWTracer: Failed to query capabilities %d\n", err);
return err;
}
err = mlx5_fw_tracer_allocate_strings_db(tracer);
if (err) {
mlx5_core_warn(dev, "FWTracer: Allocate strings DB failed %d\n", err);
return err;
}
mlx5_fw_tracer_init_saved_traces_array(tracer);
return 0;
}
int mlx5_fw_tracer_reload(struct mlx5_fw_tracer *tracer)
{
struct mlx5_core_dev *dev;
int err;
if (IS_ERR_OR_NULL(tracer))
return -EINVAL;
dev = tracer->dev;
mlx5_fw_tracer_cleanup(tracer);
err = mlx5_fw_tracer_recreate_strings_db(tracer);
if (err) {
mlx5_core_warn(dev, "Failed to recreate FW tracer strings DB\n");
return err;
}
err = mlx5_fw_tracer_init(tracer);
if (err) {
mlx5_core_warn(dev, "Failed to re-initialize FW tracer\n");
return err;
}
return 0;
}
static int fw_tracer_event(struct notifier_block *nb, unsigned long action, void *data) static int fw_tracer_event(struct notifier_block *nb, unsigned long action, void *data)
{ {
struct mlx5_fw_tracer *tracer = mlx5_nb_cof(nb, struct mlx5_fw_tracer, nb); struct mlx5_fw_tracer *tracer = mlx5_nb_cof(nb, struct mlx5_fw_tracer, nb);
......
...@@ -191,5 +191,6 @@ void mlx5_fw_tracer_destroy(struct mlx5_fw_tracer *tracer); ...@@ -191,5 +191,6 @@ void mlx5_fw_tracer_destroy(struct mlx5_fw_tracer *tracer);
int mlx5_fw_tracer_trigger_core_dump_general(struct mlx5_core_dev *dev); int mlx5_fw_tracer_trigger_core_dump_general(struct mlx5_core_dev *dev);
int mlx5_fw_tracer_get_saved_traces_objects(struct mlx5_fw_tracer *tracer, int mlx5_fw_tracer_get_saved_traces_objects(struct mlx5_fw_tracer *tracer,
struct devlink_fmsg *fmsg); struct devlink_fmsg *fmsg);
int mlx5_fw_tracer_reload(struct mlx5_fw_tracer *tracer);
#endif #endif
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
/* Copyright (c) 2020, Mellanox Technologies inc. All rights reserved. */ /* Copyright (c) 2020, Mellanox Technologies inc. All rights reserved. */
#include "fw_reset.h" #include "fw_reset.h"
#include "diag/fw_tracer.h"
enum { enum {
MLX5_FW_RESET_FLAGS_RESET_REQUESTED, MLX5_FW_RESET_FLAGS_RESET_REQUESTED,
...@@ -13,6 +14,7 @@ struct mlx5_fw_reset { ...@@ -13,6 +14,7 @@ struct mlx5_fw_reset {
struct mlx5_core_dev *dev; struct mlx5_core_dev *dev;
struct mlx5_nb nb; struct mlx5_nb nb;
struct workqueue_struct *wq; struct workqueue_struct *wq;
struct work_struct fw_live_patch_work;
struct work_struct reset_request_work; struct work_struct reset_request_work;
struct work_struct reset_reload_work; struct work_struct reset_reload_work;
struct work_struct reset_now_work; struct work_struct reset_now_work;
...@@ -192,6 +194,24 @@ static void mlx5_sync_reset_set_reset_requested(struct mlx5_core_dev *dev) ...@@ -192,6 +194,24 @@ static void mlx5_sync_reset_set_reset_requested(struct mlx5_core_dev *dev)
mlx5_start_sync_reset_poll(dev); mlx5_start_sync_reset_poll(dev);
} }
static void mlx5_fw_live_patch_event(struct work_struct *work)
{
struct mlx5_fw_reset *fw_reset = container_of(work, struct mlx5_fw_reset,
fw_live_patch_work);
struct mlx5_core_dev *dev = fw_reset->dev;
struct mlx5_fw_tracer *tracer;
mlx5_core_info(dev, "Live patch updated firmware version: %d.%d.%d\n", fw_rev_maj(dev),
fw_rev_min(dev), fw_rev_sub(dev));
tracer = dev->tracer;
if (IS_ERR_OR_NULL(tracer))
return;
if (mlx5_fw_tracer_reload(tracer))
mlx5_core_err(dev, "Failed to reload FW tracer\n");
}
static void mlx5_sync_reset_request_event(struct work_struct *work) static void mlx5_sync_reset_request_event(struct work_struct *work)
{ {
struct mlx5_fw_reset *fw_reset = container_of(work, struct mlx5_fw_reset, struct mlx5_fw_reset *fw_reset = container_of(work, struct mlx5_fw_reset,
...@@ -364,6 +384,9 @@ static int fw_reset_event_notifier(struct notifier_block *nb, unsigned long acti ...@@ -364,6 +384,9 @@ static int fw_reset_event_notifier(struct notifier_block *nb, unsigned long acti
struct mlx5_eqe *eqe = data; struct mlx5_eqe *eqe = data;
switch (eqe->sub_type) { switch (eqe->sub_type) {
case MLX5_GENERAL_SUBTYPE_FW_LIVE_PATCH_EVENT:
queue_work(fw_reset->wq, &fw_reset->fw_live_patch_work);
break;
case MLX5_GENERAL_SUBTYPE_PCI_SYNC_FOR_FW_UPDATE_EVENT: case MLX5_GENERAL_SUBTYPE_PCI_SYNC_FOR_FW_UPDATE_EVENT:
mlx5_sync_reset_events_handle(fw_reset, eqe); mlx5_sync_reset_events_handle(fw_reset, eqe);
break; break;
...@@ -421,6 +444,7 @@ int mlx5_fw_reset_init(struct mlx5_core_dev *dev) ...@@ -421,6 +444,7 @@ int mlx5_fw_reset_init(struct mlx5_core_dev *dev)
fw_reset->dev = dev; fw_reset->dev = dev;
dev->priv.fw_reset = fw_reset; dev->priv.fw_reset = fw_reset;
INIT_WORK(&fw_reset->fw_live_patch_work, mlx5_fw_live_patch_event);
INIT_WORK(&fw_reset->reset_request_work, mlx5_sync_reset_request_event); INIT_WORK(&fw_reset->reset_request_work, mlx5_sync_reset_request_event);
INIT_WORK(&fw_reset->reset_reload_work, mlx5_sync_reset_reload_work); INIT_WORK(&fw_reset->reset_reload_work, mlx5_sync_reset_reload_work);
INIT_WORK(&fw_reset->reset_now_work, mlx5_sync_reset_now_event); INIT_WORK(&fw_reset->reset_now_work, mlx5_sync_reset_now_event);
......
...@@ -366,6 +366,7 @@ enum { ...@@ -366,6 +366,7 @@ enum {
enum { enum {
MLX5_GENERAL_SUBTYPE_DELAY_DROP_TIMEOUT = 0x1, MLX5_GENERAL_SUBTYPE_DELAY_DROP_TIMEOUT = 0x1,
MLX5_GENERAL_SUBTYPE_PCI_POWER_CHANGE_EVENT = 0x5, MLX5_GENERAL_SUBTYPE_PCI_POWER_CHANGE_EVENT = 0x5,
MLX5_GENERAL_SUBTYPE_FW_LIVE_PATCH_EVENT = 0x7,
MLX5_GENERAL_SUBTYPE_PCI_SYNC_FOR_FW_UPDATE_EVENT = 0x8, MLX5_GENERAL_SUBTYPE_PCI_SYNC_FOR_FW_UPDATE_EVENT = 0x8,
}; };
......
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