libata: update ->data_xfer hook for ATAPI
authorTejun Heo <htejun@gmail.com>
Wed, 5 Dec 2007 07:43:07 +0000 (16:43 +0900)
committerJeff Garzik <jeff@garzik.org>
Wed, 23 Jan 2008 10:24:14 +0000 (05:24 -0500)
Depending on how many bytes are transferred as a unit, PIO data
transfer may consume more bytes than requested.  Knowing how much
data is consumed is necessary to determine how much is left for
draining.  This patch update ->data_xfer such that it returns the
number of consumed bytes.

While at it, it also makes the following changes.

* s/adev/dev/
* use READ/WRITE constants for rw indication
* misc clean ups

Signed-off-by: Tejun Heo <htejun@gmail.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
drivers/ata/libata-core.c
drivers/ata/pata_bf54x.c
drivers/ata/pata_ixp4xx_cf.c
drivers/ata/pata_legacy.c
drivers/ata/pata_qdi.c
drivers/ata/pata_scc.c
drivers/ata/pata_winbond.c
include/linux/libata.h

index 2c9745a..39cedd9 100644 (file)
@@ -4994,7 +4994,7 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
 
 /**
  *     ata_data_xfer - Transfer data by PIO
- *     @adev: device to target
+ *     @dev: device to target
  *     @buf: data buffer
  *     @buflen: buffer length
  *     @write_data: read/write
@@ -5003,37 +5003,44 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
  *
  *     LOCKING:
  *     Inherited from caller.
+ *
+ *     RETURNS:
+ *     Bytes consumed.
  */
