Merge branch 'post-2.6.15' of git://brick.kernel.dk/data/git/linux-2.6-block
[sfrench/cifs-2.6.git] / drivers / scsi / libata-core.c
index d81db3a3d4b9a82a916659574a20f35328329ab4..f55b9b3f7b37f1e8b4ad71e8c9950d8a1f3a9797 100644 (file)
@@ -562,16 +562,28 @@ static const u8 ata_rw_cmds[] = {
        ATA_CMD_WRITE_MULTI,
        ATA_CMD_READ_MULTI_EXT,
        ATA_CMD_WRITE_MULTI_EXT,
+       0,
+       0,
+       0,
+       ATA_CMD_WRITE_MULTI_FUA_EXT,
        /* pio */
        ATA_CMD_PIO_READ,
        ATA_CMD_PIO_WRITE,
        ATA_CMD_PIO_READ_EXT,
        ATA_CMD_PIO_WRITE_EXT,
+       0,
+       0,
+       0,
+       0,
        /* dma */
        ATA_CMD_READ,
        ATA_CMD_WRITE,
        ATA_CMD_READ_EXT,
-       ATA_CMD_WRITE_EXT
+       ATA_CMD_WRITE_EXT,
+       0,
+       0,
+       0,
+       ATA_CMD_WRITE_FUA_EXT
 };
 
 /**
@@ -584,28 +596,35 @@ static const u8 ata_rw_cmds[] = {
  *     LOCKING:
  *     caller.
  */
-void ata_rwcmd_protocol(struct ata_queued_cmd *qc)
+int ata_rwcmd_protocol(struct ata_queued_cmd *qc)
 {
        struct ata_taskfile *tf = &qc->tf;
        struct ata_device *dev = qc->dev;
+       u8 cmd;
 
-       int index, lba48, write;
+       int index, fua, lba48, write;
  
+       fua = (tf->flags & ATA_TFLAG_FUA) ? 4 : 0;
        lba48 = (tf->flags & ATA_TFLAG_LBA48) ? 2 : 0;
        write = (tf->flags & ATA_TFLAG_WRITE) ? 1 : 0;
 
        if (dev->flags & ATA_DFLAG_PIO) {
                tf->protocol = ATA_PROT_PIO;
-               index = dev->multi_count ? 0 : 4;
+               index = dev->multi_count ? 0 : 8;
        } else {
                tf->protocol = ATA_PROT_DMA;
-               index = 8;
+               index = 16;
        }
 
-       tf->command = ata_rw_cmds[index + lba48 + write];
+       cmd = ata_rw_cmds[index + fua + lba48 + write];
+       if (cmd) {
+               tf->command = cmd;
+               return 0;
+       }
+       return -1;
 }
 
