libata: implement and use ATA_QCFLAG_QUIET
[safe/jmp/linux-2.6] / drivers / ata / libata-eh.c
index 60186f8..8d64f8f 100644 (file)
@@ -33,6 +33,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/pci.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_host.h>
 #include <scsi/scsi_eh.h>
@@ -1196,7 +1197,7 @@ void ata_eh_done(struct ata_link *link, struct ata_device *dev,
  *     RETURNS:
  *     Descriptive string for @err_mask
  */
-static const char * ata_err_string(unsigned int err_mask)
+static const char *ata_err_string(unsigned int err_mask)
 {
        if (err_mask & AC_ERR_HOST_BUS)
                return "host bus error";
@@ -1249,7 +1250,7 @@ static unsigned int ata_read_log_page(struct ata_device *dev,
        tf.protocol = ATA_PROT_PIO;
 
        err_mask = ata_exec_internal(dev, &tf, NULL, DMA_FROM_DEVICE,
-                                    buf, sectors * ATA_SECT_SIZE);
+                                    buf, sectors * ATA_SECT_SIZE, 0);
 
        DPRINTK("EXIT, err_mask=%x\n", err_mask);
        return err_mask;
@@ -1363,7 +1364,7 @@ static unsigned int atapi_eh_request_sense(struct ata_queued_cmd *qc)
        }
 
        return ata_exec_internal(dev, &tf, cdb, DMA_FROM_DEVICE,
-                                sense_buf, SCSI_SENSE_BUFFERSIZE);
+                                sense_buf, SCSI_SENSE_BUFFERSIZE, 0);
 }
 
 /**
@@ -1799,10 +1800,8 @@ static void ata_eh_link_autopsy(struct ata_link *link)
                        qc->err_mask &= ~AC_ERR_OTHER;
 
                /* SENSE_VALID trumps dev/unknown error and revalidation */
-               if (qc->flags & ATA_QCFLAG_SENSE_VALID) {
+               if (qc->flags & ATA_QCFLAG_SENSE_VALID)
                        qc->err_mask &= ~(AC_ERR_DEV | AC_ERR_OTHER);
-                       ehc->i.action &= ~ATA_EH_REVALIDATE;
-               }
 
                /* accumulate error info */
                ehc->i.dev = qc->dev;
@@ -1815,7 +1814,8 @@ static void ata_eh_link_autopsy(struct ata_link *link)
        if (ap->pflags & ATA_PFLAG_FROZEN ||
            all_err_mask & (AC_ERR_HSM | AC_ERR_TIMEOUT))
                ehc->i.action |= ATA_EH_SOFTRESET;
-       else if (all_err_mask)
+       else if ((is_io && all_err_mask) ||
+                (!is_io && (all_err_mask & ~AC_ERR_DEV)))
                ehc->i.action |= ATA_EH_REVALIDATE;
 
        /* if we have offending qcs and the associated failed device */
@@ -1868,6 +1868,9 @@ static void ata_eh_link_report(struct ata_link *link)
        char tries_buf[6];
        int tag, nr_failed = 0;
 
+       if (ehc->i.flags & ATA_EHI_QUIET)
+               return;
+
        desc = NULL;
        if (ehc->i.desc[0] != '\0')
                desc = ehc->i.desc;
@@ -1875,7 +1878,9 @@ static void ata_eh_link_report(struct ata_link *link)
        for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
                struct ata_queued_cmd *qc = __ata_qc_from_tag(ap, tag);
 
-               if (!(qc->flags & ATA_QCFLAG_FAILED) || qc->dev->link != link)
+               if (!(qc->flags & ATA_QCFLAG_FAILED) || qc->dev->link != link ||
+                   ((qc->flags & ATA_QCFLAG_QUIET) &&
+                    qc->err_mask == AC_ERR_DEV))
                        continue;
                if (qc->flags & ATA_QCFLAG_SENSE_VALID && !qc->err_mask)
                        continue;
@@ -1911,6 +1916,27 @@ static void ata_eh_link_report(struct ata_link *link)
                        ata_link_printk(link, KERN_ERR, "%s\n", desc);
        }
 