-void ata_data_xfer(struct ata_device *adev, unsigned char *buf,
-                  unsigned int buflen, int write_data)
+unsigned int ata_data_xfer(struct ata_device *dev, unsigned char *buf,
+                          unsigned int buflen, int rw)
 {
-       struct ata_port *ap = adev->link->ap;
+       struct ata_port *ap = dev->link->ap;
+       void __iomem *data_addr = ap->ioaddr.data_addr;
        unsigned int words = buflen >> 1;
 
        /* Transfer multiple of 2 bytes */
-       if (write_data)
-               iowrite16_rep(ap->ioaddr.data_addr, buf, words);
+       if (rw == READ)
+               ioread16_rep(data_addr, buf, words);
        else
-               ioread16_rep(ap->ioaddr.data_addr, buf, words);
+               iowrite16_rep(data_addr, buf, words);
 
        /* Transfer trailing 1 byte, if any. */
        if (unlikely(buflen & 0x01)) {
                u16 align_buf[1] = { 0 };
                unsigned char *trailing_buf = buf + buflen - 1;
 
-               if (write_data) {
-                       memcpy(align_buf, trailing_buf, 1);
-                       iowrite16(le16_to_cpu(align_buf[0]), ap->ioaddr.data_addr);
-               } else {
-                       align_buf[0] = cpu_to_le16(ioread16(ap->ioaddr.data_addr));
+               if (rw == READ) {
+                       align_buf[0] = cpu_to_le16(ioread16(data_addr));
                        memcpy(trailing_buf, align_buf, 1);
+               } else {
+                       memcpy(align_buf, trailing_buf, 1);
+                       iowrite16(le16_to_cpu(align_buf[0]), data_addr);
                }
+               words++;
        }
+
+       return words << 1;
 }
 
 /**
  *     ata_data_xfer_noirq - Transfer data by PIO
- *     @adev: device to target
+ *     @dev: device to target
  *     @buf: data buffer
  *     @buflen: buffer length
  *     @write_data: read/write
@@ -5043,14 +5050,21 @@ void ata_data_xfer(struct ata_device *adev, unsigned char *buf,
  *
  *     LOCKING:
  *     Inherited from caller.
+ *
+ *     RETURNS:
+ *     Bytes consumed.
  */
-void ata_data_xfer_noirq(struct ata_device *adev, unsigned char *buf,
-                        unsigned int buflen, int write_data)
+unsigned int ata_data_xfer_noirq(struct ata_device *dev, unsigned char *buf,
+                                unsigned int buflen, int rw)
 {
        unsigned long flags;
+       unsigned int consumed;
+
        local_irq_save(flags);
-       ata_data_xfer(adev, buf, buflen, write_data);
+       consumed = ata_data_xfer(dev, buf, buflen, rw);
        local_irq_restore(flags);
+
+       return consumed;
 }
 
 
index 7842cc4..41cd921 100644 (file)
@@ -1167,34 +1167,36 @@ static unsigned char bfin_bmdma_status(struct ata_port *ap)
  *     Note: Original code is ata_data_xfer().
  */
 
-static void bfin_data_xfer(struct ata_device *adev, unsigned char *buf,
-                          unsigned int buflen, int write_data)
+static unsigned int bfin_data_xfer(struct ata_device *dev, unsigned char *buf,
+                                  unsigned int buflen, int rw)
 {
-       struct ata_port *ap = adev->link->ap;
-       unsigned int words = buflen >> 1;
-       unsigned short *buf16 = (u16 *) buf;
+       struct ata_port *ap = dev->link->ap;
        void __iomem *base = (void __iomem *)ap->ioaddr.ctl_addr;
+       unsigned int words = buflen >> 1;
+       unsigned short *buf16 = (u16 *)buf;
 
        /* Transfer multiple of 2 bytes */
-       if (write_data) {
-               write_atapi_data(base, words, buf16);
-       } else {
+       if (rw == READ)
                read_atapi_data(base, words, buf16);
-       }
+       else
+               write_atapi_data(base, words, buf16);
 
        /* Transfer trailing 1 byte, if any. */
        if (unlikely(buflen & 0x01)) {
                unsigned short align_buf[1] = { 0 };
                unsigned char *trailing_buf = buf + buflen - 1;
 
-               if (write_data) {
-                       memcpy(align_buf, trailing_buf, 1);
-                       write_atapi_data(base, 1, align_buf);
-               } else {
+               if (rw == READ) {
                        read_atapi_data(base, 1, align_buf);
                        memcpy(trailing_buf, align_buf, 1);
+               } else {
+                       memcpy(align_buf, trailing_buf, 1);
+                       write_atapi_data(base, 1, align_buf);
                }
+               words++;
        }
+
+       return words << 1;
 }
 
 /**
index 120b5bf..030878f 100644 (file)
@@ -42,13 +42,13 @@ static int ixp4xx_set_mode(struct ata_link *link, struct ata_device **error)
        return 0;
 }
 
-static void ixp4xx_mmio_data_xfer(struct ata_device *adev, unsigned char *buf,
-                               unsigned int buflen, int write_data)
+static unsigned int ixp4xx_mmio_data_xfer(struct ata_device *dev,
+                               unsigned char *buf, unsigned int buflen, int rw)
 {
        unsigned int i;
        unsigned int words = buflen >> 1;
        u16 *buf16 = (u16 *) buf;
-       struct ata_port *ap = adev->link->ap;
+       struct ata_port *ap = dev->link->ap;
        void __iomem *mmio = ap->ioaddr.data_addr;
        struct ixp4xx_pata_data *data = ap->host->dev->platform_data;
 
@@ -59,30 +59,32 @@ static void ixp4xx_mmio_data_xfer(struct ata_device *adev, unsigned char *buf,
        udelay(100);
 
        /* Transfer multiple of 2 bytes */
-       if (write_data) {
-               for (i = 0; i < words; i++)
-                       writew(buf16[i], mmio);
-       } else {
+       if (rw == READ)
                for (i = 0; i < words; i++)
                        buf16[i] = readw(mmio);
-       }
+       else
+               for (i = 0; i < words; i++)
+                       writew(buf16[i], mmio);
 
        /* Transfer trailing 1 byte, if any. */
        if (unlikely(buflen & 0x01)) {
                u16 align_buf[1] = { 0 };
                unsigned char *trailing_buf = buf + buflen - 1;
 
-               if (write_data) {
-                       memcpy(align_buf, trailing_buf, 1);
-                       writew(align_buf[0], mmio);
-               } else {
+               if (rw == READ) {
                        align_buf[0] = readw(mmio);
                        memcpy(trailing_buf, align_buf, 1);
+               } else {
+                       memcpy(align_buf, trailing_buf, 1);
+                       writew(align_buf[0], mmio);
                }
+               words++;
        }
 
        udelay(100);
        *data->cs0_cfg |= 0x01;
+
+       return words << 1;
 }
 
 static struct scsi_host_template ixp4xx_sht = {
index 17159b5..dae85aa 100644 (file)
@@ -249,13 +249,14 @@ static void pdc20230_set_piomode(struct ata_port *ap, struct ata_device *adev)
 
 }
 
-static void pdc_data_xfer_vlb(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data)
+static unsigned int pdc_data_xfer_vlb(struct ata_device *dev,
+                               unsigned char *buf, unsigned int buflen, int rw)
 {
-       struct ata_port *ap = adev->link->ap;
-       int slop = buflen & 3;
-       unsigned long flags;
-
        if (ata_id_has_dword_io(adev->id)) {
+               struct ata_port *ap = dev->link->ap;
+               int slop = buflen & 3;
+               unsigned long flags;
+
                local_irq_save(flags);
 
                /* Perform the 32bit I/O synchronization sequence */
@@ -264,26 +265,27 @@ static void pdc_data_xfer_vlb(struct ata_device *adev, unsigned char *buf, unsig
                ioread8(ap->ioaddr.nsect_addr);
 
                /* Now the data */
-
-               if (write_data)
-                       iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
-               else
+               if (rw == READ)
                        ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
+               else
+                       iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
 
                if (unlikely(slop)) {
-                       __le32 pad = 0;
-                       if (write_data) {
-                               memcpy(&pad, buf + buflen - slop, slop);
-                               iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
-                       } else {
+                       u32 pad;
+                       if (rw == READ) {
                                pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
                                memcpy(buf + buflen - slop, &pad, slop);
+                       } else {
+                               memcpy(&pad, buf + buflen - slop, slop);
+                               iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
                        }
+                       buflen += 4 - slop;
                }
                local_irq_restore(flags);
-       }
-       else
-               ata_data_xfer_noirq(adev, buf, buflen, write_data);
+       } else
+               buflen = ata_data_xfer_noirq(dev, buf, buflen, rw);
+
+       return buflen;
 }
 
 static struct ata_port_operations pdc20230_port_ops = {
index a4c0e50..9f308ed 100644 (file)
@@ -124,29 +124,33 @@ static unsigned int qdi_qc_issue_prot(struct ata_queued_cmd *qc)
        return ata_qc_issue_prot(qc);
 }
 
-static void qdi_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data)
+static unsigned int qdi_data_xfer(struct ata_device *dev, unsigned char *buf,
+                                 unsigned int buflen, int rw)
 {
-       struct ata_port *ap = adev->link->ap;
-       int slop = buflen & 3;
+       if (ata_id_has_dword_io(dev->id)) {
+               struct ata_port *ap = dev->link->ap;
+               int slop = buflen & 3;
 
-       if (ata_id_has_dword_io(adev->id)) {
-               if (write_data)
-                       iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
-               else
+               if (rw == READ)
                        ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
+               else
+                       iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
 
                if (unlikely(slop)) {
-                       __le32 pad = 0;
-                       if (write_data) {
-                               memcpy(&pad, buf + buflen - slop, slop);
-                               iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
-                       } else {
+                       u32 pad;
+                       if (rw == READ) {
                                pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
                                memcpy(buf + buflen - slop, &pad, slop);
+                       } else {
+                               memcpy(&pad, buf + buflen - slop, slop);
+                               iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
                        }
+                       buflen += 4 - slop;
                }
        } else
-               ata_data_xfer(adev, buf, buflen, write_data);
+               buflen = ata_data_xfer(dev, buf, buflen, rw);
+
+       return buflen;
 }
 
 static struct scsi_host_template qdi_sht = {
index ea2ef9f..55055b2 100644 (file)
@@ -768,45 +768,47 @@ static u8 scc_bmdma_status (struct ata_port *ap)
 
 /**
  *     scc_data_xfer - Transfer data by PIO
- *     @adev: device for this I/O
+ *     @dev: device for this I/O
  *     @buf: data buffer
  *     @buflen: buffer length
- *     @write_data: read/write
+ *     @rw: read/write
  *
  *     Note: Original code is ata_data_xfer().
  */
 
-static void scc_data_xfer (struct ata_device *adev, unsigned char *buf,
-                          unsigned int buflen, int write_data)
+static unsigned int scc_data_xfer (struct ata_device *dev, unsigned char *buf,
+                                  unsigned int buflen, int rw)
 {
-       struct ata_port *ap = adev->link->ap;
+       struct ata_port *ap = dev->link->ap;
        unsigned int words = buflen >> 1;
        unsigned int i;
        u16 *buf16 = (u16 *) buf;
        void __iomem *mmio = ap->ioaddr.data_addr;
 
        /* Transfer multiple of 2 bytes */
-       if (write_data) {
-               for (i = 0; i < words; i++)
-                       out_be32(mmio, cpu_to_le16(buf16[i]));
-       } else {
+       if (rw == READ)
                for (i = 0; i < words; i++)
                        buf16[i] = le16_to_cpu(in_be32(mmio));
-       }
+       else
+               for (i = 0; i < words; i++)
+                       out_be32(mmio, cpu_to_le16(buf16[i]));
 
        /* Transfer trailing 1 byte, if any. */
        if (unlikely(buflen & 0x01)) {
                u16 align_buf[1] = { 0 };
                unsigned char *trailing_buf = buf + buflen - 1;
 
-               if (write_data) {
-                       memcpy(align_buf, trailing_buf, 1);
-                       out_be32(mmio, cpu_to_le16(align_buf[0]));
-               } else {
+               if (rw == READ) {
                        align_buf[0] = le16_to_cpu(in_be32(mmio));
                        memcpy(trailing_buf, align_buf, 1);
+               } else {
+                       memcpy(align_buf, trailing_buf, 1);
+                       out_be32(mmio, cpu_to_le16(align_buf[0]));
                }
+               words++;
        }
+
+       return words << 1;
 }
 
 /**
index 7116a9e..7312e91 100644 (file)
@@ -92,29 +92,33 @@ static void winbond_set_piomode(struct ata_port *ap, struct ata_device *adev)
 }
 
 
-static void winbond_data_xfer(struct ata_device *adev, unsigned char *buf, unsigned int buflen, int write_data)
+static void winbond_data_xfer(struct ata_device *dev, unsigned char *buf,
+                             unsigned int buflen, int rw)
 {
-       struct ata_port *ap = adev->link->ap;
+       struct ata_port *ap = dev->link->ap;
        int slop = buflen & 3;
 
-       if (ata_id_has_dword_io(adev->id)) {
-               if (write_data)
-                       iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
-               else
+       if (ata_id_has_dword_io(dev->id)) {
+               if (rw == READ)
                        ioread32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
+               else
+                       iowrite32_rep(ap->ioaddr.data_addr, buf, buflen >> 2);
 
                if (unlikely(slop)) {
-                       __le32 pad = 0;
-                       if (write_data) {
-                               memcpy(&pad, buf + buflen - slop, slop);
-                               iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
-                       } else {
+                       u32 pad;
+                       if (rw == READ) {
                                pad = cpu_to_le32(ioread32(ap->ioaddr.data_addr));
                                memcpy(buf + buflen - slop, &pad, slop);
+                       } else {
+                               memcpy(&pad, buf + buflen - slop, slop);
+                               iowrite32(le32_to_cpu(pad), ap->ioaddr.data_addr);
                        }
+                       buflen += 4 - slop;
                }
        } else
-               ata_data_xfer(adev, buf, buflen, write_data);
+               buflen = ata_data_xfer(dev, buf, buflen, rw);
+
+       return buflen;
 }
 
 static struct scsi_host_template winbond_sht = {
index 03afcd6..7fa96cb 100644 (file)
@@ -701,7 +701,8 @@ struct ata_port_operations {
        void (*bmdma_setup) (struct ata_queued_cmd *qc);
        void (*bmdma_start) (struct ata_queued_cmd *qc);
 
-       void (*data_xfer) (struct ata_device *, unsigned char *, unsigned int, int);
+       unsigned int (*data_xfer) (struct ata_device *dev, unsigned char *buf,
+                                  unsigned int buflen, int rw);
 
        int (*qc_defer) (struct ata_queued_cmd *qc);
        void (*qc_prep) (struct ata_queued_cmd *qc);
@@ -881,10 +882,10 @@ extern void ata_exec_command(struct ata_port *ap, const struct ata_taskfile *tf)
 extern int ata_port_start(struct ata_port *ap);
 extern int ata_sff_port_start(struct ata_port *ap);
 extern irqreturn_t ata_interrupt(int irq, void *dev_instance);
-extern void ata_data_xfer(struct ata_device *adev, unsigned char *buf,
-                         unsigned int buflen, int write_data);
-extern void ata_data_xfer_noirq(struct ata_device *adev, unsigned char *buf,
-                               unsigned int buflen, int write_data);
+extern unsigned int ata_data_xfer(struct ata_device *dev,
+                       unsigned char *buf, unsigned int buflen, int rw);
+extern unsigned int ata_data_xfer_noirq(struct ata_device *dev,
+                       unsigned char *buf, unsigned int buflen, int rw);
 extern int ata_std_qc_defer(struct ata_queued_cmd *qc);
 extern void ata_dumb_qc_prep(struct ata_queued_cmd *qc);
 extern void ata_qc_prep(struct ata_queued_cmd *qc);