You've already forked linux-apfs
mirror of
https://github.com/linux-apfs/linux-apfs.git
synced 2026-05-01 15:00:59 -07:00
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:
+12
-50
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user