aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-core.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata/libata-core.c')
-rw-r--r--drivers/ata/libata-core.c67
1 files changed, 54 insertions, 13 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 50ae20101d10..8ee56e5cfb0c 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -3118,6 +3118,55 @@ int ata_busy_sleep(struct ata_port *ap,
}
/**
+ * ata_wait_after_reset - wait before checking status after reset
+ * @ap: port containing status register to be polled
+ * @deadline: deadline jiffies for the operation
+ *
+ * After reset, we need to pause a while before reading status.
+ * Also, certain combination of controller and device report 0xff
+ * for some duration (e.g. until SATA PHY is up and running)
+ * which is interpreted as empty port in ATA world. This
+ * function also waits for such devices to get out of 0xff
+ * status.
+ *
+ * LOCKING:
+ * Kernel thread context (may sleep).
+ */
+void ata_wait_after_reset(struct ata_port *ap, unsigned long deadline)
+{
+ unsigned long until = jiffies + ATA_TMOUT_FF_WAIT;
+
+ if (time_before(until, deadline))
+ deadline = until;
+
+ /* Spec mandates ">= 2ms" before checking status. We wait
+ * 150ms, because that was the magic delay used for ATAPI
+ * devices in Hale Landis's ATADRVR, for the period of time
+ * between when the ATA command register is written, and then
+ * status is checked. Because waiting for "a while" before
+ * checking status is fine, post SRST, we perform this magic
+ * delay here as well.
+ *
+ * Old drivers/ide uses the 2mS rule and then waits for ready.
+ */
+ msleep(150);
+
+ /* Wait for 0xff to clear. 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.
+ */
+ while (1) {
+ u8 status = ata_chk_status(ap);
+
+ if (status != 0xff || time_after(jiffies, deadline))
+ return;
+
+ msleep(50);
+ }
+}
+
+/**
* ata_wait_ready - sleep until BSY clears, or timeout
* @ap: port containing status register to be polled
* @deadline: deadline jiffies for the operation
@@ -3254,17 +3303,8 @@ static int ata_bus_softreset(struct ata_port *ap, unsigned int devmask,
ap->ops->set_piomode(ap, dev);
}
- /* spec mandates ">= 2ms" before checking status.
- * We wait 150ms, because that was the magic delay used for
- * ATAPI devices in Hale Landis's ATADRVR, for the period of time
- * between when the ATA command register is written, and then
- * status is checked. Because waiting for "a while" before
- * checking status is fine, post SRST, we perform this magic
- * delay here as well.
- *
- * Old drivers/ide uses the 2mS rule and then waits for ready
- */
- msleep(150);
+ /* wait a while before checking status */
+ ata_wait_after_reset(ap, deadline);
/* Before we perform post reset processing we want to see if
* the bus shows 0xFF because the odd clown forgets the D7
@@ -3691,8 +3731,8 @@ int sata_std_hardreset(struct ata_link *link, unsigned int *class,
return 0;
}
- /* wait a while before checking status, see SRST for more info */
- msleep(150);
+ /* wait a while before checking status */
+ ata_wait_after_reset(ap, deadline);
/* If PMP is supported, we have to do follow-up SRST. Note
* that some PMPs don't send D2H Reg FIS after hardreset at
@@ -7358,6 +7398,7 @@ EXPORT_SYMBOL_GPL(ata_port_disable);
EXPORT_SYMBOL_GPL(ata_ratelimit);
EXPORT_SYMBOL_GPL(ata_wait_register);
EXPORT_SYMBOL_GPL(ata_busy_sleep);
+EXPORT_SYMBOL_GPL(ata_wait_after_reset);
EXPORT_SYMBOL_GPL(ata_wait_ready);
EXPORT_SYMBOL_GPL(ata_port_queue_task);
EXPORT_SYMBOL_GPL(ata_scsi_ioctl);