Commit 08cf69d0 authored by Tejun Heo's avatar Tejun Heo Committed by Jeff Garzik

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: default avatarTejun Heo <htejun@gmail.com>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent 416dc9ed
...@@ -2184,25 +2184,32 @@ int ata_eh_reset(struct ata_link *link, int classify, ...@@ -2184,25 +2184,32 @@ int ata_eh_reset(struct ata_link *link, int classify,
"follow-up softreset required " "follow-up softreset required "
"but no softreset avaliable\n"); "but no softreset avaliable\n");
rc = -EINVAL; rc = -EINVAL;
goto out; goto fail;
} }
ata_eh_about_to_do(link, NULL, ATA_EH_RESET_MASK); ata_eh_about_to_do(link, NULL, ATA_EH_RESET_MASK);
rc = ata_do_reset(link, reset, classes, deadline); 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 */ /* -EAGAIN can happen if we skipped followup SRST */
if (rc && rc != -EAGAIN) if (rc && rc != -EAGAIN)
goto fail; 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) { ata_link_for_each_dev(dev, link) {
/* After the reset, the device state is PIO 0 and the /* After the reset, the device state is PIO 0 and the
* controller state is undefined. Reset also wakes up * controller state is undefined. Reset also wakes up
......
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