-static const char * xfer_mode_str[] = {
+static const char * const xfer_mode_str[] = {
        "UDMA/16",
        "UDMA/25",
        "UDMA/33",
@@ -1046,6 +1065,105 @@ static unsigned int ata_pio_modes(const struct ata_device *adev)
        return modes;
 }
 
+struct ata_exec_internal_arg {
+       unsigned int err_mask;
+       struct ata_taskfile *tf;
+       struct completion *waiting;
+};
+
+int ata_qc_complete_internal(struct ata_queued_cmd *qc)
+{
+       struct ata_exec_internal_arg *arg = qc->private_data;
+       struct completion *waiting = arg->waiting;
+
+       if (!(qc->err_mask & ~AC_ERR_DEV))
+               qc->ap->ops->tf_read(qc->ap, arg->tf);
+       arg->err_mask = qc->err_mask;
+       arg->waiting = NULL;
+       complete(waiting);
+
+       return 0;
+}
+
+/**
+ *     ata_exec_internal - execute libata internal command
+ *     @ap: Port to which the command is sent
+ *     @dev: Device to which the command is sent
+ *     @tf: Taskfile registers for the command and the result
+ *     @dma_dir: Data tranfer direction of the command
+ *     @buf: Data buffer of the command
+ *     @buflen: Length of data buffer
+ *
+ *     Executes libata internal command with timeout.  @tf contains
+ *     command on entry and result on return.  Timeout and error
+ *     conditions are reported via return value.  No recovery action
+ *     is taken after a command times out.  It's caller's duty to
+ *     clean up after timeout.
+ *
+ *     LOCKING:
+ *     None.  Should be called with kernel context, might sleep.
+ */
+
+static unsigned
+ata_exec_internal(struct ata_port *ap, struct ata_device *dev,
+                 struct ata_taskfile *tf,
+                 int dma_dir, void *buf, unsigned int buflen)
+{
+       u8 command = tf->command;
+       struct ata_queued_cmd *qc;
+       DECLARE_COMPLETION(wait);
+       unsigned long flags;
+       struct ata_exec_internal_arg arg;
+
+       spin_lock_irqsave(&ap->host_set->lock, flags);
+
+       qc = ata_qc_new_init(ap, dev);
+       BUG_ON(qc == NULL);
+
+       qc->tf = *tf;
+       qc->dma_dir = dma_dir;
+       if (dma_dir != DMA_NONE) {
+               ata_sg_init_one(qc, buf, buflen);
+               qc->nsect = buflen / ATA_SECT_SIZE;
+       }
+
+       arg.waiting = &wait;
+       arg.tf = tf;
+       qc->private_data = &arg;
+       qc->complete_fn = ata_qc_complete_internal;
+
+       if (ata_qc_issue(qc))
+               goto issue_fail;
+
+       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+       if (!wait_for_completion_timeout(&wait, ATA_TMOUT_INTERNAL)) {
+               spin_lock_irqsave(&ap->host_set->lock, flags);
+
+               /* We're racing with irq here.  If we lose, the
+                * following test prevents us from completing the qc
+                * again.  If completion irq occurs after here but
+                * before the caller cleans up, it will result in a
+                * spurious interrupt.  We can live with that.
+                */
+               if (arg.waiting) {
+                       qc->err_mask = AC_ERR_OTHER;
+                       ata_qc_complete(qc);
+                       printk(KERN_WARNING "ata%u: qc timeout (cmd 0x%x)\n",
+                              ap->id, command);
+               }
+
+               spin_unlock_irqrestore(&ap->host_set->lock, flags);
+       }
+
+       return arg.err_mask;
+
+ issue_fail:
+       ata_qc_free(qc);
+       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+       return AC_ERR_OTHER;
+}
+
 /**
  *     ata_dev_identify - obtain IDENTIFY x DEVICE page
  *     @ap: port on which device we wish to probe resides
@@ -1075,9 +1193,8 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
        u16 tmp;
        unsigned long xfer_modes;
        unsigned int using_edd;
-       DECLARE_COMPLETION(wait);
-       struct ata_queued_cmd *qc;
-       unsigned long flags;
+       struct ata_taskfile tf;
+       unsigned int err_mask;
        int rc;
 
        if (!ata_dev_present(dev)) {
@@ -1098,40 +1215,26 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
 
        ata_dev_select(ap, device, 1, 1); /* select device 0/1 */
 
-       qc = ata_qc_new_init(ap, dev);
-       BUG_ON(qc == NULL);
-
-       ata_sg_init_one(qc, dev->id, sizeof(dev->id));
-       qc->dma_dir = DMA_FROM_DEVICE;
-       qc->tf.protocol = ATA_PROT_PIO;
-       qc->nsect = 1;
-
 retry:
+       ata_tf_init(ap, &tf, device);
+
        if (dev->class == ATA_DEV_ATA) {
-               qc->tf.command = ATA_CMD_ID_ATA;
+               tf.command = ATA_CMD_ID_ATA;
                DPRINTK("do ATA identify\n");
        } else {
-               qc->tf.command = ATA_CMD_ID_ATAPI;
+               tf.command = ATA_CMD_ID_ATAPI;
                DPRINTK("do ATAPI identify\n");
        }
 
-       qc->waiting = &wait;
-       qc->complete_fn = ata_qc_complete_noop;
+       tf.protocol = ATA_PROT_PIO;
 
-       spin_lock_irqsave(&ap->host_set->lock, flags);
-       rc = ata_qc_issue(qc);
-       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+       err_mask = ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE,
+                                    dev->id, sizeof(dev->id));
 
