Skip to content

Commit f257c73

Browse files
idoschdavem330
authored andcommitted
mlxsw: pci: Add support for new reset flow
The driver resets the device during probe and during a devlink reload. The current reset method reloads the current firmware version or a pending one, if one was previously flashed using devlink. However, the current reset method does not result in a PCI hot reset, preventing the PCI firmware from being upgraded, unless the system is rebooted. To solve this problem, a new reset command (6) was implemented in the firmware. Unlike the current command (1), after issuing the new command the device will not start the reset immediately, but only after a PCI hot reset. Implement the new reset method by first verifying that it is supported by the current firmware version by querying the Management Capabilities Mask (MCAM) register. If supported, issue the new reset command (6) via MRSR register followed by a PCI reset by calling __pci_reset_function_locked(). Once the PCI firmware is operational, go back to the regular reset flow and wait for the entire device to become ready. That is, repeatedly read the "system_status" register from the BAR until a value of "FW_READY" (0x5E) appears. Tested: # for i in $(seq 1 10); do devlink dev reload pci/0000:01:00.0; done Signed-off-by: Ido Schimmel <[email protected]> Reviewed-by: Petr Machata <[email protected]> Signed-off-by: Petr Machata <[email protected]> Reviewed-by: Simon Horman <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 8d9da46 commit f257c73

File tree

2 files changed

+45
-1
lines changed

2 files changed

+45
-1
lines changed

drivers/net/ethernet/mellanox/mlxsw/pci.c

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1476,6 +1476,33 @@ static int mlxsw_pci_sys_ready_wait(struct mlxsw_pci *mlxsw_pci,
14761476
return -EBUSY;
14771477
}
14781478

1479+
static int mlxsw_pci_reset_at_pci_disable(struct mlxsw_pci *mlxsw_pci)
1480+
{
1481+
struct pci_dev *pdev = mlxsw_pci->pdev;
1482+
char mrsr_pl[MLXSW_REG_MRSR_LEN];
1483+
int err;
1484+
1485+
mlxsw_reg_mrsr_pack(mrsr_pl,
1486+
MLXSW_REG_MRSR_COMMAND_RESET_AT_PCI_DISABLE);
1487+
err = mlxsw_reg_write(mlxsw_pci->core, MLXSW_REG(mrsr), mrsr_pl);
1488+
if (err)
1489+
return err;
1490+
1491+
device_lock_assert(&pdev->dev);
1492+
1493+
pci_cfg_access_lock(pdev);
1494+
pci_save_state(pdev);
1495+
1496+
err = __pci_reset_function_locked(pdev);
1497+
if (err)
1498+
pci_err(pdev, "PCI function reset failed with %d\n", err);
1499+
1500+
pci_restore_state(pdev);
1501+
pci_cfg_access_unlock(pdev);
1502+
1503+
return err;
1504+
}
1505+
14791506
static int mlxsw_pci_reset_sw(struct mlxsw_pci *mlxsw_pci)
14801507
{
14811508
char mrsr_pl[MLXSW_REG_MRSR_LEN];
@@ -1488,6 +1515,8 @@ static int
14881515
mlxsw_pci_reset(struct mlxsw_pci *mlxsw_pci, const struct pci_device_id *id)
14891516
{
14901517
struct pci_dev *pdev = mlxsw_pci->pdev;
1518+
char mcam_pl[MLXSW_REG_MCAM_LEN];
1519+
bool pci_reset_supported;
14911520
u32 sys_status;
14921521
int err;
14931522

@@ -1498,10 +1527,23 @@ mlxsw_pci_reset(struct mlxsw_pci *mlxsw_pci, const struct pci_device_id *id)
14981527
return err;
14991528
}
15001529

1501-
err = mlxsw_pci_reset_sw(mlxsw_pci);
1530+
mlxsw_reg_mcam_pack(mcam_pl,
1531+
MLXSW_REG_MCAM_FEATURE_GROUP_ENHANCED_FEATURES);
1532+
err = mlxsw_reg_query(mlxsw_pci->core, MLXSW_REG(mcam), mcam_pl);
15021533
if (err)
15031534
return err;
15041535

1536+
mlxsw_reg_mcam_unpack(mcam_pl, MLXSW_REG_MCAM_PCI_RESET,
1537+
&pci_reset_supported);
1538+
1539+
if (pci_reset_supported) {
1540+
pci_dbg(pdev, "Starting PCI reset flow\n");
1541+
err = mlxsw_pci_reset_at_pci_disable(mlxsw_pci);
1542+
} else {
1543+
pci_dbg(pdev, "Starting software reset flow\n");
1544+
err = mlxsw_pci_reset_sw(mlxsw_pci);
1545+
}
1546+
15051547
err = mlxsw_pci_sys_ready_wait(mlxsw_pci, id, &sys_status);
15061548
if (err) {
15071549
dev_err(&pdev->dev, "Failed to reach system ready status after reset. Status is 0x%x\n",

drivers/net/ethernet/mellanox/mlxsw/reg.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10594,6 +10594,8 @@ MLXSW_ITEM32(reg, mcam, feature_group, 0x00, 16, 8);
1059410594
enum mlxsw_reg_mcam_mng_feature_cap_mask_bits {
1059510595
/* If set, MCIA supports 128 bytes payloads. Otherwise, 48 bytes. */
1059610596
MLXSW_REG_MCAM_MCIA_128B = 34,
10597+
/* If set, MRSR.command=6 is supported. */
10598+
MLXSW_REG_MCAM_PCI_RESET = 48,
1059710599
};
1059810600

1059910601
#define MLXSW_REG_BYTES_PER_DWORD 0x4

0 commit comments

Comments
 (0)