From patchwork Wed Dec 23 23:48:32 2009 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ben Hutchings X-Patchwork-Id: 41720 X-Patchwork-Delegate: davem@davemloft.net Return-Path: X-Original-To: patchwork-incoming@ozlabs.org Delivered-To: patchwork-incoming@ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 2B787B7BEB for ; Thu, 24 Dec 2009 10:48:57 +1100 (EST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1757518AbZLWXsg (ORCPT ); Wed, 23 Dec 2009 18:48:36 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1756796AbZLWXsg (ORCPT ); Wed, 23 Dec 2009 18:48:36 -0500 Received: from mail.solarflare.com ([216.237.3.220]:28270 "EHLO exchange.solarflare.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1757517AbZLWXsf (ORCPT ); Wed, 23 Dec 2009 18:48:35 -0500 Received: from [10.17.20.50] ([10.17.20.50]) by exchange.solarflare.com over TLS secured channel with Microsoft SMTPSVC(6.0.3790.3959); Wed, 23 Dec 2009 15:48:49 -0800 Subject: [PATCH 6/8] sfc: QT2025C: Work around PHY firmware initialisation bug From: Ben Hutchings To: David Miller Cc: netdev@vger.kernel.org, linux-net-drivers@solarflare.com Organization: Solarflare Communications Date: Wed, 23 Dec 2009 23:48:32 +0000 Message-Id: <1261612112.2782.98.camel@achroite.uk.solarflarecom.com> Mime-Version: 1.0 X-Mailer: Evolution 2.22.1 (2.22.1-2.fc9) X-OriginalArrivalTime: 23 Dec 2009 23:48:49.0432 (UTC) FILETIME=[796F7180:01CA842A] X-TM-AS-Product-Ver: SMEX-8.0.0.1181-6.000.1038-17086.005 X-TM-AS-Result: No--9.252100-0.000000-31 X-TM-AS-User-Approved-Sender: Yes X-TM-AS-User-Blocked-Sender: No Sender: netdev-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: netdev@vger.kernel.org From: Matthew Slattery 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 --- 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);