-       if (rc)
-               goto err_out;
-       else
-               wait_for_completion(&wait);
-
-       spin_lock_irqsave(&ap->host_set->lock, flags);
-       ap->ops->tf_read(ap, &qc->tf);
-       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+       if (err_mask) {
+               if (err_mask & ~AC_ERR_DEV)
+                       goto err_out;
 
-       if (qc->tf.command & ATA_ERR) {
                /*
                 * arg!  EDD works for all test cases, but seems to return
                 * the ATA signature for some ATAPI devices.  Until the
@@ -1144,13 +1247,9 @@ retry:
                 * to have this problem.
                 */
                if ((using_edd) && (dev->class == ATA_DEV_ATA)) {
-                       u8 err = qc->tf.feature;
+                       u8 err = tf.feature;
                        if (err & ATA_ABORTED) {
                                dev->class = ATA_DEV_ATAPI;
-                               qc->cursg = 0;
-                               qc->cursg_ofs = 0;
-                               qc->cursect = 0;
-                               qc->nsect = 1;
                                goto retry;
                        }
                }
@@ -1263,7 +1362,7 @@ retry:
        }
 
        /* ATAPI-specific feature tests */
-       else {
+       else if (dev->class == ATA_DEV_ATAPI) {
                if (ata_id_is_ata(dev->id))             /* sanity check */
                        goto err_out_nosup;
 
@@ -1420,11 +1519,23 @@ void __sata_phy_reset(struct ata_port *ap)
        } while (time_before(jiffies, timeout));
 
        /* TODO: phy layer with polling, timeouts, etc. */
-       if (sata_dev_present(ap))
+       sstatus = scr_read(ap, SCR_STATUS);
+       if (sata_dev_present(ap)) {
+               const char *speed;
+               u32 tmp;
+
+               tmp = (sstatus >> 4) & 0xf;
+               if (tmp & (1 << 0))
+                       speed = "1.5";
+               else if (tmp & (1 << 1))
+                       speed = "3.0";
+               else
+                       speed = "<unknown>";
+               printk(KERN_INFO "ata%u: SATA link up %s Gbps (SStatus %X)\n",
+                      ap->id, speed, sstatus);
                ata_port_probe(ap);
-       else {
-               sstatus = scr_read(ap, SCR_STATUS);
-               printk(KERN_INFO "ata%u: no device found (phy stat %08x)\n",
+       } else {
+               printk(KERN_INFO "ata%u: SATA link down (SStatus %X)\n",
                       ap->id, sstatus);
                ata_port_disable(ap);
        }
@@ -1570,11 +1681,13 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed,
 
        /*
         * Find the mode. 
-       */
+        */
 
        if (!(s = ata_timing_find_mode(speed)))
                return -EINVAL;
 
+       memcpy(t, s, sizeof(*s));
+
        /*
         * If the drive is an EIDE drive, it can tell us it needs extended
         * PIO/MW_DMA cycle timing.
@@ -1595,7 +1708,7 @@ int ata_timing_compute(struct ata_device *adev, unsigned short speed,
         * Convert the timing to bus clock counts.
         */
 
-       ata_timing_quantize(s, t, T, UT);
+       ata_timing_quantize(t, t, T, UT);
 
        /*
         * Even in DMA/UDMA modes we still use PIO access for IDENTIFY, S.M.A.R.T
@@ -2045,7 +2158,7 @@ static void ata_pr_blacklisted(const struct ata_port *ap,
                ap->id, dev->devno);
 }
 
-static const char * ata_dma_blacklist [] = {
+static const char * const ata_dma_blacklist [] = {
        "WDC AC11000H",
        "WDC AC22100H",
        "WDC AC32500H",
@@ -2240,34 +2353,23 @@ static int ata_choose_xfer_mode(const struct ata_port *ap,
 
 static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev)
 {
-       DECLARE_COMPLETION(wait);
-       struct ata_queued_cmd *qc;
-       int rc;
-       unsigned long flags;
+       struct ata_taskfile tf;
 
        /* set up set-features taskfile */
        DPRINTK("set features - xfer mode\n");
 
-       qc = ata_qc_new_init(ap, dev);
-       BUG_ON(qc == NULL);
-
-       qc->tf.command = ATA_CMD_SET_FEATURES;
-       qc->tf.feature = SETFEATURES_XFER;
-       qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
-       qc->tf.protocol = ATA_PROT_NODATA;
-       qc->tf.nsect = dev->xfer_mode;
-
-       qc->waiting = &wait;
-       qc->complete_fn = ata_qc_complete_noop;
-
-       spin_lock_irqsave(&ap->host_set->lock, flags);
-       rc = ata_qc_issue(qc);
-       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+       ata_tf_init(ap, &tf, dev->devno);
+       tf.command = ATA_CMD_SET_FEATURES;
+       tf.feature = SETFEATURES_XFER;
+       tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+       tf.protocol = ATA_PROT_NODATA;
+       tf.nsect = dev->xfer_mode;
 
-       if (rc)
+       if (ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0)) {
+               printk(KERN_ERR "ata%u: failed to set xfermode, disabled\n",
+                      ap->id);
                ata_port_disable(ap);
-       else
-               wait_for_completion(&wait);
+       }
 
        DPRINTK("EXIT\n");
 }
@@ -2282,41 +2384,25 @@ static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev)
 
 static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev)
 {
-       DECLARE_COMPLETION(wait);
-       struct ata_queued_cmd *qc;
-       unsigned long flags;
-       int rc;
-
-       qc = ata_qc_new_init(ap, dev);
-       BUG_ON(qc == NULL);
+       struct ata_taskfile tf;
 
-       ata_sg_init_one(qc, dev->id, sizeof(dev->id));
-       qc->dma_dir = DMA_FROM_DEVICE;
+       ata_tf_init(ap, &tf, dev->devno);
 
        if (dev->class == ATA_DEV_ATA) {
-               qc->tf.command = ATA_CMD_ID_ATA;
+               tf.command = ATA_CMD_ID_ATA;
                DPRINTK("do ATA identify\n");
        } else {
-               qc->tf.command = ATA_CMD_ID_ATAPI;
+               tf.command = ATA_CMD_ID_ATAPI;
                DPRINTK("do ATAPI identify\n");
        }
 
-       qc->tf.flags |= ATA_TFLAG_DEVICE;
-       qc->tf.protocol = ATA_PROT_PIO;
-       qc->nsect = 1;
+       tf.flags |= ATA_TFLAG_DEVICE;
+       tf.protocol = ATA_PROT_PIO;
 
-       qc->waiting = &wait;
-       qc->complete_fn = ata_qc_complete_noop;
-
-       spin_lock_irqsave(&ap->host_set->lock, flags);
-       rc = ata_qc_issue(qc);
-       spin_unlock_irqrestore(&ap->host_set->lock, flags);
-
-       if (rc)
+       if (ata_exec_internal(ap, dev, &tf, DMA_FROM_DEVICE,
+                             dev->id, sizeof(dev->id)))
                goto err_out;
 
-       wait_for_completion(&wait);
-
        swap_buf_le16(dev->id, ATA_ID_WORDS);
 
        ata_dump_id(dev);
@@ -2325,6 +2411,7 @@ static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev)
 
        return;
 err_out:
