libata: implement ata_wait_after_reset()
[deliverable/linux.git] / drivers / ata / libata-core.c
index 50ae20101d10f555615165154bd5428e6fbec1b4..8ee56e5cfb0c945cb067c15e0d33a81dca3bf922 100644 (file)
@@ -3117,6 +3117,55 @@ int ata_busy_sleep(struct ata_port *ap,
        return 0;
 }
 
+/**
+ *     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
@@ -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);
This page took 0.027912 seconds and 5 git commands to generate.