[PATCH] libata: err_mask misc fix
[safe/jmp/linux-2.6] / drivers / scsi / libata-core.c
index 5ca9760..e4c4007 100644 (file)
@@ -51,8 +51,8 @@
 #include <linux/jiffies.h>
 #include <linux/scatterlist.h>
 #include <scsi/scsi.h>
-#include "scsi.h"
 #include "scsi_priv.h"
+#include <scsi/scsi_cmnd.h>
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
 #include <asm/io.h>
@@ -295,28 +295,6 @@ void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
 }
 
 /**
- *     ata_exec - issue ATA command to host controller
- *     @ap: port to which command is being issued
- *     @tf: ATA taskfile register set
- *
- *     Issues PIO/MMIO write to ATA command register, with proper
- *     synchronization with interrupt handler / other threads.
- *
- *     LOCKING:
- *     Obtains host_set lock.
- */
-
-static inline void ata_exec(struct ata_port *ap, const struct ata_taskfile *tf)
-{
-       unsigned long flags;
-
-       DPRINTK("ata%u: cmd 0x%X\n", ap->id, tf->command);
-       spin_lock_irqsave(&ap->host_set->lock, flags);
-       ap->ops->exec_command(ap, tf);
-       spin_unlock_irqrestore(&ap->host_set->lock, flags);
-}
-
-/**
  *     ata_tf_to_host - issue ATA taskfile to host controller
  *     @ap: port to which command is being issued
  *     @tf: ATA taskfile register set
@@ -326,30 +304,11 @@ static inline void ata_exec(struct ata_port *ap, const struct ata_taskfile *tf)
  *     other threads.
  *
  *     LOCKING:
- *     Obtains host_set lock.
- */
-
-static void ata_tf_to_host(struct ata_port *ap, const struct ata_taskfile *tf)
-{
-       ap->ops->tf_load(ap, tf);
-
-       ata_exec(ap, tf);
-}
-
-/**
- *     ata_tf_to_host_nolock - issue ATA taskfile to host controller
- *     @ap: port to which command is being issued
- *     @tf: ATA taskfile register set
- *
- *     Issues ATA taskfile register set to ATA host controller,
- *     with proper synchronization with interrupt handler and
- *     other threads.
- *
- *     LOCKING:
  *     spin_lock_irqsave(host_set lock)
  */
 
