Skip to content

Commit 9c86b07

Browse files
ShayAgrosSaeed Mahameed
authored andcommitted
net/mlx5: Added fw version query command
Using the MCQI and MCQS registers, we query the running and pending fw version of the HCA. The MCQS is queried with sequentially increasing component index, until a component of type BOOT_IMG is found. Querying this component's version using the MCQI register yields the running and pending fw version of the HCA. Querying MCQI for the pending fw version should be done only after validating that such fw version exists. This is done my checking 'component update state' field in MCQS output. Signed-off-by: Shay Agroskin <[email protected]> Reviewed-by: Jakub Kicinski <[email protected]> Signed-off-by: Saeed Mahameed <[email protected]>
1 parent e08a976 commit 9c86b07

File tree

2 files changed

+201
-20
lines changed

2 files changed

+201
-20
lines changed

drivers/net/ethernet/mellanox/mlx5/core/fw.c

Lines changed: 199 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,37 @@
3737
#include "mlx5_core.h"
3838
#include "../../mlxfw/mlxfw.h"
3939

40+
enum {
41+
MCQS_IDENTIFIER_BOOT_IMG = 0x1,
42+
MCQS_IDENTIFIER_OEM_NVCONFIG = 0x4,
43+
MCQS_IDENTIFIER_MLNX_NVCONFIG = 0x5,
44+
MCQS_IDENTIFIER_CS_TOKEN = 0x6,
45+
MCQS_IDENTIFIER_DBG_TOKEN = 0x7,
46+
MCQS_IDENTIFIER_GEARBOX = 0xA,
47+
};
48+
49+
enum {
50+
MCQS_UPDATE_STATE_IDLE,
51+
MCQS_UPDATE_STATE_IN_PROGRESS,
52+
MCQS_UPDATE_STATE_APPLIED,
53+
MCQS_UPDATE_STATE_ACTIVE,
54+
MCQS_UPDATE_STATE_ACTIVE_PENDING_RESET,
55+
MCQS_UPDATE_STATE_FAILED,
56+
MCQS_UPDATE_STATE_CANCELED,
57+
MCQS_UPDATE_STATE_BUSY,
58+
};
59+
60+
enum {
61+
MCQI_INFO_TYPE_CAPABILITIES = 0x0,
62+
MCQI_INFO_TYPE_VERSION = 0x1,
63+
MCQI_INFO_TYPE_ACTIVATION_METHOD = 0x5,
64+
};
65+
66+
enum {
67+
MCQI_FW_RUNNING_VERSION = 0,
68+
MCQI_FW_STORED_VERSION = 1,
69+
};
70+
4071
static int mlx5_cmd_query_adapter(struct mlx5_core_dev *dev, u32 *out,
4172
int outlen)
4273
{
@@ -398,33 +429,49 @@ static int mlx5_reg_mcda_set(struct mlx5_core_dev *dev,
398429
}
399430

400431
static int mlx5_reg_mcqi_query(struct mlx5_core_dev *dev,
401-
u16 component_index,
402-
u32 *max_component_size,
403-
u8 *log_mcda_word_size,
404-
u16 *mcda_max_write_size)
432+
u16 component_index, bool read_pending,
433+
u8 info_type, u16 data_size, void *mcqi_data)
405434
{
406-
u32 out[MLX5_ST_SZ_DW(mcqi_reg) + MLX5_ST_SZ_DW(mcqi_cap)];
407-
int offset = MLX5_ST_SZ_DW(mcqi_reg);
408-
u32 in[MLX5_ST_SZ_DW(mcqi_reg)];
435+
u32 out[MLX5_ST_SZ_DW(mcqi_reg) + MLX5_UN_SZ_DW(mcqi_reg_data)] = {};
436+
u32 in[MLX5_ST_SZ_DW(mcqi_reg)] = {};
437+
void *data;
409438
int err;
410439

411-
memset(in, 0, sizeof(in));
412-
memset(out, 0, sizeof(out));
413-
414440
MLX5_SET(mcqi_reg, in, component_index, component_index);
415-
MLX5_SET(mcqi_reg, in, data_size, MLX5_ST_SZ_BYTES(mcqi_cap));
441+
MLX5_SET(mcqi_reg, in, read_pending_component, read_pending);
442+
MLX5_SET(mcqi_reg, in, info_type, info_type);
443+
MLX5_SET(mcqi_reg, in, data_size, data_size);
416444

417445
err = mlx5_core_access_reg(dev, in, sizeof(in), out,
418-
sizeof(out), MLX5_REG_MCQI, 0, 0);
446+
MLX5_ST_SZ_BYTES(mcqi_reg) + data_size,
447+
MLX5_REG_MCQI, 0, 0);
419448
if (err)
420-
goto out;
449+
return err;
421450