+       printk(KERN_ERR "ata%u: failed to reread ID, disabled\n", ap->id);
        ata_port_disable(ap);
 }
 
@@ -2338,10 +2425,7 @@ err_out:
 
 static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev)
 {
-       DECLARE_COMPLETION(wait);
-       struct ata_queued_cmd *qc;
-       int rc;
-       unsigned long flags;
+       struct ata_taskfile tf;
        u16 sectors = dev->id[6];
        u16 heads   = dev->id[3];
 
@@ -2352,26 +2436,18 @@ static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev)
        /* set up init dev params taskfile */
        DPRINTK("init dev params \n");
 
-       qc = ata_qc_new_init(ap, dev);
-       BUG_ON(qc == NULL);
-
-       qc->tf.command = ATA_CMD_INIT_DEV_PARAMS;
-       qc->tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
-       qc->tf.protocol = ATA_PROT_NODATA;
-       qc->tf.nsect = sectors;
-       qc->tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */
-
-       qc->waiting = &wait;
-       qc->complete_fn = ata_qc_complete_noop;
-
-       spin_lock_irqsave(&ap->host_set->lock, flags);
-       rc = ata_qc_issue(qc);
-       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+       ata_tf_init(ap, &tf, dev->devno);
+       tf.command = ATA_CMD_INIT_DEV_PARAMS;
+       tf.flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE;
+       tf.protocol = ATA_PROT_NODATA;
+       tf.nsect = sectors;
+       tf.device |= (heads - 1) & 0x0f; /* max head = num. of heads - 1 */
 
-       if (rc)
+       if (ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0)) {
+               printk(KERN_ERR "ata%u: failed to init parameters, disabled\n",
+                      ap->id);
                ata_port_disable(ap);
-       else
-               wait_for_completion(&wait);
+       }
 
        DPRINTK("EXIT\n");
 }
@@ -2399,7 +2475,7 @@ static void ata_sg_clean(struct ata_queued_cmd *qc)
        if (qc->flags & ATA_QCFLAG_SINGLE)
                assert(qc->n_elem == 1);
 
-       DPRINTK("unmapping %u sg elements\n", qc->n_elem);
+       VPRINTK("unmapping %u sg elements\n", qc->n_elem);
 
        /* if we padded the buffer out to 32-bit bound, and data
         * xfer direction is from-device, we must copy from the
@@ -2409,18 +2485,21 @@ static void ata_sg_clean(struct ata_queued_cmd *qc)
                pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ);
 
        if (qc->flags & ATA_QCFLAG_SG) {
-               dma_unmap_sg(ap->host_set->dev, sg, qc->n_elem, dir);
+               if (qc->n_elem)
+                       dma_unmap_sg(ap->host_set->dev, sg, qc->n_elem, dir);
                /* restore last sg */
                sg[qc->orig_n_elem - 1].length += qc->pad_len;
                if (pad_buf) {
                        struct scatterlist *psg = &qc->pad_sgent;
                        void *addr = kmap_atomic(psg->page, KM_IRQ0);
                        memcpy(addr + psg->offset, pad_buf, qc->pad_len);
-                       kunmap_atomic(psg->page, KM_IRQ0);
+                       kunmap_atomic(addr, KM_IRQ0);
                }
        } else {
-               dma_unmap_single(ap->host_set->dev, sg_dma_address(&sg[0]),
-                                sg_dma_len(&sg[0]), dir);
+               if (sg_dma_len(&sg[0]) > 0)
+                       dma_unmap_single(ap->host_set->dev,
+                               sg_dma_address(&sg[0]), sg_dma_len(&sg[0]),
+                               dir);
                /* restore sg */
                sg->length += qc->pad_len;
                if (pad_buf)
@@ -2619,6 +2698,11 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc)
                        sg->length, qc->pad_len);
        }
 
