]> err.no Git - linux-2.6/blobdiff - drivers/ata/libata-sff.c
Merge branch 'upstream-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jgarzi...
[linux-2.6] / drivers / ata / libata-sff.c
index 78912c5011adc3248738b512019937a6a7623d4a..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,
@@ -1206,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;
 
@@ -1220,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;
 
@@ -1406,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...)
@@ -1868,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);
@@ -1898,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;
 }
@@ -1921,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;
 }
 
 /**
@@ -2062,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,
@@ -2757,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);