-void ata_tf_to_host_nolock(struct ata_port *ap, const struct ata_taskfile *tf)
+static inline void ata_tf_to_host(struct ata_port *ap,
+                                 const struct ata_taskfile *tf)
 {
        ap->ops->tf_load(ap, tf);
        ap->ops->exec_command(ap, tf);
@@ -372,7 +331,7 @@ static void ata_tf_read_pio(struct ata_port *ap, struct ata_taskfile *tf)
        struct ata_ioports *ioaddr = &ap->ioaddr;
 
        tf->command = ata_check_status(ap);
-       tf->feature = ata_chk_err(ap);
+       tf->feature = inb(ioaddr->error_addr);
        tf->nsect = inb(ioaddr->nsect_addr);
        tf->lbal = inb(ioaddr->lbal_addr);
        tf->lbam = inb(ioaddr->lbam_addr);
@@ -406,7 +365,7 @@ static void ata_tf_read_mmio(struct ata_port *ap, struct ata_taskfile *tf)
        struct ata_ioports *ioaddr = &ap->ioaddr;
 
        tf->command = ata_check_status(ap);
-       tf->feature = ata_chk_err(ap);
+       tf->feature = readb((void __iomem *)ioaddr->error_addr);
        tf->nsect = readb((void __iomem *)ioaddr->nsect_addr);
        tf->lbal = readb((void __iomem *)ioaddr->lbal_addr);
        tf->lbam = readb((void __iomem *)ioaddr->lbam_addr);
@@ -527,30 +486,6 @@ u8 ata_altstatus(struct ata_port *ap)
 
 
 /**
- *     ata_chk_err - Read device error reg
- *     @ap: port where the device is
- *
- *     Reads ATA taskfile error register for
- *     currently-selected device and return its value.
- *
- *     Note: may NOT be used as the check_err() entry in
- *     ata_port_operations.
- *
- *     LOCKING:
- *     Inherited from caller.
- */
-u8 ata_chk_err(struct ata_port *ap)
-{
-       if (ap->ops->check_err)
-               return ap->ops->check_err(ap);
-
-       if (ap->flags & ATA_FLAG_MMIO) {
-               return readb((void __iomem *) ap->ioaddr.error_addr);
-       }
-       return inb(ap->ioaddr.error_addr);
-}
-
-/**
  *     ata_tf_to_fis - Convert ATA taskfile to SATA FIS structure
  *     @tf: Taskfile to convert
  *     @fis: Buffer into which data will output
@@ -597,8 +532,7 @@ void ata_tf_to_fis(const struct ata_taskfile *tf, u8 *fis, u8 pmp)
  *     @fis: Buffer from which data will be input
  *     @tf: Taskfile to output
  *
- *     Converts a standard ATA taskfile to a Serial ATA
- *     FIS structure (Register - Host to Device).
+ *     Converts a serial ATA FIS structure to a standard ATA taskfile.
  *
  *     LOCKING:
  *     Inherited from caller.
@@ -671,7 +605,7 @@ void ata_rwcmd_protocol(struct ata_queued_cmd *qc)
        tf->command = ata_rw_cmds[index + lba48 + write];
 }
 
-static const char * xfer_mode_str[] = {
+static const char * const xfer_mode_str[] = {
        "UDMA/16",
        "UDMA/25",
        "UDMA/33",
@@ -902,8 +836,8 @@ static u8 ata_dev_try_classify(struct ata_port *ap, unsigned int device)
 
        memset(&tf, 0, sizeof(tf));
 
-       err = ata_chk_err(ap);
        ap->ops->tf_read(ap, &tf);
+       err = tf.feature;
 
        dev->class = ATA_DEV_NONE;
 
@@ -1112,6 +1046,30 @@ static unsigned int ata_pio_modes(const struct ata_device *adev)
        return modes;
 }
 
+static int ata_qc_wait_err(struct ata_queued_cmd *qc,
+                          struct completion *wait)
+{
+       int rc = 0;
+
+       if (wait_for_completion_timeout(wait, 30 * HZ) < 1) {
+               /* timeout handling */
+               qc->err_mask |= ac_err_mask(ata_chk_status(qc->ap));
+
+               if (!qc->err_mask) {
+                       printk(KERN_WARNING "ata%u: slow completion (cmd %x)\n",
+                              qc->ap->id, qc->tf.command);
+               } else {
+                       printk(KERN_WARNING "ata%u: qc timeout (cmd %x)\n",
+                              qc->ap->id, qc->tf.command);
+                       rc = -EIO;
+               }
+
+               ata_qc_complete(qc);
+       }
+
+       return rc;
+}
+
 /**
  *     ata_dev_identify - obtain IDENTIFY x DEVICE page
  *     @ap: port on which device we wish to probe resides
@@ -1140,7 +1098,6 @@ static void ata_dev_identify(struct ata_port *ap, unsigned int device)
        unsigned int major_version;
        u16 tmp;
        unsigned long xfer_modes;
-       u8 status;
        unsigned int using_edd;
        DECLARE_COMPLETION(wait);
        struct ata_queued_cmd *qc;
@@ -1192,10 +1149,13 @@ retry:
        if (rc)
                goto err_out;
        else
-               wait_for_completion(&wait);
+               ata_qc_wait_err(qc, &wait);
 
-       status = ata_chk_status(ap);
-       if (status & ATA_ERR) {
+       spin_lock_irqsave(&ap->host_set->lock, flags);
+       ap->ops->tf_read(ap, &qc->tf);
+       spin_unlock_irqrestore(&ap->host_set->lock, flags);
+
+       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
@@ -1207,14 +1167,15 @@ retry:
                 * ATA software reset (SRST, the default) does not appear
                 * to have this problem.
                 */
