Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Moshe Shemesh <moshe@mellanox.com>
Reviewed-by: Saeed Mahameed <saeedm@nvidia.com>
Signed-off-by: Jakub Kicinski <kuba@kernel.org>

authored by

Moshe Shemesh and committed by
Jakub Kicinski
2d693567 b4f7cbb3

+78
+52
drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.c
··· 1066 1066 kvfree(tracer); 1067 1067 } 1068 1068 1069 + static int mlx5_fw_tracer_recreate_strings_db(struct mlx5_fw_tracer *tracer) 1070 + { 1071 + struct mlx5_core_dev *dev; 1072 + int err; 1073 + 1074 + cancel_work_sync(&tracer->read_fw_strings_work); 1075 + mlx5_fw_tracer_clean_ready_list(tracer); 1076 + mlx5_fw_tracer_clean_print_hash(tracer); 1077 + mlx5_fw_tracer_clean_saved_traces_array(tracer); 1078 + mlx5_fw_tracer_free_strings_db(tracer); 1079 + 1080 + dev = tracer->dev; 1081 + err = mlx5_query_mtrc_caps(tracer); 1082 + if (err) { 1083 + mlx5_core_dbg(dev, "FWTracer: Failed to query capabilities %d\n", err); 1084 + return err; 1085 + } 1086 + 1087 + err = mlx5_fw_tracer_allocate_strings_db(tracer); 1088 + if (err) { 1089 + mlx5_core_warn(dev, "FWTracer: Allocate strings DB failed %d\n", err); 1090 + return err; 1091 + } 1092 + mlx5_fw_tracer_init_saved_traces_array(tracer); 1093 + 1094 + return 0; 1095 + } 1096 + 1097 + int mlx5_fw_tracer_reload(struct mlx5_fw_tracer *tracer) 1098 + { 1099 + struct mlx5_core_dev *dev; 1100 + int err; 1101 + 1102 + if (IS_ERR_OR_NULL(tracer)) 1103 + return -EINVAL; 1104 + 1105 + dev = tracer->dev; 1106 + mlx5_fw_tracer_cleanup(tracer); 1107 + err = mlx5_fw_tracer_recreate_strings_db(tracer); 1108 + if (err) { 1109 + mlx5_core_warn(dev, "Failed to recreate FW tracer strings DB\n"); 1110 + return err; 1111 + } 1112 + err = mlx5_fw_tracer_init(tracer); 1113 + if (err) { 1114 + mlx5_core_warn(dev, "Failed to re-initialize FW tracer\n"); 1115 + return err; 1116 + } 1117 + 1118 + return 0; 1119 + } 1120 + 1069 1121 static int fw_tracer_event(struct notifier_block *nb, unsigned long action, void *data) 1070 1122 { 1071 1123 struct mlx5_fw_tracer *tracer = mlx5_nb_cof(nb, struct mlx5_fw_tracer, nb);
+1
drivers/net/ethernet/mellanox/mlx5/core/diag/fw_tracer.h
··· 191 191 int mlx5_fw_tracer_trigger_core_dump_general(struct mlx5_core_dev *dev); 192 192 int mlx5_fw_tracer_get_saved_traces_objects(struct mlx5_fw_tracer *tracer, 193 193 struct devlink_fmsg *fmsg); 194 + int mlx5_fw_tracer_reload(struct mlx5_fw_tracer *tracer); 194 195 195 196 #endif
+24
drivers/net/ethernet/mellanox/mlx5/core/fw_reset.c
··· 2 2 /* Copyright (c) 2020, Mellanox Technologies inc. All rights reserved. */ 3 3 4 4 #include "fw_reset.h" 5 + #include "diag/fw_tracer.h" 5 6 6 7 enum { 7 8 MLX5_FW_RESET_FLAGS_RESET_REQUESTED, ··· 14 13 struct mlx5_core_dev *dev; 15 14 struct mlx5_nb nb; 16 15 struct workqueue_struct *wq; 16 + struct work_struct fw_live_patch_work; 17 17 struct work_struct reset_request_work; 18 18 struct work_struct reset_reload_work; 19 19 struct work_struct reset_now_work; ··· 194 192 mlx5_start_sync_reset_poll(dev); 195 193 } 196 194 195 + static void mlx5_fw_live_patch_event(struct work_struct *work) 196 + { 197 + struct mlx5_fw_reset *fw_reset = container_of(work, struct mlx5_fw_reset, 198 + fw_live_patch_work); 199 + struct mlx5_core_dev *dev = fw_reset->dev; 200 + struct mlx5_fw_tracer *tracer; 201 + 202 + mlx5_core_info(dev, "Live patch updated firmware version: %d.%d.%d\n", fw_rev_maj(dev), 203 + fw_rev_min(dev), fw_rev_sub(dev)); 204 + 205 + tracer = dev->tracer; 206 + if (IS_ERR_OR_NULL(tracer)) 207 + return; 208 + 209 + if (mlx5_fw_tracer_reload(tracer)) 210 + mlx5_core_err(dev, "Failed to reload FW tracer\n"); 211 + } 212 + 197 213 static void mlx5_sync_reset_request_event(struct work_struct *work) 198 214 { 199 215 struct mlx5_fw_reset *fw_reset = container_of(work, struct mlx5_fw_reset, ··· 384 364 struct mlx5_eqe *eqe = data; 385 365 386 366 switch (eqe->sub_type) { 367 + case MLX5_GENERAL_SUBTYPE_FW_LIVE_PATCH_EVENT: 368 + queue_work(fw_reset->wq, &fw_reset->fw_live_patch_work); 369 + break; 387 370 case MLX5_GENERAL_SUBTYPE_PCI_SYNC_FOR_FW_UPDATE_EVENT: 388 371 mlx5_sync_reset_events_handle(fw_reset, eqe); 389 372 break; ··· 444 421 fw_reset->dev = dev; 445 422 dev->priv.fw_reset = fw_reset; 446 423 424 + INIT_WORK(&fw_reset->fw_live_patch_work, mlx5_fw_live_patch_event); 447 425 INIT_WORK(&fw_reset->reset_request_work, mlx5_sync_reset_request_event); 448 426 INIT_WORK(&fw_reset->reset_reload_work, mlx5_sync_reset_reload_work); 449 427 INIT_WORK(&fw_reset->reset_now_work, mlx5_sync_reset_now_event);
+1
include/linux/mlx5/device.h
··· 366 366 enum { 367 367 MLX5_GENERAL_SUBTYPE_DELAY_DROP_TIMEOUT = 0x1, 368 368 MLX5_GENERAL_SUBTYPE_PCI_POWER_CHANGE_EVENT = 0x5, 369 + MLX5_GENERAL_SUBTYPE_FW_LIVE_PATCH_EVENT = 0x7, 369 370 MLX5_GENERAL_SUBTYPE_PCI_SYNC_FOR_FW_UPDATE_EVENT = 0x8, 370 371 }; 371 372