422-
*max_component_size = MLX5_GET(mcqi_cap, out + offset, max_component_size);
423-
*log_mcda_word_size = MLX5_GET(mcqi_cap, out + offset, log_mcda_word_size);
424-
*mcda_max_write_size = MLX5_GET(mcqi_cap, out + offset, mcda_max_write_size);
451+
data = MLX5_ADDR_OF(mcqi_reg, out, data);
452+
memcpy(mcqi_data, data, data_size);
425453

426-
out:
427-
return err;
454+
return 0;
455+
}
456+
457+
static int mlx5_reg_mcqi_caps_query(struct mlx5_core_dev *dev, u16 component_index,
458+
u32 *max_component_size, u8 *log_mcda_word_size,
459+
u16 *mcda_max_write_size)
460+
{
461+
u32 mcqi_reg[MLX5_ST_SZ_DW(mcqi_cap)] = {};
462+
int err;
463+
464+
err = mlx5_reg_mcqi_query(dev, component_index, 0,
465+
MCQI_INFO_TYPE_CAPABILITIES,
466+
MLX5_ST_SZ_BYTES(mcqi_cap), mcqi_reg);
467+
if (err)
468+
return err;
469+
470+
*max_component_size = MLX5_GET(mcqi_cap, mcqi_reg, max_component_size);
471+
*log_mcda_word_size = MLX5_GET(mcqi_cap, mcqi_reg, log_mcda_word_size);
472+
*mcda_max_write_size = MLX5_GET(mcqi_cap, mcqi_reg, mcda_max_write_size);
473+
474+
return 0;
428475
}
429476

