Commit b18af883 authored by David S. Miller's avatar David S. Miller

Merge branch 'mlxsw-Introduce-fw_fatal-health-reporter-and-test-cmd-to

-trigger-test-event'

Ido Schimmel says:

====================
mlxsw: Introduce fw_fatal health reporter and test cmd to trigger test event

Jiri says:

This patch set introduces a health reporter for mlxsw that reports FW
fatal events. Alongside that, it introduces a test command that is used
to trigger a dummy FW fatal event by user:

$ sudo devlink health test pci/0000:03:00.0 reporter fw_fatal

$ devlink health
pci/0000:03:00.0:
  reporter fw_fatal
    state error error 1 recover 0 last_dump_date 2020-07-27 last_dump_time 16:33:27 auto_dump true

$ sudo devlink health dump show pci/0000:03:00.0 reporter fw_fatal -j -p
{
    "irisc_id": 0,
    "event": [
        "id": 3 ],
    "method": "query",
    "long_process": false,
    "command_type": "mad",
    "reg_attr_id": 0
}

As a dependency, the FW validation and flashing is moved to core.c.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents ef8e692d 7d83ee11
This diff is collapsed.
...@@ -280,6 +280,8 @@ struct mlxsw_driver { ...@@ -280,6 +280,8 @@ struct mlxsw_driver {
struct list_head list; struct list_head list;
const char *kind; const char *kind;
size_t priv_size; size_t priv_size;
const struct mlxsw_fw_rev *fw_req_rev;
const char *fw_filename;
int (*init)(struct mlxsw_core *mlxsw_core, int (*init)(struct mlxsw_core *mlxsw_core,
const struct mlxsw_bus_info *mlxsw_bus_info, const struct mlxsw_bus_info *mlxsw_bus_info,
struct netlink_ext_ack *extack); struct netlink_ext_ack *extack);
...@@ -324,9 +326,6 @@ struct mlxsw_driver { ...@@ -324,9 +326,6 @@ struct mlxsw_driver {
unsigned int sb_index, u16 tc_index, unsigned int sb_index, u16 tc_index,
enum devlink_sb_pool_type pool_type, enum devlink_sb_pool_type pool_type,
u32 *p_cur, u32 *p_max); u32 *p_cur, u32 *p_max);
int (*flash_update)(struct mlxsw_core *mlxsw_core,
const char *file_name, const char *component,
struct netlink_ext_ack *extack);
int (*trap_init)(struct mlxsw_core *mlxsw_core, int (*trap_init)(struct mlxsw_core *mlxsw_core,
const struct devlink_trap *trap, void *trap_ctx); const struct devlink_trap *trap, void *trap_ctx);
void (*trap_fini)(struct mlxsw_core *mlxsw_core, void (*trap_fini)(struct mlxsw_core *mlxsw_core,
...@@ -371,6 +370,7 @@ struct mlxsw_driver { ...@@ -371,6 +370,7 @@ struct mlxsw_driver {
u8 txhdr_len; u8 txhdr_len;
const struct mlxsw_config_profile *profile; const struct mlxsw_config_profile *profile;
bool res_query_enabled; bool res_query_enabled;
bool fw_fatal_enabled;
}; };
int mlxsw_core_kvd_sizes_get(struct mlxsw_core *mlxsw_core, int mlxsw_core_kvd_sizes_get(struct mlxsw_core *mlxsw_core,
...@@ -378,9 +378,6 @@ int mlxsw_core_kvd_sizes_get(struct mlxsw_core *mlxsw_core, ...@@ -378,9 +378,6 @@ int mlxsw_core_kvd_sizes_get(struct mlxsw_core *mlxsw_core,
u64 *p_single_size, u64 *p_double_size, u64 *p_single_size, u64 *p_double_size,
u64 *p_linear_size); u64 *p_linear_size);
void mlxsw_core_fw_flash_start(struct mlxsw_core *mlxsw_core);
void mlxsw_core_fw_flash_end(struct mlxsw_core *mlxsw_core);
u32 mlxsw_core_read_frc_h(struct mlxsw_core *mlxsw_core); u32 mlxsw_core_read_frc_h(struct mlxsw_core *mlxsw_core);
u32 mlxsw_core_read_frc_l(struct mlxsw_core *mlxsw_core); u32 mlxsw_core_read_frc_l(struct mlxsw_core *mlxsw_core);
......
...@@ -5579,6 +5579,7 @@ MLXSW_ITEM32(reg, htgt, type, 0x00, 8, 4); ...@@ -5579,6 +5579,7 @@ MLXSW_ITEM32(reg, htgt, type, 0x00, 8, 4);
enum mlxsw_reg_htgt_trap_group { enum mlxsw_reg_htgt_trap_group {
MLXSW_REG_HTGT_TRAP_GROUP_EMAD, MLXSW_REG_HTGT_TRAP_GROUP_EMAD,
MLXSW_REG_HTGT_TRAP_GROUP_MFDE,
MLXSW_REG_HTGT_TRAP_GROUP_SP_STP, MLXSW_REG_HTGT_TRAP_GROUP_SP_STP,
MLXSW_REG_HTGT_TRAP_GROUP_SP_LACP, MLXSW_REG_HTGT_TRAP_GROUP_SP_LACP,
MLXSW_REG_HTGT_TRAP_GROUP_SP_LLDP, MLXSW_REG_HTGT_TRAP_GROUP_SP_LLDP,
...@@ -9821,6 +9822,26 @@ static inline void mlxsw_reg_mtptptp_pack(char *payload, ...@@ -9821,6 +9822,26 @@ static inline void mlxsw_reg_mtptptp_pack(char *payload,
mlxsw_reg_mtptpt_message_type_set(payload, message_type); mlxsw_reg_mtptpt_message_type_set(payload, message_type);
} }
/* MFGD - Monitoring FW General Debug Register
* -------------------------------------------
*/
#define MLXSW_REG_MFGD_ID 0x90F0
#define MLXSW_REG_MFGD_LEN 0x0C
MLXSW_REG_DEFINE(mfgd, MLXSW_REG_MFGD_ID, MLXSW_REG_MFGD_LEN);
/* reg_mfgd_fw_fatal_event_mode
* 0 - don't check FW fatal (default)
* 1 - check FW fatal - enable MFDE trap
* Access: RW
*/
MLXSW_ITEM32(reg, mfgd, fatal_event_mode, 0x00, 9, 2);
/* reg_mfgd_trigger_test
* Access: WO
*/
MLXSW_ITEM32(reg, mfgd, trigger_test, 0x00, 11, 1);
/* MGPIR - Management General Peripheral Information Register /* MGPIR - Management General Peripheral Information Register
* ---------------------------------------------------------- * ----------------------------------------------------------
* MGPIR register allows software to query the hardware and * MGPIR register allows software to query the hardware and
...@@ -9880,6 +9901,84 @@ mlxsw_reg_mgpir_unpack(char *payload, u8 *num_of_devices, ...@@ -9880,6 +9901,84 @@ mlxsw_reg_mgpir_unpack(char *payload, u8 *num_of_devices,
*num_of_modules = mlxsw_reg_mgpir_num_of_modules_get(payload); *num_of_modules = mlxsw_reg_mgpir_num_of_modules_get(payload);
} }
/* MFDE - Monitoring FW Debug Register
* -----------------------------------
*/
#define MLXSW_REG_MFDE_ID 0x9200
#define MLXSW_REG_MFDE_LEN 0x18
MLXSW_REG_DEFINE(mfde, MLXSW_REG_MFDE_ID, MLXSW_REG_MFDE_LEN);
/* reg_mfde_irisc_id
* Which irisc triggered the event
* Access: RO
*/
MLXSW_ITEM32(reg, mfde, irisc_id, 0x00, 8, 4);
enum mlxsw_reg_mfde_event_id {
MLXSW_REG_MFDE_EVENT_ID_CRSPACE_TO = 1,
/* KVD insertion machine stopped */
MLXSW_REG_MFDE_EVENT_ID_KVD_IM_STOP,
};
/* reg_mfde_event_id
* Access: RO
*/
MLXSW_ITEM32(reg, mfde, event_id, 0x00, 0, 8);
enum mlxsw_reg_mfde_method {
MLXSW_REG_MFDE_METHOD_QUERY,
MLXSW_REG_MFDE_METHOD_WRITE,
};
/* reg_mfde_method
* Access: RO
*/
MLXSW_ITEM32(reg, mfde, method, 0x04, 29, 1);
/* reg_mfde_long_process
* Indicates if the command is in long_process mode.
* Access: RO
*/
MLXSW_ITEM32(reg, mfde, long_process, 0x04, 28, 1);
enum mlxsw_reg_mfde_command_type {
MLXSW_REG_MFDE_COMMAND_TYPE_MAD,
MLXSW_REG_MFDE_COMMAND_TYPE_EMAD,
MLXSW_REG_MFDE_COMMAND_TYPE_CMDIF,
};
/* reg_mfde_command_type
* Access: RO
*/
MLXSW_ITEM32(reg, mfde, command_type, 0x04, 24, 2);
/* reg_mfde_reg_attr_id
* EMAD - register id, MAD - attibute id
* Access: RO
*/
MLXSW_ITEM32(reg, mfde, reg_attr_id, 0x04, 0, 16);
/* reg_mfde_log_address
* crspace address accessed, which resulted in timeout.
* Valid in case event_id == MLXSW_REG_MFDE_EVENT_ID_CRSPACE_TO
* Access: RO
*/
MLXSW_ITEM32(reg, mfde, log_address, 0x10, 0, 32);
/* reg_mfde_log_id
* Which irisc triggered the timeout.
* Valid in case event_id == MLXSW_REG_MFDE_EVENT_ID_CRSPACE_TO
* Access: RO
*/
MLXSW_ITEM32(reg, mfde, log_id, 0x14, 0, 4);
/* reg_mfde_pipes_mask
* Bit per kvh pipe.
* Access: RO
*/
MLXSW_ITEM32(reg, mfde, pipes_mask, 0x10, 0, 16);
/* TNGCR - Tunneling NVE General Configuration Register /* TNGCR - Tunneling NVE General Configuration Register
* ---------------------------------------------------- * ----------------------------------------------------
* The TNGCR register is used for setting up the NVE Tunneling configuration. * The TNGCR register is used for setting up the NVE Tunneling configuration.
...@@ -10993,7 +11092,9 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { ...@@ -10993,7 +11092,9 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = {
MLXSW_REG(mtpppc), MLXSW_REG(mtpppc),
MLXSW_REG(mtpptr), MLXSW_REG(mtpptr),
MLXSW_REG(mtptpt), MLXSW_REG(mtptpt),
MLXSW_REG(mfgd),
MLXSW_REG(mgpir), MLXSW_REG(mgpir),
MLXSW_REG(mfde),
MLXSW_REG(tngcr), MLXSW_REG(tngcr),
MLXSW_REG(tnumt), MLXSW_REG(tnumt),
MLXSW_REG(tnqcr), MLXSW_REG(tnqcr),
......
...@@ -162,8 +162,6 @@ struct mlxsw_sp { ...@@ -162,8 +162,6 @@ struct mlxsw_sp {
struct mlxsw_sp_counter_pool *counter_pool; struct mlxsw_sp_counter_pool *counter_pool;
struct mlxsw_sp_span *span; struct mlxsw_sp_span *span;
struct mlxsw_sp_trap *trap; struct mlxsw_sp_trap *trap;
const struct mlxsw_fw_rev *req_rev;
const char *fw_filename;
const struct mlxsw_sp_kvdl_ops *kvdl_ops; const struct mlxsw_sp_kvdl_ops *kvdl_ops;
const struct mlxsw_afa_ops *afa_ops; const struct mlxsw_afa_ops *afa_ops;
const struct mlxsw_afk_ops *afk_ops; const struct mlxsw_afk_ops *afk_ops;
......
...@@ -120,6 +120,8 @@ enum { ...@@ -120,6 +120,8 @@ enum {
}; };
enum mlxsw_event_trap_id { enum mlxsw_event_trap_id {
/* Fatal Event generated by FW */
MLXSW_TRAP_ID_MFDE = 0x3,
/* Port Up/Down event generated by hardware */ /* Port Up/Down event generated by hardware */
MLXSW_TRAP_ID_PUDE = 0x8, MLXSW_TRAP_ID_PUDE = 0x8,
/* PTP Ingress FIFO has a new entry */ /* PTP Ingress FIFO has a new entry */
......
...@@ -566,6 +566,7 @@ enum devlink_health_reporter_state { ...@@ -566,6 +566,7 @@ enum devlink_health_reporter_state {
* @dump: callback to dump an object * @dump: callback to dump an object
* if priv_ctx is NULL, run a full dump * if priv_ctx is NULL, run a full dump
* @diagnose: callback to diagnose the current status * @diagnose: callback to diagnose the current status
* @test: callback to trigger a test event
*/ */
struct devlink_health_reporter_ops { struct devlink_health_reporter_ops {
...@@ -578,6 +579,8 @@ struct devlink_health_reporter_ops { ...@@ -578,6 +579,8 @@ struct devlink_health_reporter_ops {
int (*diagnose)(struct devlink_health_reporter *reporter, int (*diagnose)(struct devlink_health_reporter *reporter,
struct devlink_fmsg *fmsg, struct devlink_fmsg *fmsg,
struct netlink_ext_ack *extack); struct netlink_ext_ack *extack);
int (*test)(struct devlink_health_reporter *reporter,
struct netlink_ext_ack *extack);
}; };
/** /**
......
...@@ -122,6 +122,8 @@ enum devlink_command { ...@@ -122,6 +122,8 @@ enum devlink_command {
DEVLINK_CMD_TRAP_POLICER_NEW, DEVLINK_CMD_TRAP_POLICER_NEW,
DEVLINK_CMD_TRAP_POLICER_DEL, DEVLINK_CMD_TRAP_POLICER_DEL,
DEVLINK_CMD_HEALTH_REPORTER_TEST,
/* add new commands above here */ /* add new commands above here */
__DEVLINK_CMD_MAX, __DEVLINK_CMD_MAX,
DEVLINK_CMD_MAX = __DEVLINK_CMD_MAX - 1 DEVLINK_CMD_MAX = __DEVLINK_CMD_MAX - 1
......
...@@ -6096,6 +6096,28 @@ devlink_nl_cmd_health_reporter_dump_clear_doit(struct sk_buff *skb, ...@@ -6096,6 +6096,28 @@ devlink_nl_cmd_health_reporter_dump_clear_doit(struct sk_buff *skb,
return 0; return 0;
} }
static int devlink_nl_cmd_health_reporter_test_doit(struct sk_buff *skb,
struct genl_info *info)
{
struct devlink *devlink = info->user_ptr[0];
struct devlink_health_reporter *reporter;
int err;
reporter = devlink_health_reporter_get_from_info(devlink, info);
if (!reporter)
return -EINVAL;
if (!reporter->ops->test) {
devlink_health_reporter_put(reporter);
return -EOPNOTSUPP;
}
err = reporter->ops->test(reporter, info->extack);
devlink_health_reporter_put(reporter);
return err;
}
struct devlink_stats { struct devlink_stats {
u64 rx_bytes; u64 rx_bytes;
u64 rx_packets; u64 rx_packets;
...@@ -7316,6 +7338,14 @@ static const struct genl_ops devlink_nl_ops[] = { ...@@ -7316,6 +7338,14 @@ static const struct genl_ops devlink_nl_ops[] = {
.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT | .internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT |
DEVLINK_NL_FLAG_NO_LOCK, DEVLINK_NL_FLAG_NO_LOCK,
}, },
{
.cmd = DEVLINK_CMD_HEALTH_REPORTER_TEST,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
.doit = devlink_nl_cmd_health_reporter_test_doit,
.flags = GENL_ADMIN_PERM,
.internal_flags = DEVLINK_NL_FLAG_NEED_DEVLINK_OR_PORT |
DEVLINK_NL_FLAG_NO_LOCK,
},
{ {
.cmd = DEVLINK_CMD_FLASH_UPDATE, .cmd = DEVLINK_CMD_FLASH_UPDATE,
.validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP, .validate = GENL_DONT_VALIDATE_STRICT | GENL_DONT_VALIDATE_DUMP,
......
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