-               if ((using_edd) && (qc->tf.command == ATA_CMD_ID_ATA)) {
-                       u8 err = ata_chk_err(ap);
+               if ((using_edd) && (dev->class == ATA_DEV_ATA)) {
+                       u8 err = qc->tf.feature;
                        if (err & ATA_ABORTED) {
                                dev->class = ATA_DEV_ATAPI;
                                qc->cursg = 0;
                                qc->cursg_ofs = 0;
                                qc->cursect = 0;
                                qc->nsect = 1;
+                               qc->err_mask = 0;
                                goto retry;
                        }
                }
@@ -1327,7 +1288,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;
 
@@ -1484,11 +1445,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);
        }
@@ -1634,11 +1607,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.
@@ -1659,7 +1634,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
@@ -1934,12 +1909,14 @@ static void ata_bus_post_reset(struct ata_port *ap, unsigned int devmask)
  *
  *     LOCKING:
  *     PCI/etc. bus probe sem.
+ *     Obtains host_set lock.
  *
  */
 
 static unsigned int ata_bus_edd(struct ata_port *ap)
 {
        struct ata_taskfile tf;
+       unsigned long flags;
 
        /* set up execute-device-diag (bus reset) taskfile */
        /* also, take interrupts to a known state (disabled) */
@@ -1950,7 +1927,9 @@ static unsigned int ata_bus_edd(struct ata_port *ap)
        tf.protocol = ATA_PROT_NODATA;
 
        /* do bus reset */
+       spin_lock_irqsave(&ap->host_set->lock, flags);
        ata_tf_to_host(ap, &tf);
+       spin_unlock_irqrestore(&ap->host_set->lock, flags);
 
        /* spec says at least 2ms.  but who knows with those
         * crazy ATAPI devices...
@@ -2105,7 +2084,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",
@@ -2327,7 +2306,7 @@ static void ata_dev_set_xfermode(struct ata_port *ap, struct ata_device *dev)
        if (rc)
                ata_port_disable(ap);
        else
-               wait_for_completion(&wait);
+               ata_qc_wait_err(qc, &wait);
 
        DPRINTK("EXIT\n");
 }
@@ -2375,7 +2354,7 @@ static void ata_dev_reread_id(struct ata_port *ap, struct ata_device *dev)
        if (rc)
                goto err_out;
 
-       wait_for_completion(&wait);
+       ata_qc_wait_err(qc, &wait);
 
        swap_buf_le16(dev->id, ATA_ID_WORDS);
 
@@ -2431,7 +2410,7 @@ static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev)
        if (rc)
                ata_port_disable(ap);
        else
-               wait_for_completion(&wait);
+               ata_qc_wait_err(qc, &wait);
 
        DPRINTK("EXIT\n");
 }
@@ -2449,8 +2428,9 @@ static void ata_dev_init_params(struct ata_port *ap, struct ata_device *dev)
 static void ata_sg_clean(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
-       struct scatterlist *sg = qc->sg;
+       struct scatterlist *sg = qc->__sg;
        int dir = qc->dma_dir;
+       void *pad_buf = NULL;
 
        assert(qc->flags & ATA_QCFLAG_DMAMAP);
        assert(sg != NULL);
@@ -2458,16 +2438,40 @@ 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 (qc->flags & ATA_QCFLAG_SG)
-               dma_unmap_sg(ap->host_set->dev, sg, qc->n_elem, dir);
-       else
-               dma_unmap_single(ap->host_set->dev, sg_dma_address(&sg[0]),
-                                sg_dma_len(&sg[0]), dir);
+       /* if we padded the buffer out to 32-bit bound, and data
+        * xfer direction is from-device, we must copy from the
+        * pad buffer back into the supplied buffer
+        */
+       if (qc->pad_len && !(qc->tf.flags & ATA_TFLAG_WRITE))
+               pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ);
+
+       if (qc->flags & ATA_QCFLAG_SG) {
+               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);
+               }
+       } else {
+               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)
+                       memcpy(qc->buf_virt + sg->length - qc->pad_len,
+                              pad_buf, qc->pad_len);
+       }
 
        qc->flags &= ~ATA_QCFLAG_DMAMAP;
