libata: Add 32bit PIO support
authorAlan Cox <alan@redhat.com>
Mon, 5 Jan 2009 14:16:39 +0000 (14:16 +0000)
committerJeff Garzik <jgarzik@redhat.com>
Thu, 8 Jan 2009 21:34:27 +0000 (16:34 -0500)
This matters for some controllers and in one or two cases almost doubles
PIO performance. Add a bmdma32 operations set we can inherit and activate
it for some controllers

Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
drivers/ata/ata_piix.c
drivers/ata/libata-sff.c
drivers/ata/pata_ali.c
drivers/ata/pata_amd.c
drivers/ata/pata_mpiix.c
drivers/ata/pata_sil680.c
include/linux/libata.h

index 78659546130c413d70b6dbb534fc32ce2871efa7..887d8f46a287312fd554d77a1c498f37a30cd307 100644 (file)
@@ -310,7 +310,7 @@ static struct scsi_host_template piix_sht = {
 };
 
 static struct ata_port_operations piix_pata_ops = {
-       .inherits               = &ata_bmdma_port_ops,
+       .inherits               = &ata_bmdma32_port_ops,
        .cable_detect           = ata_cable_40wire,
        .set_piomode            = piix_set_piomode,
        .set_dmamode            = piix_set_dmamode,
index 9033d164c4ece13f876777fd7fbb549e4c27456b..b58549fac4603df3c6dc7b356c3d8568b041fa8d 100644 (file)
@@ -78,6 +78,13 @@ const struct ata_port_operations ata_bmdma_port_ops = {
        .bmdma_status           = ata_bmdma_status,
 };
 
+const struct ata_port_operations ata_bmdma32_port_ops = {
+       .inherits               = &ata_bmdma_port_ops,
+
+       .sff_data_xfer          = ata_sff_data_xfer32,
+};
+EXPORT_SYMBOL_GPL(ata_bmdma32_port_ops);
+
 /**
  *     ata_fill_sg - Fill PCI IDE PRD table
  *     @qc: Metadata associated with taskfile to be transferred
@@ -718,6 +725,52 @@ unsigned int ata_sff_data_xfer(struct ata_device *dev, unsigned char *buf,
        return words << 1;
 }
 
+/**
+ *     ata_sff_data_xfer32 - Transfer data by PIO
+ *     @dev: device to target
+ *     @buf: data buffer
+ *     @buflen: buffer length
+ *     @rw: read/write
+ *
+ *     Transfer data from/to the device data register by PIO using 32bit
+ *     I/O operations.
+ *
+ *     LOCKING:
+ *     Inherited from caller.
+ *
+ *     RETURNS:
+ *     Bytes consumed.
+ */
+
+unsigned int ata_sff_data_xfer32(struct ata_device *dev, unsigned char *buf,
+                              unsigned int buflen, int rw)
+{
+       struct ata_port *ap = dev->link->ap;
+       void __iomem *data_addr = ap->ioaddr.data_addr;
+       unsigned int words = buflen >> 2;
+       int slop = buflen & 3;
+
+       /* Transfer multiple of 4 bytes */
+       if (rw == READ)
+               ioread32_rep(data_addr, buf, words);
+       else
+               iowrite32_rep(data_addr, buf, words);
+
+       if (unlikely(slop)) {
+               __le32 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);
+               }
+               words++;
+       }
+       return words << 2;
+}
+EXPORT_SYMBOL_GPL(ata_sff_data_xfer32);
+
 /**
  *     ata_sff_data_xfer_noirq - Transfer data by PIO
  *     @dev: device to target
index a4f9e39442c64eceb0c1ff79e7c3dd10b5724b1b..a7999c19f0c92bc4185a4ae532ec5395c3eb3253 100644 (file)
@@ -151,8 +151,7 @@ static void ali_fifo_control(struct ata_port *ap, struct ata_device *adev, int o
 
        pci_read_config_byte(pdev, pio_fifo, &fifo);
        fifo &= ~(0x0F << shift);
-       if (on)
-               fifo |= (on << shift);
+       fifo |= (on << shift);
        pci_write_config_byte(pdev, pio_fifo, fifo);
 }
 
@@ -370,10 +369,11 @@ static struct ata_port_operations ali_early_port_ops = {
        .inherits       = &ata_sff_port_ops,
        .cable_detect   = ata_cable_40wire,
        .set_piomode    = ali_set_piomode,
+       .sff_data_xfer  = ata_sff_data_xfer32,
 };
 
 static const struct ata_port_operations ali_dma_base_ops = {
-       .inherits       = &ata_bmdma_port_ops,
+       .inherits       = &ata_bmdma32_port_ops,
        .set_piomode    = ali_set_piomode,
        .set_dmamode    = ali_set_dmamode,
 };
index 0ec9c7d9fe9d607250a07bc47a6ce4d3c087041a..63719ab9ea4448839d64d81faa187250ef21637d 100644 (file)
@@ -24,7 +24,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_amd"
-#define DRV_VERSION "0.3.10"
+#define DRV_VERSION "0.3.11"
 
 /**
  *     timing_setup            -       shared timing computation and load
@@ -345,7 +345,7 @@ static struct scsi_host_template amd_sht = {
 };
 
 static const struct ata_port_operations amd_base_port_ops = {
-       .inherits       = &ata_bmdma_port_ops,
+       .inherits       = &ata_bmdma32_port_ops,
        .prereset       = amd_pre_reset,
 };
 
index 7c8faa48b5f3b054c9017981ed8588bf339f2b37..aa576cac4d1756f7071d95fbf66ce6c579b26a8b 100644 (file)
@@ -35,7 +35,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_mpiix"
-#define DRV_VERSION "0.7.6"
+#define DRV_VERSION "0.7.7"
 
 enum {
        IDETIM = 0x6C,          /* IDE control register */
