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>
This commit is contained in:
Tejun Heo
2008-04-07 22:47:19 +09:00
committed by Jeff Garzik
parent 705e76beb9
commit aa2731ad9a
4 changed files with 114 additions and 50 deletions
+12 -50
View File
@@ -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);
}
/**