430477
struct mlx5_mlxfw_dev {
@@ -440,8 +487,13 @@ static int mlx5_component_query(struct mlxfw_dev *mlxfw_dev,
440487
container_of(mlxfw_dev, struct mlx5_mlxfw_dev, mlxfw_dev);
441488
struct mlx5_core_dev *dev = mlx5_mlxfw_dev->mlx5_core_dev;
442489

443-
return mlx5_reg_mcqi_query(dev, component_index, p_max_size,
444-
p_align_bits, p_max_write_size);
490+
if (!MLX5_CAP_GEN(dev, mcam_reg) || !MLX5_CAP_MCAM_REG(dev, mcqi)) {
491+
mlx5_core_warn(dev, "caps query isn't supported by running FW\n");
492+
return -EOPNOTSUPP;
493+
}
494+
495+
return mlx5_reg_mcqi_caps_query(dev, component_index, p_max_size,
496+
p_align_bits, p_max_write_size);
445497
}
446498

447499
static int mlx5_fsm_lock(struct mlxfw_dev *mlxfw_dev, u32 *fwhandle)
@@ -581,3 +633,130 @@ int mlx5_firmware_flash(struct mlx5_core_dev *dev,
581633
return mlxfw_firmware_flash(&mlx5_mlxfw_dev.mlxfw_dev,
582634
firmware, extack);
583635
}
636+
637+
static int mlx5_reg_mcqi_version_query(struct mlx5_core_dev *dev,
638+
u16 component_index, bool read_pending,
639+
u32 *mcqi_version_out)
640+
{
641+
return mlx5_reg_mcqi_query(dev, component_index, read_pending,
642+
MCQI_INFO_TYPE_VERSION,
643+
MLX5_ST_SZ_BYTES(mcqi_version),
644+
mcqi_version_out);
645+
}
646+
647+
static int mlx5_reg_mcqs_query(struct mlx5_core_dev *dev, u32 *out,
648+
u16 component_index)
649+
{
650+
u8 out_sz = MLX5_ST_SZ_BYTES(mcqs_reg);
651+
u32 in[MLX5_ST_SZ_DW(mcqs_reg)] = {};
652+
int err;
653+
654+
memset(out, 0, out_sz);
655+
656+
MLX5_SET(mcqs_reg, in, component_index, component_index);
657+
658+
err = mlx5_core_access_reg(dev, in, sizeof(in), out,
659+
out_sz, MLX5_REG_MCQS, 0, 0);
660+
return err;
661+
}
662+
663+
/* scans component index sequentially, to find the boot img index */
664+
static int mlx5_get_boot_img_component_index(struct mlx5_core_dev *dev)
665+
{
666+
u32 out[MLX5_ST_SZ_DW(mcqs_reg)] = {};
667+
u16 identifier, component_idx = 0;
668+
bool quit;
669+
int err;
670+
671+
do {
672+
err = mlx5_reg_mcqs_query(dev, out, component_idx);
673+
if (err)
674+
return err;
675+
676+
identifier = MLX5_GET(mcqs_reg, out, identifier);
677+
quit = !!MLX5_GET(mcqs_reg, out, last_index_flag);
678+
quit |= identifier == MCQS_IDENTIFIER_BOOT_IMG;
679+
} while (!quit && ++component_idx);
680+
681+
if (identifier != MCQS_IDENTIFIER_BOOT_IMG) {
682+
mlx5_core_warn(dev, "mcqs: can't find boot_img component ix, last scanned idx %d\n",
683+
component_idx);
684+
return -EOPNOTSUPP;
685+
}
686+
687+
return component_idx;
688+
}
689+
690+
static int
691+
mlx5_fw_image_pending(struct mlx5_core_dev *dev,
692+
int component_index,
693+
bool *pending_version_exists)
694+
{
695+
u32 out[MLX5_ST_SZ_DW(mcqs_reg)];
696+
u8 component_update_state;
697+
int err;
698+
699+
err = mlx5_reg_mcqs_query(dev, out, component_index);
700+
if (err)
701+
return err;
702+
703+
component_update_state = MLX5_GET(mcqs_reg, out, component_update_state);
704+
705+
if (component_update_state == MCQS_UPDATE_STATE_IDLE) {
706+
*pending_version_exists = false;
707+
} else if (component_update_state == MCQS_UPDATE_STATE_ACTIVE_PENDING_RESET) {
708+
*pending_version_exists = true;
709+
} else {
710+
mlx5_core_warn(dev,
711+
"mcqs: can't read pending fw version while fw state is %d\n",
712+
component_update_state);
713+
return -ENODATA;
714+
}
715+
return 0;
716+
}
717+
718+
int mlx5_fw_version_query(struct mlx5_core_dev *dev,
719+
u32 *running_ver, u32 *pending_ver)
720+
{
721+
u32 reg_mcqi_version[MLX5_ST_SZ_DW(mcqi_version)] = {};
722+
bool pending_version_exists;
723+
int component_index;
724+
int err;
725+
726+
if (!MLX5_CAP_GEN(dev, mcam_reg) || !MLX5_CAP_MCAM_REG(dev, mcqi) ||
727+
!MLX5_CAP_MCAM_REG(dev, mcqs)) {
728+
mlx5_core_warn(dev, "fw query isn't supported by the FW\n");
729+
return -EOPNOTSUPP;
730+
}
731+
732+
component_index = mlx5_get_boot_img_component_index(dev);
733+
if (component_index < 0)
734+
return component_index;
735+
736+
err = mlx5_reg_mcqi_version_query(dev, component_index,
737+
MCQI_FW_RUNNING_VERSION,
738+
reg_mcqi_version);
739+
if (err)
740+
return err;
741+
742+
*running_ver = MLX5_GET(mcqi_version, reg_mcqi_version, version);
743+
744+
err = mlx5_fw_image_pending(dev, component_index, &pending_version_exists);
745+
if (err)
746+
return err;
747+
748+
if (!pending_version_exists) {
749+
*pending_ver = 0;
750+
return 0;
751+
}
752+
753+
err = mlx5_reg_mcqi_version_query(dev, component_index,
754+
MCQI_FW_STORED_VERSION,
755+
reg_mcqi_version);
756+
if (err)
757+
return err;
758+
759+
*pending_ver = MLX5_GET(mcqi_version, reg_mcqi_version, version);
760+
761+
return 0;
762+
}

drivers/net/ethernet/mellanox/mlx5/core/mlx5_core.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,8 @@ int mlx5_set_mtppse(struct mlx5_core_dev *mdev, u8 pin, u8 arm, u8 mode);
205205

206206
int mlx5_firmware_flash(struct mlx5_core_dev *dev, const struct firmware *fw,
207207
struct netlink_ext_ack *extack);
208+
int mlx5_fw_version_query(struct mlx5_core_dev *dev,
209+
u32 *running_ver, u32 *stored_ver);
208210

209211
void mlx5e_init(void);
210212
void mlx5e_cleanup(void);

0 commit comments

Comments
 (0)