]> git.baikalelectronics.ru Git - kernel.git/commitdiff
mlxsw: pci: Only issue reset when system is ready
authorIdo Schimmel <idosch@mellanox.com>
Thu, 19 Mar 2020 11:25:39 +0000 (13:25 +0200)
committerDavid S. Miller <davem@davemloft.net>
Fri, 20 Mar 2020 03:23:27 +0000 (20:23 -0700)
During initialization the driver issues a software reset command and
then waits for the system status to change back to "ready" state.

However, before issuing the reset command the driver does not check that
the system is actually in "ready" state. On Spectrum-{1,2} systems this
was always the case as the hardware initialization time is very short.
On Spectrum-3 systems this is no longer the case. This results in the
software reset command timing-out and the driver failing to load:

[ 6.347591] mlxsw_spectrum3 0000:06:00.0: Cmd exec timed-out (opcode=40(ACCESS_REG),opcode_mod=0,in_mod=0)
[ 6.358382] mlxsw_spectrum3 0000:06:00.0: Reg cmd access failed (reg_id=9023(mrsr),type=write)
[ 6.368028] mlxsw_spectrum3 0000:06:00.0: cannot register bus device
[ 6.375274] mlxsw_spectrum3: probe of 0000:06:00.0 failed with error -110

Fix this by waiting for the system to become ready both before issuing
the reset command and afterwards. In case of failure, print the last
system status to aid in debugging.

Fixes: 30c81368ffac ("mlxsw: spectrum: Extend to support Spectrum-3 ASIC")
Signed-off-by: Ido Schimmel <idosch@mellanox.com>
Reviewed-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlxsw/pci.c

index 914c33e46fb47bc038460dd9f9d897edc84d0007..e9ded1a6e1312cc6073aac4c242bc3745f4c6342 100644 (file)
@@ -1322,36 +1322,64 @@ static void mlxsw_pci_mbox_free(struct mlxsw_pci *mlxsw_pci,
                            mbox->mapaddr);
 }
 
-static int mlxsw_pci_sw_reset(struct mlxsw_pci *mlxsw_pci,
-                             const struct pci_device_id *id)
+static int mlxsw_pci_sys_ready_wait(struct mlxsw_pci *mlxsw_pci,
+                                   const struct pci_device_id *id,
+                                   u32 *p_sys_status)
 {
        unsigned long end;
-       char mrsr_pl[MLXSW_REG_MRSR_LEN];
-       int err;
+       u32 val;
 
-       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. */
+       /* We must wait for the HW to become responsive. */
        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);
-
+               val = mlxsw_pci_read32(mlxsw_pci, FW_READY);
                if ((val & MLXSW_PCI_FW_READY_MASK) == MLXSW_PCI_FW_READY_MAGIC)
                        return 0;
                cond_resched();
        } while (time_before(jiffies, end));
+
+       *p_sys_status = val & MLXSW_PCI_FW_READY_MASK;
+
        return -EBUSY;
 }
 
+static int mlxsw_pci_sw_reset(struct mlxsw_pci *mlxsw_pci,
+                             const struct pci_device_id *id)
+{
+       struct pci_dev *pdev = mlxsw_pci->pdev;
+       char mrsr_pl[MLXSW_REG_MRSR_LEN];
+       u32 sys_status;
+       int err;
+
+       err = mlxsw_pci_sys_ready_wait(mlxsw_pci, id, &sys_status);
+       if (err) {
+               dev_err(&pdev->dev, "Failed to reach system ready status before reset. Status is 0x%x\n",
+                       sys_status);
+               return err;
+       }
+
+       mlxsw_reg_mrsr_pack(mrsr_pl);
+       err = mlxsw_reg_write(mlxsw_pci->core, MLXSW_REG(mrsr), mrsr_pl);
+       if (err)
+               return err;
+
+       err = mlxsw_pci_sys_ready_wait(mlxsw_pci, id, &sys_status);
+       if (err) {
+               dev_err(&pdev->dev, "Failed to reach system ready status after reset. Status is 0x%x\n",
+                       sys_status);
+               return err;
+       }
+
+       return 0;
+}
+
 static int mlxsw_pci_alloc_irq_vectors(struct mlxsw_pci *mlxsw_pci)
 {
        int err;