summaryrefslogtreecommitdiff
path: root/drivers/ata/libata-sff.c
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2008-04-07 22:47:19 +0900
committerJeff Garzik <jgarzik@redhat.com>2008-04-17 15:44:22 -0400
commitaa2731ad9ad80ac3fca48bd1c4cf0eceede4810e (patch)
treedb6d3327017b9b84355aba49a5ccd5c322d3f248 /drivers/ata/libata-sff.c
parent705e76beb90b97421e1f61e857c4246799781bb5 (diff)
libata: separate out ata_wait_ready() and implement ata_wait_after_reset()
Factor out waiting logic (which is common to all ATA controllers) from ata_sff_wait_ready() into ata_wait_ready(). ata_wait_ready() takes @check_ready function pointer and uses it to poll for readiness. This allows non-SFF controllers to use ata_wait_ready() to wait for link readiness. This patch also implements ata_wait_after_reset() - generic version of ata_sff_wait_after_reset() - using ata_wait_ready(). ata_sff_wait_ready() is reimplemented using ata_wait_ready() and ata_sff_check_ready(). Functionality remains the same. Signed-off-by: Tejun Heo <htejun@gmail.com>
Diffstat (limited to 'drivers/ata/libata-sff.c')
-rw-r--r--drivers/ata/libata-sff.c62
1 files changed, 12 insertions, 50 deletions
diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c
index 6e8de3c1595e..78912c5011ad 100644
--- a/drivers/ata/libata-sff.c
+++ b/drivers/ata/libata-sff.c
@@ -308,6 +308,17 @@ int ata_sff_busy_sleep(struct ata_port *ap,
return 0;
}
+static int ata_sff_check_ready(struct ata_link *link)
+{
+ u8 status = link->ap->ops->sff_check_status(link->ap);
+
+ if (!(status & ATA_BUSY))
+ return 1;
+ if (status == 0xff)
+ return -ENODEV;
+ return 0;
+}
+
/**
* ata_sff_wait_ready - sleep until BSY clears, or timeout
* @link: SFF link to wait ready status for
@@ -324,56 +335,7 @@ int ata_sff_busy_sleep(struct ata_port *ap,
*/
int ata_sff_wait_ready(struct ata_link *link, unsigned long deadline)
{
- struct ata_port *ap = link->ap;
- unsigned long start = jiffies;
- unsigned long nodev_deadline = start + ATA_TMOUT_FF_WAIT;
- int warned = 0;
-
- if (time_after(nodev_deadline, deadline))
- nodev_deadline = deadline;
-
- while (1) {
- u8 status = ap->ops->sff_check_status(ap);
- unsigned long now = jiffies;
-
- if (!(status & ATA_BUSY))
- return 0;
-
- /* No device status could be transient. Ignore it if
- * link is online. Also, some SATA devices take a
- * long time to clear 0xff after reset. For example,
- * HHD424020F7SV00 iVDR needs >= 800ms while Quantum
- * GoVault needs even more than that. Wait for
- * ATA_TMOUT_FF_WAIT on -ENODEV if link isn't offline.
- *
- * Note that some PATA controllers (pata_ali) explode
- * if status register is read more than once when
- * there's no device attached.
- */
- if (status == 0xff) {
- if (ata_link_online(link))
- status = ATA_BUSY;
- else if ((link->ap->flags & ATA_FLAG_SATA) &&
- !ata_link_offline(link) &&
- time_before(now, nodev_deadline))
- status = ATA_BUSY;
- if (status == 0xff)
- return -ENODEV;
- }
-
- if (time_after(now, deadline))
- return -EBUSY;
-
- if (!warned && time_after(now, start + 5 * HZ) &&
- (deadline - now > 3 * HZ)) {
- ata_link_printk(link, KERN_WARNING,
- "link is slow to respond, please be patient "
- "(Status 0x%x)\n", status);
- warned = 1;
- }
-
- msleep(50);
- }
+ return ata_wait_ready(link, deadline, ata_sff_check_ready);
}
/**