]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/ata/libata-sff.c
pasemi_edac needs to include linux/edac.h
[linux-2.6-omap-h63xx.git] / drivers / ata / libata-sff.c
index 6e8de3c1595e86b081e557009befb149e8b3d7fb..2ec65a8fda79ecc46986ed0da6de7d886c71ccf5 100644 (file)
@@ -44,11 +44,13 @@ const struct ata_port_operations ata_sff_port_ops = {
 
        .qc_prep                = ata_sff_qc_prep,
        .qc_issue               = ata_sff_qc_issue,
+       .qc_fill_rtf            = ata_sff_qc_fill_rtf,
 
        .freeze                 = ata_sff_freeze,
        .thaw                   = ata_sff_thaw,
        .prereset               = ata_sff_prereset,
        .softreset              = ata_sff_softreset,
+       .hardreset              = sata_sff_hardreset,
        .postreset              = ata_sff_postreset,
        .error_handler          = ata_sff_error_handler,
        .post_internal_cmd      = ata_sff_post_internal_cmd,
@@ -308,6 +310,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 +337,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);
 }
 
 /**
@@ -1244,7 +1208,7 @@ fsm_start:
                DPRINTK("ata%u: dev %u command complete, drv_stat 0x%x\n",
                        ap->print_id, qc->dev->devno, status);
 
-               WARN_ON(qc->err_mask);
+               WARN_ON(qc->err_mask & (AC_ERR_DEV | AC_ERR_HSM));
 
                ap->hsm_task_state = HSM_ST_IDLE;
 
@@ -1258,7 +1222,7 @@ fsm_start:
                /* make sure qc->err_mask is available to
                 * know what's wrong and recover
                 */
-               WARN_ON(qc->err_mask == 0);
+               WARN_ON(!(qc->err_mask & (AC_ERR_DEV | AC_ERR_HSM)));
 
                ap->hsm_task_state = HSM_ST_IDLE;
 
@@ -1444,6 +1408,25 @@ unsigned int ata_sff_qc_issue(struct ata_queued_cmd *qc)
        return 0;
 }
 
+/**
+ *     ata_sff_qc_fill_rtf - fill result TF using ->sff_tf_read
+ *     @qc: qc to fill result TF for
+ *
+ *     @qc is finished and result TF needs to be filled.  Fill it
+ *     using ->sff_tf_read.
+ *
+ *     LOCKING:
+ *     spin_lock_irqsave(host lock)
+ *
+ *     RETURNS:
+ *     true indicating that result TF is successfully filled.
+ */
+bool ata_sff_qc_fill_rtf(struct ata_queued_cmd *qc)
+{
+       qc->ap->ops->sff_tf_read(qc->ap, &qc->result_tf);
+       return true;
+}
+
 /**
  *     ata_sff_host_intr - Handle host interrupt for given (port, task)
  *     @ap: Port on which interrupt arrived (possibly...)
@@ -1906,11 +1889,6 @@ int ata_sff_softreset(struct ata_link *link, unsigned int *classes,
 
        DPRINTK("ENTER\n");
 
-       if (ata_link_offline(link)) {
-               classes[0] = ATA_DEV_NONE;
-               goto out;
-       }
-
        /* determine if device 0/1 are present */
        if (ata_devchk(ap, 0))
                devmask |= (1 << 0);
@@ -1936,7 +1914,6 @@ int ata_sff_softreset(struct ata_link *link, unsigned int *classes,
                classes[1] = ata_sff_dev_classify(&link->device[1],
                                                  devmask & (1 << 1), &err);
 
- out:
        DPRINTK("EXIT, classes[0]=%u [1]=%u\n", classes[0], classes[1]);
        return 0;
 }
@@ -1959,50 +1936,18 @@ int ata_sff_softreset(struct ata_link *link, unsigned int *classes,
 int sata_sff_hardreset(struct ata_link *link, unsigned int *class,
                       unsigned long deadline)
 {
-       struct ata_port *ap = link->ap;
-       const unsigned long *timing = sata_ehc_deb_timing(&link->eh_context);
+       struct ata_eh_context *ehc = &link->eh_context;
+       const unsigned long *timing = sata_ehc_deb_timing(ehc);
+       bool online;
        int rc;
 
-       DPRINTK("ENTER\n");
-
-       /* do hardreset */
-       rc = sata_link_hardreset(link, timing, deadline);
-       if (rc) {
-               ata_link_printk(link, KERN_ERR,
-                               "COMRESET failed (errno=%d)\n", rc);
-               return rc;
-       }
-
-       /* TODO: phy layer with polling, timeouts, etc. */
-       if (ata_link_offline(link)) {
-               *class = ATA_DEV_NONE;
-               DPRINTK("EXIT, link offline\n");
-               return 0;
-       }
-
-       /* If PMP is supported, we have to do follow-up SRST.  Note
-        * that some PMPs don't send D2H Reg FIS after hardreset at
-        * all if the first port is empty.  Wait for it just for a
-        * second and request follow-up SRST.
-        */
-       if (ap->flags & ATA_FLAG_PMP) {
-               ata_sff_wait_after_reset(link, 1, jiffies + HZ);
-               return -EAGAIN;
-       }
-
-       /* wait for the link to become online */
-       rc = ata_sff_wait_after_reset(link, 1, deadline);
-       /* link occupied, -ENODEV too is an error */
-       if (rc) {
-               ata_link_printk(link, KERN_ERR,
-                               "COMRESET failed (errno=%d)\n", rc);
-               return rc;
-       }
-
-       *class = ata_sff_dev_classify(link->device, 1, NULL);
+       rc = sata_link_hardreset(link, timing, deadline, &online,
+                                ata_sff_check_ready);
+       if (online)
+               *class = ata_sff_dev_classify(link->device, 1, NULL);
 
        DPRINTK("EXIT, class=%u\n", *class);
-       return 0;
+       return rc;
 }
 
 /**
@@ -2100,14 +2045,12 @@ void ata_sff_error_handler(struct ata_port *ap)
 
        /* PIO and DMA engines have been stopped, perform recovery */
 
-       /* ata_sff_softreset and sata_sff_hardreset are inherited to
-        * all SFF drivers from ata_sff_port_ops.  Ignore softreset if
-        * ctl isn't accessible.  Ignore hardreset if SCR access isn't
-        * available.
+       /* Ignore ata_sff_softreset if ctl isn't accessible and
+        * built-in hardresets if SCR access isn't available.
         */
        if (softreset == ata_sff_softreset && !ap->ioaddr.ctl_addr)
                softreset = NULL;
-       if (hardreset == sata_sff_hardreset && !sata_scr_valid(&ap->link))
+       if (ata_is_builtin_hardreset(hardreset) && !sata_scr_valid(&ap->link))
                hardreset = NULL;
 
        ata_do_eh(ap, ap->ops->prereset, softreset, hardreset,
@@ -2795,6 +2738,7 @@ EXPORT_SYMBOL_GPL(ata_sff_irq_on);
 EXPORT_SYMBOL_GPL(ata_sff_irq_clear);
 EXPORT_SYMBOL_GPL(ata_sff_hsm_move);
 EXPORT_SYMBOL_GPL(ata_sff_qc_issue);
+EXPORT_SYMBOL_GPL(ata_sff_qc_fill_rtf);
 EXPORT_SYMBOL_GPL(ata_sff_host_intr);
 EXPORT_SYMBOL_GPL(ata_sff_interrupt);
 EXPORT_SYMBOL_GPL(ata_sff_freeze);