Commit 1a1284ef authored by Matthew Slattery's avatar Matthew Slattery Committed by David S. Miller

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: default avatarBen Hutchings <bhutchings@solarflare.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 0d83b2f6
......@@ -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);
......
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