+       if (!sg->length) {
+               sg_dma_address(sg) = 0;
+               goto skip_map;
+       }
+
        dma_address = dma_map_single(ap->host_set->dev, qc->buf_virt,
                                     sg->length, dir);
        if (dma_mapping_error(dma_address)) {
@@ -2628,6 +2712,7 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc)
        }
 
        sg_dma_address(sg) = dma_address;
+skip_map:
        sg_dma_len(sg) = sg->length;
 
        DPRINTK("mapped buffer of %d bytes for %s\n", sg_dma_len(sg),
@@ -2655,7 +2740,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)
        struct ata_port *ap = qc->ap;
        struct scatterlist *sg = qc->__sg;
        struct scatterlist *lsg = &sg[qc->n_elem - 1];
-       int n_elem, dir;
+       int n_elem, pre_n_elem, dir, trim_sg = 0;
 
        VPRINTK("ENTER, ata%u\n", ap->id);
        assert(qc->flags & ATA_QCFLAG_SG);
@@ -2682,20 +2767,31 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)
                if (qc->tf.flags & ATA_TFLAG_WRITE) {
                        void *addr = kmap_atomic(psg->page, KM_IRQ0);
                        memcpy(pad_buf, addr + psg->offset, qc->pad_len);
-                       kunmap_atomic(psg->page, KM_IRQ0);
+                       kunmap_atomic(addr, KM_IRQ0);
                }
 
                sg_dma_address(psg) = ap->pad_dma + (qc->tag * ATA_DMA_PAD_SZ);
                sg_dma_len(psg) = ATA_DMA_PAD_SZ;
                /* trim last sg */
                lsg->length -= qc->pad_len;
+               if (lsg->length == 0)
+                       trim_sg = 1;
 
                DPRINTK("padding done, sg[%d].length=%u pad_len=%u\n",
                        qc->n_elem - 1, lsg->length, qc->pad_len);
        }
 
+       pre_n_elem = qc->n_elem;
+       if (trim_sg && pre_n_elem)
+               pre_n_elem--;
+
+       if (!pre_n_elem) {
+               n_elem = 0;
+               goto skip_map;
+       }
+
        dir = qc->dma_dir;
-       n_elem = dma_map_sg(ap->host_set->dev, sg, qc->n_elem, dir);
+       n_elem = dma_map_sg(ap->host_set->dev, sg, pre_n_elem, dir);
        if (n_elem < 1) {
                /* restore last sg */
                lsg->length += qc->pad_len;
@@ -2704,6 +2800,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)
 
        DPRINTK("%d sg elements mapped\n", n_elem);
 
+skip_map:
        qc->n_elem = n_elem;
 
        return 0;
@@ -2718,7 +2815,7 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)
  *     None.  (grabs host lock)
  */
 
-void ata_poll_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
+void ata_poll_qc_complete(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
        unsigned long flags;
@@ -2726,7 +2823,7 @@ void ata_poll_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
        spin_lock_irqsave(&ap->host_set->lock, flags);
        ap->flags &= ~ATA_FLAG_NOINTR;
        ata_irq_on(ap);
-       ata_qc_complete(qc, err_mask);
+       ata_qc_complete(qc);
        spin_unlock_irqrestore(&ap->host_set->lock, flags);
 }
 
