120 lines
3.5 KiB
Diff
120 lines
3.5 KiB
Diff
From 1a1284ef97ca79ba747d211b697e996a248a8555 Mon Sep 17 00:00:00 2001
|
|
From: Matthew Slattery <mslattery@solarflare.com>
|
|
Date: Wed, 23 Dec 2009 13:48:32 +0000
|
|
Subject: [PATCH 6/8] sfc: QT2025C: Work around PHY firmware initialisation bug
|
|
|
|
The PHY's firmware very occasionally appears to lock up very early, but
|
|
with the heartbeat update still running. Rebooting the microcontroller
|
|
core seems to be sufficient to recover.
|
|
|
|
Signed-off-by: Ben Hutchings <bhutchings@solarflare.com>
|
|
Signed-off-by: David S. Miller <davem@davemloft.net>
|
|
---
|
|
drivers/net/sfc/qt202x_phy.c | 59 ++++++++++++++++++++++++++++++++++++-----
|
|
1 files changed, 51 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/drivers/net/sfc/qt202x_phy.c b/drivers/net/sfc/qt202x_phy.c
|
|
index 0cd6eed..326ffa4 100644
|
|
--- a/drivers/net/sfc/qt202x_phy.c
|
|
+++ b/drivers/net/sfc/qt202x_phy.c
|
|
@@ -63,11 +63,16 @@ struct qt202x_phy_data {
|
|
#define QT2022C2_MAX_RESET_TIME 500
|
|
#define QT2022C2_RESET_WAIT 10
|
|
|
|
+#define QT2025C_MAX_HEARTB_TIME (5 * HZ)
|
|
+#define QT2025C_HEARTB_WAIT 100
|
|
+#define QT2025C_MAX_FWSTART_TIME (25 * HZ / 10)
|
|
+#define QT2025C_FWSTART_WAIT 100
|
|
+
|
|
#define BUG17190_INTERVAL (2 * HZ)
|
|
|
|
-static int qt2025c_wait_reset(struct efx_nic *efx)
|
|
+static int qt2025c_wait_heartbeat(struct efx_nic *efx)
|
|
{
|
|
- unsigned long timeout = jiffies + 10 * HZ;
|
|
+ unsigned long timeout = jiffies + QT2025C_MAX_HEARTB_TIME;
|
|
int reg, old_counter = 0;
|
|
|
|
/* Wait for firmware heartbeat to start */
|
|
@@ -84,9 +89,17 @@ static int qt2025c_wait_reset(struct efx_nic *efx)
|
|
break;
|
|
if (time_after(jiffies, timeout))
|
|
return -ETIMEDOUT;
|
|
- msleep(10);
|
|
+ msleep(QT2025C_HEARTB_WAIT);
|
|
}
|
|
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+static int qt2025c_wait_fw_status_good(struct efx_nic *efx)
|
|
+{
|
|
+ unsigned long timeout = jiffies + QT2025C_MAX_FWSTART_TIME;
|
|
+ int reg;
|
|
+
|
|
/* Wait for firmware status to look good */
|
|
for (;;) {
|
|
reg = efx_mdio_read(efx, MDIO_MMD_PCS, PCS_UC8051_STATUS_REG);
|
|
@@ -98,12 +111,44 @@ static int qt2025c_wait_reset(struct efx_nic *efx)
|
|
break;
|
|
if (time_after(jiffies, timeout))
|
|
return -ETIMEDOUT;
|
|
- msleep(100);
|
|
+ msleep(QT2025C_FWSTART_WAIT);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
+static void qt2025c_restart_firmware(struct efx_nic *efx)
|
|
+{
|
|
+ /* Restart microcontroller execution of firmware from RAM */
|
|
+ efx_mdio_write(efx, 3, 0xe854, 0x00c0);
|
|
+ efx_mdio_write(efx, 3, 0xe854, 0x0040);
|
|
+ msleep(50);
|
|
+}
|
|
+
|
|
+static int qt2025c_wait_reset(struct efx_nic *efx)
|
|
+{
|
|
+ int rc;
|
|
+
|
|
+ rc = qt2025c_wait_heartbeat(efx);
|
|
+ if (rc != 0)
|
|
+ return rc;
|
|
+
|
|
+ rc = qt2025c_wait_fw_status_good(efx);
|
|
+ if (rc == -ETIMEDOUT) {
|
|
+ /* Bug 17689: occasionally heartbeat starts but firmware status
|
|
+ * code never progresses beyond 0x00. Try again, once, after
|
|
+ * restarting execution of the firmware image. */
|
|
+ EFX_LOG(efx, "bashing QT2025C microcontroller\n");
|
|
+ qt2025c_restart_firmware(efx);
|
|
+ rc = qt2025c_wait_heartbeat(efx);
|
|
+ if (rc != 0)
|
|
+ return rc;
|
|
+ rc = qt2025c_wait_fw_status_good(efx);
|
|
+ }
|
|
+
|
|
+ return rc;
|
|
+}
|
|
+
|
|
static void qt2025c_firmware_id(struct efx_nic *efx)
|
|
{
|
|
struct qt202x_phy_data *phy_data = efx->phy_data;
|
|
@@ -229,10 +274,8 @@ static int qt2025c_select_phy_mode(struct efx_nic *efx)
|
|
efx_mdio_write(efx, 1, 0xc300, 0x0002);
|
|
msleep(20);
|
|
|
|
- /* Restart microcontroller execution from RAM */
|
|
- efx_mdio_write(efx, 3, 0xe854, 0x00c0);
|
|
- efx_mdio_write(efx, 3, 0xe854, 0x0040);
|
|
- msleep(50);
|
|
+ /* Restart microcontroller execution of firmware from RAM */
|
|
+ qt2025c_restart_firmware(efx);
|
|
|
|
/* Wait for the microcontroller to be ready again */
|
|
rc = qt2025c_wait_reset(efx);
|
|
--
|
|
1.6.5.7
|
|
|