aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-eh.c
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-02-02 02:50:52 -0500
committerJeff Garzik <jeff@garzik.org>2007-05-01 07:49:53 -0400
commitd4b2bab4f26345ea1803feb23ea92fbe3f6b77bc (patch)
tree30a9826351e597828de2b402f1c41b9fca94cf95 /drivers/ata/libata-eh.c
parentdc87c3985e9b442c60994308a96f887579addc39 (diff)
libata: add deadline support to prereset and reset methods
Add @deadline to prereset and reset methods and make them honor it. ata_wait_ready() which directly takes @deadline is implemented to be used as the wait function. This patch is in preparation for EH timing improvements. * ata_wait_ready() never does busy sleep. It's only used from EH and no wait in EH is that urgent. This function also prints 'be patient' message automatically after 5 secs of waiting if more than 3 secs is remaining till deadline. * ata_bus_post_reset() now fails with error code if any of its wait fails. This is important because earlier reset tries will have shorter timeout than the spec requires. If a device fails to respond before the short timeout, reset should be retried with longer timeout rather than silently ignoring the device. There are three behavior differences. 1. Timeout is applied to both devices at once, not separately. This is more consistent with what the spec says. 2. When a device passes devchk but fails to become ready before deadline. Previouly, post_reset would just succeed and let device classification remove the device. New code fails the reset thus causing reset retry. After a few times, EH will give up disabling the port. 3. When slave device passes devchk but fails to become accessible (TF-wise) after reset. Original code disables dev1 after 30s timeout and continues as if the device doesn't exist, while the patched code fails reset. When this happens, new code fails reset on whole port rather than proceeding with only the primary device. If the failing device is suffering transient problems, new code retries reset which is a better behavior. If the failing device is actually broken, the net effect is identical to it, but not to the other device sharing the channel. In the previous code, reset would have succeeded after 30s thus detecting the working one. In the new code, reset fails and whole port gets disabled. IMO, it's a pathological case anyway (broken device sharing bus with working one) and doesn't really matter. * ata_bus_softreset() is changed to return error code from ata_bus_post_reset(). It used to return 0 unconditionally. * Spin up waiting is to be removed and not converted to honor deadline. * To be on the safe side, deadline is set to 40s for the time being. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata/libata-eh.c')
-rw-r--r--drivers/ata/libata-eh.c10
1 files changed, 5 insertions, 5 deletions
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index 2bff9adcacf1..b3f7d3c8ae60 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -1558,14 +1558,14 @@ static void ata_eh_report(struct ata_port *ap)
1558} 1558}
1559 1559
1560static int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset, 1560static int ata_do_reset(struct ata_port *ap, ata_reset_fn_t reset,
1561 unsigned int *classes) 1561 unsigned int *classes, unsigned long deadline)
1562{ 1562{
1563 int i, rc; 1563 int i, rc;
1564 1564
1565 for (i = 0; i < ATA_MAX_DEVICES; i++) 1565 for (i = 0; i < ATA_MAX_DEVICES; i++)
1566 classes[i] = ATA_DEV_UNKNOWN; 1566 classes[i] = ATA_DEV_UNKNOWN;
1567 1567
1568 rc = reset(ap, classes); 1568 rc = reset(ap, classes, deadline);
1569 if (rc) 1569 if (rc)
1570 return rc; 1570 return rc;
1571 1571
@@ -1624,7 +1624,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
1624 ehc->i.action |= ATA_EH_HARDRESET; 1624 ehc->i.action |= ATA_EH_HARDRESET;
1625 1625
1626 if (prereset) { 1626 if (prereset) {
1627 rc = prereset(ap); 1627 rc = prereset(ap, jiffies + 40 * HZ);
1628 if (rc) { 1628 if (rc) {
1629 if (rc == -ENOENT) { 1629 if (rc == -ENOENT) {
1630 ata_port_printk(ap, KERN_DEBUG, 1630 ata_port_printk(ap, KERN_DEBUG,
@@ -1676,7 +1676,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
1676 else 1676 else
1677 ehc->i.flags |= ATA_EHI_DID_SOFTRESET; 1677 ehc->i.flags |= ATA_EHI_DID_SOFTRESET;
1678 1678
1679 rc = ata_do_reset(ap, reset, classes); 1679 rc = ata_do_reset(ap, reset, classes, jiffies + 40 * HZ);
1680 1680
1681 did_followup_srst = 0; 1681 did_followup_srst = 0;
1682 if (reset == hardreset && 1682 if (reset == hardreset &&
@@ -1693,7 +1693,7 @@ static int ata_eh_reset(struct ata_port *ap, int classify,
1693 } 1693 }
1694 1694
1695 ata_eh_about_to_do(ap, NULL, ATA_EH_RESET_MASK); 1695 ata_eh_about_to_do(ap, NULL, ATA_EH_RESET_MASK);
1696 rc = ata_do_reset(ap, reset, classes); 1696 rc = ata_do_reset(ap, reset, classes, jiffies + 40 * HZ);
1697 1697
1698 if (rc == 0 && classify && 1698 if (rc == 0 && classify &&
1699 classes[0] == ATA_DEV_UNKNOWN) { 1699 classes[0] == ATA_DEV_UNKNOWN) {