@@ -2743,10 +2840,14 @@ void ata_poll_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
 
 static unsigned long ata_pio_poll(struct ata_port *ap)
 {
+       struct ata_queued_cmd *qc;
        u8 status;
        unsigned int poll_state = HSM_ST_UNKNOWN;
        unsigned int reg_state = HSM_ST_UNKNOWN;
 
+       qc = ata_qc_from_tag(ap, ap->active_tag);
+       assert(qc != NULL);
+
        switch (ap->hsm_task_state) {
        case HSM_ST:
        case HSM_ST_POLL:
@@ -2766,6 +2867,7 @@ static unsigned long ata_pio_poll(struct ata_port *ap)
        status = ata_chk_status(ap);
        if (status & ATA_BUSY) {
                if (time_after(jiffies, ap->pio_task_timeout)) {
+                       qc->err_mask |= AC_ERR_ATA_BUS;
                        ap->hsm_task_state = HSM_ST_TMOUT;
                        return 0;
                }
@@ -2800,29 +2902,31 @@ static int ata_pio_complete (struct ata_port *ap)
         * msecs, then chk-status again.  If still busy, fall back to
         * HSM_ST_POLL state.
         */
-       drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10);
-       if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
+       drv_stat = ata_busy_wait(ap, ATA_BUSY, 10);
+       if (drv_stat & ATA_BUSY) {
                msleep(2);
-               drv_stat = ata_busy_wait(ap, ATA_BUSY | ATA_DRQ, 10);
-               if (drv_stat & (ATA_BUSY | ATA_DRQ)) {
+               drv_stat = ata_busy_wait(ap, ATA_BUSY, 10);
+               if (drv_stat & ATA_BUSY) {
                        ap->hsm_task_state = HSM_ST_LAST_POLL;
                        ap->pio_task_timeout = jiffies + ATA_TMOUT_PIO;
                        return 0;
                }
        }
 
+       qc = ata_qc_from_tag(ap, ap->active_tag);
+       assert(qc != NULL);
+
        drv_stat = ata_wait_idle(ap);
        if (!ata_ok(drv_stat)) {
+               qc->err_mask |= __ac_err_mask(drv_stat);
                ap->hsm_task_state = HSM_ST_ERR;
                return 0;
        }
 
-       qc = ata_qc_from_tag(ap, ap->active_tag);
-       assert(qc != NULL);
-
        ap->hsm_task_state = HSM_ST_IDLE;
 
-       ata_poll_qc_complete(qc, 0);
+       assert(qc->err_mask == 0);
+       ata_poll_qc_complete(qc);
 
        /* another command may start at this point */
 
@@ -3130,6 +3234,7 @@ static void atapi_pio_bytes(struct ata_queued_cmd *qc)
 err_out:
        printk(KERN_INFO "ata%u: dev %u: ATAPI check failed\n",
              ap->id, dev->devno);
+       qc->err_mask |= AC_ERR_ATA_BUS;
        ap->hsm_task_state = HSM_ST_ERR;
 }
 
@@ -3168,8 +3273,16 @@ static void ata_pio_block(struct ata_port *ap)
        qc = ata_qc_from_tag(ap, ap->active_tag);
        assert(qc != NULL);
 
+       /* check error */
+       if (status & (ATA_ERR | ATA_DF)) {
+               qc->err_mask |= AC_ERR_DEV;
+               ap->hsm_task_state = HSM_ST_ERR;
+               return;
+       }
+
+       /* transfer data if any */
        if (is_atapi_taskfile(&qc->tf)) {
-               /* no more data to transfer or unsupported ATAPI command */
+               /* DRQ=0 means no more data to transfer */
                if ((status & ATA_DRQ) == 0) {
                        ap->hsm_task_state = HSM_ST_LAST;
                        return;
@@ -3179,6 +3292,7 @@ static void ata_pio_block(struct ata_port *ap)
        } else {
                /* handle BSY=0, DRQ=0 as error */
                if ((status & ATA_DRQ) == 0) {
+                       qc->err_mask |= AC_ERR_ATA_BUS;
                        ap->hsm_task_state = HSM_ST_ERR;
                        return;
                }
@@ -3196,9 +3310,14 @@ static void ata_pio_error(struct ata_port *ap)
        qc = ata_qc_from_tag(ap, ap->active_tag);
        assert(qc != NULL);
 
+       /* make sure qc->err_mask is available to 
+        * know what's wrong and recover
+        */
+       assert(qc->err_mask);
+
        ap->hsm_task_state = HSM_ST_IDLE;
 
-       ata_poll_qc_complete(qc, AC_ERR_ATA_BUS);
+       ata_poll_qc_complete(qc);
 }
 
 static void ata_pio_task(void *_data)
@@ -3263,32 +3382,11 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
        struct ata_host_set *host_set = ap->host_set;
-       struct ata_device *dev = qc->dev;
        u8 host_stat = 0, drv_stat;
        unsigned long flags;
 
        DPRINTK("ENTER\n");
 
-       /* FIXME: doesn't this conflict with timeout handling? */
-       if (qc->dev->class == ATA_DEV_ATAPI && qc->scsicmd) {
-               struct scsi_cmnd *cmd = qc->scsicmd;
-
-               if (!(cmd->eh_eflags & SCSI_EH_CANCEL_CMD)) {
-
-                       /* finish completing original command */
-                       spin_lock_irqsave(&host_set->lock, flags);
-                       __ata_qc_complete(qc);
-                       spin_unlock_irqrestore(&host_set->lock, flags);
-
-                       atapi_request_sense(ap, dev, cmd);
-
-                       cmd->result = (CHECK_CONDITION << 1) | (DID_OK << 16);
-                       scsi_finish_command(cmd);
-
-                       goto out;
-               }
-       }
-
        spin_lock_irqsave(&host_set->lock, flags);
 
        /* hack alert!  We cannot use the supplied completion
@@ -3321,13 +3419,13 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
                       ap->id, qc->tf.command, drv_stat, host_stat);
 
                /* complete taskfile transaction */
-               ata_qc_complete(qc, ac_err_mask(drv_stat));
+               qc->err_mask |= ac_err_mask(drv_stat);
+               ata_qc_complete(qc);
                break;
        }
 
        spin_unlock_irqrestore(&host_set->lock, flags);
 
-out:
        DPRINTK("EXIT\n");
 }
 
@@ -3411,30 +3509,20 @@ struct ata_queued_cmd *ata_qc_new_init(struct ata_port *ap,
 
        qc = ata_qc_new(ap);
        if (qc) {
-               qc->__sg = NULL;
-               qc->flags = 0;
                qc->scsicmd = NULL;
                qc->ap = ap;
                qc->dev = dev;
-               qc->cursect = qc->cursg = qc->cursg_ofs = 0;
-               qc->nsect = 0;
-               qc->nbytes = qc->curbytes = 0;
 
-               ata_tf_init(ap, &qc->tf, dev->devno);
+               ata_qc_reinit(qc);
        }
 
        return qc;
 }
 
-int ata_qc_complete_noop(struct ata_queued_cmd *qc, unsigned int err_mask)
-{
-       return 0;
-}
-
 static void __ata_qc_complete(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
-       unsigned int tag, do_clear = 0;
+       unsigned int tag;
 
        qc->flags = 0;
        tag = qc->tag;
@@ -3442,17 +3530,8 @@ static void __ata_qc_complete(struct ata_queued_cmd *qc)
                if (tag == ap->active_tag)
                        ap->active_tag = ATA_TAG_POISON;
                qc->tag = ATA_TAG_POISON;
-               do_clear = 1;
-       }
-
-       if (qc->waiting) {
-               struct completion *waiting = qc->waiting;
-               qc->waiting = NULL;
-               complete(waiting);
-       }
-
-       if (likely(do_clear))
                clear_bit(tag, &ap->qactive);
+       }
 }
 
 /**
@@ -3468,7 +3547,6 @@ static void __ata_qc_complete(struct ata_queued_cmd *qc)
 void ata_qc_free(struct ata_queued_cmd *qc)
 {
        assert(qc != NULL);     /* ata_qc_from_tag _might_ return NULL */