-       qc->sg = NULL;
+       qc->__sg = NULL;
 }
 
 /**
@@ -2483,15 +2487,15 @@ static void ata_sg_clean(struct ata_queued_cmd *qc)
  */
 static void ata_fill_sg(struct ata_queued_cmd *qc)
 {
-       struct scatterlist *sg = qc->sg;
        struct ata_port *ap = qc->ap;
-       unsigned int idx, nelem;
+       struct scatterlist *sg;
+       unsigned int idx;
 
-       assert(sg != NULL);
+       assert(qc->__sg != NULL);
        assert(qc->n_elem > 0);
 
        idx = 0;
-       for (nelem = qc->n_elem; nelem; nelem--,sg++) {
+       ata_for_each_sg(sg, qc) {
                u32 addr, offset;
                u32 sg_len, len;
 
@@ -2577,12 +2581,18 @@ void ata_qc_prep(struct ata_queued_cmd *qc)
 
 void ata_sg_init_one(struct ata_queued_cmd *qc, void *buf, unsigned int buflen)
 {
+       struct scatterlist *sg;
+
        qc->flags |= ATA_QCFLAG_SINGLE;
 
-       qc->sg = &qc->sgent;
+       memset(&qc->sgent, 0, sizeof(qc->sgent));
+       qc->__sg = &qc->sgent;
        qc->n_elem = 1;
+       qc->orig_n_elem = 1;
        qc->buf_virt = buf;
-       sg_init_one(qc->sg, buf, buflen);
+
+       sg = qc->__sg;
+       sg_init_one(sg, buf, buflen);
 }
 
 /**
@@ -2603,8 +2613,9 @@ void ata_sg_init(struct ata_queued_cmd *qc, struct scatterlist *sg,
                 unsigned int n_elem)
 {
        qc->flags |= ATA_QCFLAG_SG;
-       qc->sg = sg;
+       qc->__sg = sg;
        qc->n_elem = n_elem;
+       qc->orig_n_elem = n_elem;
 }
 
 /**
@@ -2624,15 +2635,47 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
        int dir = qc->dma_dir;
-       struct scatterlist *sg = qc->sg;
+       struct scatterlist *sg = qc->__sg;
        dma_addr_t dma_address;
 
+       /* we must lengthen transfers to end on a 32-bit boundary */
+       qc->pad_len = sg->length & 3;
+       if (qc->pad_len) {
+               void *pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ);
+               struct scatterlist *psg = &qc->pad_sgent;
+
+               assert(qc->dev->class == ATA_DEV_ATAPI);
+
+               memset(pad_buf, 0, ATA_DMA_PAD_SZ);
+
+               if (qc->tf.flags & ATA_TFLAG_WRITE)
+                       memcpy(pad_buf, qc->buf_virt + sg->length - qc->pad_len,
+                              qc->pad_len);
+
+               sg_dma_address(psg) = ap->pad_dma + (qc->tag * ATA_DMA_PAD_SZ);
+               sg_dma_len(psg) = ATA_DMA_PAD_SZ;
+               /* trim sg */
+               sg->length -= qc->pad_len;
+
+               DPRINTK("padding done, sg->length=%u pad_len=%u\n",
+                       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))
+       if (dma_mapping_error(dma_address)) {
+               /* restore sg */
+               sg->length += qc->pad_len;
                return -1;
+       }
 
        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),
@@ -2658,19 +2701,69 @@ static int ata_sg_setup_one(struct ata_queued_cmd *qc)
 static int ata_sg_setup(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
-       struct scatterlist *sg = qc->sg;
-       int n_elem, dir;
+       struct scatterlist *sg = qc->__sg;
+       struct scatterlist *lsg = &sg[qc->n_elem - 1];
+       int n_elem, pre_n_elem, dir, trim_sg = 0;
 
        VPRINTK("ENTER, ata%u\n", ap->id);
        assert(qc->flags & ATA_QCFLAG_SG);
 
+       /* we must lengthen transfers to end on a 32-bit boundary */
+       qc->pad_len = lsg->length & 3;
+       if (qc->pad_len) {
+               void *pad_buf = ap->pad + (qc->tag * ATA_DMA_PAD_SZ);
+               struct scatterlist *psg = &qc->pad_sgent;
+               unsigned int offset;
+
+               assert(qc->dev->class == ATA_DEV_ATAPI);
+
+               memset(pad_buf, 0, ATA_DMA_PAD_SZ);
+
+               /*
+                * psg->page/offset are used to copy to-be-written
+                * data in this function or read data in ata_sg_clean.
+                */
+               offset = lsg->offset + lsg->length - qc->pad_len;
+               psg->page = nth_page(lsg->page, offset >> PAGE_SHIFT);
+               psg->offset = offset_in_page(offset);
+
+               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);
+               }
+
+               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);
-       if (n_elem < 1)
+       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;
                return -1;