+       if (ehc->i.serror)
+               ata_port_printk(ap, KERN_ERR,
+                 "SError: { %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s}\n",
+                 ehc->i.serror & SERR_DATA_RECOVERED ? "RecovData " : "",
+                 ehc->i.serror & SERR_COMM_RECOVERED ? "RecovComm " : "",
+                 ehc->i.serror & SERR_DATA ? "UnrecovData " : "",
+                 ehc->i.serror & SERR_PERSISTENT ? "Persist " : "",
+                 ehc->i.serror & SERR_PROTOCOL ? "Proto " : "",
+                 ehc->i.serror & SERR_INTERNAL ? "HostInt " : "",
+                 ehc->i.serror & SERR_PHYRDY_CHG ? "PHYRdyChg " : "",
+                 ehc->i.serror & SERR_PHY_INT_ERR ? "PHYInt " : "",
+                 ehc->i.serror & SERR_COMM_WAKE ? "CommWake " : "",
+                 ehc->i.serror & SERR_10B_8B_ERR ? "10B8B " : "",
+                 ehc->i.serror & SERR_DISPARITY ? "Dispar " : "",
+                 ehc->i.serror & SERR_CRC ? "BadCRC " : "",
+                 ehc->i.serror & SERR_HANDSHAKE ? "Handshk " : "",
+                 ehc->i.serror & SERR_LINK_SEQ_ERR ? "LinkSeq " : "",
+                 ehc->i.serror & SERR_TRANS_ST_ERROR ? "TrStaTrns " : "",
+                 ehc->i.serror & SERR_UNRECOG_FIS ? "UnrecFIS " : "",
+                 ehc->i.serror & SERR_DEV_XCHG ? "DevExch " : "");
+
        for (tag = 0; tag < ATA_MAX_QUEUE; tag++) {
                static const char *dma_str[] = {
                        [DMA_BIDIRECTIONAL]     = "bidi",
@@ -1942,6 +1968,30 @@ static void ata_eh_link_report(struct ata_link *link)
                        res->hob_lbal, res->hob_lbam, res->hob_lbah,
                        res->device, qc->err_mask, ata_err_string(qc->err_mask),
                        qc->err_mask & AC_ERR_NCQ ? " <F>" : "");
+
+               if (res->command & (ATA_BUSY | ATA_DRDY | ATA_DF | ATA_DRQ |
+                                   ATA_ERR)) {
+                       if (res->command & ATA_BUSY)
+                               ata_dev_printk(qc->dev, KERN_ERR,
+                                 "status: { Busy }\n");
+                       else
+                               ata_dev_printk(qc->dev, KERN_ERR,
+                                 "status: { %s%s%s%s}\n",
+                                 res->command & ATA_DRDY ? "DRDY " : "",
+                                 res->command & ATA_DF ? "DF " : "",
+                                 res->command & ATA_DRQ ? "DRQ " : "",
+                                 res->command & ATA_ERR ? "ERR " : "");
+               }
+
+               if (cmd->command != ATA_CMD_PACKET &&
+                   (res->feature & (ATA_ICRC | ATA_UNC | ATA_IDNF |
+                                    ATA_ABORTED)))
+                       ata_dev_printk(qc->dev, KERN_ERR,
+                         "error: { %s%s%s%s}\n",
+                         res->feature & ATA_ICRC ? "ICRC " : "",
+                         res->feature & ATA_UNC ? "UNC " : "",
+                         res->feature & ATA_IDNF ? "IDNF " : "",
+                         res->feature & ATA_ABORTED ? "ABRT " : "");
        }
 }
 
