Commit 49fb6fe3 authored by David S. Miller's avatar David S. Miller

Merge branch 'mlxsw-use-MRSR-register-for-FW-reset'

Ido Schimmel says:

====================
mlxsw: use MRSR register for FW reset

Jiri says:

Introduce a MRSR register definition and use it to do FW reset instead
of existing mechanism using PCI BAR0 register.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents d377df78 f3a52c61
...@@ -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);
} }
......
...@@ -966,14 +966,12 @@ mlxsw_devlink_sb_occ_tc_port_bind_get(struct devlink_port *devlink_port, ...@@ -966,14 +966,12 @@ mlxsw_devlink_sb_occ_tc_port_bind_get(struct devlink_port *devlink_port,
static int mlxsw_devlink_core_bus_device_reload(struct devlink *devlink) static int mlxsw_devlink_core_bus_device_reload(struct devlink *devlink)
{ {
struct mlxsw_core *mlxsw_core = devlink_priv(devlink); struct mlxsw_core *mlxsw_core = devlink_priv(devlink);
const struct mlxsw_bus *mlxsw_bus = mlxsw_core->bus;
int err; int err;
if (!mlxsw_bus->reset) if (!(mlxsw_core->bus->features & MLXSW_BUS_F_RESET))
return -EOPNOTSUPP; return -EOPNOTSUPP;
mlxsw_core_bus_device_unregister(mlxsw_core, true); mlxsw_core_bus_device_unregister(mlxsw_core, true);
mlxsw_bus->reset(mlxsw_core->bus_priv);
err = mlxsw_core_bus_device_register(mlxsw_core->bus_info, err = mlxsw_core_bus_device_register(mlxsw_core->bus_info,
mlxsw_core->bus, mlxsw_core->bus,
mlxsw_core->bus_priv, true, mlxsw_core->bus_priv, true,
...@@ -1480,6 +1478,7 @@ static int mlxsw_core_reg_access_cmd(struct mlxsw_core *mlxsw_core, ...@@ -1480,6 +1478,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 +1500,16 @@ static int mlxsw_core_reg_access_cmd(struct mlxsw_core *mlxsw_core, ...@@ -1501,9 +1500,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 +1799,7 @@ static void mlxsw_core_buf_dump_dbg(struct mlxsw_core *mlxsw_core, ...@@ -1793,7 +1799,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 +1822,15 @@ int mlxsw_cmd_exec(struct mlxsw_core *mlxsw_core, u16 opcode, u8 opcode_mod, ...@@ -1816,7 +1822,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 +1840,6 @@ int mlxsw_cmd_exec(struct mlxsw_core *mlxsw_core, u16 opcode, u8 opcode_mod, ...@@ -1826,10 +1840,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);
......
...@@ -337,6 +337,7 @@ u64 mlxsw_core_res_get(struct mlxsw_core *mlxsw_core, ...@@ -337,6 +337,7 @@ u64 mlxsw_core_res_get(struct mlxsw_core *mlxsw_core,
mlxsw_core_res_get(mlxsw_core, MLXSW_RES_ID_##short_res_id) mlxsw_core_res_get(mlxsw_core, MLXSW_RES_ID_##short_res_id)
#define MLXSW_BUS_F_TXRX BIT(0) #define MLXSW_BUS_F_TXRX BIT(0)
#define MLXSW_BUS_F_RESET BIT(1)
struct mlxsw_bus { struct mlxsw_bus {
const char *kind; const char *kind;
...@@ -344,7 +345,6 @@ struct mlxsw_bus { ...@@ -344,7 +345,6 @@ struct mlxsw_bus {
const struct mlxsw_config_profile *profile, const struct mlxsw_config_profile *profile,
struct mlxsw_res *res); struct mlxsw_res *res);
void (*fini)(void *bus_priv); void (*fini)(void *bus_priv);
void (*reset)(void *bus_priv);
bool (*skb_transmit_busy)(void *bus_priv, bool (*skb_transmit_busy)(void *bus_priv,
const struct mlxsw_tx_info *tx_info); const struct mlxsw_tx_info *tx_info);
int (*skb_transmit)(void *bus_priv, struct sk_buff *skb, int (*skb_transmit)(void *bus_priv, struct sk_buff *skb,
......
...@@ -1371,6 +1371,51 @@ static void mlxsw_pci_mbox_free(struct mlxsw_pci *mlxsw_pci, ...@@ -1371,6 +1371,51 @@ static void mlxsw_pci_mbox_free(struct mlxsw_pci *mlxsw_pci,
mbox->mapaddr); mbox->mapaddr);
} }
static int mlxsw_pci_sw_reset(struct mlxsw_pci *mlxsw_pci,
const struct pci_device_id *id)
{
unsigned long end;
char mrsr_pl[MLXSW_REG_MRSR_LEN];
int err;
mlxsw_reg_mrsr_pack(mrsr_pl);
err = mlxsw_reg_write(mlxsw_pci->core, MLXSW_REG(mrsr), mrsr_pl);
if (err)
return err;
if (id->device == PCI_DEVICE_ID_MELLANOX_SWITCHX2) {
msleep(MLXSW_PCI_SW_RESET_TIMEOUT_MSECS);
return 0;
}
/* We must wait for the HW to become responsive once again. */
msleep(MLXSW_PCI_SW_RESET_WAIT_MSECS);
end = jiffies + msecs_to_jiffies(MLXSW_PCI_SW_RESET_TIMEOUT_MSECS);
do {
u32 val = mlxsw_pci_read32(mlxsw_pci, FW_READY);
if ((val & MLXSW_PCI_FW_READY_MASK) == MLXSW_PCI_FW_READY_MAGIC)
break;
cond_resched();
} while (time_before(jiffies, end));
return 0;
}
static int mlxsw_pci_alloc_irq_vectors(struct mlxsw_pci *mlxsw_pci)
{
int err;
err = pci_alloc_irq_vectors(mlxsw_pci->pdev, 1, 1, PCI_IRQ_MSIX);
if (err < 0)
dev_err(&mlxsw_pci->pdev->dev, "MSI-X init failed\n");
return err;
}
static void mlxsw_pci_free_irq_vectors(struct mlxsw_pci *mlxsw_pci)
{
pci_free_irq_vectors(mlxsw_pci->pdev);
}
static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core, static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core,
const struct mlxsw_config_profile *profile, const struct mlxsw_config_profile *profile,
struct mlxsw_res *res) struct mlxsw_res *res)
...@@ -1398,6 +1443,16 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core, ...@@ -1398,6 +1443,16 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core,
if (err) if (err)
goto err_out_mbox_alloc; goto err_out_mbox_alloc;
err = mlxsw_pci_sw_reset(mlxsw_pci, mlxsw_pci->id);
if (err)
goto err_sw_reset;
err = mlxsw_pci_alloc_irq_vectors(mlxsw_pci);
if (err < 0) {
dev_err(&pdev->dev, "MSI-X init failed\n");
goto err_alloc_irq;
}
err = mlxsw_cmd_query_fw(mlxsw_core, mbox); err = mlxsw_cmd_query_fw(mlxsw_core, mbox);
if (err) if (err)
goto err_query_fw; goto err_query_fw;
...@@ -1481,6 +1536,9 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core, ...@@ -1481,6 +1536,9 @@ static int mlxsw_pci_init(void *bus_priv, struct mlxsw_core *mlxsw_core,
err_doorbell_page_bar: err_doorbell_page_bar:
err_iface_rev: err_iface_rev:
err_query_fw: err_query_fw:
mlxsw_pci_free_irq_vectors(mlxsw_pci);
err_alloc_irq:
err_sw_reset:
mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.out_mbox); mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.out_mbox);
err_out_mbox_alloc: err_out_mbox_alloc:
mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.in_mbox); mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.in_mbox);
...@@ -1496,6 +1554,7 @@ static void mlxsw_pci_fini(void *bus_priv) ...@@ -1496,6 +1554,7 @@ static void mlxsw_pci_fini(void *bus_priv)
free_irq(pci_irq_vector(mlxsw_pci->pdev, 0), mlxsw_pci); free_irq(pci_irq_vector(mlxsw_pci->pdev, 0), mlxsw_pci);
mlxsw_pci_aqs_fini(mlxsw_pci); mlxsw_pci_aqs_fini(mlxsw_pci);
mlxsw_pci_fw_area_fini(mlxsw_pci); mlxsw_pci_fw_area_fini(mlxsw_pci);
mlxsw_pci_free_irq_vectors(mlxsw_pci);
mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.out_mbox); mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.out_mbox);
mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.in_mbox); mlxsw_pci_mbox_free(mlxsw_pci, &mlxsw_pci->cmd.in_mbox);
} }
...@@ -1677,58 +1736,6 @@ static int mlxsw_pci_cmd_exec(void *bus_priv, u16 opcode, u8 opcode_mod, ...@@ -1677,58 +1736,6 @@ static int mlxsw_pci_cmd_exec(void *bus_priv, u16 opcode, u8 opcode_mod,
return err; return err;
} }
static int mlxsw_pci_sw_reset(struct mlxsw_pci *mlxsw_pci,
const struct pci_device_id *id)
{
unsigned long end;
mlxsw_pci_write32(mlxsw_pci, SW_RESET, MLXSW_PCI_SW_RESET_RST_BIT);
if (id->device == PCI_DEVICE_ID_MELLANOX_SWITCHX2) {
msleep(MLXSW_PCI_SW_RESET_TIMEOUT_MSECS);
return 0;
}
/* Reset needs to be written before we read control register, and
* we must wait for the HW to become responsive once again
*/
wmb();
msleep(MLXSW_PCI_SW_RESET_WAIT_MSECS);
end = jiffies + msecs_to_jiffies(MLXSW_PCI_SW_RESET_TIMEOUT_MSECS);
do {
u32 val = mlxsw_pci_read32(mlxsw_pci, FW_READY);
if ((val & MLXSW_PCI_FW_READY_MASK) == MLXSW_PCI_FW_READY_MAGIC)
break;
cond_resched();
} while (time_before(jiffies, end));
return 0;
}
static void mlxsw_pci_free_irq_vectors(struct mlxsw_pci *mlxsw_pci)
{
pci_free_irq_vectors(mlxsw_pci->pdev);
}
static int mlxsw_pci_alloc_irq_vectors(struct mlxsw_pci *mlxsw_pci)
{
int err;
err = pci_alloc_irq_vectors(mlxsw_pci->pdev, 1, 1, PCI_IRQ_MSIX);
if (err < 0)
dev_err(&mlxsw_pci->pdev->dev, "MSI-X init failed\n");
return err;
}
static void mlxsw_pci_reset(void *bus_priv)
{
struct mlxsw_pci *mlxsw_pci = bus_priv;
mlxsw_pci_free_irq_vectors(mlxsw_pci);
mlxsw_pci_sw_reset(mlxsw_pci, mlxsw_pci->id);
mlxsw_pci_alloc_irq_vectors(mlxsw_pci);
}
static const struct mlxsw_bus mlxsw_pci_bus = { static const struct mlxsw_bus mlxsw_pci_bus = {
.kind = "pci", .kind = "pci",
.init = mlxsw_pci_init, .init = mlxsw_pci_init,
...@@ -1736,8 +1743,7 @@ static const struct mlxsw_bus mlxsw_pci_bus = { ...@@ -1736,8 +1743,7 @@ static const struct mlxsw_bus mlxsw_pci_bus = {
.skb_transmit_busy = mlxsw_pci_skb_transmit_busy, .skb_transmit_busy = mlxsw_pci_skb_transmit_busy,
.skb_transmit = mlxsw_pci_skb_transmit, .skb_transmit = mlxsw_pci_skb_transmit,
.cmd_exec = mlxsw_pci_cmd_exec, .cmd_exec = mlxsw_pci_cmd_exec,
.features = MLXSW_BUS_F_TXRX, .features = MLXSW_BUS_F_TXRX | MLXSW_BUS_F_RESET,
.reset = mlxsw_pci_reset,
}; };
static int mlxsw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) static int mlxsw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
...@@ -1795,18 +1801,6 @@ static int mlxsw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -1795,18 +1801,6 @@ static int mlxsw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
mlxsw_pci->pdev = pdev; mlxsw_pci->pdev = pdev;
pci_set_drvdata(pdev, mlxsw_pci); pci_set_drvdata(pdev, mlxsw_pci);
err = mlxsw_pci_sw_reset(mlxsw_pci, id);
if (err) {
dev_err(&pdev->dev, "Software reset failed\n");
goto err_sw_reset;
}
err = mlxsw_pci_alloc_irq_vectors(mlxsw_pci);
if (err < 0) {
dev_err(&pdev->dev, "MSI-X init failed\n");
goto err_msix_init;
}
mlxsw_pci->bus_info.device_kind = driver_name; mlxsw_pci->bus_info.device_kind = driver_name;
mlxsw_pci->bus_info.device_name = pci_name(mlxsw_pci->pdev); mlxsw_pci->bus_info.device_name = pci_name(mlxsw_pci->pdev);
mlxsw_pci->bus_info.dev = &pdev->dev; mlxsw_pci->bus_info.dev = &pdev->dev;
...@@ -1823,9 +1817,6 @@ static int mlxsw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) ...@@ -1823,9 +1817,6 @@ static int mlxsw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
return 0; return 0;
err_bus_device_register: err_bus_device_register:
mlxsw_pci_free_irq_vectors(mlxsw_pci);
err_msix_init:
err_sw_reset:
iounmap(mlxsw_pci->hw_addr); iounmap(mlxsw_pci->hw_addr);
err_ioremap: err_ioremap:
err_pci_resource_len_check: err_pci_resource_len_check:
...@@ -1843,7 +1834,6 @@ static void mlxsw_pci_remove(struct pci_dev *pdev) ...@@ -1843,7 +1834,6 @@ static void mlxsw_pci_remove(struct pci_dev *pdev)
struct mlxsw_pci *mlxsw_pci = pci_get_drvdata(pdev); struct mlxsw_pci *mlxsw_pci = pci_get_drvdata(pdev);
mlxsw_core_bus_device_unregister(mlxsw_pci->core, false); mlxsw_core_bus_device_unregister(mlxsw_pci->core, false);
mlxsw_pci_free_irq_vectors(mlxsw_pci);
iounmap(mlxsw_pci->hw_addr); iounmap(mlxsw_pci->hw_addr);
pci_release_regions(mlxsw_pci->pdev); pci_release_regions(mlxsw_pci->pdev);
pci_disable_device(mlxsw_pci->pdev); pci_disable_device(mlxsw_pci->pdev);
......
...@@ -7034,6 +7034,30 @@ static inline void mlxsw_reg_mpar_pack(char *payload, u8 local_port, ...@@ -7034,6 +7034,30 @@ static inline void mlxsw_reg_mpar_pack(char *payload, u8 local_port,
mlxsw_reg_mpar_pa_id_set(payload, pa_id); mlxsw_reg_mpar_pa_id_set(payload, pa_id);
} }
/* MRSR - Management Reset and Shutdown Register
* ---------------------------------------------
* MRSR register is used to reset or shutdown the switch or
* the entire system (when applicable).
*/
#define MLXSW_REG_MRSR_ID 0x9023
#define MLXSW_REG_MRSR_LEN 0x08
MLXSW_REG_DEFINE(mrsr, MLXSW_REG_MRSR_ID, MLXSW_REG_MRSR_LEN);
/* reg_mrsr_command
* Reset/shutdown command
* 0 - do nothing
* 1 - software reset
* Access: WO
*/
MLXSW_ITEM32(reg, mrsr, command, 0x00, 0, 4);
static inline void mlxsw_reg_mrsr_pack(char *payload)
{
MLXSW_REG_ZERO(mrsr, payload);
mlxsw_reg_mrsr_command_set(payload, 1);
}
/* MLCR - Management LED Control Register /* MLCR - Management LED Control Register
* -------------------------------------- * --------------------------------------
* Controls the system LEDs. * Controls the system LEDs.
...@@ -7898,6 +7922,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { ...@@ -7898,6 +7922,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = {
MLXSW_REG(mcia), MLXSW_REG(mcia),
MLXSW_REG(mpat), MLXSW_REG(mpat),
MLXSW_REG(mpar), MLXSW_REG(mpar),
MLXSW_REG(mrsr),
MLXSW_REG(mlcr), MLXSW_REG(mlcr),
MLXSW_REG(mpsc), MLXSW_REG(mpsc),
MLXSW_REG(mcqi), MLXSW_REG(mcqi),
......
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