Skip to content

Commit 6031681

Browse files
idoschBrian Maly
authored andcommitted
mlxsw: pci: Fix driver initialization with Spectrum-4
Cited commit added support for a new reset flow ("all reset") which is deeper than the existing reset flow ("software reset") and allows the device's PCI firmware to be upgraded. In the new flow the driver first tells the firmware that "all reset" is required by issuing a new reset command (i.e., MRSR.command=6) and then triggers the reset by having the PCI core issue a secondary bus reset (SBR). However, due to a race condition in the device's firmware the device is not always able to recover from this reset, resulting in initialization failures [1]. New firmware versions include a fix for the bug and advertise it using a new capability bit in the Management Capabilities Mask (MCAM) register. Avoid initialization failures by reading the new capability bit and triggering the new reset flow only if the bit is set. If the bit is not set, trigger a normal PCI hot reset by skipping the call to the Management Reset and Shutdown Register (MRSR). Normal PCI hot reset is weaker than "all reset", but it results in a fully operational driver and allows users to flash a new firmware, if they want to. [1] mlxsw_spectrum4 0000:01:00.0: not ready 1023ms after bus reset; waiting mlxsw_spectrum4 0000:01:00.0: not ready 2047ms after bus reset; waiting mlxsw_spectrum4 0000:01:00.0: not ready 4095ms after bus reset; waiting mlxsw_spectrum4 0000:01:00.0: not ready 8191ms after bus reset; waiting mlxsw_spectrum4 0000:01:00.0: not ready 16383ms after bus reset; waiting mlxsw_spectrum4 0000:01:00.0: not ready 32767ms after bus reset; waiting mlxsw_spectrum4 0000:01:00.0: not ready 65535ms after bus reset; giving up mlxsw_spectrum4 0000:01:00.0: PCI function reset failed with -25 mlxsw_spectrum4 0000:01:00.0: cannot register bus device mlxsw_spectrum4: probe of 0000:01:00.0 failed with error -25 Fixes: f257c73 ("mlxsw: pci: Add support for new reset flow") Reported-by: Maksym Yaremchuk <[email protected]> Signed-off-by: Ido Schimmel <[email protected]> Tested-by: Maksym Yaremchuk <[email protected]> Reviewed-by: Simon Horman <[email protected]> Signed-off-by: Petr Machata <[email protected]> Signed-off-by: David S. Miller <[email protected]> Orabug: 36811057 (cherry picked from commit 0602697) cherry-pick-repo=kernel/git/torvalds/linux.git unmodified-from-upstream: 0602697 Signed-off-by: Mikhael Goikhman <[email protected]> Signed-off-by: Qing Huang <[email protected]> Reviewed-by: Sharath Srinivasan <[email protected]> Signed-off-by: Brian Maly <[email protected]>
1 parent daf7572 commit 6031681

File tree

2 files changed

+17
-3
lines changed

2 files changed

+17
-3
lines changed

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

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1490,18 +1490,25 @@ static int mlxsw_pci_sys_ready_wait(struct mlxsw_pci *mlxsw_pci,
14901490
return -EBUSY;
14911491
}
14921492

1493-
static int mlxsw_pci_reset_at_pci_disable(struct mlxsw_pci *mlxsw_pci)
1493+
static int mlxsw_pci_reset_at_pci_disable(struct mlxsw_pci *mlxsw_pci,
1494+
bool pci_reset_sbr_supported)
14941495
{
14951496
struct pci_dev *pdev = mlxsw_pci->pdev;
14961497
char mrsr_pl[MLXSW_REG_MRSR_LEN];
14971498
int err;
14981499

1500+
if (!pci_reset_sbr_supported) {
1501+
pci_dbg(pdev, "Performing PCI hot reset instead of \"all reset\"\n");
1502+
goto sbr;
1503+
}
1504+
14991505
mlxsw_reg_mrsr_pack(mrsr_pl,
15001506
MLXSW_REG_MRSR_COMMAND_RESET_AT_PCI_DISABLE);
15011507
err = mlxsw_reg_write(mlxsw_pci->core, MLXSW_REG(mrsr), mrsr_pl);
15021508
if (err)
15031509
return err;
15041510

1511+
sbr:
15051512
device_lock_assert(&pdev->dev);
15061513

15071514
pci_cfg_access_lock(pdev);
@@ -1529,6 +1536,7 @@ static int
15291536
mlxsw_pci_reset(struct mlxsw_pci *mlxsw_pci, const struct pci_device_id *id)
15301537
{
15311538
struct pci_dev *pdev = mlxsw_pci->pdev;
1539+
bool pci_reset_sbr_supported = false;
15321540
char mcam_pl[MLXSW_REG_MCAM_LEN];
15331541
bool pci_reset_supported = false;
15341542
u32 sys_status;
@@ -1548,13 +1556,17 @@ mlxsw_pci_reset(struct mlxsw_pci *mlxsw_pci, const struct pci_device_id *id)
15481556
mlxsw_reg_mcam_pack(mcam_pl,
15491557
MLXSW_REG_MCAM_FEATURE_GROUP_ENHANCED_FEATURES);
15501558
err = mlxsw_reg_query(mlxsw_pci->core, MLXSW_REG(mcam), mcam_pl);
1551-
if (!err)
1559+
if (!err) {
15521560
mlxsw_reg_mcam_unpack(mcam_pl, MLXSW_REG_MCAM_PCI_RESET,
15531561
&pci_reset_supported);
1562+
mlxsw_reg_mcam_unpack(mcam_pl, MLXSW_REG_MCAM_PCI_RESET_SBR,
1563+
&pci_reset_sbr_supported);
1564+
}
15541565

15551566
if (pci_reset_supported) {
15561567
pci_dbg(pdev, "Starting PCI reset flow\n");
1557-
err = mlxsw_pci_reset_at_pci_disable(mlxsw_pci);
1568+
err = mlxsw_pci_reset_at_pci_disable(mlxsw_pci,
1569+
pci_reset_sbr_supported);
15581570
} else {
15591571
pci_dbg(pdev, "Starting software reset flow\n");
15601572
err = mlxsw_pci_reset_sw(mlxsw_pci);

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10668,6 +10668,8 @@ enum mlxsw_reg_mcam_mng_feature_cap_mask_bits {
1066810668
MLXSW_REG_MCAM_MCIA_128B = 34,
1066910669
/* If set, MRSR.command=6 is supported. */
1067010670
MLXSW_REG_MCAM_PCI_RESET = 48,
10671+
/* If set, MRSR.command=6 is supported with Secondary Bus Reset. */
10672+
MLXSW_REG_MCAM_PCI_RESET_SBR = 67,
1067110673
};
1067210674

1067310675
#define MLXSW_REG_BYTES_PER_DWORD 0x4

0 commit comments

Comments
 (0)