@@ -2003,6 +2053,8 @@ static int ata_eh_followup_srst_needed(struct ata_link *link,
                return 1;
        if (rc != 0)
                return 0;
+       if ((link->ap->flags & ATA_FLAG_PMP) && ata_is_host_link(link))
+               return 1;
        if (classify && !(link->flags & ATA_LFLAG_ASSUME_CLASS) &&
            classes[0] == ATA_DEV_UNKNOWN)
                return 1;
@@ -2013,30 +2065,55 @@ int ata_eh_reset(struct ata_link *link, int classify,
                 ata_prereset_fn_t prereset, ata_reset_fn_t softreset,
                 ata_reset_fn_t hardreset, ata_postreset_fn_t postreset)
 {
+       struct ata_port *ap = link->ap;
        struct ata_eh_context *ehc = &link->eh_context;
        unsigned int *classes = ehc->classes;
        int verbose = !(ehc->i.flags & ATA_EHI_QUIET);
        int try = 0;
        struct ata_device *dev;
        unsigned long deadline;
-       unsigned int action;
+       unsigned int tmp_action;
        ata_reset_fn_t reset;
+       unsigned long flags;
        int rc;
 
        /* about to reset */
+       spin_lock_irqsave(ap->lock, flags);
+       ap->pflags |= ATA_PFLAG_RESETTING;
+       spin_unlock_irqrestore(ap->lock, flags);
+
        ata_eh_about_to_do(link, NULL, ehc->i.action & ATA_EH_RESET_MASK);
 
+       ata_link_for_each_dev(dev, link) {
+               /* If we issue an SRST then an ATA drive (not ATAPI)
+                * may change configuration and be in PIO0 timing. If
+                * we do a hard reset (or are coming from power on)
+                * this is true for ATA or ATAPI. Until we've set a
+                * suitable controller mode we should not touch the
+                * bus as we may be talking too fast.
+                */
+               dev->pio_mode = XFER_PIO_0;
+
+               /* If the controller has a pio mode setup function
+                * then use it to set the chipset to rights. Don't
+                * touch the DMA setup as that will be dealt with when
+                * configuring devices.
+                */
+               if (ap->ops->set_piomode)
+                       ap->ops->set_piomode(ap, dev);
+       }
+
        /* Determine which reset to use and record in ehc->i.action.
         * prereset() may examine and modify it.
         */
-       action = ehc->i.action;
-       ehc->i.action &= ~ATA_EH_RESET_MASK;
        if (softreset && (!hardreset || (!(link->flags & ATA_LFLAG_NO_SRST) &&
                                         !sata_set_spd_needed(link) &&
-                                        !(action & ATA_EH_HARDRESET))))
-               ehc->i.action |= ATA_EH_SOFTRESET;
+                                        !(ehc->i.action & ATA_EH_HARDRESET))))
+               tmp_action = ATA_EH_SOFTRESET;
        else
