Commit 2a360bf0 authored by Jiri Pirko's avatar Jiri Pirko Committed by David S. Miller

mlxsw: cmd: Handle error after reset gracefully

There is an exception in command interface processing in case the MRSR
register is written to. The register triggers FW reset and during the
reset FW returns an error. So handle this by ignoring this error while
writing to MRSR register.
Signed-off-by: default avatarJiri Pirko <jiri@mellanox.com>
Signed-off-by: default avatarIdo Schimmel <idosch@mellanox.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 12b003b2
...@@ -58,7 +58,7 @@ static inline void mlxsw_cmd_mbox_zero(char *mbox) ...@@ -58,7 +58,7 @@ static inline void mlxsw_cmd_mbox_zero(char *mbox)
struct mlxsw_core; struct mlxsw_core;
int mlxsw_cmd_exec(struct mlxsw_core *mlxsw_core, u16 opcode, u8 opcode_mod, int mlxsw_cmd_exec(struct mlxsw_core *mlxsw_core, u16 opcode, u8 opcode_mod,
u32 in_mod, bool out_mbox_direct, u32 in_mod, bool out_mbox_direct, bool reset_ok,
char *in_mbox, size_t in_mbox_size, char *in_mbox, size_t in_mbox_size,
char *out_mbox, size_t out_mbox_size); char *out_mbox, size_t out_mbox_size);
...@@ -67,7 +67,7 @@ static inline int mlxsw_cmd_exec_in(struct mlxsw_core *mlxsw_core, u16 opcode, ...@@ -67,7 +67,7 @@ static inline int mlxsw_cmd_exec_in(struct mlxsw_core *mlxsw_core, u16 opcode,
size_t in_mbox_size) size_t in_mbox_size)
{ {
return mlxsw_cmd_exec(mlxsw_core, opcode, opcode_mod, in_mod, false, return mlxsw_cmd_exec(mlxsw_core, opcode, opcode_mod, in_mod, false,
in_mbox, in_mbox_size, NULL, 0); false, in_mbox, in_mbox_size, NULL, 0);
} }
static inline int mlxsw_cmd_exec_out(struct mlxsw_core *mlxsw_core, u16 opcode, static inline int mlxsw_cmd_exec_out(struct mlxsw_core *mlxsw_core, u16 opcode,
...@@ -76,7 +76,7 @@ static inline int mlxsw_cmd_exec_out(struct mlxsw_core *mlxsw_core, u16 opcode, ...@@ -76,7 +76,7 @@ static inline int mlxsw_cmd_exec_out(struct mlxsw_core *mlxsw_core, u16 opcode,
char *out_mbox, size_t out_mbox_size) char *out_mbox, size_t out_mbox_size)
{ {
return mlxsw_cmd_exec(mlxsw_core, opcode, opcode_mod, in_mod, return mlxsw_cmd_exec(mlxsw_core, opcode, opcode_mod, in_mod,
out_mbox_direct, NULL, 0, out_mbox_direct, false, NULL, 0,
out_mbox, out_mbox_size); out_mbox, out_mbox_size);
} }
...@@ -84,7 +84,7 @@ static inline int mlxsw_cmd_exec_none(struct mlxsw_core *mlxsw_core, u16 opcode, ...@@ -84,7 +84,7 @@ static inline int mlxsw_cmd_exec_none(struct mlxsw_core *mlxsw_core, u16 opcode,
u8 opcode_mod, u32 in_mod) u8 opcode_mod, u32 in_mod)
{ {
return mlxsw_cmd_exec(mlxsw_core, opcode, opcode_mod, in_mod, false, return mlxsw_cmd_exec(mlxsw_core, opcode, opcode_mod, in_mod, false,
NULL, 0, NULL, 0); false, NULL, 0, NULL, 0);
} }
enum mlxsw_cmd_opcode { enum mlxsw_cmd_opcode {
...@@ -179,6 +179,8 @@ enum mlxsw_cmd_status { ...@@ -179,6 +179,8 @@ enum mlxsw_cmd_status {
MLXSW_CMD_STATUS_BAD_INDEX = 0x0A, MLXSW_CMD_STATUS_BAD_INDEX = 0x0A,
/* NVMEM checksum/CRC failed. */ /* NVMEM checksum/CRC failed. */
MLXSW_CMD_STATUS_BAD_NVMEM = 0x0B, MLXSW_CMD_STATUS_BAD_NVMEM = 0x0B,
/* Device is currently running reset */
MLXSW_CMD_STATUS_RUNNING_RESET = 0x26,
/* Bad management packet (silently discarded). */ /* Bad management packet (silently discarded). */
MLXSW_CMD_STATUS_BAD_PKT = 0x30, MLXSW_CMD_STATUS_BAD_PKT = 0x30,
}; };
...@@ -208,6 +210,8 @@ static inline const char *mlxsw_cmd_status_str(u8 status) ...@@ -208,6 +210,8 @@ static inline const char *mlxsw_cmd_status_str(u8 status)
return "BAD_INDEX"; return "BAD_INDEX";
case MLXSW_CMD_STATUS_BAD_NVMEM: case MLXSW_CMD_STATUS_BAD_NVMEM:
return "BAD_NVMEM"; return "BAD_NVMEM";
case MLXSW_CMD_STATUS_RUNNING_RESET:
return "RUNNING_RESET";
case MLXSW_CMD_STATUS_BAD_PKT: case MLXSW_CMD_STATUS_BAD_PKT:
return "BAD_PKT"; return "BAD_PKT";
default: default:
...@@ -869,10 +873,12 @@ MLXSW_ITEM32(cmd_mbox, config_profile, cqe_version, 0xB0, 0, 8); ...@@ -869,10 +873,12 @@ MLXSW_ITEM32(cmd_mbox, config_profile, cqe_version, 0xB0, 0, 8);
*/ */
static inline int mlxsw_cmd_access_reg(struct mlxsw_core *mlxsw_core, static inline int mlxsw_cmd_access_reg(struct mlxsw_core *mlxsw_core,
bool reset_ok,
char *in_mbox, char *out_mbox) char *in_mbox, char *out_mbox)
{ {
return mlxsw_cmd_exec(mlxsw_core, MLXSW_CMD_OPCODE_ACCESS_REG, return mlxsw_cmd_exec(mlxsw_core, MLXSW_CMD_OPCODE_ACCESS_REG,
0, 0, false, in_mbox, MLXSW_CMD_MBOX_SIZE, 0, 0, false, reset_ok,
in_mbox, MLXSW_CMD_MBOX_SIZE,
out_mbox, MLXSW_CMD_MBOX_SIZE); out_mbox, MLXSW_CMD_MBOX_SIZE);
} }
......
...@@ -1480,6 +1480,7 @@ static int mlxsw_core_reg_access_cmd(struct mlxsw_core *mlxsw_core, ...@@ -1480,6 +1480,7 @@ static int mlxsw_core_reg_access_cmd(struct mlxsw_core *mlxsw_core,
{ {
enum mlxsw_emad_op_tlv_status status; enum mlxsw_emad_op_tlv_status status;
int err, n_retry; int err, n_retry;
bool reset_ok;
char *in_mbox, *out_mbox, *tmp; char *in_mbox, *out_mbox, *tmp;
dev_dbg(mlxsw_core->bus_info->dev, "Reg cmd access (reg_id=%x(%s),type=%s)\n", dev_dbg(mlxsw_core->bus_info->dev, "Reg cmd access (reg_id=%x(%s),type=%s)\n",
...@@ -1501,9 +1502,16 @@ static int mlxsw_core_reg_access_cmd(struct mlxsw_core *mlxsw_core, ...@@ -1501,9 +1502,16 @@ static int mlxsw_core_reg_access_cmd(struct mlxsw_core *mlxsw_core,
tmp = in_mbox + MLXSW_EMAD_OP_TLV_LEN * sizeof(u32); tmp = in_mbox + MLXSW_EMAD_OP_TLV_LEN * sizeof(u32);
mlxsw_emad_pack_reg_tlv(tmp, reg, payload); mlxsw_emad_pack_reg_tlv(tmp, reg, payload);
/* There is a special treatment needed for MRSR (reset) register.
* The command interface will return error after the command
* is executed, so tell the lower layer to expect it
* and cope accordingly.
*/
reset_ok = reg->id == MLXSW_REG_MRSR_ID;
n_retry = 0; n_retry = 0;
retry: retry:
err = mlxsw_cmd_access_reg(mlxsw_core, in_mbox, out_mbox); err = mlxsw_cmd_access_reg(mlxsw_core, reset_ok, in_mbox, out_mbox);
if (!err) { if (!err) {
err = mlxsw_emad_process_status(out_mbox, &status); err = mlxsw_emad_process_status(out_mbox, &status);
if (err) { if (err) {
...@@ -1793,7 +1801,7 @@ static void mlxsw_core_buf_dump_dbg(struct mlxsw_core *mlxsw_core, ...@@ -1793,7 +1801,7 @@ static void mlxsw_core_buf_dump_dbg(struct mlxsw_core *mlxsw_core,
} }
int mlxsw_cmd_exec(struct mlxsw_core *mlxsw_core, u16 opcode, u8 opcode_mod, int mlxsw_cmd_exec(struct mlxsw_core *mlxsw_core, u16 opcode, u8 opcode_mod,
u32 in_mod, bool out_mbox_direct, u32 in_mod, bool out_mbox_direct, bool reset_ok,
char *in_mbox, size_t in_mbox_size, char *in_mbox, size_t in_mbox_size,
char *out_mbox, size_t out_mbox_size) char *out_mbox, size_t out_mbox_size)
{ {
...@@ -1816,7 +1824,15 @@ int mlxsw_cmd_exec(struct mlxsw_core *mlxsw_core, u16 opcode, u8 opcode_mod, ...@@ -1816,7 +1824,15 @@ int mlxsw_cmd_exec(struct mlxsw_core *mlxsw_core, u16 opcode, u8 opcode_mod,
in_mbox, in_mbox_size, in_mbox, in_mbox_size,
out_mbox, out_mbox_size, &status); out_mbox, out_mbox_size, &status);
if (err == -EIO && status != MLXSW_CMD_STATUS_OK) { if (!err && out_mbox) {
dev_dbg(mlxsw_core->bus_info->dev, "Output mailbox:\n");
mlxsw_core_buf_dump_dbg(mlxsw_core, out_mbox, out_mbox_size);
}
if (reset_ok && err == -EIO &&
status == MLXSW_CMD_STATUS_RUNNING_RESET) {
err = 0;
} else if (err == -EIO && status != MLXSW_CMD_STATUS_OK) {
dev_err(mlxsw_core->bus_info->dev, "Cmd exec failed (opcode=%x(%s),opcode_mod=%x,in_mod=%x,status=%x(%s))\n", dev_err(mlxsw_core->bus_info->dev, "Cmd exec failed (opcode=%x(%s),opcode_mod=%x,in_mod=%x,status=%x(%s))\n",
opcode, mlxsw_cmd_opcode_str(opcode), opcode_mod, opcode, mlxsw_cmd_opcode_str(opcode), opcode_mod,
in_mod, status, mlxsw_cmd_status_str(status)); in_mod, status, mlxsw_cmd_status_str(status));
...@@ -1826,10 +1842,6 @@ int mlxsw_cmd_exec(struct mlxsw_core *mlxsw_core, u16 opcode, u8 opcode_mod, ...@@ -1826,10 +1842,6 @@ int mlxsw_cmd_exec(struct mlxsw_core *mlxsw_core, u16 opcode, u8 opcode_mod,
in_mod); in_mod);
} }
if (!err && out_mbox) {
dev_dbg(mlxsw_core->bus_info->dev, "Output mailbox:\n");
mlxsw_core_buf_dump_dbg(mlxsw_core, out_mbox, out_mbox_size);
}
return err; return err;
} }
EXPORT_SYMBOL(mlxsw_cmd_exec); EXPORT_SYMBOL(mlxsw_cmd_exec);
......
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