]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/scsi/libata-core.c
Merge branch 'upstream-fixes' of master.kernel.org:/pub/scm/linux/kernel/git/jgarzik...
[linux-2.6-omap-h63xx.git] / drivers / scsi / libata-core.c
index ff18fa7044c593ebe61ebd184cc45ffbbc91b771..ba1eb8b38e0030a7860187c15a7a405285198e80 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>
@@ -532,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.
@@ -1144,7 +1143,7 @@ retry:
                 * ATA software reset (SRST, the default) does not appear
                 * to have this problem.
                 */
-               if ((using_edd) && (qc->tf.command == ATA_CMD_ID_ATA)) {
+               if ((using_edd) && (dev->class == ATA_DEV_ATA)) {
                        u8 err = qc->tf.feature;
                        if (err & ATA_ABORTED) {
                                dev->class = ATA_DEV_ATAPI;
@@ -1264,7 +1263,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;
 
@@ -2390,8 +2389,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);
@@ -2399,16 +2399,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;
 }
 
 /**
@@ -2424,15 +2448,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;
 
@@ -2518,12 +2542,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);
 }
 
 /**
@@ -2544,8 +2574,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;
 }
 
 /**
@@ -2565,15 +2596,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),
@@ -2599,19 +2662,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;
@@ -2620,7 +2733,7 @@ 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)
@@ -2654,7 +2767,6 @@ static unsigned long ata_pio_poll(struct ata_port *ap)
        u8 status;
        unsigned int poll_state = HSM_ST_UNKNOWN;
        unsigned int reg_state = HSM_ST_UNKNOWN;
-       const unsigned int tmout_state = HSM_ST_TMOUT;
 
        switch (ap->hsm_task_state) {
        case HSM_ST:
@@ -2675,7 +2787,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)) {
-                       ap->hsm_task_state = tmout_state;
+                       ap->hsm_task_state = HSM_ST_TMOUT;
                        return 0;
                }
                ap->hsm_task_state = poll_state;
@@ -2880,7 +2992,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;
@@ -2930,7 +3042,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;
@@ -2963,7 +3075,7 @@ next_sg:
                return;
        }
 
-       sg = &qc->sg[qc->cursg];
+       sg = &qc->__sg[qc->cursg];
 
        page = sg->page;
        offset = sg->offset + qc->cursg_ofs;
@@ -3172,32 +3284,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
@@ -3236,7 +3327,6 @@ static void ata_qc_timeout(struct ata_queued_cmd *qc)
 
        spin_unlock_irqrestore(&host_set->lock, flags);
 
-out:
        DPRINTK("EXIT\n");
 }
 
@@ -3320,16 +3410,11 @@ 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;
@@ -3385,7 +3470,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.
@@ -4004,11 +4089,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;
@@ -4032,6 +4124,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)
@@ -4463,6 +4556,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);
@@ -4499,6 +4593,7 @@ static struct ata_probe_ent *ata_pci_init_legacy_port(struct pci_dev *pdev, stru
        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)
        {