summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-10-31 02:17:04 +0100
committerJeff Garzik <jeff@garzik.org>2007-11-03 13:46:54 +0100
commit08cf69d005acda706bc014c61301993758ce9c5f (patch)
treea7254a45b25ea52bc77a3340650a9b45386f1650 /drivers
parentlibata: cosmetic clean up / reorganization of ata_eh_reset() (diff)
downloadlinux-08cf69d005acda706bc014c61301993758ce9c5f.tar.xz
linux-08cf69d005acda706bc014c61301993758ce9c5f.zip
libata: more robust reset failure handling
Reset failure is a critical error. It results in disabling the link requiring user intervention to re-enable it. Make reset failure handling more robust such that libata EH doesn't give up too early. * Temporary glitches during hardreset may lead to classification failure when there's no softreset available. Retry instead of giving up. * Initial softreset or follow up softreset may fail classification. Move classification error handling block out of followup softreset block such that both cases are handled and retry instead of giving up. Also, on the last try, give ATA class a blind shot. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/ata/libata-eh.c25
1 files changed, 16 insertions, 9 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index dae2174f3877..7a2e54e92164 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -2184,25 +2184,32 @@ int ata_eh_reset(struct ata_link *link, int classify,
"follow-up softreset required "
"but no softreset avaliable\n");
rc = -EINVAL;
- goto out;
+ goto fail;
}
ata_eh_about_to_do(link, NULL, ATA_EH_RESET_MASK);
rc = ata_do_reset(link, reset, classes, deadline);
-
- if (rc == 0 && classify && classes[0] == ATA_DEV_UNKNOWN &&
- !(lflags & ATA_LFLAG_ASSUME_CLASS)) {
- ata_link_printk(link, KERN_ERR,
- "classification failed\n");
- rc = -EINVAL;
- goto out;
- }
}
/* -EAGAIN can happen if we skipped followup SRST */
if (rc && rc != -EAGAIN)
goto fail;
+ /* was classification successful? */
+ if (classify && classes[0] == ATA_DEV_UNKNOWN &&
+ !(lflags & ATA_LFLAG_ASSUME_CLASS)) {
+ if (try < max_tries) {
+ ata_link_printk(link, KERN_WARNING,
+ "classification failed\n");
+ rc = -EINVAL;
+ goto fail;
+ }
+
+ ata_link_printk(link, KERN_WARNING,
+ "classfication failed, assuming ATA\n");
+ lflags |= ATA_LFLAG_ASSUME_ATA;
+ }
+
ata_link_for_each_dev(dev, link) {
/* After the reset, the device state is PIO 0 and the
* controller state is undefined. Reset also wakes up