-               ehc->i.action |= ATA_EH_HARDRESET;
+               tmp_action = ATA_EH_HARDRESET;
+
+       ehc->i.action = (ehc->i.action & ~ATA_EH_RESET_MASK) | tmp_action;
 
        if (prereset) {
                rc = prereset(link, jiffies + ATA_EH_PRERESET_TIMEOUT);
@@ -2133,7 +2210,8 @@ int ata_eh_reset(struct ata_link *link, int classify,
                                "(errno=%d), retrying in %u secs\n",
                                rc, (jiffies_to_msecs(delta) + 999) / 1000);
 
-                       schedule_timeout_uninterruptible(delta);
+                       while (delta)
+                               delta = schedule_timeout_uninterruptible(delta);
                }
 
                if (rc == -EPIPE ||
@@ -2150,9 +2228,11 @@ int ata_eh_reset(struct ata_link *link, int classify,
                ata_link_for_each_dev(dev, link) {
                        /* After the reset, the device state is PIO 0
                         * and the controller state is undefined.
-                        * Record the mode.
+                        * Reset also wakes up drives from sleeping
+                        * mode.
                         */
                        dev->pio_mode = XFER_PIO_0;
+                       dev->flags &= ~ATA_DFLAG_SLEEPING;
 
                        if (ata_link_offline(link))
                                continue;
@@ -2180,6 +2260,11 @@ int ata_eh_reset(struct ata_link *link, int classify,
  out:
        /* clear hotplug flag */
        ehc->i.flags &= ~ATA_EHI_HOTPLUGGED;
+
+       spin_lock_irqsave(ap->lock, flags);
+       ap->pflags &= ~ATA_PFLAG_RESETTING;
+       spin_unlock_irqrestore(ap->lock, flags);
+
        return rc;
 }
 
@@ -2207,6 +2292,8 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
                        readid_flags |= ATA_READID_POSTRESET;
 
                if ((action & ATA_EH_REVALIDATE) && ata_dev_enabled(dev)) {
+                       WARN_ON(dev->class == ATA_DEV_PMP);
+
                        if (ata_link_offline(link)) {
                                rc = -EIO;
                                goto err;
@@ -2232,8 +2319,11 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
                           ata_class_enabled(ehc->classes[dev->devno])) {
                        dev->class = ehc->classes[dev->devno];
 
-                       rc = ata_dev_read_id(dev, &dev->class, readid_flags,
-                                            dev->id);
+                       if (dev->class == ATA_DEV_PMP)
+                               rc = sata_pmp_attach(dev);
+                       else
+                               rc = ata_dev_read_id(dev, &dev->class,
+                                                    readid_flags, dev->id);
                        switch (rc) {
                        case 0:
                                new_mask |= 1 << dev->devno;
@@ -2262,7 +2352,8 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
         * device detection messages backwards.
         */
        ata_link_for_each_dev(dev, link) {
-               if (!(new_mask & (1 << dev->devno)))
+               if (!(new_mask & (1 << dev->devno)) ||
+                   dev->class == ATA_DEV_PMP)
                        continue;
 
                ehc->i.flags |= ATA_EHI_PRINTINFO;
@@ -2347,7 +2438,7 @@ static int ata_eh_handle_dev_fail(struct ata_device *dev, int err)
                /* give it just one more chance */
                ehc->tries[dev->devno] = min(ehc->tries[dev->devno], 1);
        case -EIO:
-               if (ehc->tries[dev->devno] == 1) {
+               if (ehc->tries[dev->devno] == 1 && dev->pio_mode > XFER_PIO_0) {
                        /* This is the last chance, better to slow
                         * down than lose it.
                         */
@@ -2489,7 +2580,11 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
 
        /* reset */
        if (reset) {
-               ata_eh_freeze_port(ap);
+               /* if PMP is attached, this function only deals with
+                * downstream links, port should stay thawed.
+                */
+               if (!ap->nr_pmp_links)
+                       ata_eh_freeze_port(ap);
 
                ata_port_for_each_link(link, ap) {
                        struct ata_eh_context *ehc = &link->eh_context;
@@ -2507,7 +2602,8 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
                        }
                }
 
-               ata_eh_thaw_port(ap);
+               if (!ap->nr_pmp_links)
+                       ata_eh_thaw_port(ap);
        }
 
        /* the rest */
@@ -2519,6 +2615,12 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
                if (rc)
                        goto dev_fail;
 
+               /* if PMP got attached, return, pmp EH will take care of it */
+               if (link->device->class == ATA_DEV_PMP) {
+                       ehc->i.action = 0;
+                       return 0;
+               }
+
                /* configure transfer mode if necessary */
                if (ehc->i.flags & ATA_EHI_SETMODE) {
                        rc = ata_set_mode(link, &dev);
@@ -2527,17 +2629,27 @@ int ata_eh_recover(struct ata_port *ap, ata_prereset_fn_t prereset,
                        ehc->i.flags &= ~ATA_EHI_SETMODE;
                }
 
+               if (ehc->i.action & ATA_EHI_LPM)
+                       ata_link_for_each_dev(dev, link)
+                               ata_dev_enable_pm(dev, ap->pm_policy);
+
                /* this link is okay now */
                ehc->i.flags = 0;
                continue;
 
-       dev_fail:
+dev_fail:
                nr_failed_devs++;
                if (ata_eh_handle_dev_fail(dev, rc))
                        nr_disabled_devs++;
 
-               if (ap->pflags & ATA_PFLAG_FROZEN)
+               if (ap->pflags & ATA_PFLAG_FROZEN) {
+                       /* PMP reset requires working host port.
+                        * Can't retry if it's frozen.
+                        */
+                       if (ap->nr_pmp_links)
+                               goto out;
                        break;
+               }
        }
 
        if (nr_failed_devs) {
@@ -2586,8 +2698,15 @@ void ata_eh_finish(struct ata_port *ap)
                        /* FIXME: Once EH migration is complete,
                         * generate sense data in this function,
                         * considering both err_mask and tf.
+                        *
+                        * There's no point in retrying invalid
+                        * (detected by libata) and non-IO device
+                        * errors (rejected by device).  Finish them
+                        * immediately.
                         */
-                       if (qc->err_mask & AC_ERR_INVALID)
+                       if ((qc->err_mask & AC_ERR_INVALID) ||
+                           (!(qc->flags & ATA_QCFLAG_IO) &&
+                            qc->err_mask == AC_ERR_DEV))
                                ata_eh_qc_complete(qc);
                        else
                                ata_eh_qc_retry(qc);