-       assert(qc->waiting == NULL);    /* nothing should be waiting */
 
        __ata_qc_complete(qc);
 }
@@ -3485,7 +3563,7 @@ void ata_qc_free(struct ata_queued_cmd *qc)
  *     spin_lock_irqsave(host_set lock)
  */
 
-void ata_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
+void ata_qc_complete(struct ata_queued_cmd *qc)
 {
        int rc;
 
@@ -3502,7 +3580,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc, unsigned int err_mask)
        qc->flags &= ~ATA_QCFLAG_ACTIVE;
 
        /* call completion callback */
-       rc = qc->complete_fn(qc, err_mask);
+       rc = qc->complete_fn(qc);
 
        /* if callback indicates not to complete command (non-zero),
         * return immediately
@@ -3940,7 +4018,8 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
                ap->ops->irq_clear(ap);
 
                /* complete taskfile transaction */
-               ata_qc_complete(qc, ac_err_mask(status));
+               qc->err_mask |= ac_err_mask(status);
+               ata_qc_complete(qc);
                break;
 
        default:
@@ -4034,13 +4113,17 @@ static void atapi_packet_task(void *_data)
 
        /* sleep-wait for BSY to clear */
        DPRINTK("busy wait\n");
-       if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB))
-               goto err_out_status;
+       if (ata_busy_sleep(ap, ATA_TMOUT_CDB_QUICK, ATA_TMOUT_CDB)) {
+               qc->err_mask |= AC_ERR_ATA_BUS;
+               goto err_out;
+       }
 
        /* make sure DRQ is set */
        status = ata_chk_status(ap);
-       if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ)
+       if ((status & (ATA_BUSY | ATA_DRQ)) != ATA_DRQ) {
+               qc->err_mask |= AC_ERR_ATA_BUS;
                goto err_out;
+       }
 
        /* send SCSI cdb */
        DPRINTK("send cdb\n");
@@ -4072,10 +4155,8 @@ static void atapi_packet_task(void *_data)
 
        return;
 
-err_out_status:
-       status = ata_chk_status(ap);
 err_out:
-       ata_poll_qc_complete(qc, __ac_err_mask(status));
+       ata_poll_qc_complete(qc);
 }
 
 
@@ -4092,6 +4173,96 @@ err_out:
  *     Inherited from caller.
  */
 