+       }
 
        DPRINTK("%d sg elements mapped\n", n_elem);
 
+skip_map:
        qc->n_elem = n_elem;
 
        return 0;
@@ -2679,13 +2772,13 @@ static int ata_sg_setup(struct ata_queued_cmd *qc)
 /**
  *     ata_poll_qc_complete - turn irq back on and finish qc
  *     @qc: Command to complete
- *     @drv_stat: ATA status register content
+ *     @err_mask: ATA status register content
  *
  *     LOCKING:
  *     None.  (grabs host lock)
  */
 
-void ata_poll_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
+void ata_poll_qc_complete(struct ata_queued_cmd *qc)
 {
        struct ata_port *ap = qc->ap;
        unsigned long flags;
@@ -2693,7 +2786,7 @@ void ata_poll_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
        spin_lock_irqsave(&ap->host_set->lock, flags);
        ap->flags &= ~ATA_FLAG_NOINTR;
        ata_irq_on(ap);
-       ata_qc_complete(qc, drv_stat);
+       ata_qc_complete(qc);
        spin_unlock_irqrestore(&ap->host_set->lock, flags);
 }
 
@@ -2710,10 +2803,13 @@ void ata_poll_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
 
 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;
-       const unsigned int tmout_state = HSM_ST_TMOUT;
+
+       qc = ata_qc_from_tag(ap, ap->active_tag);
+       assert(qc != NULL);
 
        switch (ap->hsm_task_state) {
        case HSM_ST:
@@ -2734,7 +2830,8 @@ 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)) {
-                       ap->hsm_task_state = tmout_state;
+                       qc->err_mask |= AC_ERR_ATA_BUS;
+                       ap->hsm_task_state = HSM_ST_TMOUT;
                        return 0;
                }
                ap->hsm_task_state = poll_state;
@@ -2768,29 +2865,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, drv_stat);
+       assert(qc->err_mask == 0);
+       ata_poll_qc_complete(qc);
 
        /* another command may start at this point */
 
@@ -2939,7 +3038,7 @@ static void ata_data_xfer(struct ata_port *ap, unsigned char *buf,
 static void ata_pio_sector(struct ata_queued_cmd *qc)
 {
        int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
-       struct scatterlist *sg = qc->sg;
+       struct scatterlist *sg = qc->__sg;
        struct ata_port *ap = qc->ap;
        struct page *page;
        unsigned int offset;
@@ -2989,7 +3088,7 @@ static void ata_pio_sector(struct ata_queued_cmd *qc)
 static void __atapi_pio_bytes(struct ata_queued_cmd *qc, unsigned int bytes)
 {
        int do_write = (qc->tf.flags & ATA_TFLAG_WRITE);
-       struct scatterlist *sg = qc->sg;
+       struct scatterlist *sg = qc->__sg;
        struct ata_port *ap = qc->ap;
        struct page *page;
        unsigned char *buf;
@@ -3022,7 +3121,7 @@ next_sg:
                return;
        }
 
-       sg = &qc->sg[qc->cursg];
+       sg = &qc->__sg[qc->cursg];
 
        page = sg->page;
        offset = sg->offset + qc->cursg_ofs;
@@ -3098,6 +3197,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;
 }
 
@@ -3136,8 +3236,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;
@@ -3147,6 +3255,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;
                }
