Skip to content

Commit

Permalink
libata: Add 32bit PIO support
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Alan Cox authored and Jeff Garzik committed Jan 8, 2009
1 parent e427fe0 commit 871af12
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 9 deletions.
2 changes: 1 addition & 1 deletion drivers/ata/ata_piix.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
53 changes: 53 additions & 0 deletions drivers/ata/libata-sff.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
6 changes: 3 additions & 3 deletions drivers/ata/pata_ali.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down Expand Up @@ -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,
};
Expand Down
4 changes: 2 additions & 2 deletions drivers/ata/pata_amd.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
};

Expand Down
3 changes: 2 additions & 1 deletion drivers/ata/pata_mpiix.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions drivers/ata/pata_sil680.c
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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,
Expand Down
3 changes: 3 additions & 0 deletions include/linux/libata.h
Original file line number Diff line number Diff line change
Expand Up @@ -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) \
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit 871af12

Please sign in to comment.