+/*
+ * Execute a 'simple' command, that only consists of the opcode 'cmd' itself,
+ * without filling any other registers
+ */
+static int ata_do_simple_cmd(struct ata_port *ap, struct ata_device *dev,
+                            u8 cmd)
+{
+       struct ata_taskfile tf;
+       int err;
+
+       ata_tf_init(ap, &tf, dev->devno);
+
+       tf.command = cmd;
+       tf.flags |= ATA_TFLAG_DEVICE;
+       tf.protocol = ATA_PROT_NODATA;
+
+       err = ata_exec_internal(ap, dev, &tf, DMA_NONE, NULL, 0);
+       if (err)
+               printk(KERN_ERR "%s: ata command failed: %d\n",
+                               __FUNCTION__, err);
+
+       return err;
+}
+
+static int ata_flush_cache(struct ata_port *ap, struct ata_device *dev)
+{
+       u8 cmd;
+
+       if (!ata_try_flush_cache(dev))
+               return 0;
+
+       if (ata_id_has_flush_ext(dev->id))
+               cmd = ATA_CMD_FLUSH_EXT;
+       else
+               cmd = ATA_CMD_FLUSH;
+
+       return ata_do_simple_cmd(ap, dev, cmd);
+}
+
+static int ata_standby_drive(struct ata_port *ap, struct ata_device *dev)
+{
+       return ata_do_simple_cmd(ap, dev, ATA_CMD_STANDBYNOW1);
+}
+
+static int ata_start_drive(struct ata_port *ap, struct ata_device *dev)
+{
+       return ata_do_simple_cmd(ap, dev, ATA_CMD_IDLEIMMEDIATE);
+}
+
+/**
+ *     ata_device_resume - wakeup a previously suspended devices
+ *
+ *     Kick the drive back into action, by sending it an idle immediate
+ *     command and making sure its transfer mode matches between drive
+ *     and host.
+ *
+ */
+int ata_device_resume(struct ata_port *ap, struct ata_device *dev)
+{
+       if (ap->flags & ATA_FLAG_SUSPENDED) {
+               ap->flags &= ~ATA_FLAG_SUSPENDED;
+               ata_set_mode(ap);
+       }
+       if (!ata_dev_present(dev))
+               return 0;
+       if (dev->class == ATA_DEV_ATA)
+               ata_start_drive(ap, dev);
+
+       return 0;
+}
+
+/**
+ *     ata_device_suspend - prepare a device for suspend
+ *
+ *     Flush the cache on the drive, if appropriate, then issue a
+ *     standbynow command.
+ *
+ */
+int ata_device_suspend(struct ata_port *ap, struct ata_device *dev)
+{
+       if (!ata_dev_present(dev))
+               return 0;
+       if (dev->class == ATA_DEV_ATA)
+               ata_flush_cache(ap, dev);
+
+       ata_standby_drive(ap, dev);
+       ap->flags |= ATA_FLAG_SUSPENDED;
+       return 0;
+}
+
 int ata_port_start (struct ata_port *ap)
 {
        struct device *dev = ap->host_set->dev;
@@ -4840,6 +5011,23 @@ int pci_test_config_bits(struct pci_dev *pdev, const struct pci_bits *bits)
 
        return (tmp == bits->val) ? 1 : 0;
 }
+
+int ata_pci_device_suspend(struct pci_dev *pdev, pm_message_t state)
+{
+       pci_save_state(pdev);
+       pci_disable_device(pdev);
+       pci_set_power_state(pdev, PCI_D3hot);
+       return 0;
+}
+
+int ata_pci_device_resume(struct pci_dev *pdev)
+{
+       pci_set_power_state(pdev, PCI_D0);
+       pci_restore_state(pdev);
+       pci_enable_device(pdev);
+       pci_set_master(pdev);
+       return 0;
+}
 #endif /* CONFIG_PCI */
 
 
@@ -4943,4 +5131,11 @@ EXPORT_SYMBOL_GPL(ata_pci_host_stop);
 EXPORT_SYMBOL_GPL(ata_pci_init_native_mode);
 EXPORT_SYMBOL_GPL(ata_pci_init_one);
 EXPORT_SYMBOL_GPL(ata_pci_remove_one);
+EXPORT_SYMBOL_GPL(ata_pci_device_suspend);
+EXPORT_SYMBOL_GPL(ata_pci_device_resume);
 #endif /* CONFIG_PCI */
+
+EXPORT_SYMBOL_GPL(ata_device_suspend);
+EXPORT_SYMBOL_GPL(ata_device_resume);
+EXPORT_SYMBOL_GPL(ata_scsi_device_suspend);
+EXPORT_SYMBOL_GPL(ata_scsi_device_resume);