@@ -3158,18 +3267,20 @@ static void ata_pio_block(struct ata_port *ap)
 static void ata_pio_error(struct ata_port *ap)
 {
        struct ata_queued_cmd *qc;
-       u8 drv_stat;
+
+       printk(KERN_WARNING "ata%u: PIO error\n", ap->id);
 
        qc = ata_qc_from_tag(ap, ap->active_tag);
        assert(qc != NULL);
 
-       drv_stat = ata_chk_status(ap);
-       printk(KERN_WARNING "ata%u: PIO error, drv_stat 0x%x\n",
-              ap->id, drv_stat);
+       /* 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, drv_stat | ATA_ERR);
+       ata_poll_qc_complete(qc);
 }
 
 static void ata_pio_task(void *_data)
@@ -3234,32 +3345,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
@@ -3292,13 +3382,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, 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");
 }
 
@@ -3382,22 +3472,17 @@ 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, u8 drv_stat)
+int ata_qc_complete_noop(struct ata_queued_cmd *qc)
 {
        return 0;
 }
@@ -3447,7 +3532,7 @@ void ata_qc_free(struct ata_queued_cmd *qc)
 /**
  *     ata_qc_complete - Complete an active ATA command
  *     @qc: Command to complete
- *     @drv_stat: ATA Status register contents
+ *     @err_mask: ATA Status register contents
  *
  *     Indicate to the mid and upper layers that an ATA
  *     command has completed, with either an ok or not-ok status.
@@ -3456,7 +3541,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, u8 drv_stat)
+void ata_qc_complete(struct ata_queued_cmd *qc)
 {
        int rc;
 
@@ -3473,7 +3558,7 @@ void ata_qc_complete(struct ata_queued_cmd *qc, u8 drv_stat)
        qc->flags &= ~ATA_QCFLAG_ACTIVE;
 
        /* call completion callback */
-       rc = qc->complete_fn(qc, drv_stat);
+       rc = qc->complete_fn(qc);
 
        /* if callback indicates not to complete command (non-zero),
         * return immediately
@@ -3580,7 +3665,7 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc)
 
        switch (qc->tf.protocol) {
        case ATA_PROT_NODATA:
-               ata_tf_to_host_nolock(ap, &qc->tf);
+               ata_tf_to_host(ap, &qc->tf);
                break;
 
        case ATA_PROT_DMA:
@@ -3591,20 +3676,20 @@ int ata_qc_issue_prot(struct ata_queued_cmd *qc)
 
        case ATA_PROT_PIO: /* load tf registers, initiate polling pio */
                ata_qc_set_polling(qc);
-               ata_tf_to_host_nolock(ap, &qc->tf);
+               ata_tf_to_host(ap, &qc->tf);
                ap->hsm_task_state = HSM_ST;
                queue_work(ata_wq, &ap->pio_task);
                break;
 
        case ATA_PROT_ATAPI:
                ata_qc_set_polling(qc);
-               ata_tf_to_host_nolock(ap, &qc->tf);
+               ata_tf_to_host(ap, &qc->tf);
                queue_work(ata_wq, &ap->packet_task);
                break;
 
        case ATA_PROT_ATAPI_NODATA:
                ap->flags |= ATA_FLAG_NOINTR;
-               ata_tf_to_host_nolock(ap, &qc->tf);
+               ata_tf_to_host(ap, &qc->tf);
                queue_work(ata_wq, &ap->packet_task);
                break;
 
@@ -3911,7 +3996,8 @@ inline unsigned int ata_host_intr (struct ata_port *ap,
                ap->ops->irq_clear(ap);
 
                /* complete taskfile transaction */
-               ata_qc_complete(qc, status);
+               qc->err_mask |= ac_err_mask(status);
+               ata_qc_complete(qc);
                break;
 
        default:
@@ -4005,13 +4091,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))
+       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");
@@ -4044,7 +4134,7 @@ static void atapi_packet_task(void *_data)
        return;
 
 err_out:
