From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751904AbdAMMsQ (ORCPT ); Fri, 13 Jan 2017 07:48:16 -0500 Received: from mail-wm0-f45.google.com ([74.125.82.45]:38374 "EHLO mail-wm0-f45.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751567AbdAMMsN (ORCPT ); Fri, 13 Jan 2017 07:48:13 -0500 From: Bartosz Golaszewski To: Kevin Hilman , Sekhar Nori , Patrick Titiano , Michael Turquette , Tejun Heo , Rob Herring , Mark Rutland , Russell King , David Lechner Cc: linux-ide@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Bartosz Golaszewski Subject: [PATCH 04/10] sata: hardreset: retry if phys link is down Date: Fri, 13 Jan 2017 13:37:58 +0100 Message-Id: <1484311084-31547-5-git-send-email-bgolaszewski@baylibre.com> X-Mailer: git-send-email 2.1.4 In-Reply-To: <1484311084-31547-1-git-send-email-bgolaszewski@baylibre.com> References: <1484311084-31547-1-git-send-email-bgolaszewski@baylibre.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The sata core driver already retries to resume the link because some controllers ignore writes to the SControl register. We have a use case with the da850 SATA controller where at PLL0 frequency of 456MHz (needed to properly service the LCD controller) the chip becomes unstable and the hardreset operation is ignored the first time 50% of times. Retrying just the resume operation doesn't work - we need to issue the phy/wake reset again to make it work. If ata_phys_link_offline() returns true in sata_link_hardreset(), retry a couple times before really giving up. Signed-off-by: Bartosz Golaszewski --- drivers/ata/libata-core.c | 16 ++++++++++++---- include/linux/libata.h | 4 +++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 9cd0a2d..3b848a3 100644 --- a/drivers/ata/libata-core.c +++ b/drivers/ata/libata-core.c @@ -3985,8 +3985,8 @@ int sata_link_hardreset(struct ata_link *link, const unsigned long *timing, unsigned long deadline, bool *online, int (*check_ready)(struct ata_link *)) { + int rc, retry = ATA_LINK_RESET_TRIES; u32 scontrol; - int rc; DPRINTK("ENTER\n"); @@ -4009,7 +4009,7 @@ int sata_link_hardreset(struct ata_link *link, const unsigned long *timing, sata_set_spd(link); } - +retry: /* issue phy wake/reset */ if ((rc = sata_scr_read(link, SCR_CONTROL, &scontrol))) goto out; @@ -4028,9 +4028,17 @@ int sata_link_hardreset(struct ata_link *link, const unsigned long *timing, rc = sata_link_resume(link, timing, deadline); if (rc) goto out; - /* if link is offline nothing more to do */ - if (ata_phys_link_offline(link)) + + if (ata_phys_link_offline(link)) { + if (retry--) { + ata_link_warn(link, + "link still offline after hardreset - retrying\n"); + goto retry; + } + + /* if link is still offline nothing more to do */ goto out; + } /* Link is online. From this point, -ENODEV too is an error. */ if (online) diff --git a/include/linux/libata.h b/include/linux/libata.h index c170be5..2c840c0 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h @@ -392,8 +392,10 @@ enum { /* max tries if error condition is still set after ->error_handler */ ATA_EH_MAX_TRIES = 5, - /* sometimes resuming a link requires several retries */ + /* sometimes resuming a link requires several retries... */ ATA_LINK_RESUME_TRIES = 5, + /* ... and sometimes we need to retry the whole reset procedure */ + ATA_LINK_RESET_TRIES = 5, /* how hard are we gonna try to probe/recover devices */ ATA_PROBE_MAX_TRIES = 3, -- 2.9.3