diff options
author | Tejun Heo <tj@kernel.org> | 2008-10-13 19:21:28 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@suse.de> | 2008-10-22 14:13:18 -0700 |
commit | dd5d2d841e954134a06ea6b6e414b90b9b80b4e5 (patch) | |
tree | 2154e9c235b5bde5f02a6c4ae1cfa65fb1447923 | |
parent | c8d4a26cf27050f22e3aa493c04982a34774780e (diff) |
libata: always do follow-up SRST if hardreset returned -EAGAIN
commit 5dbfc9cb59d4ad75199949d7dd8a8c6d7bc518df upstream
As an optimization, follow-up SRST used to be skipped if
classification wasn't requested even when hardreset requested it via
-EAGAIN. However, some hardresets can't wait for device readiness and
skipping SRST can cause timeout or other failures during revalidation.
Always perform follow-up SRST if hardreset returns -EAGAIN. This
makes reset paths more predictable and thus less error-prone.
While at it, move hardreset error checking such that it's done right
after hardreset is finished. This simplifies followup SRST condition
check a bit and makes the reset path easier to modify.
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
Cc: Chuck Ebbert <cebbert@redhat.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
-rw-r--r-- | drivers/ata/libata-eh.c | 20 |
1 files changed, 6 insertions, 14 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c index 7894d83ea1eb..4b0f24fc89f7 100644 --- a/drivers/ata/libata-eh.c +++ b/drivers/ata/libata-eh.c @@ -2050,18 +2050,12 @@ static int ata_do_reset(struct ata_link *link, ata_reset_fn_t reset, } static int ata_eh_followup_srst_needed(struct ata_link *link, - int rc, int classify, - const unsigned int *classes) + int rc, const unsigned int *classes) { if ((link->flags & ATA_LFLAG_NO_SRST) || ata_link_offline(link)) return 0; - if (rc == -EAGAIN) { - if (classify) - return 1; - rc = 0; - } - if (rc != 0) - return 0; + if (rc == -EAGAIN) + return 1; if (sata_pmp_supported(link->ap) && ata_is_host_link(link)) return 1; return 0; @@ -2174,9 +2168,11 @@ int ata_eh_reset(struct ata_link *link, int classify, ehc->i.flags |= ATA_EHI_DID_SOFTRESET; rc = ata_do_reset(link, reset, classes, deadline); + if (rc && rc != -EAGAIN) + goto fail; if (reset == hardreset && - ata_eh_followup_srst_needed(link, rc, classify, classes)) { + ata_eh_followup_srst_needed(link, rc, classes)) { /* okay, let's do follow-up softreset */ reset = softreset; @@ -2191,10 +2187,6 @@ int ata_eh_reset(struct ata_link *link, int classify, ata_eh_about_to_do(link, NULL, ATA_EH_RESET); rc = ata_do_reset(link, reset, classes, deadline); } - - /* -EAGAIN can happen if we skipped followup SRST */ - if (rc && rc != -EAGAIN) - goto fail; } else { if (verbose) ata_link_printk(link, KERN_INFO, "no reset method " |