-       ata_poll_qc_complete(qc, ATA_ERR);
+       ata_poll_qc_complete(qc);
 }
 
 
@@ -4064,11 +4154,18 @@ err_out:
 int ata_port_start (struct ata_port *ap)
 {
        struct device *dev = ap->host_set->dev;
+       int rc;
 
        ap->prd = dma_alloc_coherent(dev, ATA_PRD_TBL_SZ, &ap->prd_dma, GFP_KERNEL);
        if (!ap->prd)
                return -ENOMEM;
 
+       rc = ata_pad_alloc(ap, dev);
+       if (rc) {
+               dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma);
+               return rc;
+       }
+
        DPRINTK("prd alloc, virt %p, dma %llx\n", ap->prd, (unsigned long long) ap->prd_dma);
 
        return 0;
@@ -4092,6 +4189,7 @@ void ata_port_stop (struct ata_port *ap)
        struct device *dev = ap->host_set->dev;
 
        dma_free_coherent(dev, ATA_PRD_TBL_SZ, ap->prd, ap->prd_dma);
+       ata_pad_free(ap, dev);
 }
 
 void ata_host_stop (struct ata_host_set *host_set)
@@ -4149,8 +4247,6 @@ static void ata_host_init(struct ata_port *ap, struct Scsi_Host *host,
        host->unique_id = ata_unique_id++;
        host->max_cmd_len = 12;
 
-       scsi_assign_lock(host, &host_set->lock);
-
        ap->flags = ATA_FLAG_PORT_DISABLED;
        ap->id = host->unique_id;
        ap->host = host;
@@ -4525,6 +4621,7 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int
 
        probe_ent->irq = pdev->irq;
        probe_ent->irq_flags = SA_SHIRQ;
+       probe_ent->private_data = port[0]->private_data;
 
        if (ports & ATA_PORT_PRIMARY) {
                probe_ent->port[p].cmd_addr = pci_resource_start(pdev, 0);
@@ -4550,17 +4647,18 @@ ata_pci_init_native_mode(struct pci_dev *pdev, struct ata_port_info **port, int
        return probe_ent;
 }
 
-static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, struct ata_port_info **port, int port_num)
+static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, struct ata_port_info *port, int port_num)
 {
        struct ata_probe_ent *probe_ent;
 
-       probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port[0]);
+       probe_ent = ata_probe_ent_alloc(pci_dev_to_dev(pdev), port);
        if (!probe_ent)
                return NULL;
 
        probe_ent->legacy_mode = 1;
        probe_ent->n_ports = 1;
        probe_ent->hard_port_no = port_num;
+       probe_ent->private_data = port->private_data;
 
        switch(port_num)
        {
@@ -4701,9 +4799,9 @@ int ata_pci_init_one (struct pci_dev *pdev, struct ata_port_info **port_info,
 
        if (legacy_mode) {
                if (legacy_mode & (1 << 0))
-                       probe_ent = ata_pci_init_legacy_port(pdev, port, 0);
+                       probe_ent = ata_pci_init_legacy_port(pdev, port[0], 0);
                if (legacy_mode & (1 << 1))
-                       probe_ent2 = ata_pci_init_legacy_port(pdev, port, 1);
+                       probe_ent2 = ata_pci_init_legacy_port(pdev, port[1], 1);
        } else {
                if (n_ports == 2)
                        probe_ent = ata_pci_init_native_mode(pdev, port, ATA_PORT_PRIMARY | ATA_PORT_SECONDARY);
@@ -4867,7 +4965,6 @@ EXPORT_SYMBOL_GPL(ata_tf_to_fis);
 EXPORT_SYMBOL_GPL(ata_tf_from_fis);
 EXPORT_SYMBOL_GPL(ata_check_status);
 EXPORT_SYMBOL_GPL(ata_altstatus);
-EXPORT_SYMBOL_GPL(ata_chk_err);
 EXPORT_SYMBOL_GPL(ata_exec_command);
 EXPORT_SYMBOL_GPL(ata_port_start);
 EXPORT_SYMBOL_GPL(ata_port_stop);