@@ -146,6 +146,7 @@ static struct ata_port_operations mpiix_port_ops = {
        .cable_detect   = ata_cable_40wire,
        .set_piomode    = mpiix_set_piomode,
        .prereset       = mpiix_pre_reset,
+       .sff_data_xfer  = ata_sff_data_xfer32,
 };
 
 static int mpiix_init_one(struct pci_dev *dev, const struct pci_device_id *id)
index 83580a59db58bf7e4fdddd62dbd8da7d596fc3dc..9e764e5747e6c7d1ff273d6bd562d4fcdc77aaf8 100644 (file)
@@ -32,7 +32,7 @@
 #include <linux/libata.h>
 
 #define DRV_NAME "pata_sil680"
-#define DRV_VERSION "0.4.8"
+#define DRV_VERSION "0.4.9"
 
 #define SIL680_MMIO_BAR                5
 
@@ -195,7 +195,7 @@ static struct scsi_host_template sil680_sht = {
 };
 
 static struct ata_port_operations sil680_port_ops = {
-       .inherits       = &ata_bmdma_port_ops,
+       .inherits       = &ata_bmdma32_port_ops,
        .cable_detect   = sil680_cable_detect,
        .set_piomode    = sil680_set_piomode,
        .set_dmamode    = sil680_set_dmamode,
index 3449de597eff8810a1538672da316f33a6ad6cd6..4f7c8fb4d3fe6173b80788be019e5439efacdbbb 100644 (file)
@@ -1518,6 +1518,7 @@ extern void sata_pmp_error_handler(struct ata_port *ap);
 
 extern const struct ata_port_operations ata_sff_port_ops;
 extern const struct ata_port_operations ata_bmdma_port_ops;
+extern const struct ata_port_operations ata_bmdma32_port_ops;
 
 /* PIO only, sg_tablesize and dma_boundary limits can be removed */
 #define ATA_PIO_SHT(drv_name)                                  \
@@ -1545,6 +1546,8 @@ extern void ata_sff_exec_command(struct ata_port *ap,
                                 const struct ata_taskfile *tf);
 extern unsigned int ata_sff_data_xfer(struct ata_device *dev,
                        unsigned char *buf, unsigned int buflen, int rw);
+extern unsigned int ata_sff_data_xfer32(struct ata_device *dev,
+                       unsigned char *buf, unsigned int buflen, int rw);
 extern unsigned int ata_sff_data_xfer_noirq(struct ata_device *dev,
                        unsigned char *buf, unsigned int buflen, int rw);
 extern u8 ata_sff_irq_on(struct ata_port *ap);